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/public-api/scripting/scripting.h>
37 #include <dali/internal/common/internal-constants.h>
38 #include <dali/internal/event/common/event-thread-services.h>
39 #include <dali/internal/event/render-tasks/render-task-impl.h>
40 #include <dali/internal/event/actors/camera-actor-impl.h>
41 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
42 #include <dali/internal/event/common/property-helper.h>
43 #include <dali/internal/event/common/stage-impl.h>
44 #include <dali/internal/event/common/type-info-impl.h>
45 #include <dali/internal/event/actor-attachments/actor-attachment-impl.h>
46 #include <dali/internal/event/animation/constraint-impl.h>
47 #include <dali/internal/event/common/projection.h>
48 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
49 #include <dali/internal/update/common/animatable-property.h>
50 #include <dali/internal/update/nodes/node-messages.h>
51 #include <dali/internal/update/nodes/node-declarations.h>
52 #include <dali/internal/update/animation/scene-graph-constraint.h>
53 #include <dali/internal/event/events/actor-gesture-data.h>
54 #include <dali/internal/common/message.h>
55 #include <dali/integration-api/debug.h>
57 #ifdef DYNAMICS_SUPPORT
58 #include <dali/internal/event/dynamics/dynamics-body-config-impl.h>
59 #include <dali/internal/event/dynamics/dynamics-body-impl.h>
60 #include <dali/internal/event/dynamics/dynamics-joint-impl.h>
61 #include <dali/internal/event/dynamics/dynamics-world-impl.h>
64 using Dali::Internal::SceneGraph::Node;
65 using Dali::Internal::SceneGraph::AnimatableProperty;
66 using Dali::Internal::SceneGraph::PropertyBase;
70 namespace ResizePolicy
75 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )DALI_ENUM_TO_STRING( FIXED )
76 DALI_ENUM_TO_STRING( USE_NATURAL_SIZE )
77 DALI_ENUM_TO_STRING( FILL_TO_PARENT )
78 DALI_ENUM_TO_STRING( SIZE_RELATIVE_TO_PARENT )
79 DALI_ENUM_TO_STRING( SIZE_FIXED_OFFSET_FROM_PARENT )
80 DALI_ENUM_TO_STRING( FIT_TO_CHILDREN )
81 DALI_ENUM_TO_STRING( DIMENSION_DEPENDENCY )
82 DALI_ENUM_TO_STRING( USE_ASSIGNED_SIZE )
83 DALI_ENUM_TO_STRING_TABLE_END( Type )
85 } // unnamed namespace
88 namespace SizeScalePolicy
92 // Enumeration to / from string conversion tables
93 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )DALI_ENUM_TO_STRING( USE_SIZE_SET )
94 DALI_ENUM_TO_STRING( FIT_WITH_ASPECT_RATIO )
95 DALI_ENUM_TO_STRING( FILL_WITH_ASPECT_RATIO )
96 DALI_ENUM_TO_STRING_TABLE_END( Type )
97 } // unnamed namespace
103 unsigned int Actor::mActorCounter = 0;
106 * Struct to collect relayout variables
108 struct Actor::RelayoutData
111 : sizeModeFactor( Vector3::ONE ), preferredSize( Vector2::ZERO ), sizeSetPolicy( SizeScalePolicy::USE_SIZE_SET ), relayoutEnabled( false ), insideRelayout( false )
113 // Set size negotiation defaults
114 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
116 resizePolicies[ i ] = ResizePolicy::FIXED;
117 negotiatedDimensions[ i ] = 0.0f;
118 dimensionNegotiated[ i ] = false;
119 dimensionDirty[ i ] = false;
120 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
121 dimensionPadding[ i ] = Vector2( 0.0f, 0.0f );
122 minimumSize[ i ] = 0.0f;
123 maximumSize[ i ] = FLT_MAX;
127 ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies
129 Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies
131 Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
133 float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
135 float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be
136 float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be
138 bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated
139 bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
141 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
143 Vector2 preferredSize; ///< The preferred size of the actor
145 SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
147 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
148 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
151 #ifdef DYNAMICS_SUPPORT
153 // Encapsulate actor related dynamics data
156 DynamicsData( Actor* slotOwner )
157 : slotDelegate( slotOwner )
161 typedef std::map<Actor*, DynamicsJointPtr> JointContainer;
162 typedef std::vector<DynamicsJointPtr> ReferencedJointContainer;
164 DynamicsBodyPtr body;
165 JointContainer joints;
166 ReferencedJointContainer referencedJoints;
168 SlotDelegate< Actor > slotDelegate;
171 #endif // DYNAMICS_SUPPORT
173 namespace // unnamed namespace
179 * We want to discourage the use of property strings (minimize string comparisons),
180 * particularly for the default properties.
181 * Name Type writable animatable constraint-input enum for index-checking
183 DALI_PROPERTY_TABLE_BEGIN
184 DALI_PROPERTY( "parent-origin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
185 DALI_PROPERTY( "parent-origin-x", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
186 DALI_PROPERTY( "parent-origin-y", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
187 DALI_PROPERTY( "parent-origin-z", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
188 DALI_PROPERTY( "anchor-point", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
189 DALI_PROPERTY( "anchor-point-x", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
190 DALI_PROPERTY( "anchor-point-y", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
191 DALI_PROPERTY( "anchor-point-z", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
192 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
193 DALI_PROPERTY( "size-width", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
194 DALI_PROPERTY( "size-height", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
195 DALI_PROPERTY( "size-depth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
196 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
197 DALI_PROPERTY( "position-x", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
198 DALI_PROPERTY( "position-y", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
199 DALI_PROPERTY( "position-z", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
200 DALI_PROPERTY( "world-position", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
201 DALI_PROPERTY( "world-position-x", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
202 DALI_PROPERTY( "world-position-y", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
203 DALI_PROPERTY( "world-position-z", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
204 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
205 DALI_PROPERTY( "world-orientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
206 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
207 DALI_PROPERTY( "scale-x", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
208 DALI_PROPERTY( "scale-y", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
209 DALI_PROPERTY( "scale-z", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
210 DALI_PROPERTY( "world-scale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
211 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
212 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
213 DALI_PROPERTY( "color-red", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
214 DALI_PROPERTY( "color-green", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
215 DALI_PROPERTY( "color-blue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
216 DALI_PROPERTY( "color-alpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
217 DALI_PROPERTY( "world-color", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
218 DALI_PROPERTY( "world-matrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
219 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
220 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
221 DALI_PROPERTY( "leave-required", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
222 DALI_PROPERTY( "inherit-orientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
223 DALI_PROPERTY( "inherit-scale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
224 DALI_PROPERTY( "color-mode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
225 DALI_PROPERTY( "position-inheritance", STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE )
226 DALI_PROPERTY( "draw-mode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
227 DALI_PROPERTY( "size-mode-factor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
228 DALI_PROPERTY( "width-resize-policy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
229 DALI_PROPERTY( "height-resize-policy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
230 DALI_PROPERTY( "size-scale-policy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
231 DALI_PROPERTY( "width-for-height", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
232 DALI_PROPERTY( "height-for-width", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
233 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
234 DALI_PROPERTY( "minimum-size", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
235 DALI_PROPERTY( "maximum-size", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
236 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
240 const char* const SIGNAL_TOUCHED = "touched";
241 const char* const SIGNAL_HOVERED = "hovered";
242 const char* const SIGNAL_MOUSE_WHEEL_EVENT = "mouse-wheel-event";
243 const char* const SIGNAL_ON_STAGE = "on-stage";
244 const char* const SIGNAL_OFF_STAGE = "off-stage";
248 const char* const ACTION_SHOW = "show";
249 const char* const ACTION_HIDE = "hide";
251 BaseHandle CreateActor()
253 return Dali::Actor::New();
256 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
258 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
259 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
260 SignalConnectorType signalConnector3( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
261 SignalConnectorType signalConnector4( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
263 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
264 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
267 * @brief Extract a given dimension from a Vector2
269 * @param[in] values The values to extract from
270 * @param[in] dimension The dimension to extract
271 * @return Return the value for the dimension
273 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
277 case Dimension::WIDTH:
282 case Dimension::HEIGHT:
284 return values.height;
297 * @brief Extract a given dimension from a Vector3
299 * @param[in] values The values to extract from
300 * @param[in] dimension The dimension to extract
301 * @return Return the value for the dimension
303 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
305 return GetDimensionValue( values.GetVectorXY(), dimension );
308 } // unnamed namespace
310 ActorPtr Actor::New()
312 ActorPtr actor( new Actor( BASIC ) );
314 // Second-phase construction
320 const std::string& Actor::GetName() const
325 void Actor::SetName( const std::string& name )
331 // ATTENTION: string for debug purposes is not thread safe.
332 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
336 unsigned int Actor::GetId() const
341 void Actor::Attach( ActorAttachment& attachment )
343 DALI_ASSERT_DEBUG( !mAttachment && "An Actor can only have one attachment" );
347 attachment.Connect();
350 mAttachment = ActorAttachmentPtr( &attachment );
353 ActorAttachmentPtr Actor::GetAttachment()
358 bool Actor::OnStage() const
363 Dali::Layer Actor::GetLayer()
367 // Short-circuit for Layer derived actors
370 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
373 // Find the immediate Layer parent
374 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
376 if( parent->IsLayer() )
378 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
385 void Actor::Add( Actor& child )
387 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
388 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
392 mChildren = new ActorContainer;
395 Actor* const oldParent( child.mParent );
397 // child might already be ours
398 if( this != oldParent )
400 // if we already have parent, unparent us first
403 oldParent->Remove( child ); // This causes OnChildRemove callback
405 // Old parent may need to readjust to missing child
406 if( oldParent->RelayoutDependentOnChildren() )
408 oldParent->RelayoutRequest();
412 // Guard against Add() during previous OnChildRemove callback
415 // Do this first, since user callbacks from within SetParent() may need to remove child
416 mChildren->push_back( Dali::Actor( &child ) );
418 // SetParent asserts that child can be added
419 child.SetParent( this );
421 // Notification for derived classes
424 // Only put in a relayout request if there is a suitable dependency
425 if( RelayoutDependentOnChildren() )
433 void Actor::Insert( unsigned int index, Actor& child )
435 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
436 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
440 mChildren = new ActorContainer;
443 Actor* const oldParent( child.mParent );
445 // since an explicit position has been given, always insert, even if already a child
448 oldParent->Remove( child ); // This causes OnChildRemove callback
450 // Old parent may need to readjust to missing child
451 if( oldParent->RelayoutDependentOnChildren() )
453 oldParent->RelayoutRequest();
457 // Guard against Add() during previous OnChildRemove callback
460 // Do this first, since user callbacks from within SetParent() may need to remove child
461 if( index < GetChildCount() )
463 ActorIter it = mChildren->begin();
464 std::advance( it, index );
465 mChildren->insert( it, Dali::Actor( &child ) );
469 mChildren->push_back( Dali::Actor( &child ) );
471 // SetParent asserts that child can be added
472 child.SetParent( this, index );
474 // Notification for derived classes
477 // Only put in a relayout request if there is a suitable dependency
478 if( RelayoutDependentOnChildren() )
483 if( child.RelayoutDependentOnParent() )
485 child.RelayoutRequest();
490 void Actor::Remove( Actor& child )
492 DALI_ASSERT_ALWAYS( this != &child && "Cannot remove actor from itself" );
502 // Find the child in mChildren, and unparent it
503 ActorIter end = mChildren->end();
504 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
506 Actor& actor = GetImplementation( *iter );
508 if( &actor == &child )
510 // Keep handle for OnChildRemove notification
511 removed = Dali::Actor( &actor );
513 // Do this first, since user callbacks from within SetParent() may need to add the child
514 mChildren->erase( iter );
516 DALI_ASSERT_DEBUG( actor.GetParent() == this );
517 actor.SetParent( NULL );
525 // Notification for derived classes
526 OnChildRemove( GetImplementation( removed ) );
528 // Only put in a relayout request if there is a suitable dependency
529 if( RelayoutDependentOnChildren() )
536 void Actor::Unparent()
540 // Remove this actor from the parent. The remove will put a relayout request in for
541 // the parent if required
542 mParent->Remove( *this );
543 // mParent is now NULL!
547 unsigned int Actor::GetChildCount() const
549 return ( NULL != mChildren ) ? mChildren->size() : 0;
552 Dali::Actor Actor::GetChildAt( unsigned int index ) const
554 DALI_ASSERT_ALWAYS( index < GetChildCount() );
556 return ( ( mChildren ) ? ( *mChildren )[ index ] : Dali::Actor() );
559 ActorPtr Actor::FindChildByName( const std::string& actorName )
562 if( actorName == mName )
568 ActorIter end = mChildren->end();
569 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
571 child = GetImplementation( *iter ).FindChildByName( actorName );
582 ActorPtr Actor::FindChildById( const unsigned int id )
591 ActorIter end = mChildren->end();
592 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
594 child = GetImplementation( *iter ).FindChildById( id );
605 void Actor::SetParentOrigin( const Vector3& origin )
609 // mNode is being used in a separate thread; queue a message to set the value & base value
610 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
613 // Cache for event-thread access
616 // not allocated, check if different from default
617 if( ParentOrigin::DEFAULT != origin )
619 mParentOrigin = new Vector3( origin );
624 // check if different from current costs more than just set
625 *mParentOrigin = origin;
629 void Actor::SetParentOriginX( float x )
631 const Vector3& current = GetCurrentParentOrigin();
633 SetParentOrigin( Vector3( x, current.y, current.z ) );
636 void Actor::SetParentOriginY( float y )
638 const Vector3& current = GetCurrentParentOrigin();
640 SetParentOrigin( Vector3( current.x, y, current.z ) );
643 void Actor::SetParentOriginZ( float z )
645 const Vector3& current = GetCurrentParentOrigin();
647 SetParentOrigin( Vector3( current.x, current.y, z ) );
650 const Vector3& Actor::GetCurrentParentOrigin() const
652 // Cached for event-thread access
653 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
656 void Actor::SetAnchorPoint( const Vector3& anchor )
660 // mNode is being used in a separate thread; queue a message to set the value & base value
661 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
664 // Cache for event-thread access
667 // not allocated, check if different from default
668 if( AnchorPoint::DEFAULT != anchor )
670 mAnchorPoint = new Vector3( anchor );
675 // check if different from current costs more than just set
676 *mAnchorPoint = anchor;
680 void Actor::SetAnchorPointX( float x )
682 const Vector3& current = GetCurrentAnchorPoint();
684 SetAnchorPoint( Vector3( x, current.y, current.z ) );
687 void Actor::SetAnchorPointY( float y )
689 const Vector3& current = GetCurrentAnchorPoint();
691 SetAnchorPoint( Vector3( current.x, y, current.z ) );
694 void Actor::SetAnchorPointZ( float z )
696 const Vector3& current = GetCurrentAnchorPoint();
698 SetAnchorPoint( Vector3( current.x, current.y, z ) );
701 const Vector3& Actor::GetCurrentAnchorPoint() const
703 // Cached for event-thread access
704 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
707 void Actor::SetPosition( float x, float y )
709 SetPosition( Vector3( x, y, 0.0f ) );
712 void Actor::SetPosition( float x, float y, float z )
714 SetPosition( Vector3( x, y, z ) );
717 void Actor::SetPosition( const Vector3& position )
719 mTargetPosition = position;
723 // mNode is being used in a separate thread; queue a message to set the value & base value
724 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::Bake, position );
728 void Actor::SetX( float x )
730 mTargetPosition.x = x;
734 // mNode is being used in a separate thread; queue a message to set the value & base value
735 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeX, x );
739 void Actor::SetY( float y )
741 mTargetPosition.y = y;
745 // mNode is being used in a separate thread; queue a message to set the value & base value
746 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeY, y );
750 void Actor::SetZ( float z )
752 mTargetPosition.z = z;
756 // mNode is being used in a separate thread; queue a message to set the value & base value
757 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeZ, z );
761 void Actor::TranslateBy( const Vector3& distance )
763 mTargetPosition += distance;
767 // mNode is being used in a separate thread; queue a message to set the value & base value
768 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeRelative, distance );
772 const Vector3& Actor::GetCurrentPosition() const
776 // mNode is being used in a separate thread; copy the value from the previous update
777 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
780 return Vector3::ZERO;
783 const Vector3& Actor::GetTargetPosition() const
785 return mTargetPosition;
788 const Vector3& Actor::GetCurrentWorldPosition() const
792 // mNode is being used in a separate thread; copy the value from the previous update
793 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
796 return Vector3::ZERO;
799 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
801 // this flag is not animatable so keep the value
802 mPositionInheritanceMode = mode;
805 // mNode is being used in a separate thread; queue a message to set the value
806 SetPositionInheritanceModeMessage( GetEventThreadServices(), *mNode, mode );
810 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
812 // Cached for event-thread access
813 return mPositionInheritanceMode;
816 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
818 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
819 normalizedAxis.Normalize();
821 Quaternion orientation( angle, normalizedAxis );
823 SetOrientation( orientation );
826 void Actor::SetOrientation( const Quaternion& orientation )
830 // mNode is being used in a separate thread; queue a message to set the value & base value
831 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::Bake, orientation );
835 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
839 // mNode is being used in a separate thread; queue a message to set the value & base value
840 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, Quaternion(angle, axis) );
844 void Actor::RotateBy( const Quaternion& relativeRotation )
848 // mNode is being used in a separate thread; queue a message to set the value & base value
849 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, relativeRotation );
853 const Quaternion& Actor::GetCurrentOrientation() const
857 // mNode is being used in a separate thread; copy the value from the previous update
858 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
861 return Quaternion::IDENTITY;
864 const Quaternion& Actor::GetCurrentWorldOrientation() const
868 // mNode is being used in a separate thread; copy the value from the previous update
869 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
872 return Quaternion::IDENTITY;
875 void Actor::SetScale( float scale )
877 SetScale( Vector3( scale, scale, scale ) );
880 void Actor::SetScale( float x, float y, float z )
882 SetScale( Vector3( x, y, z ) );
885 void Actor::SetScale( const Vector3& scale )
889 // mNode is being used in a separate thread; queue a message to set the value & base value
890 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::Bake, scale );
894 void Actor::SetScaleX( float x )
898 // mNode is being used in a separate thread; queue a message to set the value & base value
899 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeX, x );
903 void Actor::SetScaleY( float y )
907 // mNode is being used in a separate thread; queue a message to set the value & base value
908 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeY, y );
912 void Actor::SetScaleZ( float z )
916 // mNode is being used in a separate thread; queue a message to set the value & base value
917 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeZ, z );
921 void Actor::SetInitialVolume( const Vector3& volume )
925 // mNode is being used in a separate thread; queue a message to set the value
926 SetInitialVolumeMessage( GetEventThreadServices(), *mNode, volume );
930 void Actor::SetTransmitGeometryScaling( bool transmitGeometryScaling )
934 // mNode is being used in a separate thread; queue a message to set the value
935 SetTransmitGeometryScalingMessage( GetEventThreadServices(), *mNode, transmitGeometryScaling );
939 bool Actor::GetTransmitGeometryScaling() const
943 // mNode is being used in a separate thread; copy the value from the previous update
944 return mNode->GetTransmitGeometryScaling();
950 void Actor::ScaleBy( const Vector3& relativeScale )
954 // mNode is being used in a separate thread; queue a message to set the value & base value
955 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeRelativeMultiply, relativeScale );
959 const Vector3& Actor::GetCurrentScale() const
963 // mNode is being used in a separate thread; copy the value from the previous update
964 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
970 const Vector3& Actor::GetCurrentWorldScale() const
974 // mNode is being used in a separate thread; copy the value from the previous update
975 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
981 void Actor::SetInheritScale( bool inherit )
983 // non animateable so keep local copy
984 mInheritScale = inherit;
987 // mNode is being used in a separate thread; queue a message to set the value
988 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
992 bool Actor::IsScaleInherited() const
994 return mInheritScale;
997 Matrix Actor::GetCurrentWorldMatrix() const
1001 // World matrix is no longer updated unless there is something observing the node.
1002 // Need to calculate it from node's world position, orientation and scale:
1003 BufferIndex updateBufferIndex = GetEventThreadServices().GetEventBufferIndex();
1004 Matrix worldMatrix(false);
1005 worldMatrix.SetTransformComponents( mNode->GetWorldScale( updateBufferIndex ),
1006 mNode->GetWorldOrientation( updateBufferIndex ),
1007 mNode->GetWorldPosition( updateBufferIndex ) );
1011 return Matrix::IDENTITY;
1014 void Actor::SetVisible( bool visible )
1018 // mNode is being used in a separate thread; queue a message to set the value & base value
1019 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
1023 bool Actor::IsVisible() const
1027 // mNode is being used in a separate thread; copy the value from the previous update
1028 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
1034 void Actor::SetOpacity( float opacity )
1038 // mNode is being used in a separate thread; queue a message to set the value & base value
1039 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
1043 float Actor::GetCurrentOpacity() const
1047 // mNode is being used in a separate thread; copy the value from the previous update
1048 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1054 const Vector4& Actor::GetCurrentWorldColor() const
1058 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1061 return Color::WHITE;
1064 void Actor::SetColor( const Vector4& color )
1068 // mNode is being used in a separate thread; queue a message to set the value & base value
1069 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1073 void Actor::SetColorRed( float red )
1077 // mNode is being used in a separate thread; queue a message to set the value & base value
1078 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1082 void Actor::SetColorGreen( float green )
1086 // mNode is being used in a separate thread; queue a message to set the value & base value
1087 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1091 void Actor::SetColorBlue( float blue )
1095 // mNode is being used in a separate thread; queue a message to set the value & base value
1096 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1100 const Vector4& Actor::GetCurrentColor() const
1104 // mNode is being used in a separate thread; copy the value from the previous update
1105 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1108 return Color::WHITE;
1111 void Actor::SetInheritOrientation( bool inherit )
1113 // non animateable so keep local copy
1114 mInheritOrientation = inherit;
1117 // mNode is being used in a separate thread; queue a message to set the value
1118 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1122 bool Actor::IsOrientationInherited() const
1124 return mInheritOrientation;
1127 void Actor::SetSizeModeFactor( const Vector3& factor )
1129 EnsureRelayoutData();
1131 mRelayoutData->sizeModeFactor = factor;
1134 const Vector3& Actor::GetSizeModeFactor() const
1136 EnsureRelayoutData();
1138 return mRelayoutData->sizeModeFactor;
1141 void Actor::SetColorMode( ColorMode colorMode )
1143 // non animateable so keep local copy
1144 mColorMode = colorMode;
1147 // mNode is being used in a separate thread; queue a message to set the value
1148 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1152 ColorMode Actor::GetColorMode() const
1154 // we have cached copy
1158 void Actor::SetSize( float width, float height )
1160 SetSize( Vector2( width, height ) );
1163 void Actor::SetSize( float width, float height, float depth )
1165 SetSize( Vector3( width, height, depth ) );
1168 void Actor::SetSize( const Vector2& size )
1170 SetSize( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1173 void Actor::SetSizeInternal( const Vector2& size )
1175 SetSizeInternal( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1178 float Actor::CalculateSizeZ( const Vector2& size ) const
1180 return std::min( size.width, size.height );
1183 void Actor::SetSize( const Vector3& size )
1185 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1187 SetPreferredSize( size.GetVectorXY() );
1191 SetSizeInternal( size );
1195 void Actor::SetSizeInternal( const Vector3& size )
1201 // mNode is being used in a separate thread; queue a message to set the value & base value
1202 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::Bake, mTargetSize );
1204 // Notification for derived classes
1205 OnSizeSet( mTargetSize );
1207 // Raise a relayout request if the flag is not locked
1208 if( mRelayoutData && !mRelayoutData->insideRelayout )
1215 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1217 mTargetSize = targetSize;
1219 // Notify deriving classes
1220 OnSizeAnimation( animation, targetSize );
1223 void Actor::SetWidth( float width )
1227 // mNode is being used in a separate thread; queue a message to set the value & base value
1228 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeX, width );
1232 void Actor::SetHeight( float height )
1236 // mNode is being used in a separate thread; queue a message to set the value & base value
1237 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeY, height );
1241 void Actor::SetDepth( float depth )
1245 // mNode is being used in a separate thread; queue a message to set the value & base value
1246 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeZ, depth );
1250 const Vector3& Actor::GetTargetSize() const
1255 const Vector3& Actor::GetCurrentSize() const
1259 // mNode is being used in a separate thread; copy the value from the previous update
1260 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1263 return Vector3::ZERO;
1266 Vector3 Actor::GetNaturalSize() const
1268 // It is up to deriving classes to return the appropriate natural size
1269 return Vector3( 0.0f, 0.0f, 0.0f );
1272 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1274 EnsureRelayoutData();
1276 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1278 if( dimension & ( 1 << i ) )
1280 mRelayoutData->resizePolicies[ i ] = policy;
1284 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1286 if( dimension & Dimension::WIDTH )
1288 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1291 if( dimension & Dimension::HEIGHT )
1293 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1297 // If calling SetResizePolicy, assume we want relayout enabled
1298 SetRelayoutEnabled( true );
1300 OnSetResizePolicy( policy, dimension );
1302 // Trigger relayout on this control
1306 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1308 EnsureRelayoutData();
1310 // If more than one dimension is requested, just return the first one found
1311 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1313 if( ( dimension & ( 1 << i ) ) )
1315 return mRelayoutData->resizePolicies[ i ];
1319 return ResizePolicy::FIXED; // Default
1322 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1324 EnsureRelayoutData();
1326 mRelayoutData->sizeSetPolicy = policy;
1329 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1331 EnsureRelayoutData();
1333 return mRelayoutData->sizeSetPolicy;
1336 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1338 EnsureRelayoutData();
1340 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1342 if( dimension & ( 1 << i ) )
1344 mRelayoutData->dimensionDependencies[ i ] = dependency;
1349 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1351 EnsureRelayoutData();
1353 // If more than one dimension is requested, just return the first one found
1354 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1356 if( ( dimension & ( 1 << i ) ) )
1358 return mRelayoutData->dimensionDependencies[ i ];
1362 return Dimension::ALL_DIMENSIONS; // Default
1365 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1367 // If relayout data has not been allocated yet and the client is requesting
1368 // to disable it, do nothing
1369 if( mRelayoutData || relayoutEnabled )
1371 EnsureRelayoutData();
1373 mRelayoutData->relayoutEnabled = relayoutEnabled;
1377 bool Actor::IsRelayoutEnabled() const
1379 // Assume that if relayout data has not been allocated yet then
1380 // relayout is disabled
1381 return mRelayoutData && mRelayoutData->relayoutEnabled;
1384 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1386 EnsureRelayoutData();
1388 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1390 if( dimension & ( 1 << i ) )
1392 mRelayoutData->dimensionDirty[ i ] = dirty;
1397 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1399 EnsureRelayoutData();
1401 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1403 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1412 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1414 EnsureRelayoutData();
1416 return mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1419 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1421 EnsureRelayoutData();
1423 return mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1426 #ifdef DYNAMICS_SUPPORT
1428 //--------------- Dynamics ---------------
1430 void Actor::DisableDynamics()
1432 if( NULL != mDynamicsData )
1434 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1436 // ensure dynamics object are disconnected from scene
1437 DisconnectDynamics();
1439 // delete joint owned by this actor
1440 while( !mDynamicsData->joints.empty() )
1442 RemoveDynamicsJoint( mDynamicsData->joints.begin()->second );
1445 // delete other joints referencing this actor
1446 while( !mDynamicsData->referencedJoints.empty() )
1448 DynamicsJointPtr joint( *(mDynamicsData->referencedJoints.begin()) );
1449 ActorPtr jointOwner( joint->GetActor( true ) );
1452 jointOwner->RemoveDynamicsJoint( joint );
1456 mDynamicsData->referencedJoints.erase( mDynamicsData->referencedJoints.begin() );
1459 // delete the DynamicsBody object
1460 mDynamicsData->body.Reset();
1462 // Discard Dynamics data structure
1463 delete mDynamicsData;
1464 mDynamicsData = NULL;
1468 DynamicsBodyPtr Actor::GetDynamicsBody() const
1470 DynamicsBodyPtr body;
1472 if( NULL != mDynamicsData )
1474 body = mDynamicsData->body;
1480 DynamicsBodyPtr Actor::EnableDynamics(DynamicsBodyConfigPtr bodyConfig)
1482 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1484 if( NULL == mDynamicsData )
1486 mDynamicsData = new DynamicsData( this );
1489 if( !mDynamicsData->body )
1491 mDynamicsData->body = new DynamicsBody(mName, bodyConfig, *this, *(const_cast<SceneGraph::Node*>(mNode)) );
1495 DynamicsWorldPtr world( DynamicsWorld::Get() );
1498 if( mParent == world->GetRootActor().Get() )
1500 mDynamicsData->body->Connect( GetEventThreadServices() );
1506 return mDynamicsData->body;
1509 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offset )
1511 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1512 return AddDynamicsJoint( attachedActor, offset, ( GetCurrentPosition() + offset ) - attachedActor->GetCurrentPosition() );
1515 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offsetA, const Vector3& offsetB )
1517 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1518 DALI_ASSERT_ALWAYS( this != attachedActor.Get() && "Cannot create a joint to oneself!" );
1520 DynamicsJointPtr joint;
1522 DynamicsWorldPtr world( DynamicsWorld::Get() );
1526 if( NULL != mDynamicsData )
1528 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1530 if( mDynamicsData->joints.end() != it )
1532 // use existing joint
1538 DynamicsBodyPtr bodyA( GetDynamicsBody() );
1539 DynamicsBodyPtr bodyB( attachedActor->GetDynamicsBody() );
1543 bodyA = EnableDynamics( new DynamicsBodyConfig );
1548 bodyB = attachedActor->EnableDynamics( new DynamicsBodyConfig );
1551 joint = new DynamicsJoint(world, bodyA, bodyB, offsetA, offsetB);
1552 mDynamicsData->joints[ attachedActor.Get() ] = joint;
1554 if( OnStage() && attachedActor->OnStage() )
1556 joint->Connect( GetEventThreadServices() );
1559 attachedActor->ReferenceJoint( joint );
1561 attachedActor->OnStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1562 attachedActor->OffStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1569 const int Actor::GetNumberOfJoints() const
1571 return static_cast<int>( NULL != mDynamicsData ? mDynamicsData->joints.size() : 0 );
1574 DynamicsJointPtr Actor::GetDynamicsJointByIndex( const int index ) const
1576 DynamicsJointPtr joint;
1578 if( NULL != mDynamicsData )
1580 if( index >= 0 && index < static_cast<int>(mDynamicsData->joints.size()) )
1582 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.begin() );
1584 for( int i = 0; i < index; ++i )
1596 DynamicsJointPtr Actor::GetDynamicsJoint( ActorPtr attachedActor ) const
1598 DynamicsJointPtr joint;
1600 if( NULL != mDynamicsData )
1602 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1604 if( mDynamicsData->joints.end() != it )
1606 // use existing joint
1614 void Actor::RemoveDynamicsJoint( DynamicsJointPtr joint )
1616 if( NULL != mDynamicsData )
1618 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1619 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1621 for(; it != endIt; ++it )
1623 if( it->second == joint.Get() )
1625 ActorPtr attachedActor( it->first );
1627 if( OnStage() && attachedActor && attachedActor->OnStage() )
1629 joint->Disconnect( GetEventThreadServices() );
1634 attachedActor->ReleaseJoint( joint );
1635 attachedActor->OnStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1636 attachedActor->OffStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1639 mDynamicsData->joints.erase(it);
1646 void Actor::ReferenceJoint( DynamicsJointPtr joint )
1648 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1650 if( NULL != mDynamicsData )
1652 mDynamicsData->referencedJoints.push_back(joint);
1656 void Actor::ReleaseJoint( DynamicsJointPtr joint )
1658 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1660 if( NULL != mDynamicsData )
1662 DynamicsData::ReferencedJointContainer::iterator it( std::find( mDynamicsData->referencedJoints.begin(), mDynamicsData->referencedJoints.end(), joint ) );
1664 if( it != mDynamicsData->referencedJoints.end() )
1666 mDynamicsData->referencedJoints.erase( it );
1671 void Actor::SetDynamicsRoot(bool flag)
1673 if( mIsDynamicsRoot != flag )
1675 mIsDynamicsRoot = flag;
1677 if( OnStage() && mChildren )
1679 // walk the children connecting or disconnecting any dynamics enabled child from the dynamics simulation
1680 ActorIter end = mChildren->end();
1681 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
1683 Actor& child = GetImplementation(*iter);
1685 if( child.GetDynamicsBody() )
1687 if( mIsDynamicsRoot )
1689 child.ConnectDynamics();
1693 child.DisconnectDynamics();
1701 bool Actor::IsDynamicsRoot() const
1703 return mIsDynamicsRoot;
1706 void Actor::AttachedActorOnStage( Dali::Actor actor )
1708 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1712 ActorPtr attachedActor( &GetImplementation(actor) );
1714 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1715 if( NULL != mDynamicsData )
1717 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1718 if( mDynamicsData->joints.end() != it )
1720 DynamicsJointPtr joint( it->second );
1721 joint->Connect( GetEventThreadServices() );
1727 void Actor::AttachedActorOffStage( Dali::Actor actor )
1729 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1733 ActorPtr attachedActor( &GetImplementation(actor) );
1735 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1736 if( NULL != mDynamicsData )
1738 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1739 if( mDynamicsData->joints.end() != it )
1741 DynamicsJointPtr joint( it->second );
1742 joint->Disconnect( GetEventThreadServices() );
1748 void Actor::ConnectDynamics()
1750 if( NULL != mDynamicsData && mDynamicsData->body )
1752 if( OnStage() && mParent && mParent->IsDynamicsRoot() )
1754 mDynamicsData->body->Connect( GetEventThreadServices() );
1756 // Connect all joints where attachedActor is also on stage
1757 if( !mDynamicsData->joints.empty() )
1759 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1760 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1762 for(; it != endIt; ++it )
1764 Actor* attachedActor( it->first );
1765 if( NULL != attachedActor && attachedActor->OnStage() )
1767 DynamicsJointPtr joint( it->second );
1769 joint->Connect( GetEventThreadServices() );
1777 void Actor::DisconnectDynamics()
1779 if( NULL != mDynamicsData && mDynamicsData->body )
1783 mDynamicsData->body->Disconnect( GetEventThreadServices() );
1785 // Disconnect all joints
1786 if( !mDynamicsData->joints.empty() )
1788 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1789 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1791 for(; it != endIt; ++it )
1793 DynamicsJointPtr joint( it->second );
1795 joint->Disconnect( GetEventThreadServices() );
1802 #endif // DYNAMICS_SUPPORT
1804 void Actor::SetOverlay( bool enable )
1806 // Setting STENCIL will override OVERLAY
1807 if( DrawMode::STENCIL != mDrawMode )
1809 SetDrawMode( enable ? DrawMode::OVERLAY : DrawMode::NORMAL );
1813 bool Actor::IsOverlay() const
1815 return ( DrawMode::OVERLAY == mDrawMode );
1818 void Actor::SetDrawMode( DrawMode::Type drawMode )
1820 // this flag is not animatable so keep the value
1821 mDrawMode = drawMode;
1824 // mNode is being used in a separate thread; queue a message to set the value
1825 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1829 DrawMode::Type Actor::GetDrawMode() const
1834 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1836 // only valid when on-stage
1839 const RenderTaskList& taskList = Stage::GetCurrent()->GetRenderTaskList();
1841 Vector2 converted( screenX, screenY );
1843 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1844 const int taskCount = taskList.GetTaskCount();
1845 for( int i = taskCount - 1; i >= 0; --i )
1847 Dali::RenderTask task = taskList.GetTask( i );
1848 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1850 // found a task where this conversion was ok so return
1858 bool Actor::ScreenToLocal( RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1860 bool retval = false;
1861 // only valid when on-stage
1864 CameraActor* camera = renderTask.GetCameraActor();
1868 renderTask.GetViewport( viewport );
1870 // need to translate coordinates to render tasks coordinate space
1871 Vector2 converted( screenX, screenY );
1872 if( renderTask.TranslateCoordinates( converted ) )
1874 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1881 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1883 // Early-out if mNode is NULL
1889 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1891 // Calculate the ModelView matrix
1892 Matrix modelView( false/*don't init*/);
1893 // need to use the components as world matrix is only updated for actors that need it
1894 modelView.SetTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1895 Matrix::Multiply( modelView, modelView, viewMatrix );
1897 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1898 Matrix invertedMvp( false/*don't init*/);
1899 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1900 bool success = invertedMvp.Invert();
1902 // Convert to GL coordinates
1903 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1908 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1915 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1921 if( XyPlaneIntersect( nearPos, farPos, local ) )
1923 Vector3 size = GetCurrentSize();
1924 localX = local.x + size.x * 0.5f;
1925 localY = local.y + size.y * 0.5f;
1936 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1939 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1941 Mathematical Formulation
1943 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1945 ( p - c ) dot ( p - c ) = r^2
1947 Given a ray with a point of origin 'o', and a direction vector 'd':
1949 ray(t) = o + td, t >= 0
1951 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1953 (o + td - c ) dot ( o + td - c ) = r^2
1955 To solve for t we first expand the above into a more recognisable quadratic equation form
1957 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1966 B = 2( o - c ) dot d
1967 C = ( o - c ) dot ( o - c ) - r^2
1969 which can be solved using a standard quadratic formula.
1971 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1973 Practical Simplification
1975 In a renderer, we often differentiate between world space and object space. In the object space
1976 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1977 into object space, the mathematical solution presented above can be simplified significantly.
1979 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1983 and we can find the t at which the (transformed) ray intersects the sphere by
1985 ( o + td ) dot ( o + td ) = r^2
1987 According to the reasoning above, we expand the above quadratic equation into the general form
1991 which now has coefficients:
1998 // Early out if mNode is NULL
2004 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
2006 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
2007 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
2008 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
2010 // Compute the radius is not needed, square radius it's enough.
2011 const Vector3& size( mNode->GetSize( bufferIndex ) );
2013 // Scale the sphere.
2014 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
2016 const float width = size.width * scale.width;
2017 const float height = size.height * scale.height;
2019 float squareSphereRadius = 0.5f * ( width * width + height * height );
2021 float a = rayDir.Dot( rayDir ); // a
2022 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
2023 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
2025 return ( b2 * b2 - a * c ) >= 0.f;
2028 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
2035 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
2037 // Transforms the ray to the local reference system.
2039 // Calculate the inverse of Model matrix
2040 Matrix invModelMatrix( false/*don't init*/);
2041 // need to use the components as world matrix is only updated for actors that need it
2042 invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
2044 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
2045 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
2047 // Test with the actor's XY plane (Normal = 0 0 1 1).
2049 float a = -rayOriginLocal.z;
2050 float b = rayDirLocal.z;
2052 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
2054 // Ray travels distance * rayDirLocal to intersect with plane.
2057 const Vector3& size = mNode->GetSize( bufferIndex );
2059 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
2060 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
2062 // Test with the actor's geometry.
2063 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
2070 void Actor::SetLeaveRequired( bool required )
2072 mLeaveRequired = required;
2075 bool Actor::GetLeaveRequired() const
2077 return mLeaveRequired;
2080 void Actor::SetKeyboardFocusable( bool focusable )
2082 mKeyboardFocusable = focusable;
2085 bool Actor::IsKeyboardFocusable() const
2087 return mKeyboardFocusable;
2090 bool Actor::GetTouchRequired() const
2092 return !mTouchedSignal.Empty() || mDerivedRequiresTouch;
2095 bool Actor::GetHoverRequired() const
2097 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
2100 bool Actor::GetMouseWheelEventRequired() const
2102 return !mMouseWheelEventSignal.Empty() || mDerivedRequiresMouseWheelEvent;
2105 bool Actor::IsHittable() const
2107 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
2110 ActorGestureData& Actor::GetGestureData()
2112 // Likely scenario is that once gesture-data is created for this actor, the actor will require
2113 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
2114 if( NULL == mGestureData )
2116 mGestureData = new ActorGestureData;
2118 return *mGestureData;
2121 bool Actor::IsGestureRequred( Gesture::Type type ) const
2123 return mGestureData && mGestureData->IsGestureRequred( type );
2126 bool Actor::EmitTouchEventSignal( const TouchEvent& event )
2128 bool consumed = false;
2130 if( !mTouchedSignal.Empty() )
2132 Dali::Actor handle( this );
2133 consumed = mTouchedSignal.Emit( handle, event );
2138 // Notification for derived classes
2139 consumed = OnTouchEvent( event );
2145 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
2147 bool consumed = false;
2149 if( !mHoveredSignal.Empty() )
2151 Dali::Actor handle( this );
2152 consumed = mHoveredSignal.Emit( handle, event );
2157 // Notification for derived classes
2158 consumed = OnHoverEvent( event );
2164 bool Actor::EmitMouseWheelEventSignal( const MouseWheelEvent& event )
2166 bool consumed = false;
2168 if( !mMouseWheelEventSignal.Empty() )
2170 Dali::Actor handle( this );
2171 consumed = mMouseWheelEventSignal.Emit( handle, event );
2176 // Notification for derived classes
2177 consumed = OnMouseWheelEvent( event );
2183 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
2185 return mTouchedSignal;
2188 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
2190 return mHoveredSignal;
2193 Dali::Actor::MouseWheelEventSignalType& Actor::MouseWheelEventSignal()
2195 return mMouseWheelEventSignal;
2198 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
2200 return mOnStageSignal;
2203 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
2205 return mOffStageSignal;
2208 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
2210 return mOnRelayoutSignal;
2213 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
2215 bool connected( true );
2216 Actor* actor = dynamic_cast< Actor* >( object );
2218 if( 0 == strcmp( signalName.c_str(), SIGNAL_TOUCHED ) ) // don't want to convert char* to string
2220 actor->TouchedSignal().Connect( tracker, functor );
2222 else if( 0 == strcmp( signalName.c_str(), SIGNAL_HOVERED ) )
2224 actor->HoveredSignal().Connect( tracker, functor );
2226 else if( 0 == strcmp( signalName.c_str(), SIGNAL_MOUSE_WHEEL_EVENT ) )
2228 actor->MouseWheelEventSignal().Connect( tracker, functor );
2230 else if( 0 == strcmp( signalName.c_str(), SIGNAL_ON_STAGE ) )
2232 actor->OnStageSignal().Connect( tracker, functor );
2234 else if( 0 == strcmp( signalName.c_str(), SIGNAL_OFF_STAGE ) )
2236 actor->OffStageSignal().Connect( tracker, functor );
2240 // signalName does not match any signal
2247 Actor::Actor( DerivedType derivedType )
2251 mParentOrigin( NULL ),
2252 mAnchorPoint( NULL ),
2253 mRelayoutData( NULL ),
2254 #ifdef DYNAMICS_SUPPORT
2255 mDynamicsData( NULL ),
2257 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
2258 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 )
2262 void Actor::Initialize()
2265 SceneGraph::Node* node = CreateNode();
2267 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
2268 mNode = node; // Keep raw-pointer to Node
2272 GetEventThreadServices().RegisterObject( this );
2277 // Remove mParent pointers from children even if we're destroying core,
2278 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2281 ActorConstIter endIter = mChildren->end();
2282 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2284 Actor& actor = GetImplementation( *iter );
2285 actor.SetParent( NULL );
2290 // Guard to allow handle destruction after Core has been destroyed
2291 if( EventThreadServices::IsCoreRunning() )
2295 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2296 mNode = NULL; // Node is about to be destroyed
2299 GetEventThreadServices().UnregisterObject( this );
2302 #ifdef DYNAMICS_SUPPORT
2304 delete mDynamicsData;
2307 // Cleanup optional gesture data
2308 delete mGestureData;
2310 // Cleanup optional parent origin and anchor
2311 delete mParentOrigin;
2312 delete mAnchorPoint;
2314 // Delete optional relayout data
2317 delete mRelayoutData;
2321 void Actor::ConnectToStage( int index )
2323 // This container is used instead of walking the Actor hierachy.
2324 // It protects us when the Actor hierachy is modified during OnStageConnectionExternal callbacks.
2325 ActorContainer connectionList;
2327 // This stage is atomic i.e. not interrupted by user callbacks
2328 RecursiveConnectToStage( connectionList, index );
2330 // Notify applications about the newly connected actors.
2331 const ActorIter endIter = connectionList.end();
2332 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2334 Actor& actor = GetImplementation( *iter );
2335 actor.NotifyStageConnection();
2341 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, int index )
2343 DALI_ASSERT_ALWAYS( !OnStage() );
2347 ConnectToSceneGraph( index );
2349 // Notification for internal derived classes
2350 OnStageConnectionInternal();
2352 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2353 connectionList.push_back( Dali::Actor( this ) );
2355 // Recursively connect children
2358 ActorConstIter endIter = mChildren->end();
2359 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2361 Actor& actor = GetImplementation( *iter );
2362 actor.RecursiveConnectToStage( connectionList );
2368 * This method is called when the Actor is connected to the Stage.
2369 * The parent must have added its Node to the scene-graph.
2370 * The child must connect its Node to the parent's Node.
2371 * This is resursive; the child calls ConnectToStage() for its children.
2373 void Actor::ConnectToSceneGraph( int index )
2375 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2379 // Reparent Node in next Update
2380 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode, index );
2383 // Notify attachment
2386 mAttachment->Connect();
2389 #ifdef DYNAMICS_SUPPORT
2391 if( NULL != mDynamicsData )
2397 // Request relayout on all actors that are added to the scenegraph
2400 // Notification for Object::Observers
2404 void Actor::NotifyStageConnection()
2406 // Actors can be removed (in a callback), before the on-stage stage is reported.
2407 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2408 if( OnStage() && !mOnStageSignalled )
2410 // Notification for external (CustomActor) derived classes
2411 OnStageConnectionExternal();
2413 if( !mOnStageSignal.Empty() )
2415 Dali::Actor handle( this );
2416 mOnStageSignal.Emit( handle );
2419 // Guard against Remove during callbacks
2422 mOnStageSignalled = true; // signal required next time Actor is removed
2427 void Actor::DisconnectFromStage()
2429 // This container is used instead of walking the Actor hierachy.
2430 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2431 ActorContainer disconnectionList;
2433 // This stage is atomic i.e. not interrupted by user callbacks
2434 RecursiveDisconnectFromStage( disconnectionList );
2436 // Notify applications about the newly disconnected actors.
2437 const ActorIter endIter = disconnectionList.end();
2438 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2440 Actor& actor = GetImplementation( *iter );
2441 actor.NotifyStageDisconnection();
2445 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2447 DALI_ASSERT_ALWAYS( OnStage() );
2449 // Recursively disconnect children
2452 ActorConstIter endIter = mChildren->end();
2453 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2455 Actor& actor = GetImplementation( *iter );
2456 actor.RecursiveDisconnectFromStage( disconnectionList );
2460 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2461 disconnectionList.push_back( Dali::Actor( this ) );
2463 // Notification for internal derived classes
2464 OnStageDisconnectionInternal();
2466 DisconnectFromSceneGraph();
2472 * This method is called by an actor or its parent, before a node removal message is sent.
2473 * This is recursive; the child calls DisconnectFromStage() for its children.
2475 void Actor::DisconnectFromSceneGraph()
2477 // Notification for Object::Observers
2478 OnSceneObjectRemove();
2480 // Notify attachment
2483 mAttachment->Disconnect();
2486 #ifdef DYNAMICS_SUPPORT
2488 if( NULL != mDynamicsData )
2490 DisconnectDynamics();
2495 void Actor::NotifyStageDisconnection()
2497 // Actors can be added (in a callback), before the off-stage state is reported.
2498 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2499 // only do this step if there is a stage, i.e. Core is not being shut down
2500 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2502 // Notification for external (CustomeActor) derived classes
2503 OnStageDisconnectionExternal();
2505 if( !mOffStageSignal.Empty() )
2507 Dali::Actor handle( this );
2508 mOffStageSignal.Emit( handle );
2511 // Guard against Add during callbacks
2514 mOnStageSignalled = false; // signal required next time Actor is added
2519 bool Actor::IsNodeConnected() const
2521 bool connected( false );
2526 if( mNode->IsRoot() || mNode->GetParent() )
2535 unsigned int Actor::GetDefaultPropertyCount() const
2537 return DEFAULT_PROPERTY_COUNT;
2540 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2542 indices.reserve( DEFAULT_PROPERTY_COUNT );
2544 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2546 indices.push_back( i );
2550 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2552 if( index < DEFAULT_PROPERTY_COUNT )
2554 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2560 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2562 Property::Index index = Property::INVALID_INDEX;
2564 // Look for name in default properties
2565 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2567 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2568 if( 0 == strcmp( name.c_str(), property->name ) ) // dont want to convert rhs to string
2578 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2580 if( index < DEFAULT_PROPERTY_COUNT )
2582 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2588 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2590 if( index < DEFAULT_PROPERTY_COUNT )
2592 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2598 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2600 if( index < DEFAULT_PROPERTY_COUNT )
2602 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2608 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2610 if( index < DEFAULT_PROPERTY_COUNT )
2612 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2615 // index out of range...return Property::NONE
2616 return Property::NONE;
2619 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2623 case Dali::Actor::Property::PARENT_ORIGIN:
2625 SetParentOrigin( property.Get< Vector3 >() );
2629 case Dali::Actor::Property::PARENT_ORIGIN_X:
2631 SetParentOriginX( property.Get< float >() );
2635 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2637 SetParentOriginY( property.Get< float >() );
2641 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2643 SetParentOriginZ( property.Get< float >() );
2647 case Dali::Actor::Property::ANCHOR_POINT:
2649 SetAnchorPoint( property.Get< Vector3 >() );
2653 case Dali::Actor::Property::ANCHOR_POINT_X:
2655 SetAnchorPointX( property.Get< float >() );
2659 case Dali::Actor::Property::ANCHOR_POINT_Y:
2661 SetAnchorPointY( property.Get< float >() );
2665 case Dali::Actor::Property::ANCHOR_POINT_Z:
2667 SetAnchorPointZ( property.Get< float >() );
2671 case Dali::Actor::Property::SIZE:
2673 SetSize( property.Get< Vector3 >() );
2677 case Dali::Actor::Property::SIZE_WIDTH:
2679 SetWidth( property.Get< float >() );
2683 case Dali::Actor::Property::SIZE_HEIGHT:
2685 SetHeight( property.Get< float >() );
2689 case Dali::Actor::Property::SIZE_DEPTH:
2691 SetDepth( property.Get< float >() );
2695 case Dali::Actor::Property::POSITION:
2697 SetPosition( property.Get< Vector3 >() );
2701 case Dali::Actor::Property::POSITION_X:
2703 SetX( property.Get< float >() );
2707 case Dali::Actor::Property::POSITION_Y:
2709 SetY( property.Get< float >() );
2713 case Dali::Actor::Property::POSITION_Z:
2715 SetZ( property.Get< float >() );
2719 case Dali::Actor::Property::ORIENTATION:
2721 SetOrientation( property.Get< Quaternion >() );
2725 case Dali::Actor::Property::SCALE:
2727 SetScale( property.Get< Vector3 >() );
2731 case Dali::Actor::Property::SCALE_X:
2733 SetScaleX( property.Get< float >() );
2737 case Dali::Actor::Property::SCALE_Y:
2739 SetScaleY( property.Get< float >() );
2743 case Dali::Actor::Property::SCALE_Z:
2745 SetScaleZ( property.Get< float >() );
2749 case Dali::Actor::Property::VISIBLE:
2751 SetVisible( property.Get< bool >() );
2755 case Dali::Actor::Property::COLOR:
2757 SetColor( property.Get< Vector4 >() );
2761 case Dali::Actor::Property::COLOR_RED:
2763 SetColorRed( property.Get< float >() );
2767 case Dali::Actor::Property::COLOR_GREEN:
2769 SetColorGreen( property.Get< float >() );
2773 case Dali::Actor::Property::COLOR_BLUE:
2775 SetColorBlue( property.Get< float >() );
2779 case Dali::Actor::Property::COLOR_ALPHA:
2781 SetOpacity( property.Get< float >() );
2785 case Dali::Actor::Property::NAME:
2787 SetName( property.Get< std::string >() );
2791 case Dali::Actor::Property::SENSITIVE:
2793 SetSensitive( property.Get< bool >() );
2797 case Dali::Actor::Property::LEAVE_REQUIRED:
2799 SetLeaveRequired( property.Get< bool >() );
2803 case Dali::Actor::Property::INHERIT_ORIENTATION:
2805 SetInheritOrientation( property.Get< bool >() );
2809 case Dali::Actor::Property::INHERIT_SCALE:
2811 SetInheritScale( property.Get< bool >() );
2815 case Dali::Actor::Property::COLOR_MODE:
2817 SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2821 case Dali::Actor::Property::POSITION_INHERITANCE:
2823 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2827 case Dali::Actor::Property::DRAW_MODE:
2829 SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2833 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2835 SetSizeModeFactor( property.Get< Vector3 >() );
2839 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2841 SetResizePolicy( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount ), Dimension::WIDTH );
2845 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2847 SetResizePolicy( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount ), Dimension::HEIGHT );
2851 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2853 SetSizeScalePolicy( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount ) );
2857 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2859 if( property.Get< bool >() )
2861 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2866 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2868 if( property.Get< bool >() )
2870 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2875 case Dali::Actor::Property::PADDING:
2877 Vector4 padding = property.Get< Vector4 >();
2878 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2879 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2883 case Dali::Actor::Property::MINIMUM_SIZE:
2885 Vector2 size = property.Get< Vector2 >();
2886 SetMinimumSize( size.x, Dimension::WIDTH );
2887 SetMinimumSize( size.y, Dimension::HEIGHT );
2891 case Dali::Actor::Property::MAXIMUM_SIZE:
2893 Vector2 size = property.Get< Vector2 >();
2894 SetMaximumSize( size.x, Dimension::WIDTH );
2895 SetMaximumSize( size.y, Dimension::HEIGHT );
2901 // this can happen in the case of a non-animatable default property so just do nothing
2907 // TODO: This method needs to be removed
2908 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2910 switch( entry.type )
2912 case Property::BOOLEAN:
2914 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2915 DALI_ASSERT_DEBUG( NULL != property );
2917 // property is being used in a separate thread; queue a message to set the property
2918 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2923 case Property::INTEGER:
2925 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2926 DALI_ASSERT_DEBUG( NULL != property );
2928 // property is being used in a separate thread; queue a message to set the property
2929 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2934 case Property::UNSIGNED_INTEGER:
2936 const AnimatableProperty< unsigned int >* property = dynamic_cast< const AnimatableProperty< unsigned int >* >( entry.GetSceneGraphProperty() );
2937 DALI_ASSERT_DEBUG( NULL != property );
2939 // property is being used in a separate thread; queue a message to set the property
2940 SceneGraph::NodePropertyMessage<unsigned int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<unsigned int>::Bake, value.Get<unsigned int>() );
2945 case Property::FLOAT:
2947 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2948 DALI_ASSERT_DEBUG( NULL != property );
2950 // property is being used in a separate thread; queue a message to set the property
2951 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2956 case Property::VECTOR2:
2958 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2959 DALI_ASSERT_DEBUG( NULL != property );
2961 // property is being used in a separate thread; queue a message to set the property
2962 if(entry.componentIndex == 0)
2964 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2966 else if(entry.componentIndex == 1)
2968 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2972 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2978 case Property::VECTOR3:
2980 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2981 DALI_ASSERT_DEBUG( NULL != property );
2983 // property is being used in a separate thread; queue a message to set the property
2984 if(entry.componentIndex == 0)
2986 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2988 else if(entry.componentIndex == 1)
2990 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2992 else if(entry.componentIndex == 2)
2994 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2998 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
3004 case Property::VECTOR4:
3006 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
3007 DALI_ASSERT_DEBUG( NULL != property );
3009 // property is being used in a separate thread; queue a message to set the property
3010 if(entry.componentIndex == 0)
3012 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
3014 else if(entry.componentIndex == 1)
3016 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
3018 else if(entry.componentIndex == 2)
3020 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
3022 else if(entry.componentIndex == 3)
3024 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
3028 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3034 case Property::ROTATION:
3036 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3037 DALI_ASSERT_DEBUG( NULL != property );
3039 // property is being used in a separate thread; queue a message to set the property
3040 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3045 case Property::MATRIX:
3047 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3048 DALI_ASSERT_DEBUG( NULL != property );
3050 // property is being used in a separate thread; queue a message to set the property
3051 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3056 case Property::MATRIX3:
3058 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3059 DALI_ASSERT_DEBUG( NULL != property );
3061 // property is being used in a separate thread; queue a message to set the property
3062 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3069 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
3075 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3077 Property::Value value;
3081 case Dali::Actor::Property::PARENT_ORIGIN:
3083 value = GetCurrentParentOrigin();
3087 case Dali::Actor::Property::PARENT_ORIGIN_X:
3089 value = GetCurrentParentOrigin().x;
3093 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3095 value = GetCurrentParentOrigin().y;
3099 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3101 value = GetCurrentParentOrigin().z;
3105 case Dali::Actor::Property::ANCHOR_POINT:
3107 value = GetCurrentAnchorPoint();
3111 case Dali::Actor::Property::ANCHOR_POINT_X:
3113 value = GetCurrentAnchorPoint().x;
3117 case Dali::Actor::Property::ANCHOR_POINT_Y:
3119 value = GetCurrentAnchorPoint().y;
3123 case Dali::Actor::Property::ANCHOR_POINT_Z:
3125 value = GetCurrentAnchorPoint().z;
3129 case Dali::Actor::Property::SIZE:
3131 value = GetCurrentSize();
3135 case Dali::Actor::Property::SIZE_WIDTH:
3137 value = GetCurrentSize().width;
3141 case Dali::Actor::Property::SIZE_HEIGHT:
3143 value = GetCurrentSize().height;
3147 case Dali::Actor::Property::SIZE_DEPTH:
3149 value = GetCurrentSize().depth;
3153 case Dali::Actor::Property::POSITION:
3155 value = GetCurrentPosition();
3159 case Dali::Actor::Property::POSITION_X:
3161 value = GetCurrentPosition().x;
3165 case Dali::Actor::Property::POSITION_Y:
3167 value = GetCurrentPosition().y;
3171 case Dali::Actor::Property::POSITION_Z:
3173 value = GetCurrentPosition().z;
3177 case Dali::Actor::Property::WORLD_POSITION:
3179 value = GetCurrentWorldPosition();
3183 case Dali::Actor::Property::WORLD_POSITION_X:
3185 value = GetCurrentWorldPosition().x;
3189 case Dali::Actor::Property::WORLD_POSITION_Y:
3191 value = GetCurrentWorldPosition().y;
3195 case Dali::Actor::Property::WORLD_POSITION_Z:
3197 value = GetCurrentWorldPosition().z;
3201 case Dali::Actor::Property::ORIENTATION:
3203 value = GetCurrentOrientation();
3207 case Dali::Actor::Property::WORLD_ORIENTATION:
3209 value = GetCurrentWorldOrientation();
3213 case Dali::Actor::Property::SCALE:
3215 value = GetCurrentScale();
3219 case Dali::Actor::Property::SCALE_X:
3221 value = GetCurrentScale().x;
3225 case Dali::Actor::Property::SCALE_Y:
3227 value = GetCurrentScale().y;
3231 case Dali::Actor::Property::SCALE_Z:
3233 value = GetCurrentScale().z;
3237 case Dali::Actor::Property::WORLD_SCALE:
3239 value = GetCurrentWorldScale();
3243 case Dali::Actor::Property::VISIBLE:
3245 value = IsVisible();
3249 case Dali::Actor::Property::COLOR:
3251 value = GetCurrentColor();
3255 case Dali::Actor::Property::COLOR_RED:
3257 value = GetCurrentColor().r;
3261 case Dali::Actor::Property::COLOR_GREEN:
3263 value = GetCurrentColor().g;
3267 case Dali::Actor::Property::COLOR_BLUE:
3269 value = GetCurrentColor().b;
3273 case Dali::Actor::Property::COLOR_ALPHA:
3275 value = GetCurrentColor().a;
3279 case Dali::Actor::Property::WORLD_COLOR:
3281 value = GetCurrentWorldColor();
3285 case Dali::Actor::Property::WORLD_MATRIX:
3287 value = GetCurrentWorldMatrix();
3291 case Dali::Actor::Property::NAME:
3297 case Dali::Actor::Property::SENSITIVE:
3299 value = IsSensitive();
3303 case Dali::Actor::Property::LEAVE_REQUIRED:
3305 value = GetLeaveRequired();
3309 case Dali::Actor::Property::INHERIT_ORIENTATION:
3311 value = IsOrientationInherited();
3315 case Dali::Actor::Property::INHERIT_SCALE:
3317 value = IsScaleInherited();
3321 case Dali::Actor::Property::COLOR_MODE:
3323 value = Scripting::GetColorMode( GetColorMode() );
3327 case Dali::Actor::Property::POSITION_INHERITANCE:
3329 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
3333 case Dali::Actor::Property::DRAW_MODE:
3335 value = Scripting::GetDrawMode( GetDrawMode() );
3339 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3341 value = GetSizeModeFactor();
3345 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3347 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3351 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3353 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3357 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3359 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3363 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3365 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3369 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3371 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3375 case Dali::Actor::Property::PADDING:
3377 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3378 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3379 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3383 case Dali::Actor::Property::MINIMUM_SIZE:
3385 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3389 case Dali::Actor::Property::MAXIMUM_SIZE:
3391 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3397 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3405 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3410 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3412 // This method should only return an object connected to the scene-graph
3413 return OnStage() ? mNode : NULL;
3416 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3418 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3420 const PropertyBase* property( NULL );
3422 // This method should only return a property of an object connected to the scene-graph
3428 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3430 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3431 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3433 property = animatable->GetSceneGraphProperty();
3435 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3437 CustomPropertyMetadata* custom = FindCustomProperty( index );
3438 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3440 property = custom->GetSceneGraphProperty();
3442 else if( NULL != mNode )
3446 case Dali::Actor::Property::SIZE:
3447 property = &mNode->mSize;
3450 case Dali::Actor::Property::SIZE_WIDTH:
3451 property = &mNode->mSize;
3454 case Dali::Actor::Property::SIZE_HEIGHT:
3455 property = &mNode->mSize;
3458 case Dali::Actor::Property::SIZE_DEPTH:
3459 property = &mNode->mSize;
3462 case Dali::Actor::Property::POSITION:
3463 property = &mNode->mPosition;
3466 case Dali::Actor::Property::POSITION_X:
3467 property = &mNode->mPosition;
3470 case Dali::Actor::Property::POSITION_Y:
3471 property = &mNode->mPosition;
3474 case Dali::Actor::Property::POSITION_Z:
3475 property = &mNode->mPosition;
3478 case Dali::Actor::Property::ORIENTATION:
3479 property = &mNode->mOrientation;
3482 case Dali::Actor::Property::SCALE:
3483 property = &mNode->mScale;
3486 case Dali::Actor::Property::SCALE_X:
3487 property = &mNode->mScale;
3490 case Dali::Actor::Property::SCALE_Y:
3491 property = &mNode->mScale;
3494 case Dali::Actor::Property::SCALE_Z:
3495 property = &mNode->mScale;
3498 case Dali::Actor::Property::VISIBLE:
3499 property = &mNode->mVisible;
3502 case Dali::Actor::Property::COLOR:
3503 property = &mNode->mColor;
3506 case Dali::Actor::Property::COLOR_RED:
3507 property = &mNode->mColor;
3510 case Dali::Actor::Property::COLOR_GREEN:
3511 property = &mNode->mColor;
3514 case Dali::Actor::Property::COLOR_BLUE:
3515 property = &mNode->mColor;
3518 case Dali::Actor::Property::COLOR_ALPHA:
3519 property = &mNode->mColor;
3530 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3532 const PropertyInputImpl* property( NULL );
3534 // This method should only return a property of an object connected to the scene-graph
3540 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3542 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3543 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3545 property = animatable->GetSceneGraphProperty();
3547 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3549 CustomPropertyMetadata* custom = FindCustomProperty( index );
3550 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3551 property = custom->GetSceneGraphProperty();
3553 else if( NULL != mNode )
3557 case Dali::Actor::Property::PARENT_ORIGIN:
3558 property = &mNode->mParentOrigin;
3561 case Dali::Actor::Property::PARENT_ORIGIN_X:
3562 property = &mNode->mParentOrigin;
3565 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3566 property = &mNode->mParentOrigin;
3569 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3570 property = &mNode->mParentOrigin;
3573 case Dali::Actor::Property::ANCHOR_POINT:
3574 property = &mNode->mAnchorPoint;
3577 case Dali::Actor::Property::ANCHOR_POINT_X:
3578 property = &mNode->mAnchorPoint;
3581 case Dali::Actor::Property::ANCHOR_POINT_Y:
3582 property = &mNode->mAnchorPoint;
3585 case Dali::Actor::Property::ANCHOR_POINT_Z:
3586 property = &mNode->mAnchorPoint;
3589 case Dali::Actor::Property::SIZE:
3590 property = &mNode->mSize;
3593 case Dali::Actor::Property::SIZE_WIDTH:
3594 property = &mNode->mSize;
3597 case Dali::Actor::Property::SIZE_HEIGHT:
3598 property = &mNode->mSize;
3601 case Dali::Actor::Property::SIZE_DEPTH:
3602 property = &mNode->mSize;
3605 case Dali::Actor::Property::POSITION:
3606 property = &mNode->mPosition;
3609 case Dali::Actor::Property::POSITION_X:
3610 property = &mNode->mPosition;
3613 case Dali::Actor::Property::POSITION_Y:
3614 property = &mNode->mPosition;
3617 case Dali::Actor::Property::POSITION_Z:
3618 property = &mNode->mPosition;
3621 case Dali::Actor::Property::WORLD_POSITION:
3622 property = &mNode->mWorldPosition;
3625 case Dali::Actor::Property::WORLD_POSITION_X:
3626 property = &mNode->mWorldPosition;
3629 case Dali::Actor::Property::WORLD_POSITION_Y:
3630 property = &mNode->mWorldPosition;
3633 case Dali::Actor::Property::WORLD_POSITION_Z:
3634 property = &mNode->mWorldPosition;
3637 case Dali::Actor::Property::ORIENTATION:
3638 property = &mNode->mOrientation;
3641 case Dali::Actor::Property::WORLD_ORIENTATION:
3642 property = &mNode->mWorldOrientation;
3645 case Dali::Actor::Property::SCALE:
3646 property = &mNode->mScale;
3649 case Dali::Actor::Property::SCALE_X:
3650 property = &mNode->mScale;
3653 case Dali::Actor::Property::SCALE_Y:
3654 property = &mNode->mScale;
3657 case Dali::Actor::Property::SCALE_Z:
3658 property = &mNode->mScale;
3661 case Dali::Actor::Property::WORLD_SCALE:
3662 property = &mNode->mWorldScale;
3665 case Dali::Actor::Property::VISIBLE:
3666 property = &mNode->mVisible;
3669 case Dali::Actor::Property::COLOR:
3670 property = &mNode->mColor;
3673 case Dali::Actor::Property::COLOR_RED:
3674 property = &mNode->mColor;
3677 case Dali::Actor::Property::COLOR_GREEN:
3678 property = &mNode->mColor;
3681 case Dali::Actor::Property::COLOR_BLUE:
3682 property = &mNode->mColor;
3685 case Dali::Actor::Property::COLOR_ALPHA:
3686 property = &mNode->mColor;
3689 case Dali::Actor::Property::WORLD_COLOR:
3690 property = &mNode->mWorldColor;
3693 case Dali::Actor::Property::WORLD_MATRIX:
3694 property = &mNode->mWorldMatrix;
3705 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3707 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3709 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3711 // check whether the animatable property is registered already, if not then register one.
3712 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3713 if( animatableProperty )
3715 componentIndex = animatableProperty->componentIndex;
3722 case Dali::Actor::Property::PARENT_ORIGIN_X:
3723 case Dali::Actor::Property::ANCHOR_POINT_X:
3724 case Dali::Actor::Property::SIZE_WIDTH:
3725 case Dali::Actor::Property::POSITION_X:
3726 case Dali::Actor::Property::WORLD_POSITION_X:
3727 case Dali::Actor::Property::SCALE_X:
3728 case Dali::Actor::Property::COLOR_RED:
3734 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3735 case Dali::Actor::Property::ANCHOR_POINT_Y:
3736 case Dali::Actor::Property::SIZE_HEIGHT:
3737 case Dali::Actor::Property::POSITION_Y:
3738 case Dali::Actor::Property::WORLD_POSITION_Y:
3739 case Dali::Actor::Property::SCALE_Y:
3740 case Dali::Actor::Property::COLOR_GREEN:
3746 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3747 case Dali::Actor::Property::ANCHOR_POINT_Z:
3748 case Dali::Actor::Property::SIZE_DEPTH:
3749 case Dali::Actor::Property::POSITION_Z:
3750 case Dali::Actor::Property::WORLD_POSITION_Z:
3751 case Dali::Actor::Property::SCALE_Z:
3752 case Dali::Actor::Property::COLOR_BLUE:
3758 case Dali::Actor::Property::COLOR_ALPHA:
3772 return componentIndex;
3775 void Actor::SetParent( Actor* parent, int index )
3779 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3783 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3786 // Instruct each actor to create a corresponding node in the scene graph
3787 ConnectToStage( index );
3790 else // parent being set to NULL
3792 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3796 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3799 DALI_ASSERT_ALWAYS( mNode != NULL );
3803 // Disconnect the Node & its children from the scene-graph.
3804 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3807 // Instruct each actor to discard pointers to the scene-graph
3808 DisconnectFromStage();
3813 SceneGraph::Node* Actor::CreateNode() const
3818 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const std::vector< Property::Value >& attributes )
3821 Actor* actor = dynamic_cast< Actor* >( object );
3825 if( 0 == strcmp( actionName.c_str(), ACTION_SHOW ) ) // dont want to convert char* to string
3827 actor->SetVisible( true );
3830 else if( 0 == strcmp( actionName.c_str(), ACTION_HIDE ) )
3832 actor->SetVisible( false );
3840 void Actor::EnsureRelayoutData() const
3842 // Assign relayout data.
3843 if( !mRelayoutData )
3845 mRelayoutData = new RelayoutData();
3849 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3851 // Check if actor is dependent on parent
3852 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3854 if( ( dimension & ( 1 << i ) ) )
3856 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3857 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3867 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3869 // Check if actor is dependent on children
3870 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3872 if( ( dimension & ( 1 << i ) ) )
3874 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3875 switch( resizePolicy )
3877 case ResizePolicy::FIT_TO_CHILDREN:
3878 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3894 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3896 return Actor::RelayoutDependentOnChildren( dimension );
3899 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3901 // Check each possible dimension and see if it is dependent on the input one
3902 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3904 if( dimension & ( 1 << i ) )
3906 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3913 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3915 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3917 if( dimension & ( 1 << i ) )
3919 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3924 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3926 // If more than one dimension is requested, just return the first one found
3927 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3929 if( ( dimension & ( 1 << i ) ) )
3931 return mRelayoutData->negotiatedDimensions[ i ];
3935 return 0.0f; // Default
3938 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3940 EnsureRelayoutData();
3942 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3944 if( dimension & ( 1 << i ) )
3946 mRelayoutData->dimensionPadding[ i ] = padding;
3951 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3953 EnsureRelayoutData();
3955 // If more than one dimension is requested, just return the first one found
3956 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3958 if( ( dimension & ( 1 << i ) ) )
3960 return mRelayoutData->dimensionPadding[ i ];
3964 return Vector2( 0.0f, 0.0f ); // Default
3967 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
3969 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3971 if( dimension & ( 1 << i ) )
3973 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3978 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
3980 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3982 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
3991 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
3993 // Could be overridden in derived classes.
3994 return CalculateChildSizeBase( child, dimension );
3997 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
3999 // Fill to parent, taking size mode factor into account
4000 switch( child.GetResizePolicy( dimension ) )
4002 case ResizePolicy::FILL_TO_PARENT:
4004 return GetLatestSize( dimension );
4007 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4009 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4012 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4014 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4019 return GetLatestSize( dimension );
4024 float Actor::GetHeightForWidth( float width )
4026 // Could be overridden in derived classes.
4027 float height = 0.0f;
4029 const Vector3 naturalSize = GetNaturalSize();
4030 if( naturalSize.width > 0.0f )
4032 height = naturalSize.height * width / naturalSize.width;
4038 float Actor::GetWidthForHeight( float height )
4040 // Could be overridden in derived classes.
4043 const Vector3 naturalSize = GetNaturalSize();
4044 if( naturalSize.height > 0.0f )
4046 width = naturalSize.width * height / naturalSize.height;
4052 float Actor::GetLatestSize( Dimension::Type dimension ) const
4054 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4057 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4059 Vector2 padding = GetPadding( dimension );
4061 return GetLatestSize( dimension ) + padding.x + padding.y;
4064 float Actor::NegotiateFromParent( Dimension::Type dimension )
4066 Actor* parent = GetParent();
4069 Vector2 padding( GetPadding( dimension ) );
4070 Vector2 parentPadding( parent->GetPadding( dimension ) );
4071 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4077 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4079 float maxDimensionPoint = 0.0f;
4081 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4083 Dali::Actor child = GetChildAt( i );
4084 Actor& childImpl = GetImplementation( child );
4086 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4088 // Calculate the min and max points that the children range across
4089 float childPosition = GetDimensionValue( childImpl.GetTargetPosition(), dimension );
4090 float dimensionSize = childImpl.GetRelayoutSize( dimension );
4091 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4095 return maxDimensionPoint;
4098 float Actor::GetSize( Dimension::Type dimension ) const
4100 return GetDimensionValue( GetTargetSize(), dimension );
4103 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4105 return GetDimensionValue( GetNaturalSize(), dimension );
4108 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4110 switch( GetResizePolicy( dimension ) )
4112 case ResizePolicy::USE_NATURAL_SIZE:
4114 return GetNaturalSize( dimension );
4117 case ResizePolicy::FIXED:
4119 return GetDimensionValue( GetPreferredSize(), dimension );
4122 case ResizePolicy::USE_ASSIGNED_SIZE:
4124 return GetDimensionValue( maximumSize, dimension );
4127 case ResizePolicy::FILL_TO_PARENT:
4128 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4129 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4131 return NegotiateFromParent( dimension );
4134 case ResizePolicy::FIT_TO_CHILDREN:
4136 return NegotiateFromChildren( dimension );
4139 case ResizePolicy::DIMENSION_DEPENDENCY:
4141 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4144 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4146 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4149 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4151 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4163 return 0.0f; // Default
4166 float Actor::ClampDimension( float size, Dimension::Type dimension )
4168 const float minSize = GetMinimumSize( dimension );
4169 const float maxSize = GetMaximumSize( dimension );
4171 return std::max( minSize, std::min( size, maxSize ) );
4174 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4176 // Check if it needs to be negotiated
4177 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4179 // Check that we havn't gotten into an infinite loop
4180 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4181 bool recursionFound = false;
4182 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4184 if( *it == searchActor )
4186 recursionFound = true;
4191 if( !recursionFound )
4193 // Record the path that we have taken
4194 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4196 // Dimension dependency check
4197 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4199 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4201 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4203 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4207 // Parent dependency check
4208 Actor* parent = GetParent();
4209 if( parent && RelayoutDependentOnParent( dimension ) )
4211 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4214 // Children dependency check
4215 if( RelayoutDependentOnChildren( dimension ) )
4217 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4219 Dali::Actor child = GetChildAt( i );
4220 Actor& childImpl = GetImplementation( child );
4222 // Only relayout child first if it is not dependent on this actor
4223 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4225 childImpl.NegotiateDimension( dimension, allocatedSize, recursionStack );
4230 // For deriving classes
4231 OnCalculateRelayoutSize( dimension );
4233 // All dependencies checked, calculate the size and set negotiated flag
4234 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4236 SetNegotiatedDimension( newSize, dimension );
4237 SetLayoutNegotiated( true, dimension );
4239 // For deriving classes
4240 OnLayoutNegotiated( newSize, dimension );
4242 // This actor has been successfully processed, pop it off the recursion stack
4243 recursionStack.pop_back();
4247 // TODO: Break infinite loop
4248 SetLayoutNegotiated( true, dimension );
4253 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4255 // Negotiate all dimensions that require it
4256 ActorDimensionStack recursionStack;
4258 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4260 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4263 NegotiateDimension( dimension, allocatedSize, recursionStack );
4267 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4269 switch( mRelayoutData->sizeSetPolicy )
4271 case SizeScalePolicy::USE_SIZE_SET:
4276 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4278 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4279 const Vector3 naturalSize = GetNaturalSize();
4280 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4282 const float sizeRatio = size.width / size.height;
4283 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4285 if( naturalSizeRatio < sizeRatio )
4287 return Vector2( naturalSizeRatio * size.height, size.height );
4289 else if( naturalSizeRatio > sizeRatio )
4291 return Vector2( size.width, size.width / naturalSizeRatio );
4302 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4304 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4305 const Vector3 naturalSize = GetNaturalSize();
4306 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4308 const float sizeRatio = size.width / size.height;
4309 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4311 if( naturalSizeRatio < sizeRatio )
4313 return Vector2( size.width, size.width / naturalSizeRatio );
4315 else if( naturalSizeRatio > sizeRatio )
4317 return Vector2( naturalSizeRatio * size.height, size.height );
4335 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4337 // Do the set actor size
4338 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4340 // Adjust for size set policy
4341 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4343 // Lock the flag to stop recursive relayouts on set size
4344 mRelayoutData->insideRelayout = true;
4345 SetSize( negotiatedSize );
4346 mRelayoutData->insideRelayout = false;
4348 // Clear flags for all dimensions
4349 SetLayoutDirty( false );
4351 // Give deriving classes a chance to respond
4352 OnRelayout( negotiatedSize, container );
4354 if( !mOnRelayoutSignal.Empty() )
4356 Dali::Actor handle( this );
4357 mOnRelayoutSignal.Emit( handle );
4361 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4363 // Do the negotiation
4364 NegotiateDimensions( allocatedSize );
4366 // Set the actor size
4367 SetNegotiatedSize( container );
4369 // Negotiate down to children
4370 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4372 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4374 Dali::Actor child = GetChildAt( i );
4376 // Only relayout if required
4377 if( GetImplementation( child ).RelayoutRequired() )
4379 container.Add( child, newBounds );
4384 void Actor::RelayoutRequest( Dimension::Type dimension )
4386 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4387 if( relayoutController )
4389 Dali::Actor self( this );
4390 relayoutController->RequestRelayout( self, dimension );
4394 void Actor::PropagateRelayoutFlags()
4396 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4397 if( relayoutController )
4399 Dali::Actor self( this );
4400 relayoutController->PropagateFlags( self );
4404 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4408 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4412 void Actor::SetPreferredSize( const Vector2& size )
4414 EnsureRelayoutData();
4416 if( size.width > 0.0f )
4418 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4421 if( size.height > 0.0f )
4423 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4426 mRelayoutData->preferredSize = size;
4431 Vector2 Actor::GetPreferredSize() const
4433 EnsureRelayoutData();
4435 return mRelayoutData->preferredSize;
4438 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4440 EnsureRelayoutData();
4442 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4444 if( dimension & ( 1 << i ) )
4446 mRelayoutData->minimumSize[ i ] = size;
4453 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4455 EnsureRelayoutData();
4457 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4459 if( dimension & ( 1 << i ) )
4461 return mRelayoutData->minimumSize[ i ];
4465 return 0.0f; // Default
4468 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4470 EnsureRelayoutData();
4472 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4474 if( dimension & ( 1 << i ) )
4476 mRelayoutData->maximumSize[ i ] = size;
4483 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4485 EnsureRelayoutData();
4487 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4489 if( dimension & ( 1 << i ) )
4491 return mRelayoutData->maximumSize[ i ];
4495 return 0.0f; // Default
4498 } // namespace Internal