2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/event/actors/actor-impl.h>
28 #include <dali/public-api/common/dali-common.h>
29 #include <dali/public-api/common/constants.h>
30 #include <dali/public-api/math/vector2.h>
31 #include <dali/public-api/math/vector3.h>
32 #include <dali/public-api/math/radian.h>
33 #include <dali/public-api/object/type-registry.h>
34 #include <dali/public-api/scripting/scripting.h>
36 #include <dali/internal/common/internal-constants.h>
37 #include <dali/internal/event/common/event-thread-services.h>
38 #include <dali/internal/event/render-tasks/render-task-impl.h>
39 #include <dali/internal/event/actors/camera-actor-impl.h>
40 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
41 #include <dali/internal/event/common/property-helper.h>
42 #include <dali/internal/event/common/stage-impl.h>
43 #include <dali/internal/event/actor-attachments/actor-attachment-impl.h>
44 #include <dali/internal/event/animation/constraint-impl.h>
45 #include <dali/internal/event/common/projection.h>
46 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
47 #include <dali/internal/update/common/animatable-property.h>
48 #include <dali/internal/update/nodes/node-messages.h>
49 #include <dali/internal/update/nodes/node-declarations.h>
50 #include <dali/internal/update/animation/scene-graph-constraint.h>
51 #include <dali/internal/event/events/actor-gesture-data.h>
52 #include <dali/internal/common/message.h>
53 #include <dali/integration-api/debug.h>
55 #ifdef DYNAMICS_SUPPORT
56 #include <dali/internal/event/dynamics/dynamics-body-config-impl.h>
57 #include <dali/internal/event/dynamics/dynamics-body-impl.h>
58 #include <dali/internal/event/dynamics/dynamics-joint-impl.h>
59 #include <dali/internal/event/dynamics/dynamics-world-impl.h>
62 using Dali::Internal::SceneGraph::Node;
63 using Dali::Internal::SceneGraph::AnimatableProperty;
64 using Dali::Internal::SceneGraph::PropertyBase;
72 unsigned int Actor::mActorCounter = 0;
73 ActorContainer Actor::mNullChildren;
76 * Struct to collect relayout variables
78 struct Actor::RelayoutData
81 : sizeModeFactor( Vector3::ONE ), preferredSize( Vector2::ZERO ), sizeSetPolicy( USE_SIZE_SET ), sizeMode( USE_OWN_SIZE ), relayoutEnabled( false ), insideRelayout( false )
83 // Set size negotiation defaults
84 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
86 resizePolicies[ i ] = FIXED;
87 negotiatedDimensions[ i ] = 0.0f;
88 dimensionNegotiated[ i ] = false;
89 dimensionDirty[ i ] = false;
90 dimensionDependencies[ i ] = ALL_DIMENSIONS;
91 dimensionPadding[ i ] = Vector2( 0.0f, 0.0f );
92 minimumSize[ i ] = 0.0f;
93 maximumSize[ i ] = FLT_MAX;
97 ResizePolicy resizePolicies[ DIMENSION_COUNT ]; ///< Resize policies
99 Dimension dimensionDependencies[ DIMENSION_COUNT ]; ///< A list of dimension dependencies
101 Vector2 dimensionPadding[ DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
103 float negotiatedDimensions[ DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
105 float minimumSize[ DIMENSION_COUNT ]; ///< The minimum size an actor can be
106 float maximumSize[ DIMENSION_COUNT ]; ///< The maximum size an actor can be
108 bool dimensionNegotiated[ DIMENSION_COUNT ]; ///< Has the dimension been negotiated
109 bool dimensionDirty[ DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
111 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
113 Vector2 preferredSize; ///< The preferred size of the actor
115 SizeScalePolicy sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
116 SizeMode sizeMode :2; ///< Determines how the actors parent affects the actors size
118 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
119 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
122 #ifdef DYNAMICS_SUPPORT
124 // Encapsulate actor related dynamics data
127 DynamicsData( Actor* slotOwner )
128 : slotDelegate( slotOwner )
132 typedef std::map<Actor*, DynamicsJointPtr> JointContainer;
133 typedef std::vector<DynamicsJointPtr> ReferencedJointContainer;
135 DynamicsBodyPtr body;
136 JointContainer joints;
137 ReferencedJointContainer referencedJoints;
139 SlotDelegate< Actor > slotDelegate;
142 #endif // DYNAMICS_SUPPORT
144 namespace // unnamed namespace
150 * We want to discourage the use of property strings (minimize string comparisons),
151 * particularly for the default properties.
152 * Name Type writable animatable constraint-input enum for index-checking
154 DALI_PROPERTY_TABLE_BEGIN
155 DALI_PROPERTY( "parent-origin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
156 DALI_PROPERTY( "parent-origin-x", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
157 DALI_PROPERTY( "parent-origin-y", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
158 DALI_PROPERTY( "parent-origin-z", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
159 DALI_PROPERTY( "anchor-point", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
160 DALI_PROPERTY( "anchor-point-x", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
161 DALI_PROPERTY( "anchor-point-y", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
162 DALI_PROPERTY( "anchor-point-z", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
163 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
164 DALI_PROPERTY( "size-width", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
165 DALI_PROPERTY( "size-height", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
166 DALI_PROPERTY( "size-depth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
167 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
168 DALI_PROPERTY( "position-x", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
169 DALI_PROPERTY( "position-y", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
170 DALI_PROPERTY( "position-z", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
171 DALI_PROPERTY( "world-position", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
172 DALI_PROPERTY( "world-position-x", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
173 DALI_PROPERTY( "world-position-y", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
174 DALI_PROPERTY( "world-position-z", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
175 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
176 DALI_PROPERTY( "world-orientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
177 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
178 DALI_PROPERTY( "scale-x", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
179 DALI_PROPERTY( "scale-y", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
180 DALI_PROPERTY( "scale-z", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
181 DALI_PROPERTY( "world-scale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
182 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
183 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
184 DALI_PROPERTY( "color-red", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
185 DALI_PROPERTY( "color-green", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
186 DALI_PROPERTY( "color-blue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
187 DALI_PROPERTY( "color-alpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
188 DALI_PROPERTY( "world-color", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
189 DALI_PROPERTY( "world-matrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
190 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
191 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
192 DALI_PROPERTY( "leave-required", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
193 DALI_PROPERTY( "inherit-orientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
194 DALI_PROPERTY( "inherit-scale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
195 DALI_PROPERTY( "color-mode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
196 DALI_PROPERTY( "position-inheritance", STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE )
197 DALI_PROPERTY( "draw-mode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
198 DALI_PROPERTY( "size-mode", STRING, true, false, false, Dali::Actor::Property::SIZE_MODE )
199 DALI_PROPERTY( "size-mode-factor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
200 DALI_PROPERTY( "relayout-enabled", BOOLEAN, true, false, false, Dali::Actor::Property::RELAYOUT_ENABLED )
201 DALI_PROPERTY( "width-resize-policy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
202 DALI_PROPERTY( "height-resize-policy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
203 DALI_PROPERTY( "size-scale-policy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
204 DALI_PROPERTY( "width-for-height", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
205 DALI_PROPERTY( "height-for-width", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
206 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
207 DALI_PROPERTY( "minimum-size", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
208 DALI_PROPERTY( "maximum-size", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
209 DALI_PROPERTY( "preferred-size", VECTOR2, true, false, false, Dali::Actor::Property::PREFERRED_SIZE )
210 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
214 const char* const SIGNAL_TOUCHED = "touched";
215 const char* const SIGNAL_HOVERED = "hovered";
216 const char* const SIGNAL_MOUSE_WHEEL_EVENT = "mouse-wheel-event";
217 const char* const SIGNAL_ON_STAGE = "on-stage";
218 const char* const SIGNAL_OFF_STAGE = "off-stage";
222 const char* const ACTION_SHOW = "show";
223 const char* const ACTION_HIDE = "hide";
225 // Enumeration to / from string conversion tables
227 DALI_ENUM_TO_STRING_TABLE_BEGIN( SizeMode )DALI_ENUM_TO_STRING( USE_OWN_SIZE )
228 DALI_ENUM_TO_STRING( SIZE_RELATIVE_TO_PARENT )
229 DALI_ENUM_TO_STRING( SIZE_FIXED_OFFSET_FROM_PARENT )
230 DALI_ENUM_TO_STRING_TABLE_END( SizeMode )
232 DALI_ENUM_TO_STRING_TABLE_BEGIN( ResizePolicy )DALI_ENUM_TO_STRING( FIXED )
233 DALI_ENUM_TO_STRING( USE_NATURAL_SIZE )
234 DALI_ENUM_TO_STRING( USE_ASSIGNED_SIZE )
235 DALI_ENUM_TO_STRING( FILL_TO_PARENT )
236 DALI_ENUM_TO_STRING( FIT_TO_CHILDREN )
237 DALI_ENUM_TO_STRING( DIMENSION_DEPENDENCY )
238 DALI_ENUM_TO_STRING_TABLE_END( ResizePolicy )
240 DALI_ENUM_TO_STRING_TABLE_BEGIN( SizeScalePolicy )DALI_ENUM_TO_STRING( USE_SIZE_SET )
241 DALI_ENUM_TO_STRING( FIT_WITH_ASPECT_RATIO )
242 DALI_ENUM_TO_STRING( FILL_WITH_ASPECT_RATIO )
243 DALI_ENUM_TO_STRING_TABLE_END( SizeScalePolicy )
245 BaseHandle CreateActor()
247 return Dali::Actor::New();
250 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
252 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
253 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
254 SignalConnectorType signalConnector3( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
255 SignalConnectorType signalConnector4( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
257 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
258 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
261 * @brief Extract a given dimension from a Vector2
263 * @param[in] values The values to extract from
264 * @param[in] dimension The dimension to extract
265 * @return Return the value for the dimension
267 float GetDimensionValue( const Vector2& values, Dimension dimension )
278 return values.height;
291 * @brief Extract a given dimension from a Vector3
293 * @param[in] values The values to extract from
294 * @param[in] dimension The dimension to extract
295 * @return Return the value for the dimension
297 float GetDimensionValue( const Vector3& values, Dimension dimension )
299 return GetDimensionValue( values.GetVectorXY(), dimension );
302 } // unnamed namespace
304 ActorPtr Actor::New()
306 ActorPtr actor( new Actor( BASIC ) );
308 // Second-phase construction
314 const std::string& Actor::GetName() const
319 void Actor::SetName( const std::string& name )
325 // ATTENTION: string for debug purposes is not thread safe.
326 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
330 unsigned int Actor::GetId() const
335 void Actor::Attach( ActorAttachment& attachment )
337 DALI_ASSERT_DEBUG( !mAttachment && "An Actor can only have one attachment" );
341 attachment.Connect();
344 mAttachment = ActorAttachmentPtr( &attachment );
347 ActorAttachmentPtr Actor::GetAttachment()
352 bool Actor::OnStage() const
357 Dali::Layer Actor::GetLayer()
361 // Short-circuit for Layer derived actors
364 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
367 // Find the immediate Layer parent
368 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
370 if( parent->IsLayer() )
372 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
379 void Actor::Add( Actor& child )
381 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
382 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
386 mChildren = new ActorContainer;
389 Actor* const oldParent( child.mParent );
391 // child might already be ours
392 if( this != oldParent )
394 // if we already have parent, unparent us first
397 oldParent->Remove( child ); // This causes OnChildRemove callback
399 // Old parent may need to readjust to missing child
400 if( oldParent->RelayoutDependentOnChildren() )
402 oldParent->RelayoutRequest();
406 // Guard against Add() during previous OnChildRemove callback
409 // Do this first, since user callbacks from within SetParent() may need to remove child
410 mChildren->push_back( Dali::Actor( &child ) );
412 // SetParent asserts that child can be added
413 child.SetParent( this );
415 // Notification for derived classes
418 // Only put in a relayout request if there is a suitable dependency
419 if( RelayoutDependentOnChildren() )
424 if( child.RelayoutDependentOnParent() )
426 child.RelayoutRequest();
432 void Actor::Insert( unsigned int index, Actor& child )
434 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
435 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
439 mChildren = new ActorContainer;
442 Actor* const oldParent( child.mParent );
444 // since an explicit position has been given, always insert, even if already a child
447 oldParent->Remove( child ); // This causes OnChildRemove callback
449 // Old parent may need to readjust to missing child
450 if( oldParent->RelayoutDependentOnChildren() )
452 oldParent->RelayoutRequest();
456 // Guard against Add() during previous OnChildRemove callback
459 // Do this first, since user callbacks from within SetParent() may need to remove child
460 if( index < GetChildCount() )
462 ActorIter it = mChildren->begin();
463 std::advance( it, index );
464 mChildren->insert( it, Dali::Actor( &child ) );
468 mChildren->push_back( Dali::Actor( &child ) );
470 // SetParent asserts that child can be added
471 child.SetParent( this, index );
473 // Notification for derived classes
476 // Only put in a relayout request if there is a suitable dependency
477 if( RelayoutDependentOnChildren() )
482 if( child.RelayoutDependentOnParent() )
484 child.RelayoutRequest();
489 void Actor::Remove( Actor& child )
491 DALI_ASSERT_ALWAYS( this != &child && "Cannot remove actor from itself" );
501 // Find the child in mChildren, and unparent it
502 ActorIter end = mChildren->end();
503 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
505 Actor& actor = GetImplementation( *iter );
507 if( &actor == &child )
509 // Keep handle for OnChildRemove notification
510 removed = Dali::Actor( &actor );
512 // Do this first, since user callbacks from within SetParent() may need to add the child
513 mChildren->erase( iter );
515 DALI_ASSERT_DEBUG( actor.GetParent() == this );
516 actor.SetParent( NULL );
524 // Notification for derived classes
525 OnChildRemove( GetImplementation( removed ) );
527 // Only put in a relayout request if there is a suitable dependency
528 if( RelayoutDependentOnChildren() )
535 void Actor::Unparent()
539 // Remove this actor from the parent. The remove will put a relayout request in for
540 // the parent if required
541 mParent->Remove( *this );
542 // mParent is now NULL!
546 unsigned int Actor::GetChildCount() const
548 return ( NULL != mChildren ) ? mChildren->size() : 0;
551 Dali::Actor Actor::GetChildAt( unsigned int index ) const
553 DALI_ASSERT_ALWAYS( index < GetChildCount() );
555 return ( ( mChildren ) ? ( *mChildren )[ index ] : Dali::Actor() );
558 ActorContainer Actor::GetChildren()
560 if( NULL != mChildren )
565 // return copy of mNullChildren
566 return mNullChildren;
569 const ActorContainer& Actor::GetChildren() const
571 if( NULL != mChildren )
576 // return const reference to mNullChildren
577 return mNullChildren;
580 ActorPtr Actor::FindChildByName( const std::string& actorName )
583 if( actorName == mName )
589 ActorIter end = mChildren->end();
590 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
592 child = GetImplementation( *iter ).FindChildByName( actorName );
603 ActorPtr Actor::FindChildById( const unsigned int id )
612 ActorIter end = mChildren->end();
613 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
615 child = GetImplementation( *iter ).FindChildById( id );
626 void Actor::SetParentOrigin( const Vector3& origin )
630 // mNode is being used in a separate thread; queue a message to set the value & base value
631 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
634 // Cache for event-thread access
637 // not allocated, check if different from default
638 if( ParentOrigin::DEFAULT != origin )
640 mParentOrigin = new Vector3( origin );
645 // check if different from current costs more than just set
646 *mParentOrigin = origin;
650 void Actor::SetParentOriginX( float x )
652 const Vector3& current = GetCurrentParentOrigin();
654 SetParentOrigin( Vector3( x, current.y, current.z ) );
657 void Actor::SetParentOriginY( float y )
659 const Vector3& current = GetCurrentParentOrigin();
661 SetParentOrigin( Vector3( current.x, y, current.z ) );
664 void Actor::SetParentOriginZ( float z )
666 const Vector3& current = GetCurrentParentOrigin();
668 SetParentOrigin( Vector3( current.x, current.y, z ) );
671 const Vector3& Actor::GetCurrentParentOrigin() const
673 // Cached for event-thread access
674 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
677 void Actor::SetAnchorPoint( const Vector3& anchor )
681 // mNode is being used in a separate thread; queue a message to set the value & base value
682 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
685 // Cache for event-thread access
688 // not allocated, check if different from default
689 if( AnchorPoint::DEFAULT != anchor )
691 mAnchorPoint = new Vector3( anchor );
696 // check if different from current costs more than just set
697 *mAnchorPoint = anchor;
701 void Actor::SetAnchorPointX( float x )
703 const Vector3& current = GetCurrentAnchorPoint();
705 SetAnchorPoint( Vector3( x, current.y, current.z ) );
708 void Actor::SetAnchorPointY( float y )
710 const Vector3& current = GetCurrentAnchorPoint();
712 SetAnchorPoint( Vector3( current.x, y, current.z ) );
715 void Actor::SetAnchorPointZ( float z )
717 const Vector3& current = GetCurrentAnchorPoint();
719 SetAnchorPoint( Vector3( current.x, current.y, z ) );
722 const Vector3& Actor::GetCurrentAnchorPoint() const
724 // Cached for event-thread access
725 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
728 void Actor::SetPosition( float x, float y )
730 SetPosition( Vector3( x, y, 0.0f ) );
733 void Actor::SetPosition( float x, float y, float z )
735 SetPosition( Vector3( x, y, z ) );
738 void Actor::SetPosition( const Vector3& position )
742 // mNode is being used in a separate thread; queue a message to set the value & base value
743 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::Bake, position );
747 void Actor::SetX( float x )
751 // mNode is being used in a separate thread; queue a message to set the value & base value
752 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeX, x );
756 void Actor::SetY( float y )
760 // mNode is being used in a separate thread; queue a message to set the value & base value
761 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeY, y );
765 void Actor::SetZ( float z )
769 // mNode is being used in a separate thread; queue a message to set the value & base value
770 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeZ, z );
774 void Actor::TranslateBy( const Vector3& distance )
778 // mNode is being used in a separate thread; queue a message to set the value & base value
779 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeRelative, distance );
783 const Vector3& Actor::GetCurrentPosition() const
787 // mNode is being used in a separate thread; copy the value from the previous update
788 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
791 return Vector3::ZERO;
794 const Vector3& Actor::GetCurrentWorldPosition() const
798 // mNode is being used in a separate thread; copy the value from the previous update
799 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
802 return Vector3::ZERO;
805 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
807 // this flag is not animatable so keep the value
808 mPositionInheritanceMode = mode;
811 // mNode is being used in a separate thread; queue a message to set the value
812 SetPositionInheritanceModeMessage( GetEventThreadServices(), *mNode, mode );
816 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
818 // Cached for event-thread access
819 return mPositionInheritanceMode;
822 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
824 Vector4 normalizedAxis( axis.x, axis.y, axis.z, 0.0f );
825 normalizedAxis.Normalize();
827 Quaternion orientation( Quaternion::FromAxisAngle( normalizedAxis, angle ) );
829 SetOrientation( orientation );
832 void Actor::SetOrientation( const Quaternion& orientation )
836 // mNode is being used in a separate thread; queue a message to set the value & base value
837 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::Bake, orientation );
841 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
845 // mNode is being used in a separate thread; queue a message to set the value & base value
846 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, Quaternion(angle, axis) );
850 void Actor::RotateBy( const Quaternion& relativeRotation )
854 // mNode is being used in a separate thread; queue a message to set the value & base value
855 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, relativeRotation );
859 const Quaternion& Actor::GetCurrentOrientation() const
863 // mNode is being used in a separate thread; copy the value from the previous update
864 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
867 return Quaternion::IDENTITY;
870 const Quaternion& Actor::GetCurrentWorldOrientation() const
874 // mNode is being used in a separate thread; copy the value from the previous update
875 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
878 return Quaternion::IDENTITY;
881 void Actor::SetScale( float scale )
883 SetScale( Vector3( scale, scale, scale ) );
886 void Actor::SetScale( float x, float y, float z )
888 SetScale( Vector3( x, y, z ) );
891 void Actor::SetScale( const Vector3& scale )
895 // mNode is being used in a separate thread; queue a message to set the value & base value
896 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::Bake, scale );
900 void Actor::SetScaleX( float x )
904 // mNode is being used in a separate thread; queue a message to set the value & base value
905 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeX, x );
909 void Actor::SetScaleY( float y )
913 // mNode is being used in a separate thread; queue a message to set the value & base value
914 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeY, y );
918 void Actor::SetScaleZ( float z )
922 // mNode is being used in a separate thread; queue a message to set the value & base value
923 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeZ, z );
927 void Actor::SetInitialVolume( const Vector3& volume )
931 // mNode is being used in a separate thread; queue a message to set the value
932 SetInitialVolumeMessage( GetEventThreadServices(), *mNode, volume );
936 void Actor::SetTransmitGeometryScaling( bool transmitGeometryScaling )
940 // mNode is being used in a separate thread; queue a message to set the value
941 SetTransmitGeometryScalingMessage( GetEventThreadServices(), *mNode, transmitGeometryScaling );
945 bool Actor::GetTransmitGeometryScaling() const
949 // mNode is being used in a separate thread; copy the value from the previous update
950 return mNode->GetTransmitGeometryScaling();
956 void Actor::ScaleBy( const Vector3& relativeScale )
960 // mNode is being used in a separate thread; queue a message to set the value & base value
961 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeRelativeMultiply, relativeScale );
965 const Vector3& Actor::GetCurrentScale() const
969 // mNode is being used in a separate thread; copy the value from the previous update
970 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
976 const Vector3& Actor::GetCurrentWorldScale() const
980 // mNode is being used in a separate thread; copy the value from the previous update
981 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
987 void Actor::SetInheritScale( bool inherit )
989 // non animateable so keep local copy
990 mInheritScale = inherit;
993 // mNode is being used in a separate thread; queue a message to set the value
994 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
998 bool Actor::IsScaleInherited() const
1000 return mInheritScale;
1003 Matrix Actor::GetCurrentWorldMatrix() const
1007 // World matrix is no longer updated unless there is something observing the node.
1008 // Need to calculate it from node's world position, orientation and scale:
1009 BufferIndex updateBufferIndex = GetEventThreadServices().GetEventBufferIndex();
1010 Matrix worldMatrix(false);
1011 worldMatrix.SetTransformComponents( mNode->GetWorldScale( updateBufferIndex ),
1012 mNode->GetWorldOrientation( updateBufferIndex ),
1013 mNode->GetWorldPosition( updateBufferIndex ) );
1017 return Matrix::IDENTITY;
1020 void Actor::SetVisible( bool visible )
1024 // mNode is being used in a separate thread; queue a message to set the value & base value
1025 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
1029 bool Actor::IsVisible() const
1033 // mNode is being used in a separate thread; copy the value from the previous update
1034 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
1040 void Actor::SetOpacity( float opacity )
1044 // mNode is being used in a separate thread; queue a message to set the value & base value
1045 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
1049 float Actor::GetCurrentOpacity() const
1053 // mNode is being used in a separate thread; copy the value from the previous update
1054 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1060 const Vector4& Actor::GetCurrentWorldColor() const
1064 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1067 return Color::WHITE;
1070 void Actor::SetColor( const Vector4& color )
1074 // mNode is being used in a separate thread; queue a message to set the value & base value
1075 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1079 void Actor::SetColorRed( float red )
1083 // mNode is being used in a separate thread; queue a message to set the value & base value
1084 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1088 void Actor::SetColorGreen( float green )
1092 // mNode is being used in a separate thread; queue a message to set the value & base value
1093 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1097 void Actor::SetColorBlue( float blue )
1101 // mNode is being used in a separate thread; queue a message to set the value & base value
1102 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1106 const Vector4& Actor::GetCurrentColor() const
1110 // mNode is being used in a separate thread; copy the value from the previous update
1111 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1114 return Color::WHITE;
1117 void Actor::SetInheritOrientation( bool inherit )
1119 // non animateable so keep local copy
1120 mInheritOrientation = inherit;
1123 // mNode is being used in a separate thread; queue a message to set the value
1124 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1128 bool Actor::IsOrientationInherited() const
1130 return mInheritOrientation;
1133 void Actor::SetSizeMode( SizeMode mode )
1135 EnsureRelayoutData();
1137 mRelayoutData->sizeMode = mode;
1140 void Actor::SetSizeModeFactor( const Vector3& factor )
1142 EnsureRelayoutData();
1144 mRelayoutData->sizeModeFactor = factor;
1147 SizeMode Actor::GetSizeMode() const
1149 EnsureRelayoutData();
1151 return mRelayoutData->sizeMode;
1154 const Vector3& Actor::GetSizeModeFactor() const
1156 EnsureRelayoutData();
1158 return mRelayoutData->sizeModeFactor;
1161 void Actor::SetColorMode( ColorMode colorMode )
1163 // non animateable so keep local copy
1164 mColorMode = colorMode;
1167 // mNode is being used in a separate thread; queue a message to set the value
1168 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1172 ColorMode Actor::GetColorMode() const
1174 // we have cached copy
1178 void Actor::SetSize( float width, float height )
1180 SetSize( Vector2( width, height ) );
1183 void Actor::SetSize( float width, float height, float depth )
1185 SetSize( Vector3( width, height, depth ) );
1188 void Actor::SetSize( const Vector2& size )
1190 SetSize( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1193 float Actor::CalculateSizeZ( const Vector2& size ) const
1195 return std::min( size.width, size.height );
1198 void Actor::SetSize( const Vector3& size )
1204 // mNode is being used in a separate thread; queue a message to set the value & base value
1205 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::Bake, mTargetSize );
1207 // Notification for derived classes
1208 OnSizeSet( mTargetSize );
1210 // Raise a relayout request if the flag is not locked
1211 if( mRelayoutData && !mRelayoutData->insideRelayout )
1218 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1220 mTargetSize = targetSize;
1222 // Notify deriving classes
1223 OnSizeAnimation( animation, targetSize );
1226 void Actor::SetWidth( float width )
1230 // mNode is being used in a separate thread; queue a message to set the value & base value
1231 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeX, width );
1235 void Actor::SetHeight( float height )
1239 // mNode is being used in a separate thread; queue a message to set the value & base value
1240 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeY, height );
1244 void Actor::SetDepth( float depth )
1248 // mNode is being used in a separate thread; queue a message to set the value & base value
1249 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeZ, depth );
1253 const Vector3& Actor::GetTargetSize() const
1258 const Vector3& Actor::GetCurrentSize() const
1262 // mNode is being used in a separate thread; copy the value from the previous update
1263 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1266 return Vector3::ZERO;
1269 Vector3 Actor::GetNaturalSize() const
1271 // It is up to deriving classes to return the appropriate natural size
1272 return Vector3( 0.0f, 0.0f, 0.0f );
1275 void Actor::SetResizePolicy( ResizePolicy policy, Dimension dimension )
1277 EnsureRelayoutData();
1279 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
1281 if( dimension & ( 1 << i ) )
1283 mRelayoutData->resizePolicies[ i ] = policy;
1287 OnSetResizePolicy( policy, dimension );
1289 // Trigger relayout on this control
1293 ResizePolicy Actor::GetResizePolicy( Dimension dimension ) const
1295 EnsureRelayoutData();
1297 // If more than one dimension is requested, just return the first one found
1298 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
1300 if( ( dimension & ( 1 << i ) ) )
1302 return mRelayoutData->resizePolicies[ i ];
1306 return FIXED; // Default
1309 void Actor::SetSizeScalePolicy( SizeScalePolicy policy )
1311 EnsureRelayoutData();
1313 mRelayoutData->sizeSetPolicy = policy;
1316 SizeScalePolicy Actor::GetSizeScalePolicy() const
1318 EnsureRelayoutData();
1320 return mRelayoutData->sizeSetPolicy;
1323 void Actor::SetDimensionDependency( Dimension dimension, Dimension dependency )
1325 EnsureRelayoutData();
1327 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
1329 if( dimension & ( 1 << i ) )
1331 mRelayoutData->dimensionDependencies[ i ] = dependency;
1332 mRelayoutData->resizePolicies[ i ] = DIMENSION_DEPENDENCY;
1337 Dimension Actor::GetDimensionDependency( Dimension dimension ) const
1339 EnsureRelayoutData();
1341 // If more than one dimension is requested, just return the first one found
1342 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
1344 if( ( dimension & ( 1 << i ) ) )
1346 return mRelayoutData->dimensionDependencies[ i ];
1350 return ALL_DIMENSIONS; // Default
1353 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1355 // If relayout data has not been allocated yet and the client is requesting
1356 // to disable it, do nothing
1357 if( mRelayoutData || relayoutEnabled )
1359 EnsureRelayoutData();
1361 mRelayoutData->relayoutEnabled = relayoutEnabled;
1365 bool Actor::IsRelayoutEnabled() const
1367 // Assume that if relayout data has not been allocated yet then
1368 // relayout is disabled
1369 return mRelayoutData && mRelayoutData->relayoutEnabled;
1372 void Actor::SetLayoutDirty( bool dirty, Dimension dimension )
1374 EnsureRelayoutData();
1376 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
1378 if( dimension & ( 1 << i ) )
1380 mRelayoutData->dimensionDirty[ i ] = dirty;
1385 bool Actor::IsLayoutDirty( Dimension dimension ) const
1387 EnsureRelayoutData();
1389 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
1391 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1400 bool Actor::RelayoutPossible( Dimension dimension ) const
1402 EnsureRelayoutData();
1404 return mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1407 bool Actor::RelayoutRequired( Dimension dimension ) const
1409 EnsureRelayoutData();
1411 return mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1414 #ifdef DYNAMICS_SUPPORT
1416 //--------------- Dynamics ---------------
1418 void Actor::DisableDynamics()
1420 if( NULL != mDynamicsData )
1422 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1424 // ensure dynamics object are disconnected from scene
1425 DisconnectDynamics();
1427 // delete joint owned by this actor
1428 while( !mDynamicsData->joints.empty() )
1430 RemoveDynamicsJoint( mDynamicsData->joints.begin()->second );
1433 // delete other joints referencing this actor
1434 while( !mDynamicsData->referencedJoints.empty() )
1436 DynamicsJointPtr joint( *(mDynamicsData->referencedJoints.begin()) );
1437 ActorPtr jointOwner( joint->GetActor( true ) );
1440 jointOwner->RemoveDynamicsJoint( joint );
1444 mDynamicsData->referencedJoints.erase( mDynamicsData->referencedJoints.begin() );
1447 // delete the DynamicsBody object
1448 mDynamicsData->body.Reset();
1450 // Discard Dynamics data structure
1451 delete mDynamicsData;
1452 mDynamicsData = NULL;
1456 DynamicsBodyPtr Actor::GetDynamicsBody() const
1458 DynamicsBodyPtr body;
1460 if( NULL != mDynamicsData )
1462 body = mDynamicsData->body;
1468 DynamicsBodyPtr Actor::EnableDynamics(DynamicsBodyConfigPtr bodyConfig)
1470 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1472 if( NULL == mDynamicsData )
1474 mDynamicsData = new DynamicsData( this );
1477 if( !mDynamicsData->body )
1479 mDynamicsData->body = new DynamicsBody(mName, bodyConfig, *this, *(const_cast<SceneGraph::Node*>(mNode)) );
1483 DynamicsWorldPtr world( DynamicsWorld::Get() );
1486 if( mParent == world->GetRootActor().Get() )
1488 mDynamicsData->body->Connect( GetEventThreadServices() );
1494 return mDynamicsData->body;
1497 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offset )
1499 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1500 return AddDynamicsJoint( attachedActor, offset, ( GetCurrentPosition() + offset ) - attachedActor->GetCurrentPosition() );
1503 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offsetA, const Vector3& offsetB )
1505 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1506 DALI_ASSERT_ALWAYS( this != attachedActor.Get() && "Cannot create a joint to oneself!" );
1508 DynamicsJointPtr joint;
1510 DynamicsWorldPtr world( DynamicsWorld::Get() );
1514 if( NULL != mDynamicsData )
1516 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1518 if( mDynamicsData->joints.end() != it )
1520 // use existing joint
1526 DynamicsBodyPtr bodyA( GetDynamicsBody() );
1527 DynamicsBodyPtr bodyB( attachedActor->GetDynamicsBody() );
1531 bodyA = EnableDynamics( new DynamicsBodyConfig );
1536 bodyB = attachedActor->EnableDynamics( new DynamicsBodyConfig );
1539 joint = new DynamicsJoint(world, bodyA, bodyB, offsetA, offsetB);
1540 mDynamicsData->joints[ attachedActor.Get() ] = joint;
1542 if( OnStage() && attachedActor->OnStage() )
1544 joint->Connect( GetEventThreadServices() );
1547 attachedActor->ReferenceJoint( joint );
1549 attachedActor->OnStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1550 attachedActor->OffStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1557 const int Actor::GetNumberOfJoints() const
1559 return static_cast<int>( NULL != mDynamicsData ? mDynamicsData->joints.size() : 0 );
1562 DynamicsJointPtr Actor::GetDynamicsJointByIndex( const int index ) const
1564 DynamicsJointPtr joint;
1566 if( NULL != mDynamicsData )
1568 if( index >= 0 && index < static_cast<int>(mDynamicsData->joints.size()) )
1570 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.begin() );
1572 for( int i = 0; i < index; ++i )
1584 DynamicsJointPtr Actor::GetDynamicsJoint( ActorPtr attachedActor ) const
1586 DynamicsJointPtr joint;
1588 if( NULL != mDynamicsData )
1590 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1592 if( mDynamicsData->joints.end() != it )
1594 // use existing joint
1602 void Actor::RemoveDynamicsJoint( DynamicsJointPtr joint )
1604 if( NULL != mDynamicsData )
1606 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1607 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1609 for(; it != endIt; ++it )
1611 if( it->second == joint.Get() )
1613 ActorPtr attachedActor( it->first );
1615 if( OnStage() && attachedActor && attachedActor->OnStage() )
1617 joint->Disconnect( GetEventThreadServices() );
1622 attachedActor->ReleaseJoint( joint );
1623 attachedActor->OnStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1624 attachedActor->OffStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1627 mDynamicsData->joints.erase(it);
1634 void Actor::ReferenceJoint( DynamicsJointPtr joint )
1636 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1638 if( NULL != mDynamicsData )
1640 mDynamicsData->referencedJoints.push_back(joint);
1644 void Actor::ReleaseJoint( DynamicsJointPtr joint )
1646 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1648 if( NULL != mDynamicsData )
1650 DynamicsData::ReferencedJointContainer::iterator it( std::find( mDynamicsData->referencedJoints.begin(), mDynamicsData->referencedJoints.end(), joint ) );
1652 if( it != mDynamicsData->referencedJoints.end() )
1654 mDynamicsData->referencedJoints.erase( it );
1659 void Actor::SetDynamicsRoot(bool flag)
1661 if( mIsDynamicsRoot != flag )
1663 mIsDynamicsRoot = flag;
1665 if( OnStage() && mChildren )
1667 // walk the children connecting or disconnecting any dynamics enabled child from the dynamics simulation
1668 ActorIter end = mChildren->end();
1669 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
1671 Actor& child = GetImplementation(*iter);
1673 if( child.GetDynamicsBody() )
1675 if( mIsDynamicsRoot )
1677 child.ConnectDynamics();
1681 child.DisconnectDynamics();
1689 bool Actor::IsDynamicsRoot() const
1691 return mIsDynamicsRoot;
1694 void Actor::AttachedActorOnStage( Dali::Actor actor )
1696 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1700 ActorPtr attachedActor( &GetImplementation(actor) );
1702 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1703 if( NULL != mDynamicsData )
1705 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1706 if( mDynamicsData->joints.end() != it )
1708 DynamicsJointPtr joint( it->second );
1709 joint->Connect( GetEventThreadServices() );
1715 void Actor::AttachedActorOffStage( Dali::Actor actor )
1717 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1721 ActorPtr attachedActor( &GetImplementation(actor) );
1723 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1724 if( NULL != mDynamicsData )
1726 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1727 if( mDynamicsData->joints.end() != it )
1729 DynamicsJointPtr joint( it->second );
1730 joint->Disconnect( GetEventThreadServices() );
1736 void Actor::ConnectDynamics()
1738 if( NULL != mDynamicsData && mDynamicsData->body )
1740 if( OnStage() && mParent && mParent->IsDynamicsRoot() )
1742 mDynamicsData->body->Connect( GetEventThreadServices() );
1744 // Connect all joints where attachedActor is also on stage
1745 if( !mDynamicsData->joints.empty() )
1747 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1748 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1750 for(; it != endIt; ++it )
1752 Actor* attachedActor( it->first );
1753 if( NULL != attachedActor && attachedActor->OnStage() )
1755 DynamicsJointPtr joint( it->second );
1757 joint->Connect( GetEventThreadServices() );
1765 void Actor::DisconnectDynamics()
1767 if( NULL != mDynamicsData && mDynamicsData->body )
1771 mDynamicsData->body->Disconnect( GetEventThreadServices() );
1773 // Disconnect all joints
1774 if( !mDynamicsData->joints.empty() )
1776 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1777 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1779 for(; it != endIt; ++it )
1781 DynamicsJointPtr joint( it->second );
1783 joint->Disconnect( GetEventThreadServices() );
1790 #endif // DYNAMICS_SUPPORT
1792 void Actor::SetOverlay( bool enable )
1794 // Setting STENCIL will override OVERLAY
1795 if( DrawMode::STENCIL != mDrawMode )
1797 SetDrawMode( enable ? DrawMode::OVERLAY : DrawMode::NORMAL );
1801 bool Actor::IsOverlay() const
1803 return ( DrawMode::OVERLAY == mDrawMode );
1806 void Actor::SetDrawMode( DrawMode::Type drawMode )
1808 // this flag is not animatable so keep the value
1809 mDrawMode = drawMode;
1812 // mNode is being used in a separate thread; queue a message to set the value
1813 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1817 DrawMode::Type Actor::GetDrawMode() const
1822 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1824 // only valid when on-stage
1827 const RenderTaskList& taskList = Stage::GetCurrent()->GetRenderTaskList();
1829 Vector2 converted( screenX, screenY );
1831 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1832 const int taskCount = taskList.GetTaskCount();
1833 for( int i = taskCount - 1; i >= 0; --i )
1835 Dali::RenderTask task = taskList.GetTask( i );
1836 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1838 // found a task where this conversion was ok so return
1846 bool Actor::ScreenToLocal( RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1848 bool retval = false;
1849 // only valid when on-stage
1852 CameraActor* camera = renderTask.GetCameraActor();
1856 renderTask.GetViewport( viewport );
1858 // need to translate coordinates to render tasks coordinate space
1859 Vector2 converted( screenX, screenY );
1860 if( renderTask.TranslateCoordinates( converted ) )
1862 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1869 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1871 // Early-out if mNode is NULL
1877 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1879 // Calculate the ModelView matrix
1880 Matrix modelView( false/*don't init*/);
1881 // need to use the components as world matrix is only updated for actors that need it
1882 modelView.SetTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1883 Matrix::Multiply( modelView, modelView, viewMatrix );
1885 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1886 Matrix invertedMvp( false/*don't init*/);
1887 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1888 bool success = invertedMvp.Invert();
1890 // Convert to GL coordinates
1891 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1896 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1903 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1909 if( XyPlaneIntersect( nearPos, farPos, local ) )
1911 Vector3 size = GetCurrentSize();
1912 localX = local.x + size.x * 0.5f;
1913 localY = local.y + size.y * 0.5f;
1924 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1927 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1929 Mathematical Formulation
1931 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1933 ( p - c ) dot ( p - c ) = r^2
1935 Given a ray with a point of origin 'o', and a direction vector 'd':
1937 ray(t) = o + td, t >= 0
1939 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1941 (o + td - c ) dot ( o + td - c ) = r^2
1943 To solve for t we first expand the above into a more recognisable quadratic equation form
1945 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1954 B = 2( o - c ) dot d
1955 C = ( o - c ) dot ( o - c ) - r^2
1957 which can be solved using a standard quadratic formula.
1959 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1961 Practical Simplification
1963 In a renderer, we often differentiate between world space and object space. In the object space
1964 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1965 into object space, the mathematical solution presented above can be simplified significantly.
1967 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1971 and we can find the t at which the (transformed) ray intersects the sphere by
1973 ( o + td ) dot ( o + td ) = r^2
1975 According to the reasoning above, we expand the above quadratic equation into the general form
1979 which now has coefficients:
1986 // Early out if mNode is NULL
1992 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1994 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1995 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1996 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1998 // Compute the radius is not needed, square radius it's enough.
1999 const Vector3& size( mNode->GetSize( bufferIndex ) );
2001 // Scale the sphere.
2002 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
2004 const float width = size.width * scale.width;
2005 const float height = size.height * scale.height;
2007 float squareSphereRadius = 0.5f * ( width * width + height * height );
2009 float a = rayDir.Dot( rayDir ); // a
2010 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
2011 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
2013 return ( b2 * b2 - a * c ) >= 0.f;
2016 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
2023 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
2025 // Transforms the ray to the local reference system.
2027 // Calculate the inverse of Model matrix
2028 Matrix invModelMatrix( false/*don't init*/);
2029 // need to use the components as world matrix is only updated for actors that need it
2030 invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
2032 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
2033 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
2035 // Test with the actor's XY plane (Normal = 0 0 1 1).
2037 float a = -rayOriginLocal.z;
2038 float b = rayDirLocal.z;
2040 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
2042 // Ray travels distance * rayDirLocal to intersect with plane.
2045 const Vector3& size = mNode->GetSize( bufferIndex );
2047 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
2048 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
2050 // Test with the actor's geometry.
2051 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
2058 void Actor::SetLeaveRequired( bool required )
2060 mLeaveRequired = required;
2063 bool Actor::GetLeaveRequired() const
2065 return mLeaveRequired;
2068 void Actor::SetKeyboardFocusable( bool focusable )
2070 mKeyboardFocusable = focusable;
2073 bool Actor::IsKeyboardFocusable() const
2075 return mKeyboardFocusable;
2078 bool Actor::GetTouchRequired() const
2080 return !mTouchedSignal.Empty() || mDerivedRequiresTouch;
2083 bool Actor::GetHoverRequired() const
2085 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
2088 bool Actor::GetMouseWheelEventRequired() const
2090 return !mMouseWheelEventSignal.Empty() || mDerivedRequiresMouseWheelEvent;
2093 bool Actor::IsHittable() const
2095 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
2098 ActorGestureData& Actor::GetGestureData()
2100 // Likely scenario is that once gesture-data is created for this actor, the actor will require
2101 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
2102 if( NULL == mGestureData )
2104 mGestureData = new ActorGestureData;
2106 return *mGestureData;
2109 bool Actor::IsGestureRequred( Gesture::Type type ) const
2111 return mGestureData && mGestureData->IsGestureRequred( type );
2114 bool Actor::EmitTouchEventSignal( const TouchEvent& event )
2116 bool consumed = false;
2118 if( !mTouchedSignal.Empty() )
2120 Dali::Actor handle( this );
2121 consumed = mTouchedSignal.Emit( handle, event );
2126 // Notification for derived classes
2127 consumed = OnTouchEvent( event );
2133 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
2135 bool consumed = false;
2137 if( !mHoveredSignal.Empty() )
2139 Dali::Actor handle( this );
2140 consumed = mHoveredSignal.Emit( handle, event );
2145 // Notification for derived classes
2146 consumed = OnHoverEvent( event );
2152 bool Actor::EmitMouseWheelEventSignal( const MouseWheelEvent& event )
2154 bool consumed = false;
2156 if( !mMouseWheelEventSignal.Empty() )
2158 Dali::Actor handle( this );
2159 consumed = mMouseWheelEventSignal.Emit( handle, event );
2164 // Notification for derived classes
2165 consumed = OnMouseWheelEvent( event );
2171 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
2173 return mTouchedSignal;
2176 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
2178 return mHoveredSignal;
2181 Dali::Actor::MouseWheelEventSignalType& Actor::MouseWheelEventSignal()
2183 return mMouseWheelEventSignal;
2186 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
2188 return mOnStageSignal;
2191 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
2193 return mOffStageSignal;
2196 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
2198 return mOnRelayoutSignal;
2201 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
2203 bool connected( true );
2204 Actor* actor = dynamic_cast< Actor* >( object );
2206 if( 0 == strcmp( signalName.c_str(), SIGNAL_TOUCHED ) ) // don't want to convert char* to string
2208 actor->TouchedSignal().Connect( tracker, functor );
2210 else if( 0 == strcmp( signalName.c_str(), SIGNAL_HOVERED ) )
2212 actor->HoveredSignal().Connect( tracker, functor );
2214 else if( 0 == strcmp( signalName.c_str(), SIGNAL_MOUSE_WHEEL_EVENT ) )
2216 actor->MouseWheelEventSignal().Connect( tracker, functor );
2218 else if( 0 == strcmp( signalName.c_str(), SIGNAL_ON_STAGE ) )
2220 actor->OnStageSignal().Connect( tracker, functor );
2222 else if( 0 == strcmp( signalName.c_str(), SIGNAL_OFF_STAGE ) )
2224 actor->OffStageSignal().Connect( tracker, functor );
2228 // signalName does not match any signal
2235 Actor::Actor( DerivedType derivedType )
2239 mParentOrigin( NULL ),
2240 mAnchorPoint( NULL ),
2241 mRelayoutData( NULL ),
2242 #ifdef DYNAMICS_SUPPORT
2243 mDynamicsData( NULL ),
2245 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
2246 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 )
2250 void Actor::Initialize()
2253 SceneGraph::Node* node = CreateNode();
2255 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
2256 mNode = node; // Keep raw-pointer to Node
2260 GetEventThreadServices().RegisterObject( this );
2265 // Remove mParent pointers from children even if we're destroying core,
2266 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2269 ActorConstIter endIter = mChildren->end();
2270 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2272 Actor& actor = GetImplementation( *iter );
2273 actor.SetParent( NULL );
2278 // Guard to allow handle destruction after Core has been destroyed
2279 if( EventThreadServices::IsCoreRunning() )
2283 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2284 mNode = NULL; // Node is about to be destroyed
2287 GetEventThreadServices().UnregisterObject( this );
2290 #ifdef DYNAMICS_SUPPORT
2292 delete mDynamicsData;
2295 // Cleanup optional gesture data
2296 delete mGestureData;
2298 // Cleanup optional parent origin and anchor
2299 delete mParentOrigin;
2300 delete mAnchorPoint;
2302 // Delete optional relayout data
2305 delete mRelayoutData;
2309 void Actor::ConnectToStage( int index )
2311 // This container is used instead of walking the Actor hierachy.
2312 // It protects us when the Actor hierachy is modified during OnStageConnectionExternal callbacks.
2313 ActorContainer connectionList;
2315 // This stage is atomic i.e. not interrupted by user callbacks
2316 RecursiveConnectToStage( connectionList, index );
2318 // Notify applications about the newly connected actors.
2319 const ActorIter endIter = connectionList.end();
2320 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2322 Actor& actor = GetImplementation( *iter );
2323 actor.NotifyStageConnection();
2329 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, int index )
2331 DALI_ASSERT_ALWAYS( !OnStage() );
2335 ConnectToSceneGraph( index );
2337 // Notification for internal derived classes
2338 OnStageConnectionInternal();
2340 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2341 connectionList.push_back( Dali::Actor( this ) );
2343 // Recursively connect children
2346 ActorConstIter endIter = mChildren->end();
2347 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2349 Actor& actor = GetImplementation( *iter );
2350 actor.RecursiveConnectToStage( connectionList );
2356 * This method is called when the Actor is connected to the Stage.
2357 * The parent must have added its Node to the scene-graph.
2358 * The child must connect its Node to the parent's Node.
2359 * This is resursive; the child calls ConnectToStage() for its children.
2361 void Actor::ConnectToSceneGraph( int index )
2363 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2367 // Reparent Node in next Update
2368 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode, index );
2371 // Notify attachment
2374 mAttachment->Connect();
2377 #ifdef DYNAMICS_SUPPORT
2379 if( NULL != mDynamicsData )
2385 // Notification for Object::Observers
2389 void Actor::NotifyStageConnection()
2391 // Actors can be removed (in a callback), before the on-stage stage is reported.
2392 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2393 if( OnStage() && !mOnStageSignalled )
2395 // Notification for external (CustomActor) derived classes
2396 OnStageConnectionExternal();
2398 if( !mOnStageSignal.Empty() )
2400 Dali::Actor handle( this );
2401 mOnStageSignal.Emit( handle );
2404 // Guard against Remove during callbacks
2407 mOnStageSignalled = true; // signal required next time Actor is removed
2412 void Actor::DisconnectFromStage()
2414 // This container is used instead of walking the Actor hierachy.
2415 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2416 ActorContainer disconnectionList;
2418 // This stage is atomic i.e. not interrupted by user callbacks
2419 RecursiveDisconnectFromStage( disconnectionList );
2421 // Notify applications about the newly disconnected actors.
2422 const ActorIter endIter = disconnectionList.end();
2423 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2425 Actor& actor = GetImplementation( *iter );
2426 actor.NotifyStageDisconnection();
2430 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2432 DALI_ASSERT_ALWAYS( OnStage() );
2434 // Recursively disconnect children
2437 ActorConstIter endIter = mChildren->end();
2438 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2440 Actor& actor = GetImplementation( *iter );
2441 actor.RecursiveDisconnectFromStage( disconnectionList );
2445 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2446 disconnectionList.push_back( Dali::Actor( this ) );
2448 // Notification for internal derived classes
2449 OnStageDisconnectionInternal();
2451 DisconnectFromSceneGraph();
2457 * This method is called by an actor or its parent, before a node removal message is sent.
2458 * This is recursive; the child calls DisconnectFromStage() for its children.
2460 void Actor::DisconnectFromSceneGraph()
2462 // Notification for Object::Observers
2463 OnSceneObjectRemove();
2465 // Notify attachment
2468 mAttachment->Disconnect();
2471 #ifdef DYNAMICS_SUPPORT
2473 if( NULL != mDynamicsData )
2475 DisconnectDynamics();
2480 void Actor::NotifyStageDisconnection()
2482 // Actors can be added (in a callback), before the off-stage state is reported.
2483 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2484 // only do this step if there is a stage, i.e. Core is not being shut down
2485 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2487 // Notification for external (CustomeActor) derived classes
2488 OnStageDisconnectionExternal();
2490 if( !mOffStageSignal.Empty() )
2492 Dali::Actor handle( this );
2493 mOffStageSignal.Emit( handle );
2496 // Guard against Add during callbacks
2499 mOnStageSignalled = false; // signal required next time Actor is added
2504 bool Actor::IsNodeConnected() const
2506 bool connected( false );
2511 if( mNode->IsRoot() || mNode->GetParent() )
2520 unsigned int Actor::GetDefaultPropertyCount() const
2522 return DEFAULT_PROPERTY_COUNT;
2525 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2527 indices.reserve( DEFAULT_PROPERTY_COUNT );
2529 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2531 indices.push_back( i );
2535 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2537 if( index < DEFAULT_PROPERTY_COUNT )
2539 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2545 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2547 Property::Index index = Property::INVALID_INDEX;
2549 // Look for name in default properties
2550 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2552 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2553 if( 0 == strcmp( name.c_str(), property->name ) ) // dont want to convert rhs to string
2563 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2565 if( index < DEFAULT_PROPERTY_COUNT )
2567 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2573 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2575 if( index < DEFAULT_PROPERTY_COUNT )
2577 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2583 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2585 if( index < DEFAULT_PROPERTY_COUNT )
2587 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2593 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2595 if( index < DEFAULT_PROPERTY_COUNT )
2597 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2600 // index out of range...return Property::NONE
2601 return Property::NONE;
2604 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2608 case Dali::Actor::Property::PARENT_ORIGIN:
2610 SetParentOrigin( property.Get< Vector3 >() );
2614 case Dali::Actor::Property::PARENT_ORIGIN_X:
2616 SetParentOriginX( property.Get< float >() );
2620 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2622 SetParentOriginY( property.Get< float >() );
2626 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2628 SetParentOriginZ( property.Get< float >() );
2632 case Dali::Actor::Property::ANCHOR_POINT:
2634 SetAnchorPoint( property.Get< Vector3 >() );
2638 case Dali::Actor::Property::ANCHOR_POINT_X:
2640 SetAnchorPointX( property.Get< float >() );
2644 case Dali::Actor::Property::ANCHOR_POINT_Y:
2646 SetAnchorPointY( property.Get< float >() );
2650 case Dali::Actor::Property::ANCHOR_POINT_Z:
2652 SetAnchorPointZ( property.Get< float >() );
2656 case Dali::Actor::Property::SIZE:
2658 SetSize( property.Get< Vector3 >() );
2662 case Dali::Actor::Property::SIZE_WIDTH:
2664 SetWidth( property.Get< float >() );
2668 case Dali::Actor::Property::SIZE_HEIGHT:
2670 SetHeight( property.Get< float >() );
2674 case Dali::Actor::Property::SIZE_DEPTH:
2676 SetDepth( property.Get< float >() );
2680 case Dali::Actor::Property::POSITION:
2682 SetPosition( property.Get< Vector3 >() );
2686 case Dali::Actor::Property::POSITION_X:
2688 SetX( property.Get< float >() );
2692 case Dali::Actor::Property::POSITION_Y:
2694 SetY( property.Get< float >() );
2698 case Dali::Actor::Property::POSITION_Z:
2700 SetZ( property.Get< float >() );
2704 case Dali::Actor::Property::ORIENTATION:
2706 SetOrientation( property.Get< Quaternion >() );
2710 case Dali::Actor::Property::SCALE:
2712 SetScale( property.Get< Vector3 >() );
2716 case Dali::Actor::Property::SCALE_X:
2718 SetScaleX( property.Get< float >() );
2722 case Dali::Actor::Property::SCALE_Y:
2724 SetScaleY( property.Get< float >() );
2728 case Dali::Actor::Property::SCALE_Z:
2730 SetScaleZ( property.Get< float >() );
2734 case Dali::Actor::Property::VISIBLE:
2736 SetVisible( property.Get< bool >() );
2740 case Dali::Actor::Property::COLOR:
2742 SetColor( property.Get< Vector4 >() );
2746 case Dali::Actor::Property::COLOR_RED:
2748 SetColorRed( property.Get< float >() );
2752 case Dali::Actor::Property::COLOR_GREEN:
2754 SetColorGreen( property.Get< float >() );
2758 case Dali::Actor::Property::COLOR_BLUE:
2760 SetColorBlue( property.Get< float >() );
2764 case Dali::Actor::Property::COLOR_ALPHA:
2766 SetOpacity( property.Get< float >() );
2770 case Dali::Actor::Property::NAME:
2772 SetName( property.Get< std::string >() );
2776 case Dali::Actor::Property::SENSITIVE:
2778 SetSensitive( property.Get< bool >() );
2782 case Dali::Actor::Property::LEAVE_REQUIRED:
2784 SetLeaveRequired( property.Get< bool >() );
2788 case Dali::Actor::Property::INHERIT_ORIENTATION:
2790 SetInheritOrientation( property.Get< bool >() );
2794 case Dali::Actor::Property::INHERIT_SCALE:
2796 SetInheritScale( property.Get< bool >() );
2800 case Dali::Actor::Property::COLOR_MODE:
2802 SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2806 case Dali::Actor::Property::POSITION_INHERITANCE:
2808 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2812 case Dali::Actor::Property::DRAW_MODE:
2814 SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2818 case Dali::Actor::Property::SIZE_MODE:
2820 SetSizeMode( Scripting::GetEnumeration< SizeMode >( property.Get< std::string >().c_str(), SizeModeTable, SizeModeTableCount ) );
2824 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2826 SetSizeModeFactor( property.Get< Vector3 >() );
2830 case Dali::Actor::Property::RELAYOUT_ENABLED:
2832 SetRelayoutEnabled( property.Get< bool >() );
2836 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2838 SetResizePolicy( Scripting::GetEnumeration< ResizePolicy >( property.Get< std::string >().c_str(), ResizePolicyTable, ResizePolicyTableCount ), WIDTH );
2842 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2844 SetResizePolicy( Scripting::GetEnumeration< ResizePolicy >( property.Get< std::string >().c_str(), ResizePolicyTable, ResizePolicyTableCount ), HEIGHT );
2848 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2850 SetSizeScalePolicy( Scripting::GetEnumeration< SizeScalePolicy >( property.Get< std::string >().c_str(), SizeScalePolicyTable, SizeScalePolicyTableCount ) );
2854 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2856 if( property.Get< bool >() )
2858 SetDimensionDependency( WIDTH, HEIGHT );
2863 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2865 if( property.Get< bool >() )
2867 SetDimensionDependency( HEIGHT, WIDTH );
2872 case Dali::Actor::Property::PADDING:
2874 Vector4 padding = property.Get< Vector4 >();
2875 SetPadding( Vector2( padding.x, padding.y ), WIDTH );
2876 SetPadding( Vector2( padding.z, padding.w ), HEIGHT );
2880 case Dali::Actor::Property::MINIMUM_SIZE:
2882 Vector2 size = property.Get< Vector2 >();
2883 SetMinimumSize( size.x, WIDTH );
2884 SetMinimumSize( size.y, HEIGHT );
2888 case Dali::Actor::Property::MAXIMUM_SIZE:
2890 Vector2 size = property.Get< Vector2 >();
2891 SetMaximumSize( size.x, WIDTH );
2892 SetMaximumSize( size.y, HEIGHT );
2896 case Dali::Actor::Property::PREFERRED_SIZE:
2898 Vector2 size = property.Get< Vector2 >();
2899 SetPreferredSize( size );
2905 // this can happen in the case of a non-animatable default property so just do nothing
2911 // TODO: This method needs to be removed
2912 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2914 OnPropertySet( index, value );
2916 switch( entry.type )
2918 case Property::BOOLEAN:
2920 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2921 DALI_ASSERT_DEBUG( NULL != property );
2923 // property is being used in a separate thread; queue a message to set the property
2924 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2929 case Property::FLOAT:
2931 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2932 DALI_ASSERT_DEBUG( NULL != property );
2934 // property is being used in a separate thread; queue a message to set the property
2935 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2940 case Property::INTEGER:
2942 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2943 DALI_ASSERT_DEBUG( NULL != property );
2945 // property is being used in a separate thread; queue a message to set the property
2946 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2951 case Property::VECTOR2:
2953 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2954 DALI_ASSERT_DEBUG( NULL != property );
2956 // property is being used in a separate thread; queue a message to set the property
2957 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2962 case Property::VECTOR3:
2964 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2965 DALI_ASSERT_DEBUG( NULL != property );
2967 // property is being used in a separate thread; queue a message to set the property
2968 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2973 case Property::VECTOR4:
2975 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2976 DALI_ASSERT_DEBUG( NULL != property );
2978 // property is being used in a separate thread; queue a message to set the property
2979 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2984 case Property::ROTATION:
2986 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
2987 DALI_ASSERT_DEBUG( NULL != property );
2989 // property is being used in a separate thread; queue a message to set the property
2990 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
2995 case Property::MATRIX:
2997 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
2998 DALI_ASSERT_DEBUG( NULL != property );
3000 // property is being used in a separate thread; queue a message to set the property
3001 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3006 case Property::MATRIX3:
3008 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3009 DALI_ASSERT_DEBUG( NULL != property );
3011 // property is being used in a separate thread; queue a message to set the property
3012 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3019 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
3025 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3027 Property::Value value;
3031 case Dali::Actor::Property::PARENT_ORIGIN:
3033 value = GetCurrentParentOrigin();
3037 case Dali::Actor::Property::PARENT_ORIGIN_X:
3039 value = GetCurrentParentOrigin().x;
3043 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3045 value = GetCurrentParentOrigin().y;
3049 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3051 value = GetCurrentParentOrigin().z;
3055 case Dali::Actor::Property::ANCHOR_POINT:
3057 value = GetCurrentAnchorPoint();
3061 case Dali::Actor::Property::ANCHOR_POINT_X:
3063 value = GetCurrentAnchorPoint().x;
3067 case Dali::Actor::Property::ANCHOR_POINT_Y:
3069 value = GetCurrentAnchorPoint().y;
3073 case Dali::Actor::Property::ANCHOR_POINT_Z:
3075 value = GetCurrentAnchorPoint().z;
3079 case Dali::Actor::Property::SIZE:
3081 value = GetCurrentSize();
3085 case Dali::Actor::Property::SIZE_WIDTH:
3087 value = GetCurrentSize().width;
3091 case Dali::Actor::Property::SIZE_HEIGHT:
3093 value = GetCurrentSize().height;
3097 case Dali::Actor::Property::SIZE_DEPTH:
3099 value = GetCurrentSize().depth;
3103 case Dali::Actor::Property::POSITION:
3105 value = GetCurrentPosition();
3109 case Dali::Actor::Property::POSITION_X:
3111 value = GetCurrentPosition().x;
3115 case Dali::Actor::Property::POSITION_Y:
3117 value = GetCurrentPosition().y;
3121 case Dali::Actor::Property::POSITION_Z:
3123 value = GetCurrentPosition().z;
3127 case Dali::Actor::Property::WORLD_POSITION:
3129 value = GetCurrentWorldPosition();
3133 case Dali::Actor::Property::WORLD_POSITION_X:
3135 value = GetCurrentWorldPosition().x;
3139 case Dali::Actor::Property::WORLD_POSITION_Y:
3141 value = GetCurrentWorldPosition().y;
3145 case Dali::Actor::Property::WORLD_POSITION_Z:
3147 value = GetCurrentWorldPosition().z;
3151 case Dali::Actor::Property::ORIENTATION:
3153 value = GetCurrentOrientation();
3157 case Dali::Actor::Property::WORLD_ORIENTATION:
3159 value = GetCurrentWorldOrientation();
3163 case Dali::Actor::Property::SCALE:
3165 value = GetCurrentScale();
3169 case Dali::Actor::Property::SCALE_X:
3171 value = GetCurrentScale().x;
3175 case Dali::Actor::Property::SCALE_Y:
3177 value = GetCurrentScale().y;
3181 case Dali::Actor::Property::SCALE_Z:
3183 value = GetCurrentScale().z;
3187 case Dali::Actor::Property::WORLD_SCALE:
3189 value = GetCurrentWorldScale();
3193 case Dali::Actor::Property::VISIBLE:
3195 value = IsVisible();
3199 case Dali::Actor::Property::COLOR:
3201 value = GetCurrentColor();
3205 case Dali::Actor::Property::COLOR_RED:
3207 value = GetCurrentColor().r;
3211 case Dali::Actor::Property::COLOR_GREEN:
3213 value = GetCurrentColor().g;
3217 case Dali::Actor::Property::COLOR_BLUE:
3219 value = GetCurrentColor().b;
3223 case Dali::Actor::Property::COLOR_ALPHA:
3225 value = GetCurrentColor().a;
3229 case Dali::Actor::Property::WORLD_COLOR:
3231 value = GetCurrentWorldColor();
3235 case Dali::Actor::Property::WORLD_MATRIX:
3237 value = GetCurrentWorldMatrix();
3241 case Dali::Actor::Property::NAME:
3247 case Dali::Actor::Property::SENSITIVE:
3249 value = IsSensitive();
3253 case Dali::Actor::Property::LEAVE_REQUIRED:
3255 value = GetLeaveRequired();
3259 case Dali::Actor::Property::INHERIT_ORIENTATION:
3261 value = IsOrientationInherited();
3265 case Dali::Actor::Property::INHERIT_SCALE:
3267 value = IsScaleInherited();
3271 case Dali::Actor::Property::COLOR_MODE:
3273 value = Scripting::GetColorMode( GetColorMode() );
3277 case Dali::Actor::Property::POSITION_INHERITANCE:
3279 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
3283 case Dali::Actor::Property::DRAW_MODE:
3285 value = Scripting::GetDrawMode( GetDrawMode() );
3289 case Dali::Actor::Property::SIZE_MODE:
3291 value = Scripting::GetLinearEnumerationName< SizeMode >( GetSizeMode(), SizeModeTable, SizeModeTableCount );
3295 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3297 value = GetSizeModeFactor();
3301 case Dali::Actor::Property::RELAYOUT_ENABLED:
3303 value = IsRelayoutEnabled();
3307 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3309 value = Scripting::GetLinearEnumerationName< ResizePolicy >( GetResizePolicy( WIDTH ), ResizePolicyTable, ResizePolicyTableCount );
3313 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3315 value = Scripting::GetLinearEnumerationName< ResizePolicy >( GetResizePolicy( HEIGHT ), ResizePolicyTable, ResizePolicyTableCount );
3319 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3321 value = Scripting::GetLinearEnumerationName< SizeScalePolicy >( GetSizeScalePolicy(), SizeScalePolicyTable, SizeScalePolicyTableCount );
3325 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3327 value = ( GetResizePolicy( WIDTH ) == DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( WIDTH ) == HEIGHT );
3331 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3333 value = ( GetResizePolicy( HEIGHT ) == DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( HEIGHT ) == WIDTH );
3337 case Dali::Actor::Property::PADDING:
3339 Vector2 widthPadding = GetPadding( WIDTH );
3340 Vector2 heightPadding = GetPadding( HEIGHT );
3341 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3345 case Dali::Actor::Property::MINIMUM_SIZE:
3347 value = Vector2( GetMinimumSize( WIDTH ), GetMinimumSize( HEIGHT ) );
3351 case Dali::Actor::Property::MAXIMUM_SIZE:
3353 value = Vector2( GetMaximumSize( WIDTH ), GetMaximumSize( HEIGHT ) );
3357 case Dali::Actor::Property::PREFERRED_SIZE:
3359 value = GetPreferredSize();
3365 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3373 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3378 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3380 // This method should only return an object connected to the scene-graph
3381 return OnStage() ? mNode : NULL;
3384 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3386 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3388 const PropertyBase* property( NULL );
3390 // This method should only return a property of an object connected to the scene-graph
3396 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3398 AnimatablePropertyMetadata* animatable = FindAnimatableProperty( index );
3399 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3400 property = animatable->GetSceneGraphProperty();
3402 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3404 CustomPropertyMetadata* custom = FindCustomProperty( index );
3405 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3407 property = custom->GetSceneGraphProperty();
3409 else if( NULL != mNode )
3413 case Dali::Actor::Property::SIZE:
3414 property = &mNode->mSize;
3417 case Dali::Actor::Property::SIZE_WIDTH:
3418 property = &mNode->mSize;
3421 case Dali::Actor::Property::SIZE_HEIGHT:
3422 property = &mNode->mSize;
3425 case Dali::Actor::Property::SIZE_DEPTH:
3426 property = &mNode->mSize;
3429 case Dali::Actor::Property::POSITION:
3430 property = &mNode->mPosition;
3433 case Dali::Actor::Property::POSITION_X:
3434 property = &mNode->mPosition;
3437 case Dali::Actor::Property::POSITION_Y:
3438 property = &mNode->mPosition;
3441 case Dali::Actor::Property::POSITION_Z:
3442 property = &mNode->mPosition;
3445 case Dali::Actor::Property::ORIENTATION:
3446 property = &mNode->mOrientation;
3449 case Dali::Actor::Property::SCALE:
3450 property = &mNode->mScale;
3453 case Dali::Actor::Property::SCALE_X:
3454 property = &mNode->mScale;
3457 case Dali::Actor::Property::SCALE_Y:
3458 property = &mNode->mScale;
3461 case Dali::Actor::Property::SCALE_Z:
3462 property = &mNode->mScale;
3465 case Dali::Actor::Property::VISIBLE:
3466 property = &mNode->mVisible;
3469 case Dali::Actor::Property::COLOR:
3470 property = &mNode->mColor;
3473 case Dali::Actor::Property::COLOR_RED:
3474 property = &mNode->mColor;
3477 case Dali::Actor::Property::COLOR_GREEN:
3478 property = &mNode->mColor;
3481 case Dali::Actor::Property::COLOR_BLUE:
3482 property = &mNode->mColor;
3485 case Dali::Actor::Property::COLOR_ALPHA:
3486 property = &mNode->mColor;
3497 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3499 const PropertyInputImpl* property( NULL );
3501 // This method should only return a property of an object connected to the scene-graph
3507 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3509 AnimatablePropertyMetadata* animatable = FindAnimatableProperty( index );
3510 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3511 property = animatable->GetSceneGraphProperty();
3513 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3515 CustomPropertyMetadata* custom = FindCustomProperty( index );
3516 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3517 property = custom->GetSceneGraphProperty();
3519 else if( NULL != mNode )
3523 case Dali::Actor::Property::PARENT_ORIGIN:
3524 property = &mNode->mParentOrigin;
3527 case Dali::Actor::Property::PARENT_ORIGIN_X:
3528 property = &mNode->mParentOrigin;
3531 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3532 property = &mNode->mParentOrigin;
3535 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3536 property = &mNode->mParentOrigin;
3539 case Dali::Actor::Property::ANCHOR_POINT:
3540 property = &mNode->mAnchorPoint;
3543 case Dali::Actor::Property::ANCHOR_POINT_X:
3544 property = &mNode->mAnchorPoint;
3547 case Dali::Actor::Property::ANCHOR_POINT_Y:
3548 property = &mNode->mAnchorPoint;
3551 case Dali::Actor::Property::ANCHOR_POINT_Z:
3552 property = &mNode->mAnchorPoint;
3555 case Dali::Actor::Property::SIZE:
3556 property = &mNode->mSize;
3559 case Dali::Actor::Property::SIZE_WIDTH:
3560 property = &mNode->mSize;
3563 case Dali::Actor::Property::SIZE_HEIGHT:
3564 property = &mNode->mSize;
3567 case Dali::Actor::Property::SIZE_DEPTH:
3568 property = &mNode->mSize;
3571 case Dali::Actor::Property::POSITION:
3572 property = &mNode->mPosition;
3575 case Dali::Actor::Property::POSITION_X:
3576 property = &mNode->mPosition;
3579 case Dali::Actor::Property::POSITION_Y:
3580 property = &mNode->mPosition;
3583 case Dali::Actor::Property::POSITION_Z:
3584 property = &mNode->mPosition;
3587 case Dali::Actor::Property::WORLD_POSITION:
3588 property = &mNode->mWorldPosition;
3591 case Dali::Actor::Property::WORLD_POSITION_X:
3592 property = &mNode->mWorldPosition;
3595 case Dali::Actor::Property::WORLD_POSITION_Y:
3596 property = &mNode->mWorldPosition;
3599 case Dali::Actor::Property::WORLD_POSITION_Z:
3600 property = &mNode->mWorldPosition;
3603 case Dali::Actor::Property::ORIENTATION:
3604 property = &mNode->mOrientation;
3607 case Dali::Actor::Property::WORLD_ORIENTATION:
3608 property = &mNode->mWorldOrientation;
3611 case Dali::Actor::Property::SCALE:
3612 property = &mNode->mScale;
3615 case Dali::Actor::Property::SCALE_X:
3616 property = &mNode->mScale;
3619 case Dali::Actor::Property::SCALE_Y:
3620 property = &mNode->mScale;
3623 case Dali::Actor::Property::SCALE_Z:
3624 property = &mNode->mScale;
3627 case Dali::Actor::Property::WORLD_SCALE:
3628 property = &mNode->mWorldScale;
3631 case Dali::Actor::Property::VISIBLE:
3632 property = &mNode->mVisible;
3635 case Dali::Actor::Property::COLOR:
3636 property = &mNode->mColor;
3639 case Dali::Actor::Property::COLOR_RED:
3640 property = &mNode->mColor;
3643 case Dali::Actor::Property::COLOR_GREEN:
3644 property = &mNode->mColor;
3647 case Dali::Actor::Property::COLOR_BLUE:
3648 property = &mNode->mColor;
3651 case Dali::Actor::Property::COLOR_ALPHA:
3652 property = &mNode->mColor;
3655 case Dali::Actor::Property::WORLD_COLOR:
3656 property = &mNode->mWorldColor;
3659 case Dali::Actor::Property::WORLD_MATRIX:
3660 property = &mNode->mWorldMatrix;
3671 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3673 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3677 case Dali::Actor::Property::PARENT_ORIGIN_X:
3678 case Dali::Actor::Property::ANCHOR_POINT_X:
3679 case Dali::Actor::Property::SIZE_WIDTH:
3680 case Dali::Actor::Property::POSITION_X:
3681 case Dali::Actor::Property::WORLD_POSITION_X:
3682 case Dali::Actor::Property::SCALE_X:
3683 case Dali::Actor::Property::COLOR_RED:
3689 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3690 case Dali::Actor::Property::ANCHOR_POINT_Y:
3691 case Dali::Actor::Property::SIZE_HEIGHT:
3692 case Dali::Actor::Property::POSITION_Y:
3693 case Dali::Actor::Property::WORLD_POSITION_Y:
3694 case Dali::Actor::Property::SCALE_Y:
3695 case Dali::Actor::Property::COLOR_GREEN:
3701 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3702 case Dali::Actor::Property::ANCHOR_POINT_Z:
3703 case Dali::Actor::Property::SIZE_DEPTH:
3704 case Dali::Actor::Property::POSITION_Z:
3705 case Dali::Actor::Property::WORLD_POSITION_Z:
3706 case Dali::Actor::Property::SCALE_Z:
3707 case Dali::Actor::Property::COLOR_BLUE:
3713 case Dali::Actor::Property::COLOR_ALPHA:
3726 return componentIndex;
3729 void Actor::SetParent( Actor* parent, int index )
3733 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3737 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3740 // Instruct each actor to create a corresponding node in the scene graph
3741 ConnectToStage( index );
3744 else // parent being set to NULL
3746 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3750 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3753 DALI_ASSERT_ALWAYS( mNode != NULL );
3757 // Disconnect the Node & its children from the scene-graph.
3758 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3761 // Instruct each actor to discard pointers to the scene-graph
3762 DisconnectFromStage();
3767 SceneGraph::Node* Actor::CreateNode() const
3772 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const std::vector< Property::Value >& attributes )
3775 Actor* actor = dynamic_cast< Actor* >( object );
3779 if( 0 == strcmp( actionName.c_str(), ACTION_SHOW ) ) // dont want to convert char* to string
3781 actor->SetVisible( true );
3784 else if( 0 == strcmp( actionName.c_str(), ACTION_HIDE ) )
3786 actor->SetVisible( false );
3794 void Actor::EnsureRelayoutData() const
3796 // Assign relayout data.
3797 if( !mRelayoutData )
3799 mRelayoutData = new RelayoutData();
3803 bool Actor::RelayoutDependentOnParent( Dimension dimension )
3805 // Check if actor is dependent on parent
3806 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
3808 if( ( dimension & ( 1 << i ) ) )
3810 const ResizePolicy resizePolicy = GetResizePolicy( static_cast< Dimension >( 1 << i ) );
3811 if( resizePolicy == FILL_TO_PARENT )
3821 bool Actor::RelayoutDependentOnChildren( Dimension dimension )
3823 // Check if actor is dependent on children
3824 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
3826 if( ( dimension & ( 1 << i ) ) )
3828 const ResizePolicy resizePolicy = GetResizePolicy( static_cast< Dimension >( 1 << i ) );
3829 switch( resizePolicy )
3831 case FIT_TO_CHILDREN:
3832 case USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3848 bool Actor::RelayoutDependentOnChildrenBase( Dimension dimension )
3850 return Actor::RelayoutDependentOnChildren( dimension );
3853 bool Actor::RelayoutDependentOnDimension( Dimension dimension, Dimension dependentDimension )
3855 // Check each possible dimension and see if it is dependent on the input one
3856 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
3858 if( dimension & ( 1 << i ) )
3860 return mRelayoutData->resizePolicies[ i ] == DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3867 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension dimension )
3869 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
3871 if( dimension & ( 1 << i ) )
3873 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3878 float Actor::GetNegotiatedDimension( Dimension dimension ) const
3880 // If more than one dimension is requested, just return the first one found
3881 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
3883 if( ( dimension & ( 1 << i ) ) )
3885 return mRelayoutData->negotiatedDimensions[ i ];
3889 return 0.0f; // Default
3892 void Actor::SetPadding( const Vector2& padding, Dimension dimension )
3894 EnsureRelayoutData();
3896 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
3898 if( dimension & ( 1 << i ) )
3900 mRelayoutData->dimensionPadding[ i ] = padding;
3905 Vector2 Actor::GetPadding( Dimension dimension ) const
3907 EnsureRelayoutData();
3909 // If more than one dimension is requested, just return the first one found
3910 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
3912 if( ( dimension & ( 1 << i ) ) )
3914 return mRelayoutData->dimensionPadding[ i ];
3918 return Vector2( 0.0f, 0.0f ); // Default
3921 void Actor::SetLayoutNegotiated( bool negotiated, Dimension dimension )
3923 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
3925 if( dimension & ( 1 << i ) )
3927 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3932 bool Actor::IsLayoutNegotiated( Dimension dimension ) const
3934 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
3936 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
3945 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension dimension )
3947 // Could be overridden in derived classes.
3948 return CalculateChildSizeBase( child, dimension );
3951 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension dimension )
3953 // Fill to parent, taking size mode factor into account
3954 switch( child.GetSizeMode() )
3958 return GetLatestSize( dimension );
3961 case SIZE_RELATIVE_TO_PARENT:
3963 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
3966 case SIZE_FIXED_OFFSET_FROM_PARENT:
3968 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
3973 return GetLatestSize( dimension );
3978 float Actor::GetHeightForWidth( float width )
3980 // Could be overridden in derived classes.
3981 float height = 0.0f;
3983 const Vector3 naturalSize = GetNaturalSize();
3984 if( naturalSize.width > 0.0f )
3986 height = naturalSize.height * width / naturalSize.width;
3992 float Actor::GetWidthForHeight( float height )
3994 // Could be overridden in derived classes.
3997 const Vector3 naturalSize = GetNaturalSize();
3998 if( naturalSize.height > 0.0f )
4000 width = naturalSize.width * height / naturalSize.height;
4006 float Actor::GetLatestSize( Dimension dimension ) const
4008 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4011 float Actor::GetRelayoutSize( Dimension dimension ) const
4013 Vector2 padding = GetPadding( dimension );
4015 return GetLatestSize( dimension ) + padding.x + padding.y;
4018 float Actor::NegotiateFromParent( Dimension dimension )
4020 Actor* parent = GetParent();
4023 Vector2 padding( GetPadding( dimension ) );
4024 Vector2 parentPadding( parent->GetPadding( dimension ) );
4025 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4031 float Actor::NegotiateFromChildren( Dimension dimension )
4033 float minDimensionPoint = 0.0f;
4034 float maxDimensionPoint = 0.0f;
4036 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4038 Dali::Actor child = GetChildAt( i );
4039 Actor& childImpl = GetImplementation( child );
4041 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4043 // Calculate the min and max points that the children range across
4044 float childPosition = GetDimensionValue( childImpl.GetCurrentPosition(), dimension );
4045 float dimensionSize = childImpl.GetRelayoutSize( dimension );
4046 minDimensionPoint = std::min( minDimensionPoint, childPosition - dimensionSize * 0.5f );
4047 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize * 0.5f );
4051 return maxDimensionPoint - minDimensionPoint;
4054 float Actor::GetSize( Dimension dimension ) const
4056 return GetDimensionValue( GetTargetSize(), dimension );
4059 float Actor::GetNaturalSize( Dimension dimension ) const
4061 return GetDimensionValue( GetNaturalSize(), dimension );
4064 float Actor::CalculateSize( Dimension dimension, const Vector2& maximumSize )
4066 switch( GetResizePolicy( dimension ) )
4068 case USE_NATURAL_SIZE:
4070 return GetNaturalSize( dimension );
4075 return GetDimensionValue( GetPreferredSize(), dimension );
4078 case USE_ASSIGNED_SIZE:
4080 return GetDimensionValue( maximumSize, dimension );
4083 case FILL_TO_PARENT:
4085 return NegotiateFromParent( dimension );
4088 case FIT_TO_CHILDREN:
4090 return NegotiateFromChildren( dimension );
4093 case DIMENSION_DEPENDENCY:
4095 const Dimension dimensionDependency = GetDimensionDependency( dimension );
4098 if( dimension == WIDTH && dimensionDependency == HEIGHT )
4100 return GetWidthForHeight( GetNegotiatedDimension( HEIGHT ) );
4103 if( dimension == HEIGHT && dimensionDependency == WIDTH )
4105 return GetHeightForWidth( GetNegotiatedDimension( WIDTH ) );
4117 return 0.0f; // Default
4120 float Actor::ConstrainDimension( float size, Dimension dimension )
4122 const float minSize = GetMinimumSize( dimension );
4123 const float maxSize = GetMaximumSize( dimension );
4125 return std::max( minSize, std::min( size, maxSize ) );
4128 void Actor::NegotiateDimension( Dimension dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4130 // Check if it needs to be negotiated
4131 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4133 // Check that we havn't gotten into an infinite loop
4134 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4135 bool recursionFound = false;
4136 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4138 if( *it == searchActor )
4140 recursionFound = true;
4145 if( !recursionFound )
4147 // Record the path that we have taken
4148 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4150 // Dimension dependency check
4151 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
4153 Dimension dimensionToCheck = static_cast< Dimension >( 1 << i );
4155 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4157 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4161 // Parent dependency check
4162 Actor* parent = GetParent();
4163 if( parent && RelayoutDependentOnParent( dimension ) )
4165 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4168 // Children dependency check
4169 if( RelayoutDependentOnChildren( dimension ) )
4171 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4173 Dali::Actor child = GetChildAt( i );
4174 Actor& childImpl = GetImplementation( child );
4176 // Only relayout child first if it is not dependent on this actor
4177 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4179 childImpl.NegotiateDimension( dimension, allocatedSize, recursionStack );
4184 // For deriving classes
4185 OnCalculateRelayoutSize( dimension );
4187 // All dependencies checked, calculate the size and set negotiated flag
4188 const float newSize = ConstrainDimension( CalculateSize( dimension, allocatedSize ), dimension );
4190 SetNegotiatedDimension( newSize, dimension );
4191 SetLayoutNegotiated( true, dimension );
4193 // For deriving classes
4194 OnLayoutNegotiated( newSize, dimension );
4196 // This actor has been successfully processed, pop it off the recursion stack
4197 recursionStack.pop_back();
4201 // TODO: Break infinite loop
4202 SetLayoutNegotiated( true, dimension );
4207 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4209 // Negotiate all dimensions that require it
4210 ActorDimensionStack recursionStack;
4212 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
4214 const Dimension dimension = static_cast< Dimension >( 1 << i );
4217 NegotiateDimension( dimension, allocatedSize, recursionStack );
4221 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4223 switch( mRelayoutData->sizeSetPolicy )
4230 case FIT_WITH_ASPECT_RATIO:
4232 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4233 const Vector3 naturalSize = GetNaturalSize();
4234 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4236 const float sizeRatio = size.width / size.height;
4237 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4239 if( naturalSizeRatio < sizeRatio )
4241 return Vector2( naturalSizeRatio * size.height, size.height );
4243 else if( naturalSizeRatio > sizeRatio )
4245 return Vector2( size.width, size.width / naturalSizeRatio );
4256 case FILL_WITH_ASPECT_RATIO:
4258 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4259 const Vector3 naturalSize = GetNaturalSize();
4260 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4262 const float sizeRatio = size.width / size.height;
4263 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4265 if( naturalSizeRatio < sizeRatio )
4267 return Vector2( size.width, size.width / naturalSizeRatio );
4269 else if( naturalSizeRatio > sizeRatio )
4271 return Vector2( naturalSizeRatio * size.height, size.height );
4289 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4291 // Do the set actor size
4292 Vector2 negotiatedSize( GetLatestSize( WIDTH ), GetLatestSize( HEIGHT ) );
4294 // Adjust for size set policy
4295 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4297 // Lock the flag to stop recursive relayouts on set size
4298 mRelayoutData->insideRelayout = true;
4299 SetSize( negotiatedSize );
4300 mRelayoutData->insideRelayout = false;
4302 // Clear flags for all dimensions
4303 SetLayoutDirty( false );
4305 // Give deriving classes a chance to respond
4306 OnRelayout( negotiatedSize, container );
4308 if( !mOnRelayoutSignal.Empty() )
4310 Dali::Actor handle( this );
4311 mOnRelayoutSignal.Emit( handle );
4315 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4317 // Do the negotiation
4318 NegotiateDimensions( allocatedSize );
4320 // Set the actor size
4321 SetNegotiatedSize( container );
4323 // Negotiate down to children
4324 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4326 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4328 Dali::Actor child = GetChildAt( i );
4330 // Only relayout if required
4331 if( GetImplementation( child ).RelayoutRequired() )
4333 container.Add( child, newBounds );
4338 void Actor::RelayoutRequest( Dimension dimension )
4340 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4341 if( relayoutController )
4343 Dali::Actor self( this );
4344 relayoutController->RequestRelayout( self, dimension );
4348 void Actor::RelayoutRequestTree()
4350 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4351 if( relayoutController )
4353 Dali::Actor self( this );
4354 relayoutController->RequestRelayoutTree( self );
4358 void Actor::PropagateRelayoutFlags()
4360 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4361 if( relayoutController )
4363 Dali::Actor self( this );
4364 relayoutController->PropagateFlags( self );
4368 void Actor::OnCalculateRelayoutSize( Dimension dimension )
4372 void Actor::OnLayoutNegotiated( float size, Dimension dimension )
4376 void Actor::SetPreferredSize( const Vector2& size )
4378 EnsureRelayoutData();
4380 mRelayoutData->preferredSize = size;
4385 Vector2 Actor::GetPreferredSize() const
4387 EnsureRelayoutData();
4389 return mRelayoutData->preferredSize;
4392 void Actor::SetMinimumSize( float size, Dimension dimension )
4394 EnsureRelayoutData();
4396 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
4398 if( dimension & ( 1 << i ) )
4400 mRelayoutData->minimumSize[ i ] = size;
4407 float Actor::GetMinimumSize( Dimension dimension ) const
4409 EnsureRelayoutData();
4411 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
4413 if( dimension & ( 1 << i ) )
4415 return mRelayoutData->minimumSize[ i ];
4419 return 0.0f; // Default
4422 void Actor::SetMaximumSize( float size, Dimension dimension )
4424 EnsureRelayoutData();
4426 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
4428 if( dimension & ( 1 << i ) )
4430 mRelayoutData->maximumSize[ i ] = size;
4437 float Actor::GetMaximumSize( Dimension dimension ) const
4439 EnsureRelayoutData();
4441 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
4443 if( dimension & ( 1 << i ) )
4445 return mRelayoutData->maximumSize[ i ];
4449 return 0.0f; // Default
4452 } // namespace Internal