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/common/type-info-impl.h>
44 #include <dali/internal/event/actor-attachments/actor-attachment-impl.h>
45 #include <dali/internal/event/animation/constraint-impl.h>
46 #include <dali/internal/event/common/projection.h>
47 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
48 #include <dali/internal/update/common/animatable-property.h>
49 #include <dali/internal/update/nodes/node-messages.h>
50 #include <dali/internal/update/nodes/node-declarations.h>
51 #include <dali/internal/update/animation/scene-graph-constraint.h>
52 #include <dali/internal/event/events/actor-gesture-data.h>
53 #include <dali/internal/common/message.h>
54 #include <dali/integration-api/debug.h>
56 #ifdef DYNAMICS_SUPPORT
57 #include <dali/internal/event/dynamics/dynamics-body-config-impl.h>
58 #include <dali/internal/event/dynamics/dynamics-body-impl.h>
59 #include <dali/internal/event/dynamics/dynamics-joint-impl.h>
60 #include <dali/internal/event/dynamics/dynamics-world-impl.h>
63 using Dali::Internal::SceneGraph::Node;
64 using Dali::Internal::SceneGraph::AnimatableProperty;
65 using Dali::Internal::SceneGraph::PropertyBase;
73 unsigned int Actor::mActorCounter = 0;
74 ActorContainer Actor::mNullChildren;
77 * Struct to collect relayout variables
79 struct Actor::RelayoutData
82 : sizeModeFactor( Vector3::ONE ), preferredSize( Vector2::ZERO ), sizeSetPolicy( USE_SIZE_SET ), relayoutEnabled( false ), insideRelayout( false )
84 // Set size negotiation defaults
85 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
87 resizePolicies[ i ] = FIXED;
88 negotiatedDimensions[ i ] = 0.0f;
89 dimensionNegotiated[ i ] = false;
90 dimensionDirty[ i ] = false;
91 dimensionDependencies[ i ] = ALL_DIMENSIONS;
92 dimensionPadding[ i ] = Vector2( 0.0f, 0.0f );
93 minimumSize[ i ] = 0.0f;
94 maximumSize[ i ] = FLT_MAX;
98 ResizePolicy resizePolicies[ DIMENSION_COUNT ]; ///< Resize policies
100 Dimension dimensionDependencies[ DIMENSION_COUNT ]; ///< A list of dimension dependencies
102 Vector2 dimensionPadding[ DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
104 float negotiatedDimensions[ DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
106 float minimumSize[ DIMENSION_COUNT ]; ///< The minimum size an actor can be
107 float maximumSize[ DIMENSION_COUNT ]; ///< The maximum size an actor can be
109 bool dimensionNegotiated[ DIMENSION_COUNT ]; ///< Has the dimension been negotiated
110 bool dimensionDirty[ DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
112 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
114 Vector2 preferredSize; ///< The preferred size of the actor
116 SizeScalePolicy sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
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-factor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
199 DALI_PROPERTY( "relayout-enabled", BOOLEAN, true, false, false, Dali::Actor::Property::RELAYOUT_ENABLED )
200 DALI_PROPERTY( "width-resize-policy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
201 DALI_PROPERTY( "height-resize-policy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
202 DALI_PROPERTY( "size-scale-policy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
203 DALI_PROPERTY( "width-for-height", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
204 DALI_PROPERTY( "height-for-width", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
205 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
206 DALI_PROPERTY( "minimum-size", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
207 DALI_PROPERTY( "maximum-size", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
208 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
212 const char* const SIGNAL_TOUCHED = "touched";
213 const char* const SIGNAL_HOVERED = "hovered";
214 const char* const SIGNAL_MOUSE_WHEEL_EVENT = "mouse-wheel-event";
215 const char* const SIGNAL_ON_STAGE = "on-stage";
216 const char* const SIGNAL_OFF_STAGE = "off-stage";
220 const char* const ACTION_SHOW = "show";
221 const char* const ACTION_HIDE = "hide";
223 // Enumeration to / from string conversion tables
225 DALI_ENUM_TO_STRING_TABLE_BEGIN( ResizePolicy )DALI_ENUM_TO_STRING( FIXED )
226 DALI_ENUM_TO_STRING( USE_NATURAL_SIZE )
227 DALI_ENUM_TO_STRING( FILL_TO_PARENT )
228 DALI_ENUM_TO_STRING( SIZE_RELATIVE_TO_PARENT )
229 DALI_ENUM_TO_STRING( SIZE_FIXED_OFFSET_FROM_PARENT )
230 DALI_ENUM_TO_STRING( FIT_TO_CHILDREN )
231 DALI_ENUM_TO_STRING( DIMENSION_DEPENDENCY )
232 DALI_ENUM_TO_STRING( USE_ASSIGNED_SIZE )
233 DALI_ENUM_TO_STRING_TABLE_END( ResizePolicy )
235 DALI_ENUM_TO_STRING_TABLE_BEGIN( SizeScalePolicy )DALI_ENUM_TO_STRING( USE_SIZE_SET )
236 DALI_ENUM_TO_STRING( FIT_WITH_ASPECT_RATIO )
237 DALI_ENUM_TO_STRING( FILL_WITH_ASPECT_RATIO )
238 DALI_ENUM_TO_STRING_TABLE_END( SizeScalePolicy )
240 BaseHandle CreateActor()
242 return Dali::Actor::New();
245 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
247 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
248 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
249 SignalConnectorType signalConnector3( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
250 SignalConnectorType signalConnector4( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
252 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
253 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
256 * @brief Extract a given dimension from a Vector2
258 * @param[in] values The values to extract from
259 * @param[in] dimension The dimension to extract
260 * @return Return the value for the dimension
262 float GetDimensionValue( const Vector2& values, Dimension dimension )
273 return values.height;
286 * @brief Extract a given dimension from a Vector3
288 * @param[in] values The values to extract from
289 * @param[in] dimension The dimension to extract
290 * @return Return the value for the dimension
292 float GetDimensionValue( const Vector3& values, Dimension dimension )
294 return GetDimensionValue( values.GetVectorXY(), dimension );
297 } // unnamed namespace
299 ActorPtr Actor::New()
301 ActorPtr actor( new Actor( BASIC ) );
303 // Second-phase construction
309 const std::string& Actor::GetName() const
314 void Actor::SetName( const std::string& name )
320 // ATTENTION: string for debug purposes is not thread safe.
321 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
325 unsigned int Actor::GetId() const
330 void Actor::Attach( ActorAttachment& attachment )
332 DALI_ASSERT_DEBUG( !mAttachment && "An Actor can only have one attachment" );
336 attachment.Connect();
339 mAttachment = ActorAttachmentPtr( &attachment );
342 ActorAttachmentPtr Actor::GetAttachment()
347 bool Actor::OnStage() const
352 Dali::Layer Actor::GetLayer()
356 // Short-circuit for Layer derived actors
359 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
362 // Find the immediate Layer parent
363 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
365 if( parent->IsLayer() )
367 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
374 void Actor::Add( Actor& child )
376 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
377 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
381 mChildren = new ActorContainer;
384 Actor* const oldParent( child.mParent );
386 // child might already be ours
387 if( this != oldParent )
389 // if we already have parent, unparent us first
392 oldParent->Remove( child ); // This causes OnChildRemove callback
394 // Old parent may need to readjust to missing child
395 if( oldParent->RelayoutDependentOnChildren() )
397 oldParent->RelayoutRequest();
401 // Guard against Add() during previous OnChildRemove callback
404 // Do this first, since user callbacks from within SetParent() may need to remove child
405 mChildren->push_back( Dali::Actor( &child ) );
407 // SetParent asserts that child can be added
408 child.SetParent( this );
410 // Notification for derived classes
413 // Only put in a relayout request if there is a suitable dependency
414 if( RelayoutDependentOnChildren() )
419 if( child.RelayoutDependentOnParent() )
421 child.RelayoutRequest();
427 void Actor::Insert( unsigned int index, Actor& child )
429 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
430 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
434 mChildren = new ActorContainer;
437 Actor* const oldParent( child.mParent );
439 // since an explicit position has been given, always insert, even if already a child
442 oldParent->Remove( child ); // This causes OnChildRemove callback
444 // Old parent may need to readjust to missing child
445 if( oldParent->RelayoutDependentOnChildren() )
447 oldParent->RelayoutRequest();
451 // Guard against Add() during previous OnChildRemove callback
454 // Do this first, since user callbacks from within SetParent() may need to remove child
455 if( index < GetChildCount() )
457 ActorIter it = mChildren->begin();
458 std::advance( it, index );
459 mChildren->insert( it, Dali::Actor( &child ) );
463 mChildren->push_back( Dali::Actor( &child ) );
465 // SetParent asserts that child can be added
466 child.SetParent( this, index );
468 // Notification for derived classes
471 // Only put in a relayout request if there is a suitable dependency
472 if( RelayoutDependentOnChildren() )
477 if( child.RelayoutDependentOnParent() )
479 child.RelayoutRequest();
484 void Actor::Remove( Actor& child )
486 DALI_ASSERT_ALWAYS( this != &child && "Cannot remove actor from itself" );
496 // Find the child in mChildren, and unparent it
497 ActorIter end = mChildren->end();
498 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
500 Actor& actor = GetImplementation( *iter );
502 if( &actor == &child )
504 // Keep handle for OnChildRemove notification
505 removed = Dali::Actor( &actor );
507 // Do this first, since user callbacks from within SetParent() may need to add the child
508 mChildren->erase( iter );
510 DALI_ASSERT_DEBUG( actor.GetParent() == this );
511 actor.SetParent( NULL );
519 // Notification for derived classes
520 OnChildRemove( GetImplementation( removed ) );
522 // Only put in a relayout request if there is a suitable dependency
523 if( RelayoutDependentOnChildren() )
530 void Actor::Unparent()
534 // Remove this actor from the parent. The remove will put a relayout request in for
535 // the parent if required
536 mParent->Remove( *this );
537 // mParent is now NULL!
541 unsigned int Actor::GetChildCount() const
543 return ( NULL != mChildren ) ? mChildren->size() : 0;
546 Dali::Actor Actor::GetChildAt( unsigned int index ) const
548 DALI_ASSERT_ALWAYS( index < GetChildCount() );
550 return ( ( mChildren ) ? ( *mChildren )[ index ] : Dali::Actor() );
553 ActorContainer Actor::GetChildren()
555 if( NULL != mChildren )
560 // return copy of mNullChildren
561 return mNullChildren;
564 const ActorContainer& Actor::GetChildren() const
566 if( NULL != mChildren )
571 // return const reference to mNullChildren
572 return mNullChildren;
575 ActorPtr Actor::FindChildByName( const std::string& actorName )
578 if( actorName == mName )
584 ActorIter end = mChildren->end();
585 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
587 child = GetImplementation( *iter ).FindChildByName( actorName );
598 ActorPtr Actor::FindChildById( const unsigned int id )
607 ActorIter end = mChildren->end();
608 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
610 child = GetImplementation( *iter ).FindChildById( id );
621 void Actor::SetParentOrigin( const Vector3& origin )
625 // mNode is being used in a separate thread; queue a message to set the value & base value
626 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
629 // Cache for event-thread access
632 // not allocated, check if different from default
633 if( ParentOrigin::DEFAULT != origin )
635 mParentOrigin = new Vector3( origin );
640 // check if different from current costs more than just set
641 *mParentOrigin = origin;
645 void Actor::SetParentOriginX( float x )
647 const Vector3& current = GetCurrentParentOrigin();
649 SetParentOrigin( Vector3( x, current.y, current.z ) );
652 void Actor::SetParentOriginY( float y )
654 const Vector3& current = GetCurrentParentOrigin();
656 SetParentOrigin( Vector3( current.x, y, current.z ) );
659 void Actor::SetParentOriginZ( float z )
661 const Vector3& current = GetCurrentParentOrigin();
663 SetParentOrigin( Vector3( current.x, current.y, z ) );
666 const Vector3& Actor::GetCurrentParentOrigin() const
668 // Cached for event-thread access
669 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
672 void Actor::SetAnchorPoint( const Vector3& anchor )
676 // mNode is being used in a separate thread; queue a message to set the value & base value
677 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
680 // Cache for event-thread access
683 // not allocated, check if different from default
684 if( AnchorPoint::DEFAULT != anchor )
686 mAnchorPoint = new Vector3( anchor );
691 // check if different from current costs more than just set
692 *mAnchorPoint = anchor;
696 void Actor::SetAnchorPointX( float x )
698 const Vector3& current = GetCurrentAnchorPoint();
700 SetAnchorPoint( Vector3( x, current.y, current.z ) );
703 void Actor::SetAnchorPointY( float y )
705 const Vector3& current = GetCurrentAnchorPoint();
707 SetAnchorPoint( Vector3( current.x, y, current.z ) );
710 void Actor::SetAnchorPointZ( float z )
712 const Vector3& current = GetCurrentAnchorPoint();
714 SetAnchorPoint( Vector3( current.x, current.y, z ) );
717 const Vector3& Actor::GetCurrentAnchorPoint() const
719 // Cached for event-thread access
720 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
723 void Actor::SetPosition( float x, float y )
725 SetPosition( Vector3( x, y, 0.0f ) );
728 void Actor::SetPosition( float x, float y, float z )
730 SetPosition( Vector3( x, y, z ) );
733 void Actor::SetPosition( const Vector3& position )
737 // mNode is being used in a separate thread; queue a message to set the value & base value
738 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::Bake, position );
742 void Actor::SetX( float x )
746 // mNode is being used in a separate thread; queue a message to set the value & base value
747 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeX, x );
751 void Actor::SetY( float y )
755 // mNode is being used in a separate thread; queue a message to set the value & base value
756 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeY, y );
760 void Actor::SetZ( float z )
764 // mNode is being used in a separate thread; queue a message to set the value & base value
765 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeZ, z );
769 void Actor::TranslateBy( const Vector3& distance )
773 // mNode is being used in a separate thread; queue a message to set the value & base value
774 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeRelative, distance );
778 const Vector3& Actor::GetCurrentPosition() const
782 // mNode is being used in a separate thread; copy the value from the previous update
783 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
786 return Vector3::ZERO;
789 const Vector3& Actor::GetCurrentWorldPosition() const
793 // mNode is being used in a separate thread; copy the value from the previous update
794 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
797 return Vector3::ZERO;
800 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
802 // this flag is not animatable so keep the value
803 mPositionInheritanceMode = mode;
806 // mNode is being used in a separate thread; queue a message to set the value
807 SetPositionInheritanceModeMessage( GetEventThreadServices(), *mNode, mode );
811 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
813 // Cached for event-thread access
814 return mPositionInheritanceMode;
817 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
819 Vector4 normalizedAxis( axis.x, axis.y, axis.z, 0.0f );
820 normalizedAxis.Normalize();
822 Quaternion orientation( Quaternion::FromAxisAngle( normalizedAxis, angle ) );
824 SetOrientation( orientation );
827 void Actor::SetOrientation( const Quaternion& orientation )
831 // mNode is being used in a separate thread; queue a message to set the value & base value
832 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::Bake, orientation );
836 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
840 // mNode is being used in a separate thread; queue a message to set the value & base value
841 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, Quaternion(angle, axis) );
845 void Actor::RotateBy( const Quaternion& relativeRotation )
849 // mNode is being used in a separate thread; queue a message to set the value & base value
850 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, relativeRotation );
854 const Quaternion& Actor::GetCurrentOrientation() const
858 // mNode is being used in a separate thread; copy the value from the previous update
859 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
862 return Quaternion::IDENTITY;
865 const Quaternion& Actor::GetCurrentWorldOrientation() const
869 // mNode is being used in a separate thread; copy the value from the previous update
870 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
873 return Quaternion::IDENTITY;
876 void Actor::SetScale( float scale )
878 SetScale( Vector3( scale, scale, scale ) );
881 void Actor::SetScale( float x, float y, float z )
883 SetScale( Vector3( x, y, z ) );
886 void Actor::SetScale( const Vector3& scale )
890 // mNode is being used in a separate thread; queue a message to set the value & base value
891 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::Bake, scale );
895 void Actor::SetScaleX( float x )
899 // mNode is being used in a separate thread; queue a message to set the value & base value
900 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeX, x );
904 void Actor::SetScaleY( float y )
908 // mNode is being used in a separate thread; queue a message to set the value & base value
909 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeY, y );
913 void Actor::SetScaleZ( float z )
917 // mNode is being used in a separate thread; queue a message to set the value & base value
918 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeZ, z );
922 void Actor::SetInitialVolume( const Vector3& volume )
926 // mNode is being used in a separate thread; queue a message to set the value
927 SetInitialVolumeMessage( GetEventThreadServices(), *mNode, volume );
931 void Actor::SetTransmitGeometryScaling( bool transmitGeometryScaling )
935 // mNode is being used in a separate thread; queue a message to set the value
936 SetTransmitGeometryScalingMessage( GetEventThreadServices(), *mNode, transmitGeometryScaling );
940 bool Actor::GetTransmitGeometryScaling() const
944 // mNode is being used in a separate thread; copy the value from the previous update
945 return mNode->GetTransmitGeometryScaling();
951 void Actor::ScaleBy( const Vector3& relativeScale )
955 // mNode is being used in a separate thread; queue a message to set the value & base value
956 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeRelativeMultiply, relativeScale );
960 const Vector3& Actor::GetCurrentScale() const
964 // mNode is being used in a separate thread; copy the value from the previous update
965 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
971 const Vector3& Actor::GetCurrentWorldScale() const
975 // mNode is being used in a separate thread; copy the value from the previous update
976 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
982 void Actor::SetInheritScale( bool inherit )
984 // non animateable so keep local copy
985 mInheritScale = inherit;
988 // mNode is being used in a separate thread; queue a message to set the value
989 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
993 bool Actor::IsScaleInherited() const
995 return mInheritScale;
998 Matrix Actor::GetCurrentWorldMatrix() const
1002 // World matrix is no longer updated unless there is something observing the node.
1003 // Need to calculate it from node's world position, orientation and scale:
1004 BufferIndex updateBufferIndex = GetEventThreadServices().GetEventBufferIndex();
1005 Matrix worldMatrix(false);
1006 worldMatrix.SetTransformComponents( mNode->GetWorldScale( updateBufferIndex ),
1007 mNode->GetWorldOrientation( updateBufferIndex ),
1008 mNode->GetWorldPosition( updateBufferIndex ) );
1012 return Matrix::IDENTITY;
1015 void Actor::SetVisible( bool visible )
1019 // mNode is being used in a separate thread; queue a message to set the value & base value
1020 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
1024 bool Actor::IsVisible() const
1028 // mNode is being used in a separate thread; copy the value from the previous update
1029 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
1035 void Actor::SetOpacity( float opacity )
1039 // mNode is being used in a separate thread; queue a message to set the value & base value
1040 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
1044 float Actor::GetCurrentOpacity() const
1048 // mNode is being used in a separate thread; copy the value from the previous update
1049 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1055 const Vector4& Actor::GetCurrentWorldColor() const
1059 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1062 return Color::WHITE;
1065 void Actor::SetColor( const Vector4& color )
1069 // mNode is being used in a separate thread; queue a message to set the value & base value
1070 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1074 void Actor::SetColorRed( float red )
1078 // mNode is being used in a separate thread; queue a message to set the value & base value
1079 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1083 void Actor::SetColorGreen( float green )
1087 // mNode is being used in a separate thread; queue a message to set the value & base value
1088 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1092 void Actor::SetColorBlue( float blue )
1096 // mNode is being used in a separate thread; queue a message to set the value & base value
1097 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1101 const Vector4& Actor::GetCurrentColor() const
1105 // mNode is being used in a separate thread; copy the value from the previous update
1106 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1109 return Color::WHITE;
1112 void Actor::SetInheritOrientation( bool inherit )
1114 // non animateable so keep local copy
1115 mInheritOrientation = inherit;
1118 // mNode is being used in a separate thread; queue a message to set the value
1119 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1123 bool Actor::IsOrientationInherited() const
1125 return mInheritOrientation;
1128 void Actor::SetSizeModeFactor( const Vector3& factor )
1130 EnsureRelayoutData();
1132 mRelayoutData->sizeModeFactor = factor;
1135 const Vector3& Actor::GetSizeModeFactor() const
1137 EnsureRelayoutData();
1139 return mRelayoutData->sizeModeFactor;
1142 void Actor::SetColorMode( ColorMode colorMode )
1144 // non animateable so keep local copy
1145 mColorMode = colorMode;
1148 // mNode is being used in a separate thread; queue a message to set the value
1149 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1153 ColorMode Actor::GetColorMode() const
1155 // we have cached copy
1159 void Actor::SetSize( float width, float height )
1161 SetSize( Vector2( width, height ) );
1164 void Actor::SetSize( float width, float height, float depth )
1166 SetSize( Vector3( width, height, depth ) );
1169 void Actor::SetSize( const Vector2& size )
1171 SetSize( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1174 float Actor::CalculateSizeZ( const Vector2& size ) const
1176 return std::min( size.width, size.height );
1179 void Actor::SetSize( const Vector3& size )
1185 // mNode is being used in a separate thread; queue a message to set the value & base value
1186 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::Bake, mTargetSize );
1188 // Notification for derived classes
1189 OnSizeSet( mTargetSize );
1191 // Raise a relayout request if the flag is not locked
1192 if( mRelayoutData && !mRelayoutData->insideRelayout )
1199 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1201 mTargetSize = targetSize;
1203 // Notify deriving classes
1204 OnSizeAnimation( animation, targetSize );
1207 void Actor::SetWidth( float width )
1211 // mNode is being used in a separate thread; queue a message to set the value & base value
1212 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeX, width );
1216 void Actor::SetHeight( float height )
1220 // mNode is being used in a separate thread; queue a message to set the value & base value
1221 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeY, height );
1225 void Actor::SetDepth( float depth )
1229 // mNode is being used in a separate thread; queue a message to set the value & base value
1230 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeZ, depth );
1234 const Vector3& Actor::GetTargetSize() const
1239 const Vector3& Actor::GetCurrentSize() const
1243 // mNode is being used in a separate thread; copy the value from the previous update
1244 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1247 return Vector3::ZERO;
1250 Vector3 Actor::GetNaturalSize() const
1252 // It is up to deriving classes to return the appropriate natural size
1253 return Vector3( 0.0f, 0.0f, 0.0f );
1256 void Actor::SetResizePolicy( ResizePolicy policy, Dimension dimension )
1258 EnsureRelayoutData();
1260 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
1262 if( dimension & ( 1 << i ) )
1264 mRelayoutData->resizePolicies[ i ] = policy;
1268 if( policy == DIMENSION_DEPENDENCY )
1270 if( dimension & WIDTH )
1272 SetDimensionDependency( WIDTH, HEIGHT );
1275 if( dimension & HEIGHT )
1277 SetDimensionDependency( HEIGHT, WIDTH );
1281 OnSetResizePolicy( policy, dimension );
1283 // Trigger relayout on this control
1287 ResizePolicy Actor::GetResizePolicy( Dimension dimension ) const
1289 EnsureRelayoutData();
1291 // If more than one dimension is requested, just return the first one found
1292 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
1294 if( ( dimension & ( 1 << i ) ) )
1296 return mRelayoutData->resizePolicies[ i ];
1300 return FIXED; // Default
1303 void Actor::SetSizeScalePolicy( SizeScalePolicy policy )
1305 EnsureRelayoutData();
1307 mRelayoutData->sizeSetPolicy = policy;
1310 SizeScalePolicy Actor::GetSizeScalePolicy() const
1312 EnsureRelayoutData();
1314 return mRelayoutData->sizeSetPolicy;
1317 void Actor::SetDimensionDependency( Dimension dimension, Dimension dependency )
1319 EnsureRelayoutData();
1321 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
1323 if( dimension & ( 1 << i ) )
1325 mRelayoutData->dimensionDependencies[ i ] = dependency;
1330 Dimension Actor::GetDimensionDependency( Dimension dimension ) const
1332 EnsureRelayoutData();
1334 // If more than one dimension is requested, just return the first one found
1335 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
1337 if( ( dimension & ( 1 << i ) ) )
1339 return mRelayoutData->dimensionDependencies[ i ];
1343 return ALL_DIMENSIONS; // Default
1346 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1348 // If relayout data has not been allocated yet and the client is requesting
1349 // to disable it, do nothing
1350 if( mRelayoutData || relayoutEnabled )
1352 EnsureRelayoutData();
1354 mRelayoutData->relayoutEnabled = relayoutEnabled;
1358 bool Actor::IsRelayoutEnabled() const
1360 // Assume that if relayout data has not been allocated yet then
1361 // relayout is disabled
1362 return mRelayoutData && mRelayoutData->relayoutEnabled;
1365 void Actor::SetLayoutDirty( bool dirty, Dimension dimension )
1367 EnsureRelayoutData();
1369 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
1371 if( dimension & ( 1 << i ) )
1373 mRelayoutData->dimensionDirty[ i ] = dirty;
1378 bool Actor::IsLayoutDirty( Dimension dimension ) const
1380 EnsureRelayoutData();
1382 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
1384 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1393 bool Actor::RelayoutPossible( Dimension dimension ) const
1395 EnsureRelayoutData();
1397 return mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1400 bool Actor::RelayoutRequired( Dimension dimension ) const
1402 EnsureRelayoutData();
1404 return mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1407 #ifdef DYNAMICS_SUPPORT
1409 //--------------- Dynamics ---------------
1411 void Actor::DisableDynamics()
1413 if( NULL != mDynamicsData )
1415 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1417 // ensure dynamics object are disconnected from scene
1418 DisconnectDynamics();
1420 // delete joint owned by this actor
1421 while( !mDynamicsData->joints.empty() )
1423 RemoveDynamicsJoint( mDynamicsData->joints.begin()->second );
1426 // delete other joints referencing this actor
1427 while( !mDynamicsData->referencedJoints.empty() )
1429 DynamicsJointPtr joint( *(mDynamicsData->referencedJoints.begin()) );
1430 ActorPtr jointOwner( joint->GetActor( true ) );
1433 jointOwner->RemoveDynamicsJoint( joint );
1437 mDynamicsData->referencedJoints.erase( mDynamicsData->referencedJoints.begin() );
1440 // delete the DynamicsBody object
1441 mDynamicsData->body.Reset();
1443 // Discard Dynamics data structure
1444 delete mDynamicsData;
1445 mDynamicsData = NULL;
1449 DynamicsBodyPtr Actor::GetDynamicsBody() const
1451 DynamicsBodyPtr body;
1453 if( NULL != mDynamicsData )
1455 body = mDynamicsData->body;
1461 DynamicsBodyPtr Actor::EnableDynamics(DynamicsBodyConfigPtr bodyConfig)
1463 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s- (\"%s\")\n", __PRETTY_FUNCTION__, mName.c_str());
1465 if( NULL == mDynamicsData )
1467 mDynamicsData = new DynamicsData( this );
1470 if( !mDynamicsData->body )
1472 mDynamicsData->body = new DynamicsBody(mName, bodyConfig, *this, *(const_cast<SceneGraph::Node*>(mNode)) );
1476 DynamicsWorldPtr world( DynamicsWorld::Get() );
1479 if( mParent == world->GetRootActor().Get() )
1481 mDynamicsData->body->Connect( GetEventThreadServices() );
1487 return mDynamicsData->body;
1490 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offset )
1492 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1493 return AddDynamicsJoint( attachedActor, offset, ( GetCurrentPosition() + offset ) - attachedActor->GetCurrentPosition() );
1496 DynamicsJointPtr Actor::AddDynamicsJoint( ActorPtr attachedActor, const Vector3& offsetA, const Vector3& offsetB )
1498 DALI_ASSERT_ALWAYS( attachedActor && "'attachedActor' must be initialized!" );
1499 DALI_ASSERT_ALWAYS( this != attachedActor.Get() && "Cannot create a joint to oneself!" );
1501 DynamicsJointPtr joint;
1503 DynamicsWorldPtr world( DynamicsWorld::Get() );
1507 if( NULL != mDynamicsData )
1509 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1511 if( mDynamicsData->joints.end() != it )
1513 // use existing joint
1519 DynamicsBodyPtr bodyA( GetDynamicsBody() );
1520 DynamicsBodyPtr bodyB( attachedActor->GetDynamicsBody() );
1524 bodyA = EnableDynamics( new DynamicsBodyConfig );
1529 bodyB = attachedActor->EnableDynamics( new DynamicsBodyConfig );
1532 joint = new DynamicsJoint(world, bodyA, bodyB, offsetA, offsetB);
1533 mDynamicsData->joints[ attachedActor.Get() ] = joint;
1535 if( OnStage() && attachedActor->OnStage() )
1537 joint->Connect( GetEventThreadServices() );
1540 attachedActor->ReferenceJoint( joint );
1542 attachedActor->OnStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1543 attachedActor->OffStageSignal().Connect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1550 const int Actor::GetNumberOfJoints() const
1552 return static_cast<int>( NULL != mDynamicsData ? mDynamicsData->joints.size() : 0 );
1555 DynamicsJointPtr Actor::GetDynamicsJointByIndex( const int index ) const
1557 DynamicsJointPtr joint;
1559 if( NULL != mDynamicsData )
1561 if( index >= 0 && index < static_cast<int>(mDynamicsData->joints.size()) )
1563 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.begin() );
1565 for( int i = 0; i < index; ++i )
1577 DynamicsJointPtr Actor::GetDynamicsJoint( ActorPtr attachedActor ) const
1579 DynamicsJointPtr joint;
1581 if( NULL != mDynamicsData )
1583 DynamicsData::JointContainer::const_iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1585 if( mDynamicsData->joints.end() != it )
1587 // use existing joint
1595 void Actor::RemoveDynamicsJoint( DynamicsJointPtr joint )
1597 if( NULL != mDynamicsData )
1599 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1600 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1602 for(; it != endIt; ++it )
1604 if( it->second == joint.Get() )
1606 ActorPtr attachedActor( it->first );
1608 if( OnStage() && attachedActor && attachedActor->OnStage() )
1610 joint->Disconnect( GetEventThreadServices() );
1615 attachedActor->ReleaseJoint( joint );
1616 attachedActor->OnStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOnStage );
1617 attachedActor->OffStageSignal().Disconnect( mDynamicsData->slotDelegate, &Actor::AttachedActorOffStage );
1620 mDynamicsData->joints.erase(it);
1627 void Actor::ReferenceJoint( DynamicsJointPtr joint )
1629 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1631 if( NULL != mDynamicsData )
1633 mDynamicsData->referencedJoints.push_back(joint);
1637 void Actor::ReleaseJoint( DynamicsJointPtr joint )
1639 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1641 if( NULL != mDynamicsData )
1643 DynamicsData::ReferencedJointContainer::iterator it( std::find( mDynamicsData->referencedJoints.begin(), mDynamicsData->referencedJoints.end(), joint ) );
1645 if( it != mDynamicsData->referencedJoints.end() )
1647 mDynamicsData->referencedJoints.erase( it );
1652 void Actor::SetDynamicsRoot(bool flag)
1654 if( mIsDynamicsRoot != flag )
1656 mIsDynamicsRoot = flag;
1658 if( OnStage() && mChildren )
1660 // walk the children connecting or disconnecting any dynamics enabled child from the dynamics simulation
1661 ActorIter end = mChildren->end();
1662 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
1664 Actor& child = GetImplementation(*iter);
1666 if( child.GetDynamicsBody() )
1668 if( mIsDynamicsRoot )
1670 child.ConnectDynamics();
1674 child.DisconnectDynamics();
1682 bool Actor::IsDynamicsRoot() const
1684 return mIsDynamicsRoot;
1687 void Actor::AttachedActorOnStage( Dali::Actor actor )
1689 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1693 ActorPtr attachedActor( &GetImplementation(actor) );
1695 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1696 if( NULL != mDynamicsData )
1698 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1699 if( mDynamicsData->joints.end() != it )
1701 DynamicsJointPtr joint( it->second );
1702 joint->Connect( GetEventThreadServices() );
1708 void Actor::AttachedActorOffStage( Dali::Actor actor )
1710 DALI_LOG_INFO(Debug::Filter::gDynamics, Debug::Verbose, "%s\n", __PRETTY_FUNCTION__);
1714 ActorPtr attachedActor( &GetImplementation(actor) );
1716 DALI_ASSERT_DEBUG( NULL != mDynamicsData && "Dynamics not enabled on this actor!" );
1717 if( NULL != mDynamicsData )
1719 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.find( attachedActor.Get() ) );
1720 if( mDynamicsData->joints.end() != it )
1722 DynamicsJointPtr joint( it->second );
1723 joint->Disconnect( GetEventThreadServices() );
1729 void Actor::ConnectDynamics()
1731 if( NULL != mDynamicsData && mDynamicsData->body )
1733 if( OnStage() && mParent && mParent->IsDynamicsRoot() )
1735 mDynamicsData->body->Connect( GetEventThreadServices() );
1737 // Connect all joints where attachedActor is also on stage
1738 if( !mDynamicsData->joints.empty() )
1740 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1741 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1743 for(; it != endIt; ++it )
1745 Actor* attachedActor( it->first );
1746 if( NULL != attachedActor && attachedActor->OnStage() )
1748 DynamicsJointPtr joint( it->second );
1750 joint->Connect( GetEventThreadServices() );
1758 void Actor::DisconnectDynamics()
1760 if( NULL != mDynamicsData && mDynamicsData->body )
1764 mDynamicsData->body->Disconnect( GetEventThreadServices() );
1766 // Disconnect all joints
1767 if( !mDynamicsData->joints.empty() )
1769 DynamicsData::JointContainer::iterator it( mDynamicsData->joints.begin() );
1770 DynamicsData::JointContainer::iterator endIt( mDynamicsData->joints.end() );
1772 for(; it != endIt; ++it )
1774 DynamicsJointPtr joint( it->second );
1776 joint->Disconnect( GetEventThreadServices() );
1783 #endif // DYNAMICS_SUPPORT
1785 void Actor::SetOverlay( bool enable )
1787 // Setting STENCIL will override OVERLAY
1788 if( DrawMode::STENCIL != mDrawMode )
1790 SetDrawMode( enable ? DrawMode::OVERLAY : DrawMode::NORMAL );
1794 bool Actor::IsOverlay() const
1796 return ( DrawMode::OVERLAY == mDrawMode );
1799 void Actor::SetDrawMode( DrawMode::Type drawMode )
1801 // this flag is not animatable so keep the value
1802 mDrawMode = drawMode;
1805 // mNode is being used in a separate thread; queue a message to set the value
1806 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1810 DrawMode::Type Actor::GetDrawMode() const
1815 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1817 // only valid when on-stage
1820 const RenderTaskList& taskList = Stage::GetCurrent()->GetRenderTaskList();
1822 Vector2 converted( screenX, screenY );
1824 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1825 const int taskCount = taskList.GetTaskCount();
1826 for( int i = taskCount - 1; i >= 0; --i )
1828 Dali::RenderTask task = taskList.GetTask( i );
1829 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1831 // found a task where this conversion was ok so return
1839 bool Actor::ScreenToLocal( RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1841 bool retval = false;
1842 // only valid when on-stage
1845 CameraActor* camera = renderTask.GetCameraActor();
1849 renderTask.GetViewport( viewport );
1851 // need to translate coordinates to render tasks coordinate space
1852 Vector2 converted( screenX, screenY );
1853 if( renderTask.TranslateCoordinates( converted ) )
1855 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1862 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1864 // Early-out if mNode is NULL
1870 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1872 // Calculate the ModelView matrix
1873 Matrix modelView( false/*don't init*/);
1874 // need to use the components as world matrix is only updated for actors that need it
1875 modelView.SetTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1876 Matrix::Multiply( modelView, modelView, viewMatrix );
1878 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1879 Matrix invertedMvp( false/*don't init*/);
1880 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1881 bool success = invertedMvp.Invert();
1883 // Convert to GL coordinates
1884 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1889 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1896 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1902 if( XyPlaneIntersect( nearPos, farPos, local ) )
1904 Vector3 size = GetCurrentSize();
1905 localX = local.x + size.x * 0.5f;
1906 localY = local.y + size.y * 0.5f;
1917 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1920 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1922 Mathematical Formulation
1924 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1926 ( p - c ) dot ( p - c ) = r^2
1928 Given a ray with a point of origin 'o', and a direction vector 'd':
1930 ray(t) = o + td, t >= 0
1932 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1934 (o + td - c ) dot ( o + td - c ) = r^2
1936 To solve for t we first expand the above into a more recognisable quadratic equation form
1938 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1947 B = 2( o - c ) dot d
1948 C = ( o - c ) dot ( o - c ) - r^2
1950 which can be solved using a standard quadratic formula.
1952 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1954 Practical Simplification
1956 In a renderer, we often differentiate between world space and object space. In the object space
1957 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1958 into object space, the mathematical solution presented above can be simplified significantly.
1960 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1964 and we can find the t at which the (transformed) ray intersects the sphere by
1966 ( o + td ) dot ( o + td ) = r^2
1968 According to the reasoning above, we expand the above quadratic equation into the general form
1972 which now has coefficients:
1979 // Early out if mNode is NULL
1985 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1987 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1988 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1989 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1991 // Compute the radius is not needed, square radius it's enough.
1992 const Vector3& size( mNode->GetSize( bufferIndex ) );
1994 // Scale the sphere.
1995 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1997 const float width = size.width * scale.width;
1998 const float height = size.height * scale.height;
2000 float squareSphereRadius = 0.5f * ( width * width + height * height );
2002 float a = rayDir.Dot( rayDir ); // a
2003 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
2004 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
2006 return ( b2 * b2 - a * c ) >= 0.f;
2009 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
2016 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
2018 // Transforms the ray to the local reference system.
2020 // Calculate the inverse of Model matrix
2021 Matrix invModelMatrix( false/*don't init*/);
2022 // need to use the components as world matrix is only updated for actors that need it
2023 invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
2025 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
2026 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
2028 // Test with the actor's XY plane (Normal = 0 0 1 1).
2030 float a = -rayOriginLocal.z;
2031 float b = rayDirLocal.z;
2033 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
2035 // Ray travels distance * rayDirLocal to intersect with plane.
2038 const Vector3& size = mNode->GetSize( bufferIndex );
2040 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
2041 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
2043 // Test with the actor's geometry.
2044 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
2051 void Actor::SetLeaveRequired( bool required )
2053 mLeaveRequired = required;
2056 bool Actor::GetLeaveRequired() const
2058 return mLeaveRequired;
2061 void Actor::SetKeyboardFocusable( bool focusable )
2063 mKeyboardFocusable = focusable;
2066 bool Actor::IsKeyboardFocusable() const
2068 return mKeyboardFocusable;
2071 bool Actor::GetTouchRequired() const
2073 return !mTouchedSignal.Empty() || mDerivedRequiresTouch;
2076 bool Actor::GetHoverRequired() const
2078 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
2081 bool Actor::GetMouseWheelEventRequired() const
2083 return !mMouseWheelEventSignal.Empty() || mDerivedRequiresMouseWheelEvent;
2086 bool Actor::IsHittable() const
2088 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
2091 ActorGestureData& Actor::GetGestureData()
2093 // Likely scenario is that once gesture-data is created for this actor, the actor will require
2094 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
2095 if( NULL == mGestureData )
2097 mGestureData = new ActorGestureData;
2099 return *mGestureData;
2102 bool Actor::IsGestureRequred( Gesture::Type type ) const
2104 return mGestureData && mGestureData->IsGestureRequred( type );
2107 bool Actor::EmitTouchEventSignal( const TouchEvent& event )
2109 bool consumed = false;
2111 if( !mTouchedSignal.Empty() )
2113 Dali::Actor handle( this );
2114 consumed = mTouchedSignal.Emit( handle, event );
2119 // Notification for derived classes
2120 consumed = OnTouchEvent( event );
2126 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
2128 bool consumed = false;
2130 if( !mHoveredSignal.Empty() )
2132 Dali::Actor handle( this );
2133 consumed = mHoveredSignal.Emit( handle, event );
2138 // Notification for derived classes
2139 consumed = OnHoverEvent( event );
2145 bool Actor::EmitMouseWheelEventSignal( const MouseWheelEvent& event )
2147 bool consumed = false;
2149 if( !mMouseWheelEventSignal.Empty() )
2151 Dali::Actor handle( this );
2152 consumed = mMouseWheelEventSignal.Emit( handle, event );
2157 // Notification for derived classes
2158 consumed = OnMouseWheelEvent( event );
2164 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
2166 return mTouchedSignal;
2169 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
2171 return mHoveredSignal;
2174 Dali::Actor::MouseWheelEventSignalType& Actor::MouseWheelEventSignal()
2176 return mMouseWheelEventSignal;
2179 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
2181 return mOnStageSignal;
2184 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
2186 return mOffStageSignal;
2189 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
2191 return mOnRelayoutSignal;
2194 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
2196 bool connected( true );
2197 Actor* actor = dynamic_cast< Actor* >( object );
2199 if( 0 == strcmp( signalName.c_str(), SIGNAL_TOUCHED ) ) // don't want to convert char* to string
2201 actor->TouchedSignal().Connect( tracker, functor );
2203 else if( 0 == strcmp( signalName.c_str(), SIGNAL_HOVERED ) )
2205 actor->HoveredSignal().Connect( tracker, functor );
2207 else if( 0 == strcmp( signalName.c_str(), SIGNAL_MOUSE_WHEEL_EVENT ) )
2209 actor->MouseWheelEventSignal().Connect( tracker, functor );
2211 else if( 0 == strcmp( signalName.c_str(), SIGNAL_ON_STAGE ) )
2213 actor->OnStageSignal().Connect( tracker, functor );
2215 else if( 0 == strcmp( signalName.c_str(), SIGNAL_OFF_STAGE ) )
2217 actor->OffStageSignal().Connect( tracker, functor );
2221 // signalName does not match any signal
2228 Actor::Actor( DerivedType derivedType )
2232 mParentOrigin( NULL ),
2233 mAnchorPoint( NULL ),
2234 mRelayoutData( NULL ),
2235 #ifdef DYNAMICS_SUPPORT
2236 mDynamicsData( NULL ),
2238 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
2239 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 )
2243 void Actor::Initialize()
2246 SceneGraph::Node* node = CreateNode();
2248 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
2249 mNode = node; // Keep raw-pointer to Node
2253 GetEventThreadServices().RegisterObject( this );
2258 // Remove mParent pointers from children even if we're destroying core,
2259 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2262 ActorConstIter endIter = mChildren->end();
2263 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2265 Actor& actor = GetImplementation( *iter );
2266 actor.SetParent( NULL );
2271 // Guard to allow handle destruction after Core has been destroyed
2272 if( EventThreadServices::IsCoreRunning() )
2276 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2277 mNode = NULL; // Node is about to be destroyed
2280 GetEventThreadServices().UnregisterObject( this );
2283 #ifdef DYNAMICS_SUPPORT
2285 delete mDynamicsData;
2288 // Cleanup optional gesture data
2289 delete mGestureData;
2291 // Cleanup optional parent origin and anchor
2292 delete mParentOrigin;
2293 delete mAnchorPoint;
2295 // Delete optional relayout data
2298 delete mRelayoutData;
2302 void Actor::ConnectToStage( int index )
2304 // This container is used instead of walking the Actor hierachy.
2305 // It protects us when the Actor hierachy is modified during OnStageConnectionExternal callbacks.
2306 ActorContainer connectionList;
2308 // This stage is atomic i.e. not interrupted by user callbacks
2309 RecursiveConnectToStage( connectionList, index );
2311 // Notify applications about the newly connected actors.
2312 const ActorIter endIter = connectionList.end();
2313 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2315 Actor& actor = GetImplementation( *iter );
2316 actor.NotifyStageConnection();
2322 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, int index )
2324 DALI_ASSERT_ALWAYS( !OnStage() );
2328 ConnectToSceneGraph( index );
2330 // Notification for internal derived classes
2331 OnStageConnectionInternal();
2333 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2334 connectionList.push_back( Dali::Actor( this ) );
2336 // Recursively connect children
2339 ActorConstIter endIter = mChildren->end();
2340 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2342 Actor& actor = GetImplementation( *iter );
2343 actor.RecursiveConnectToStage( connectionList );
2349 * This method is called when the Actor is connected to the Stage.
2350 * The parent must have added its Node to the scene-graph.
2351 * The child must connect its Node to the parent's Node.
2352 * This is resursive; the child calls ConnectToStage() for its children.
2354 void Actor::ConnectToSceneGraph( int index )
2356 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2360 // Reparent Node in next Update
2361 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode, index );
2364 // Notify attachment
2367 mAttachment->Connect();
2370 #ifdef DYNAMICS_SUPPORT
2372 if( NULL != mDynamicsData )
2378 // Notification for Object::Observers
2382 void Actor::NotifyStageConnection()
2384 // Actors can be removed (in a callback), before the on-stage stage is reported.
2385 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2386 if( OnStage() && !mOnStageSignalled )
2388 // Notification for external (CustomActor) derived classes
2389 OnStageConnectionExternal();
2391 if( !mOnStageSignal.Empty() )
2393 Dali::Actor handle( this );
2394 mOnStageSignal.Emit( handle );
2397 // Guard against Remove during callbacks
2400 mOnStageSignalled = true; // signal required next time Actor is removed
2405 void Actor::DisconnectFromStage()
2407 // This container is used instead of walking the Actor hierachy.
2408 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2409 ActorContainer disconnectionList;
2411 // This stage is atomic i.e. not interrupted by user callbacks
2412 RecursiveDisconnectFromStage( disconnectionList );
2414 // Notify applications about the newly disconnected actors.
2415 const ActorIter endIter = disconnectionList.end();
2416 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2418 Actor& actor = GetImplementation( *iter );
2419 actor.NotifyStageDisconnection();
2423 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2425 DALI_ASSERT_ALWAYS( OnStage() );
2427 // Recursively disconnect children
2430 ActorConstIter endIter = mChildren->end();
2431 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2433 Actor& actor = GetImplementation( *iter );
2434 actor.RecursiveDisconnectFromStage( disconnectionList );
2438 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2439 disconnectionList.push_back( Dali::Actor( this ) );
2441 // Notification for internal derived classes
2442 OnStageDisconnectionInternal();
2444 DisconnectFromSceneGraph();
2450 * This method is called by an actor or its parent, before a node removal message is sent.
2451 * This is recursive; the child calls DisconnectFromStage() for its children.
2453 void Actor::DisconnectFromSceneGraph()
2455 // Notification for Object::Observers
2456 OnSceneObjectRemove();
2458 // Notify attachment
2461 mAttachment->Disconnect();
2464 #ifdef DYNAMICS_SUPPORT
2466 if( NULL != mDynamicsData )
2468 DisconnectDynamics();
2473 void Actor::NotifyStageDisconnection()
2475 // Actors can be added (in a callback), before the off-stage state is reported.
2476 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2477 // only do this step if there is a stage, i.e. Core is not being shut down
2478 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2480 // Notification for external (CustomeActor) derived classes
2481 OnStageDisconnectionExternal();
2483 if( !mOffStageSignal.Empty() )
2485 Dali::Actor handle( this );
2486 mOffStageSignal.Emit( handle );
2489 // Guard against Add during callbacks
2492 mOnStageSignalled = false; // signal required next time Actor is added
2497 bool Actor::IsNodeConnected() const
2499 bool connected( false );
2504 if( mNode->IsRoot() || mNode->GetParent() )
2513 unsigned int Actor::GetDefaultPropertyCount() const
2515 return DEFAULT_PROPERTY_COUNT;
2518 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2520 indices.reserve( DEFAULT_PROPERTY_COUNT );
2522 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2524 indices.push_back( i );
2528 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2530 if( index < DEFAULT_PROPERTY_COUNT )
2532 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2538 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2540 Property::Index index = Property::INVALID_INDEX;
2542 // Look for name in default properties
2543 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2545 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2546 if( 0 == strcmp( name.c_str(), property->name ) ) // dont want to convert rhs to string
2556 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2558 if( index < DEFAULT_PROPERTY_COUNT )
2560 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2566 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2568 if( index < DEFAULT_PROPERTY_COUNT )
2570 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2576 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2578 if( index < DEFAULT_PROPERTY_COUNT )
2580 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2586 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2588 if( index < DEFAULT_PROPERTY_COUNT )
2590 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2593 // index out of range...return Property::NONE
2594 return Property::NONE;
2597 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2601 case Dali::Actor::Property::PARENT_ORIGIN:
2603 SetParentOrigin( property.Get< Vector3 >() );
2607 case Dali::Actor::Property::PARENT_ORIGIN_X:
2609 SetParentOriginX( property.Get< float >() );
2613 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2615 SetParentOriginY( property.Get< float >() );
2619 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2621 SetParentOriginZ( property.Get< float >() );
2625 case Dali::Actor::Property::ANCHOR_POINT:
2627 SetAnchorPoint( property.Get< Vector3 >() );
2631 case Dali::Actor::Property::ANCHOR_POINT_X:
2633 SetAnchorPointX( property.Get< float >() );
2637 case Dali::Actor::Property::ANCHOR_POINT_Y:
2639 SetAnchorPointY( property.Get< float >() );
2643 case Dali::Actor::Property::ANCHOR_POINT_Z:
2645 SetAnchorPointZ( property.Get< float >() );
2649 case Dali::Actor::Property::SIZE:
2651 SetSize( property.Get< Vector3 >() );
2655 case Dali::Actor::Property::SIZE_WIDTH:
2657 SetWidth( property.Get< float >() );
2661 case Dali::Actor::Property::SIZE_HEIGHT:
2663 SetHeight( property.Get< float >() );
2667 case Dali::Actor::Property::SIZE_DEPTH:
2669 SetDepth( property.Get< float >() );
2673 case Dali::Actor::Property::POSITION:
2675 SetPosition( property.Get< Vector3 >() );
2679 case Dali::Actor::Property::POSITION_X:
2681 SetX( property.Get< float >() );
2685 case Dali::Actor::Property::POSITION_Y:
2687 SetY( property.Get< float >() );
2691 case Dali::Actor::Property::POSITION_Z:
2693 SetZ( property.Get< float >() );
2697 case Dali::Actor::Property::ORIENTATION:
2699 SetOrientation( property.Get< Quaternion >() );
2703 case Dali::Actor::Property::SCALE:
2705 SetScale( property.Get< Vector3 >() );
2709 case Dali::Actor::Property::SCALE_X:
2711 SetScaleX( property.Get< float >() );
2715 case Dali::Actor::Property::SCALE_Y:
2717 SetScaleY( property.Get< float >() );
2721 case Dali::Actor::Property::SCALE_Z:
2723 SetScaleZ( property.Get< float >() );
2727 case Dali::Actor::Property::VISIBLE:
2729 SetVisible( property.Get< bool >() );
2733 case Dali::Actor::Property::COLOR:
2735 SetColor( property.Get< Vector4 >() );
2739 case Dali::Actor::Property::COLOR_RED:
2741 SetColorRed( property.Get< float >() );
2745 case Dali::Actor::Property::COLOR_GREEN:
2747 SetColorGreen( property.Get< float >() );
2751 case Dali::Actor::Property::COLOR_BLUE:
2753 SetColorBlue( property.Get< float >() );
2757 case Dali::Actor::Property::COLOR_ALPHA:
2759 SetOpacity( property.Get< float >() );
2763 case Dali::Actor::Property::NAME:
2765 SetName( property.Get< std::string >() );
2769 case Dali::Actor::Property::SENSITIVE:
2771 SetSensitive( property.Get< bool >() );
2775 case Dali::Actor::Property::LEAVE_REQUIRED:
2777 SetLeaveRequired( property.Get< bool >() );
2781 case Dali::Actor::Property::INHERIT_ORIENTATION:
2783 SetInheritOrientation( property.Get< bool >() );
2787 case Dali::Actor::Property::INHERIT_SCALE:
2789 SetInheritScale( property.Get< bool >() );
2793 case Dali::Actor::Property::COLOR_MODE:
2795 SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2799 case Dali::Actor::Property::POSITION_INHERITANCE:
2801 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2805 case Dali::Actor::Property::DRAW_MODE:
2807 SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2811 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2813 SetSizeModeFactor( property.Get< Vector3 >() );
2817 case Dali::Actor::Property::RELAYOUT_ENABLED:
2819 SetRelayoutEnabled( property.Get< bool >() );
2823 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2825 SetResizePolicy( Scripting::GetEnumeration< ResizePolicy >( property.Get< std::string >().c_str(), ResizePolicyTable, ResizePolicyTableCount ), WIDTH );
2829 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2831 SetResizePolicy( Scripting::GetEnumeration< ResizePolicy >( property.Get< std::string >().c_str(), ResizePolicyTable, ResizePolicyTableCount ), HEIGHT );
2835 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2837 SetSizeScalePolicy( Scripting::GetEnumeration< SizeScalePolicy >( property.Get< std::string >().c_str(), SizeScalePolicyTable, SizeScalePolicyTableCount ) );
2841 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2843 if( property.Get< bool >() )
2845 SetResizePolicy( DIMENSION_DEPENDENCY, WIDTH );
2850 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2852 if( property.Get< bool >() )
2854 SetResizePolicy( DIMENSION_DEPENDENCY, HEIGHT );
2859 case Dali::Actor::Property::PADDING:
2861 Vector4 padding = property.Get< Vector4 >();
2862 SetPadding( Vector2( padding.x, padding.y ), WIDTH );
2863 SetPadding( Vector2( padding.z, padding.w ), HEIGHT );
2867 case Dali::Actor::Property::MINIMUM_SIZE:
2869 Vector2 size = property.Get< Vector2 >();
2870 SetMinimumSize( size.x, WIDTH );
2871 SetMinimumSize( size.y, HEIGHT );
2875 case Dali::Actor::Property::MAXIMUM_SIZE:
2877 Vector2 size = property.Get< Vector2 >();
2878 SetMaximumSize( size.x, WIDTH );
2879 SetMaximumSize( size.y, HEIGHT );
2885 // this can happen in the case of a non-animatable default property so just do nothing
2891 // TODO: This method needs to be removed
2892 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2894 OnPropertySet( index, value );
2896 switch( entry.type )
2898 case Property::BOOLEAN:
2900 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2901 DALI_ASSERT_DEBUG( NULL != property );
2903 // property is being used in a separate thread; queue a message to set the property
2904 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2909 case Property::FLOAT:
2911 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2912 DALI_ASSERT_DEBUG( NULL != property );
2914 // property is being used in a separate thread; queue a message to set the property
2915 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2920 case Property::INTEGER:
2922 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2923 DALI_ASSERT_DEBUG( NULL != property );
2925 // property is being used in a separate thread; queue a message to set the property
2926 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2931 case Property::VECTOR2:
2933 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2934 DALI_ASSERT_DEBUG( NULL != property );
2936 // property is being used in a separate thread; queue a message to set the property
2937 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2942 case Property::VECTOR3:
2944 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2945 DALI_ASSERT_DEBUG( NULL != property );
2947 // property is being used in a separate thread; queue a message to set the property
2948 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2953 case Property::VECTOR4:
2955 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2956 DALI_ASSERT_DEBUG( NULL != property );
2958 // property is being used in a separate thread; queue a message to set the property
2959 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2964 case Property::ROTATION:
2966 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
2967 DALI_ASSERT_DEBUG( NULL != property );
2969 // property is being used in a separate thread; queue a message to set the property
2970 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
2975 case Property::MATRIX:
2977 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
2978 DALI_ASSERT_DEBUG( NULL != property );
2980 // property is being used in a separate thread; queue a message to set the property
2981 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
2986 case Property::MATRIX3:
2988 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
2989 DALI_ASSERT_DEBUG( NULL != property );
2991 // property is being used in a separate thread; queue a message to set the property
2992 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
2999 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
3005 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3007 Property::Value value;
3011 case Dali::Actor::Property::PARENT_ORIGIN:
3013 value = GetCurrentParentOrigin();
3017 case Dali::Actor::Property::PARENT_ORIGIN_X:
3019 value = GetCurrentParentOrigin().x;
3023 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3025 value = GetCurrentParentOrigin().y;
3029 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3031 value = GetCurrentParentOrigin().z;
3035 case Dali::Actor::Property::ANCHOR_POINT:
3037 value = GetCurrentAnchorPoint();
3041 case Dali::Actor::Property::ANCHOR_POINT_X:
3043 value = GetCurrentAnchorPoint().x;
3047 case Dali::Actor::Property::ANCHOR_POINT_Y:
3049 value = GetCurrentAnchorPoint().y;
3053 case Dali::Actor::Property::ANCHOR_POINT_Z:
3055 value = GetCurrentAnchorPoint().z;
3059 case Dali::Actor::Property::SIZE:
3061 value = GetCurrentSize();
3065 case Dali::Actor::Property::SIZE_WIDTH:
3067 value = GetCurrentSize().width;
3071 case Dali::Actor::Property::SIZE_HEIGHT:
3073 value = GetCurrentSize().height;
3077 case Dali::Actor::Property::SIZE_DEPTH:
3079 value = GetCurrentSize().depth;
3083 case Dali::Actor::Property::POSITION:
3085 value = GetCurrentPosition();
3089 case Dali::Actor::Property::POSITION_X:
3091 value = GetCurrentPosition().x;
3095 case Dali::Actor::Property::POSITION_Y:
3097 value = GetCurrentPosition().y;
3101 case Dali::Actor::Property::POSITION_Z:
3103 value = GetCurrentPosition().z;
3107 case Dali::Actor::Property::WORLD_POSITION:
3109 value = GetCurrentWorldPosition();
3113 case Dali::Actor::Property::WORLD_POSITION_X:
3115 value = GetCurrentWorldPosition().x;
3119 case Dali::Actor::Property::WORLD_POSITION_Y:
3121 value = GetCurrentWorldPosition().y;
3125 case Dali::Actor::Property::WORLD_POSITION_Z:
3127 value = GetCurrentWorldPosition().z;
3131 case Dali::Actor::Property::ORIENTATION:
3133 value = GetCurrentOrientation();
3137 case Dali::Actor::Property::WORLD_ORIENTATION:
3139 value = GetCurrentWorldOrientation();
3143 case Dali::Actor::Property::SCALE:
3145 value = GetCurrentScale();
3149 case Dali::Actor::Property::SCALE_X:
3151 value = GetCurrentScale().x;
3155 case Dali::Actor::Property::SCALE_Y:
3157 value = GetCurrentScale().y;
3161 case Dali::Actor::Property::SCALE_Z:
3163 value = GetCurrentScale().z;
3167 case Dali::Actor::Property::WORLD_SCALE:
3169 value = GetCurrentWorldScale();
3173 case Dali::Actor::Property::VISIBLE:
3175 value = IsVisible();
3179 case Dali::Actor::Property::COLOR:
3181 value = GetCurrentColor();
3185 case Dali::Actor::Property::COLOR_RED:
3187 value = GetCurrentColor().r;
3191 case Dali::Actor::Property::COLOR_GREEN:
3193 value = GetCurrentColor().g;
3197 case Dali::Actor::Property::COLOR_BLUE:
3199 value = GetCurrentColor().b;
3203 case Dali::Actor::Property::COLOR_ALPHA:
3205 value = GetCurrentColor().a;
3209 case Dali::Actor::Property::WORLD_COLOR:
3211 value = GetCurrentWorldColor();
3215 case Dali::Actor::Property::WORLD_MATRIX:
3217 value = GetCurrentWorldMatrix();
3221 case Dali::Actor::Property::NAME:
3227 case Dali::Actor::Property::SENSITIVE:
3229 value = IsSensitive();
3233 case Dali::Actor::Property::LEAVE_REQUIRED:
3235 value = GetLeaveRequired();
3239 case Dali::Actor::Property::INHERIT_ORIENTATION:
3241 value = IsOrientationInherited();
3245 case Dali::Actor::Property::INHERIT_SCALE:
3247 value = IsScaleInherited();
3251 case Dali::Actor::Property::COLOR_MODE:
3253 value = Scripting::GetColorMode( GetColorMode() );
3257 case Dali::Actor::Property::POSITION_INHERITANCE:
3259 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
3263 case Dali::Actor::Property::DRAW_MODE:
3265 value = Scripting::GetDrawMode( GetDrawMode() );
3269 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3271 value = GetSizeModeFactor();
3275 case Dali::Actor::Property::RELAYOUT_ENABLED:
3277 value = IsRelayoutEnabled();
3281 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3283 value = Scripting::GetLinearEnumerationName< ResizePolicy >( GetResizePolicy( WIDTH ), ResizePolicyTable, ResizePolicyTableCount );
3287 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3289 value = Scripting::GetLinearEnumerationName< ResizePolicy >( GetResizePolicy( HEIGHT ), ResizePolicyTable, ResizePolicyTableCount );
3293 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3295 value = Scripting::GetLinearEnumerationName< SizeScalePolicy >( GetSizeScalePolicy(), SizeScalePolicyTable, SizeScalePolicyTableCount );
3299 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3301 value = ( GetResizePolicy( WIDTH ) == DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( WIDTH ) == HEIGHT );
3305 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3307 value = ( GetResizePolicy( HEIGHT ) == DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( HEIGHT ) == WIDTH );
3311 case Dali::Actor::Property::PADDING:
3313 Vector2 widthPadding = GetPadding( WIDTH );
3314 Vector2 heightPadding = GetPadding( HEIGHT );
3315 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3319 case Dali::Actor::Property::MINIMUM_SIZE:
3321 value = Vector2( GetMinimumSize( WIDTH ), GetMinimumSize( HEIGHT ) );
3325 case Dali::Actor::Property::MAXIMUM_SIZE:
3327 value = Vector2( GetMaximumSize( WIDTH ), GetMaximumSize( HEIGHT ) );
3333 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3341 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3346 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3348 // This method should only return an object connected to the scene-graph
3349 return OnStage() ? mNode : NULL;
3352 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3354 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3356 const PropertyBase* property( NULL );
3358 // This method should only return a property of an object connected to the scene-graph
3364 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3366 AnimatablePropertyMetadata* animatable = FindAnimatableProperty( index );
3369 const TypeInfo* typeInfo( GetTypeInfo() );
3372 if( Property::INVALID_INDEX != RegisterSceneGraphProperty( typeInfo->GetPropertyName( index ), index, Property::Value( typeInfo->GetPropertyType( index ) ) ) )
3374 animatable = FindAnimatableProperty( index );
3378 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3380 property = animatable->GetSceneGraphProperty();
3382 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3384 CustomPropertyMetadata* custom = FindCustomProperty( index );
3385 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3387 property = custom->GetSceneGraphProperty();
3389 else if( NULL != mNode )
3393 case Dali::Actor::Property::SIZE:
3394 property = &mNode->mSize;
3397 case Dali::Actor::Property::SIZE_WIDTH:
3398 property = &mNode->mSize;
3401 case Dali::Actor::Property::SIZE_HEIGHT:
3402 property = &mNode->mSize;
3405 case Dali::Actor::Property::SIZE_DEPTH:
3406 property = &mNode->mSize;
3409 case Dali::Actor::Property::POSITION:
3410 property = &mNode->mPosition;
3413 case Dali::Actor::Property::POSITION_X:
3414 property = &mNode->mPosition;
3417 case Dali::Actor::Property::POSITION_Y:
3418 property = &mNode->mPosition;
3421 case Dali::Actor::Property::POSITION_Z:
3422 property = &mNode->mPosition;
3425 case Dali::Actor::Property::ORIENTATION:
3426 property = &mNode->mOrientation;
3429 case Dali::Actor::Property::SCALE:
3430 property = &mNode->mScale;
3433 case Dali::Actor::Property::SCALE_X:
3434 property = &mNode->mScale;
3437 case Dali::Actor::Property::SCALE_Y:
3438 property = &mNode->mScale;
3441 case Dali::Actor::Property::SCALE_Z:
3442 property = &mNode->mScale;
3445 case Dali::Actor::Property::VISIBLE:
3446 property = &mNode->mVisible;
3449 case Dali::Actor::Property::COLOR:
3450 property = &mNode->mColor;
3453 case Dali::Actor::Property::COLOR_RED:
3454 property = &mNode->mColor;
3457 case Dali::Actor::Property::COLOR_GREEN:
3458 property = &mNode->mColor;
3461 case Dali::Actor::Property::COLOR_BLUE:
3462 property = &mNode->mColor;
3465 case Dali::Actor::Property::COLOR_ALPHA:
3466 property = &mNode->mColor;
3477 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3479 const PropertyInputImpl* property( NULL );
3481 // This method should only return a property of an object connected to the scene-graph
3487 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3489 AnimatablePropertyMetadata* animatable = FindAnimatableProperty( index );
3492 const TypeInfo* typeInfo( GetTypeInfo() );
3495 if( Property::INVALID_INDEX != RegisterSceneGraphProperty( typeInfo->GetPropertyName( index ), index, Property::Value( typeInfo->GetPropertyType( index ) ) ) )
3497 animatable = FindAnimatableProperty( index );
3501 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3503 property = animatable->GetSceneGraphProperty();
3505 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3507 CustomPropertyMetadata* custom = FindCustomProperty( index );
3508 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3509 property = custom->GetSceneGraphProperty();
3511 else if( NULL != mNode )
3515 case Dali::Actor::Property::PARENT_ORIGIN:
3516 property = &mNode->mParentOrigin;
3519 case Dali::Actor::Property::PARENT_ORIGIN_X:
3520 property = &mNode->mParentOrigin;
3523 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3524 property = &mNode->mParentOrigin;
3527 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3528 property = &mNode->mParentOrigin;
3531 case Dali::Actor::Property::ANCHOR_POINT:
3532 property = &mNode->mAnchorPoint;
3535 case Dali::Actor::Property::ANCHOR_POINT_X:
3536 property = &mNode->mAnchorPoint;
3539 case Dali::Actor::Property::ANCHOR_POINT_Y:
3540 property = &mNode->mAnchorPoint;
3543 case Dali::Actor::Property::ANCHOR_POINT_Z:
3544 property = &mNode->mAnchorPoint;
3547 case Dali::Actor::Property::SIZE:
3548 property = &mNode->mSize;
3551 case Dali::Actor::Property::SIZE_WIDTH:
3552 property = &mNode->mSize;
3555 case Dali::Actor::Property::SIZE_HEIGHT:
3556 property = &mNode->mSize;
3559 case Dali::Actor::Property::SIZE_DEPTH:
3560 property = &mNode->mSize;
3563 case Dali::Actor::Property::POSITION:
3564 property = &mNode->mPosition;
3567 case Dali::Actor::Property::POSITION_X:
3568 property = &mNode->mPosition;
3571 case Dali::Actor::Property::POSITION_Y:
3572 property = &mNode->mPosition;
3575 case Dali::Actor::Property::POSITION_Z:
3576 property = &mNode->mPosition;
3579 case Dali::Actor::Property::WORLD_POSITION:
3580 property = &mNode->mWorldPosition;
3583 case Dali::Actor::Property::WORLD_POSITION_X:
3584 property = &mNode->mWorldPosition;
3587 case Dali::Actor::Property::WORLD_POSITION_Y:
3588 property = &mNode->mWorldPosition;
3591 case Dali::Actor::Property::WORLD_POSITION_Z:
3592 property = &mNode->mWorldPosition;
3595 case Dali::Actor::Property::ORIENTATION:
3596 property = &mNode->mOrientation;
3599 case Dali::Actor::Property::WORLD_ORIENTATION:
3600 property = &mNode->mWorldOrientation;
3603 case Dali::Actor::Property::SCALE:
3604 property = &mNode->mScale;
3607 case Dali::Actor::Property::SCALE_X:
3608 property = &mNode->mScale;
3611 case Dali::Actor::Property::SCALE_Y:
3612 property = &mNode->mScale;
3615 case Dali::Actor::Property::SCALE_Z:
3616 property = &mNode->mScale;
3619 case Dali::Actor::Property::WORLD_SCALE:
3620 property = &mNode->mWorldScale;
3623 case Dali::Actor::Property::VISIBLE:
3624 property = &mNode->mVisible;
3627 case Dali::Actor::Property::COLOR:
3628 property = &mNode->mColor;
3631 case Dali::Actor::Property::COLOR_RED:
3632 property = &mNode->mColor;
3635 case Dali::Actor::Property::COLOR_GREEN:
3636 property = &mNode->mColor;
3639 case Dali::Actor::Property::COLOR_BLUE:
3640 property = &mNode->mColor;
3643 case Dali::Actor::Property::COLOR_ALPHA:
3644 property = &mNode->mColor;
3647 case Dali::Actor::Property::WORLD_COLOR:
3648 property = &mNode->mWorldColor;
3651 case Dali::Actor::Property::WORLD_MATRIX:
3652 property = &mNode->mWorldMatrix;
3663 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3665 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3669 case Dali::Actor::Property::PARENT_ORIGIN_X:
3670 case Dali::Actor::Property::ANCHOR_POINT_X:
3671 case Dali::Actor::Property::SIZE_WIDTH:
3672 case Dali::Actor::Property::POSITION_X:
3673 case Dali::Actor::Property::WORLD_POSITION_X:
3674 case Dali::Actor::Property::SCALE_X:
3675 case Dali::Actor::Property::COLOR_RED:
3681 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3682 case Dali::Actor::Property::ANCHOR_POINT_Y:
3683 case Dali::Actor::Property::SIZE_HEIGHT:
3684 case Dali::Actor::Property::POSITION_Y:
3685 case Dali::Actor::Property::WORLD_POSITION_Y:
3686 case Dali::Actor::Property::SCALE_Y:
3687 case Dali::Actor::Property::COLOR_GREEN:
3693 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3694 case Dali::Actor::Property::ANCHOR_POINT_Z:
3695 case Dali::Actor::Property::SIZE_DEPTH:
3696 case Dali::Actor::Property::POSITION_Z:
3697 case Dali::Actor::Property::WORLD_POSITION_Z:
3698 case Dali::Actor::Property::SCALE_Z:
3699 case Dali::Actor::Property::COLOR_BLUE:
3705 case Dali::Actor::Property::COLOR_ALPHA:
3718 return componentIndex;
3721 void Actor::SetParent( Actor* parent, int index )
3725 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3729 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3732 // Instruct each actor to create a corresponding node in the scene graph
3733 ConnectToStage( index );
3736 else // parent being set to NULL
3738 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3742 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3745 DALI_ASSERT_ALWAYS( mNode != NULL );
3749 // Disconnect the Node & its children from the scene-graph.
3750 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3753 // Instruct each actor to discard pointers to the scene-graph
3754 DisconnectFromStage();
3759 SceneGraph::Node* Actor::CreateNode() const
3764 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const std::vector< Property::Value >& attributes )
3767 Actor* actor = dynamic_cast< Actor* >( object );
3771 if( 0 == strcmp( actionName.c_str(), ACTION_SHOW ) ) // dont want to convert char* to string
3773 actor->SetVisible( true );
3776 else if( 0 == strcmp( actionName.c_str(), ACTION_HIDE ) )
3778 actor->SetVisible( false );
3786 void Actor::EnsureRelayoutData() const
3788 // Assign relayout data.
3789 if( !mRelayoutData )
3791 mRelayoutData = new RelayoutData();
3795 bool Actor::RelayoutDependentOnParent( Dimension dimension )
3797 // Check if actor is dependent on parent
3798 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
3800 if( ( dimension & ( 1 << i ) ) )
3802 const ResizePolicy resizePolicy = GetResizePolicy( static_cast< Dimension >( 1 << i ) );
3803 if( resizePolicy == FILL_TO_PARENT || resizePolicy == SIZE_RELATIVE_TO_PARENT || resizePolicy == SIZE_FIXED_OFFSET_FROM_PARENT )
3813 bool Actor::RelayoutDependentOnChildren( Dimension dimension )
3815 // Check if actor is dependent on children
3816 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
3818 if( ( dimension & ( 1 << i ) ) )
3820 const ResizePolicy resizePolicy = GetResizePolicy( static_cast< Dimension >( 1 << i ) );
3821 switch( resizePolicy )
3823 case FIT_TO_CHILDREN:
3824 case USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3840 bool Actor::RelayoutDependentOnChildrenBase( Dimension dimension )
3842 return Actor::RelayoutDependentOnChildren( dimension );
3845 bool Actor::RelayoutDependentOnDimension( Dimension dimension, Dimension dependentDimension )
3847 // Check each possible dimension and see if it is dependent on the input one
3848 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
3850 if( dimension & ( 1 << i ) )
3852 return mRelayoutData->resizePolicies[ i ] == DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3859 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension dimension )
3861 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
3863 if( dimension & ( 1 << i ) )
3865 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3870 float Actor::GetNegotiatedDimension( Dimension dimension ) const
3872 // If more than one dimension is requested, just return the first one found
3873 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
3875 if( ( dimension & ( 1 << i ) ) )
3877 return mRelayoutData->negotiatedDimensions[ i ];
3881 return 0.0f; // Default
3884 void Actor::SetPadding( const Vector2& padding, Dimension dimension )
3886 EnsureRelayoutData();
3888 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
3890 if( dimension & ( 1 << i ) )
3892 mRelayoutData->dimensionPadding[ i ] = padding;
3897 Vector2 Actor::GetPadding( Dimension dimension ) const
3899 EnsureRelayoutData();
3901 // If more than one dimension is requested, just return the first one found
3902 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
3904 if( ( dimension & ( 1 << i ) ) )
3906 return mRelayoutData->dimensionPadding[ i ];
3910 return Vector2( 0.0f, 0.0f ); // Default
3913 void Actor::SetLayoutNegotiated( bool negotiated, Dimension dimension )
3915 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
3917 if( dimension & ( 1 << i ) )
3919 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3924 bool Actor::IsLayoutNegotiated( Dimension dimension ) const
3926 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
3928 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
3937 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension dimension )
3939 // Could be overridden in derived classes.
3940 return CalculateChildSizeBase( child, dimension );
3943 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension dimension )
3945 // Fill to parent, taking size mode factor into account
3946 switch( child.GetResizePolicy( dimension ) )
3948 case FILL_TO_PARENT:
3950 return GetLatestSize( dimension );
3953 case SIZE_RELATIVE_TO_PARENT:
3955 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
3958 case SIZE_FIXED_OFFSET_FROM_PARENT:
3960 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
3965 return GetLatestSize( dimension );
3970 float Actor::GetHeightForWidth( float width )
3972 // Could be overridden in derived classes.
3973 float height = 0.0f;
3975 const Vector3 naturalSize = GetNaturalSize();
3976 if( naturalSize.width > 0.0f )
3978 height = naturalSize.height * width / naturalSize.width;
3984 float Actor::GetWidthForHeight( float height )
3986 // Could be overridden in derived classes.
3989 const Vector3 naturalSize = GetNaturalSize();
3990 if( naturalSize.height > 0.0f )
3992 width = naturalSize.width * height / naturalSize.height;
3998 float Actor::GetLatestSize( Dimension dimension ) const
4000 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4003 float Actor::GetRelayoutSize( Dimension dimension ) const
4005 Vector2 padding = GetPadding( dimension );
4007 return GetLatestSize( dimension ) + padding.x + padding.y;
4010 float Actor::NegotiateFromParent( Dimension dimension )
4012 Actor* parent = GetParent();
4015 Vector2 padding( GetPadding( dimension ) );
4016 Vector2 parentPadding( parent->GetPadding( dimension ) );
4017 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4023 float Actor::NegotiateFromChildren( Dimension dimension )
4025 float minDimensionPoint = 0.0f;
4026 float maxDimensionPoint = 0.0f;
4028 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4030 Dali::Actor child = GetChildAt( i );
4031 Actor& childImpl = GetImplementation( child );
4033 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4035 // Calculate the min and max points that the children range across
4036 float childPosition = GetDimensionValue( childImpl.GetCurrentPosition(), dimension );
4037 float dimensionSize = childImpl.GetRelayoutSize( dimension );
4038 minDimensionPoint = std::min( minDimensionPoint, childPosition - dimensionSize * 0.5f );
4039 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize * 0.5f );
4043 return maxDimensionPoint - minDimensionPoint;
4046 float Actor::GetSize( Dimension dimension ) const
4048 return GetDimensionValue( GetTargetSize(), dimension );
4051 float Actor::GetNaturalSize( Dimension dimension ) const
4053 return GetDimensionValue( GetNaturalSize(), dimension );
4056 float Actor::CalculateSize( Dimension dimension, const Vector2& maximumSize )
4058 switch( GetResizePolicy( dimension ) )
4060 case USE_NATURAL_SIZE:
4062 return GetNaturalSize( dimension );
4067 return GetDimensionValue( GetPreferredSize(), dimension );
4070 case USE_ASSIGNED_SIZE:
4072 return GetDimensionValue( maximumSize, dimension );
4075 case FILL_TO_PARENT:
4076 case SIZE_RELATIVE_TO_PARENT:
4077 case SIZE_FIXED_OFFSET_FROM_PARENT:
4079 return NegotiateFromParent( dimension );
4082 case FIT_TO_CHILDREN:
4084 return NegotiateFromChildren( dimension );
4087 case DIMENSION_DEPENDENCY:
4089 const Dimension dimensionDependency = GetDimensionDependency( dimension );
4092 if( dimension == WIDTH && dimensionDependency == HEIGHT )
4094 return GetWidthForHeight( GetNegotiatedDimension( HEIGHT ) );
4097 if( dimension == HEIGHT && dimensionDependency == WIDTH )
4099 return GetHeightForWidth( GetNegotiatedDimension( WIDTH ) );
4111 return 0.0f; // Default
4114 float Actor::ConstrainDimension( float size, Dimension dimension )
4116 const float minSize = GetMinimumSize( dimension );
4117 const float maxSize = GetMaximumSize( dimension );
4119 return std::max( minSize, std::min( size, maxSize ) );
4122 void Actor::NegotiateDimension( Dimension dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4124 // Check if it needs to be negotiated
4125 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4127 // Check that we havn't gotten into an infinite loop
4128 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4129 bool recursionFound = false;
4130 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4132 if( *it == searchActor )
4134 recursionFound = true;
4139 if( !recursionFound )
4141 // Record the path that we have taken
4142 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4144 // Dimension dependency check
4145 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
4147 Dimension dimensionToCheck = static_cast< Dimension >( 1 << i );
4149 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4151 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4155 // Parent dependency check
4156 Actor* parent = GetParent();
4157 if( parent && RelayoutDependentOnParent( dimension ) )
4159 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4162 // Children dependency check
4163 if( RelayoutDependentOnChildren( dimension ) )
4165 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4167 Dali::Actor child = GetChildAt( i );
4168 Actor& childImpl = GetImplementation( child );
4170 // Only relayout child first if it is not dependent on this actor
4171 if( !childImpl.RelayoutDependentOnParent( dimension ) )
4173 childImpl.NegotiateDimension( dimension, allocatedSize, recursionStack );
4178 // For deriving classes
4179 OnCalculateRelayoutSize( dimension );
4181 // All dependencies checked, calculate the size and set negotiated flag
4182 const float newSize = ConstrainDimension( CalculateSize( dimension, allocatedSize ), dimension );
4184 SetNegotiatedDimension( newSize, dimension );
4185 SetLayoutNegotiated( true, dimension );
4187 // For deriving classes
4188 OnLayoutNegotiated( newSize, dimension );
4190 // This actor has been successfully processed, pop it off the recursion stack
4191 recursionStack.pop_back();
4195 // TODO: Break infinite loop
4196 SetLayoutNegotiated( true, dimension );
4201 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4203 // Negotiate all dimensions that require it
4204 ActorDimensionStack recursionStack;
4206 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
4208 const Dimension dimension = static_cast< Dimension >( 1 << i );
4211 NegotiateDimension( dimension, allocatedSize, recursionStack );
4215 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4217 switch( mRelayoutData->sizeSetPolicy )
4224 case FIT_WITH_ASPECT_RATIO:
4226 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4227 const Vector3 naturalSize = GetNaturalSize();
4228 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4230 const float sizeRatio = size.width / size.height;
4231 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4233 if( naturalSizeRatio < sizeRatio )
4235 return Vector2( naturalSizeRatio * size.height, size.height );
4237 else if( naturalSizeRatio > sizeRatio )
4239 return Vector2( size.width, size.width / naturalSizeRatio );
4250 case FILL_WITH_ASPECT_RATIO:
4252 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4253 const Vector3 naturalSize = GetNaturalSize();
4254 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4256 const float sizeRatio = size.width / size.height;
4257 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4259 if( naturalSizeRatio < sizeRatio )
4261 return Vector2( size.width, size.width / naturalSizeRatio );
4263 else if( naturalSizeRatio > sizeRatio )
4265 return Vector2( naturalSizeRatio * size.height, size.height );
4283 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4285 // Do the set actor size
4286 Vector2 negotiatedSize( GetLatestSize( WIDTH ), GetLatestSize( HEIGHT ) );
4288 // Adjust for size set policy
4289 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4291 // Lock the flag to stop recursive relayouts on set size
4292 mRelayoutData->insideRelayout = true;
4293 SetSize( negotiatedSize );
4294 mRelayoutData->insideRelayout = false;
4296 // Clear flags for all dimensions
4297 SetLayoutDirty( false );
4299 // Give deriving classes a chance to respond
4300 OnRelayout( negotiatedSize, container );
4302 if( !mOnRelayoutSignal.Empty() )
4304 Dali::Actor handle( this );
4305 mOnRelayoutSignal.Emit( handle );
4309 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4311 // Do the negotiation
4312 NegotiateDimensions( allocatedSize );
4314 // Set the actor size
4315 SetNegotiatedSize( container );
4317 // Negotiate down to children
4318 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4320 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4322 Dali::Actor child = GetChildAt( i );
4324 // Only relayout if required
4325 if( GetImplementation( child ).RelayoutRequired() )
4327 container.Add( child, newBounds );
4332 void Actor::RelayoutRequest( Dimension dimension )
4334 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4335 if( relayoutController )
4337 Dali::Actor self( this );
4338 relayoutController->RequestRelayout( self, dimension );
4342 void Actor::RelayoutRequestTree()
4344 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4345 if( relayoutController )
4347 Dali::Actor self( this );
4348 relayoutController->RequestRelayoutTree( self );
4352 void Actor::PropagateRelayoutFlags()
4354 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4355 if( relayoutController )
4357 Dali::Actor self( this );
4358 relayoutController->PropagateFlags( self );
4362 void Actor::OnCalculateRelayoutSize( Dimension dimension )
4366 void Actor::OnLayoutNegotiated( float size, Dimension dimension )
4370 void Actor::SetPreferredSize( const Vector2& size )
4372 EnsureRelayoutData();
4374 if( size.width > 0.0f )
4376 SetResizePolicy( FIXED, WIDTH );
4379 if( size.height > 0.0f )
4381 SetResizePolicy( FIXED, HEIGHT );
4384 mRelayoutData->preferredSize = size;
4389 Vector2 Actor::GetPreferredSize() const
4391 EnsureRelayoutData();
4393 return mRelayoutData->preferredSize;
4396 void Actor::SetMinimumSize( float size, Dimension dimension )
4398 EnsureRelayoutData();
4400 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
4402 if( dimension & ( 1 << i ) )
4404 mRelayoutData->minimumSize[ i ] = size;
4411 float Actor::GetMinimumSize( Dimension dimension ) const
4413 EnsureRelayoutData();
4415 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
4417 if( dimension & ( 1 << i ) )
4419 return mRelayoutData->minimumSize[ i ];
4423 return 0.0f; // Default
4426 void Actor::SetMaximumSize( float size, Dimension dimension )
4428 EnsureRelayoutData();
4430 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
4432 if( dimension & ( 1 << i ) )
4434 mRelayoutData->maximumSize[ i ] = size;
4441 float Actor::GetMaximumSize( Dimension dimension ) const
4443 EnsureRelayoutData();
4445 for( unsigned int i = 0; i < DIMENSION_COUNT; ++i )
4447 if( dimension & ( 1 << i ) )
4449 return mRelayoutData->maximumSize[ i ];
4453 return 0.0f; // Default
4456 } // namespace Internal