2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/event/actors/actor-impl.h>
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/devel-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 using Dali::Internal::SceneGraph::Node;
57 using Dali::Internal::SceneGraph::AnimatableProperty;
58 using Dali::Internal::SceneGraph::PropertyBase;
62 namespace ResizePolicy
67 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )
68 DALI_ENUM_TO_STRING( FIXED )
69 DALI_ENUM_TO_STRING( USE_NATURAL_SIZE )
70 DALI_ENUM_TO_STRING( FILL_TO_PARENT )
71 DALI_ENUM_TO_STRING( SIZE_RELATIVE_TO_PARENT )
72 DALI_ENUM_TO_STRING( SIZE_FIXED_OFFSET_FROM_PARENT )
73 DALI_ENUM_TO_STRING( FIT_TO_CHILDREN )
74 DALI_ENUM_TO_STRING( DIMENSION_DEPENDENCY )
75 DALI_ENUM_TO_STRING( USE_ASSIGNED_SIZE )
76 DALI_ENUM_TO_STRING_TABLE_END( Type )
78 } // unnamed namespace
81 namespace SizeScalePolicy
85 // Enumeration to / from string conversion tables
86 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )
87 DALI_ENUM_TO_STRING( USE_SIZE_SET )
88 DALI_ENUM_TO_STRING( FIT_WITH_ASPECT_RATIO )
89 DALI_ENUM_TO_STRING( FILL_WITH_ASPECT_RATIO )
90 DALI_ENUM_TO_STRING_TABLE_END( Type )
91 } // unnamed namespace
97 unsigned int Actor::mActorCounter = 0;
101 /// Using a function because of library initialisation order. Vector3::ONE may not have been initialised yet.
102 inline const Vector3& GetDefaultSizeModeFactor()
107 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
108 inline const Vector2& GetDefaultPreferredSize()
110 return Vector2::ZERO;
113 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
114 inline const Vector2& GetDefaultDimensionPadding()
116 return Vector2::ZERO;
119 const SizeScalePolicy::Type DEFAULT_SIZE_SCALE_POLICY = SizeScalePolicy::USE_SIZE_SET;
121 } // unnamed namespace
124 * Struct to collect relayout variables
126 struct Actor::RelayoutData
129 : sizeModeFactor( GetDefaultSizeModeFactor() ), preferredSize( GetDefaultPreferredSize() ), sizeSetPolicy( DEFAULT_SIZE_SCALE_POLICY ), relayoutEnabled( false ), insideRelayout( false )
131 // Set size negotiation defaults
132 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
134 resizePolicies[ i ] = ResizePolicy::DEFAULT;
135 negotiatedDimensions[ i ] = 0.0f;
136 dimensionNegotiated[ i ] = false;
137 dimensionDirty[ i ] = false;
138 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
139 dimensionPadding[ i ] = GetDefaultDimensionPadding();
140 minimumSize[ i ] = 0.0f;
141 maximumSize[ i ] = FLT_MAX;
145 ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies
147 Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies
149 Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
151 float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
153 float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be
154 float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be
156 bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated
157 bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
159 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
161 Vector2 preferredSize; ///< The preferred size of the actor
163 SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
165 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
166 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
169 namespace // unnamed namespace
175 * We want to discourage the use of property strings (minimize string comparisons),
176 * particularly for the default properties.
177 * Name Type writable animatable constraint-input enum for index-checking
179 DALI_PROPERTY_TABLE_BEGIN
180 DALI_PROPERTY( "parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
181 DALI_PROPERTY( "parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
182 DALI_PROPERTY( "parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
183 DALI_PROPERTY( "parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
184 DALI_PROPERTY( "anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
185 DALI_PROPERTY( "anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
186 DALI_PROPERTY( "anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
187 DALI_PROPERTY( "anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
188 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
189 DALI_PROPERTY( "sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
190 DALI_PROPERTY( "sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
191 DALI_PROPERTY( "sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
192 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
193 DALI_PROPERTY( "positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
194 DALI_PROPERTY( "positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
195 DALI_PROPERTY( "positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
196 DALI_PROPERTY( "worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
197 DALI_PROPERTY( "worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
198 DALI_PROPERTY( "worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
199 DALI_PROPERTY( "worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
200 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
201 DALI_PROPERTY( "worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
202 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
203 DALI_PROPERTY( "scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
204 DALI_PROPERTY( "scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
205 DALI_PROPERTY( "scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
206 DALI_PROPERTY( "worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
207 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
208 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
209 DALI_PROPERTY( "colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
210 DALI_PROPERTY( "colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
211 DALI_PROPERTY( "colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
212 DALI_PROPERTY( "colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
213 DALI_PROPERTY( "worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
214 DALI_PROPERTY( "worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
215 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
216 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
217 DALI_PROPERTY( "leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
218 DALI_PROPERTY( "inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
219 DALI_PROPERTY( "inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
220 DALI_PROPERTY( "colorMode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
221 DALI_PROPERTY( "positionInheritance", STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE )
222 DALI_PROPERTY( "drawMode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
223 DALI_PROPERTY( "sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
224 DALI_PROPERTY( "widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
225 DALI_PROPERTY( "heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
226 DALI_PROPERTY( "sizeScalePolicy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
227 DALI_PROPERTY( "widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
228 DALI_PROPERTY( "heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
229 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
230 DALI_PROPERTY( "minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
231 DALI_PROPERTY( "maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
232 DALI_PROPERTY( "inheritPosition", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_POSITION )
233 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
237 const char* const SIGNAL_TOUCHED = "touched";
238 const char* const SIGNAL_HOVERED = "hovered";
239 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
240 const char* const SIGNAL_ON_STAGE = "onStage";
241 const char* const SIGNAL_OFF_STAGE = "offStage";
242 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
246 const char* const ACTION_SHOW = "show";
247 const char* const ACTION_HIDE = "hide";
249 BaseHandle CreateActor()
251 return Dali::Actor::New();
254 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
256 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
257 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
258 SignalConnectorType signalConnector3( mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal );
259 SignalConnectorType signalConnector4( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
260 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
261 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
263 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
264 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
267 * @brief Extract a given dimension from a Vector2
269 * @param[in] values The values to extract from
270 * @param[in] dimension The dimension to extract
271 * @return Return the value for the dimension
273 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
277 case Dimension::WIDTH:
281 case Dimension::HEIGHT:
283 return values.height;
294 * @brief Extract a given dimension from a Vector3
296 * @param[in] values The values to extract from
297 * @param[in] dimension The dimension to extract
298 * @return Return the value for the dimension
300 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
302 return GetDimensionValue( values.GetVectorXY(), dimension );
306 } // unnamed namespace
308 ActorPtr Actor::New()
310 ActorPtr actor( new Actor( BASIC ) );
312 // Second-phase construction
318 const std::string& Actor::GetName() const
323 void Actor::SetName( const std::string& name )
329 // ATTENTION: string for debug purposes is not thread safe.
330 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
334 unsigned int Actor::GetId() const
339 void Actor::Attach( ActorAttachment& attachment )
341 DALI_ASSERT_DEBUG( !mAttachment && "An Actor can only have one attachment" );
345 attachment.Connect();
348 mAttachment = ActorAttachmentPtr( &attachment );
351 ActorAttachmentPtr Actor::GetAttachment()
356 bool Actor::OnStage() const
361 Dali::Layer Actor::GetLayer()
365 // Short-circuit for Layer derived actors
368 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
371 // Find the immediate Layer parent
372 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
374 if( parent->IsLayer() )
376 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
383 void Actor::Add( Actor& child )
385 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
386 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
390 mChildren = new ActorContainer;
393 Actor* const oldParent( child.mParent );
395 // child might already be ours
396 if( this != oldParent )
398 // if we already have parent, unparent us first
401 oldParent->Remove( child ); // This causes OnChildRemove callback
403 // Old parent may need to readjust to missing child
404 if( oldParent->RelayoutDependentOnChildren() )
406 oldParent->RelayoutRequest();
410 // Guard against Add() during previous OnChildRemove callback
413 // Do this first, since user callbacks from within SetParent() may need to remove child
414 mChildren->push_back( ActorPtr( &child ) );
416 // SetParent asserts that child can be added
417 child.SetParent( this );
419 // Notification for derived classes
422 // Only put in a relayout request if there is a suitable dependency
423 if( RelayoutDependentOnChildren() )
431 void Actor::Remove( Actor& child )
433 if( (this == &child) || (!mChildren) )
435 // no children or removing itself
441 // Find the child in mChildren, and unparent it
442 ActorIter end = mChildren->end();
443 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
445 ActorPtr actor = (*iter);
447 if( actor.Get() == &child )
449 // Keep handle for OnChildRemove notification
452 // Do this first, since user callbacks from within SetParent() may need to add the child
453 mChildren->erase( iter );
455 DALI_ASSERT_DEBUG( actor->GetParent() == this );
456 actor->SetParent( NULL );
464 // Notification for derived classes
465 OnChildRemove( *(removed.Get()) );
467 // Only put in a relayout request if there is a suitable dependency
468 if( RelayoutDependentOnChildren() )
475 void Actor::Unparent()
479 // Remove this actor from the parent. The remove will put a relayout request in for
480 // the parent if required
481 mParent->Remove( *this );
482 // mParent is now NULL!
486 unsigned int Actor::GetChildCount() const
488 return ( NULL != mChildren ) ? mChildren->size() : 0;
491 ActorPtr Actor::GetChildAt( unsigned int index ) const
493 DALI_ASSERT_ALWAYS( index < GetChildCount() );
495 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
498 ActorPtr Actor::FindChildByName( const std::string& actorName )
501 if( actorName == mName )
507 ActorIter end = mChildren->end();
508 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
510 child = (*iter)->FindChildByName( actorName );
521 ActorPtr Actor::FindChildById( const unsigned int id )
530 ActorIter end = mChildren->end();
531 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
533 child = (*iter)->FindChildById( id );
544 void Actor::SetParentOrigin( const Vector3& origin )
548 // mNode is being used in a separate thread; queue a message to set the value & base value
549 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
552 // Cache for event-thread access
555 // not allocated, check if different from default
556 if( ParentOrigin::DEFAULT != origin )
558 mParentOrigin = new Vector3( origin );
563 // check if different from current costs more than just set
564 *mParentOrigin = origin;
568 void Actor::SetParentOriginX( float x )
570 const Vector3& current = GetCurrentParentOrigin();
572 SetParentOrigin( Vector3( x, current.y, current.z ) );
575 void Actor::SetParentOriginY( float y )
577 const Vector3& current = GetCurrentParentOrigin();
579 SetParentOrigin( Vector3( current.x, y, current.z ) );
582 void Actor::SetParentOriginZ( float z )
584 const Vector3& current = GetCurrentParentOrigin();
586 SetParentOrigin( Vector3( current.x, current.y, z ) );
589 const Vector3& Actor::GetCurrentParentOrigin() const
591 // Cached for event-thread access
592 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
595 void Actor::SetAnchorPoint( const Vector3& anchor )
599 // mNode is being used in a separate thread; queue a message to set the value & base value
600 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
603 // Cache for event-thread access
606 // not allocated, check if different from default
607 if( AnchorPoint::DEFAULT != anchor )
609 mAnchorPoint = new Vector3( anchor );
614 // check if different from current costs more than just set
615 *mAnchorPoint = anchor;
619 void Actor::SetAnchorPointX( float x )
621 const Vector3& current = GetCurrentAnchorPoint();
623 SetAnchorPoint( Vector3( x, current.y, current.z ) );
626 void Actor::SetAnchorPointY( float y )
628 const Vector3& current = GetCurrentAnchorPoint();
630 SetAnchorPoint( Vector3( current.x, y, current.z ) );
633 void Actor::SetAnchorPointZ( float z )
635 const Vector3& current = GetCurrentAnchorPoint();
637 SetAnchorPoint( Vector3( current.x, current.y, z ) );
640 const Vector3& Actor::GetCurrentAnchorPoint() const
642 // Cached for event-thread access
643 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
646 void Actor::SetPosition( float x, float y )
648 SetPosition( Vector3( x, y, 0.0f ) );
651 void Actor::SetPosition( float x, float y, float z )
653 SetPosition( Vector3( x, y, z ) );
656 void Actor::SetPosition( const Vector3& position )
658 mTargetPosition = position;
662 // mNode is being used in a separate thread; queue a message to set the value & base value
663 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::Bake, position );
667 void Actor::SetX( float x )
669 mTargetPosition.x = x;
673 // mNode is being used in a separate thread; queue a message to set the value & base value
674 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeX, x );
678 void Actor::SetY( float y )
680 mTargetPosition.y = y;
684 // mNode is being used in a separate thread; queue a message to set the value & base value
685 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeY, y );
689 void Actor::SetZ( float z )
691 mTargetPosition.z = z;
695 // mNode is being used in a separate thread; queue a message to set the value & base value
696 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeZ, z );
700 void Actor::TranslateBy( const Vector3& distance )
702 mTargetPosition += distance;
706 // mNode is being used in a separate thread; queue a message to set the value & base value
707 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeRelative, distance );
711 const Vector3& Actor::GetCurrentPosition() const
715 // mNode is being used in a separate thread; copy the value from the previous update
716 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
719 return Vector3::ZERO;
722 const Vector3& Actor::GetTargetPosition() const
724 return mTargetPosition;
727 const Vector3& Actor::GetCurrentWorldPosition() const
731 // mNode is being used in a separate thread; copy the value from the previous update
732 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
735 return Vector3::ZERO;
738 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
740 // this flag is not animatable so keep the value
741 mPositionInheritanceMode = mode;
744 // mNode is being used in a separate thread; queue a message to set the value
745 SetPositionInheritanceModeMessage( GetEventThreadServices(), *mNode, mode );
749 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
751 // Cached for event-thread access
752 return mPositionInheritanceMode;
755 void Actor::SetInheritPosition( bool inherit )
757 mInheritPosition = inherit;
760 SetInheritPositionMessage( GetEventThreadServices(), *mNode, inherit );
764 bool Actor::IsPositionInherited() const
766 return mInheritPosition;
769 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
771 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
772 normalizedAxis.Normalize();
774 Quaternion orientation( angle, normalizedAxis );
776 SetOrientation( orientation );
779 void Actor::SetOrientation( const Quaternion& orientation )
783 // mNode is being used in a separate thread; queue a message to set the value & base value
784 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::Bake, orientation );
788 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
792 // mNode is being used in a separate thread; queue a message to set the value & base value
793 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, Quaternion(angle, axis) );
797 void Actor::RotateBy( const Quaternion& relativeRotation )
801 // mNode is being used in a separate thread; queue a message to set the value & base value
802 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, relativeRotation );
806 const Quaternion& Actor::GetCurrentOrientation() const
810 // mNode is being used in a separate thread; copy the value from the previous update
811 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
814 return Quaternion::IDENTITY;
817 const Quaternion& Actor::GetCurrentWorldOrientation() const
821 // mNode is being used in a separate thread; copy the value from the previous update
822 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
825 return Quaternion::IDENTITY;
828 void Actor::SetScale( float scale )
830 SetScale( Vector3( scale, scale, scale ) );
833 void Actor::SetScale( float x, float y, float z )
835 SetScale( Vector3( x, y, z ) );
838 void Actor::SetScale( const Vector3& scale )
842 // mNode is being used in a separate thread; queue a message to set the value & base value
843 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::Bake, scale );
847 void Actor::SetScaleX( float x )
851 // mNode is being used in a separate thread; queue a message to set the value & base value
852 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeX, x );
856 void Actor::SetScaleY( float y )
860 // mNode is being used in a separate thread; queue a message to set the value & base value
861 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeY, y );
865 void Actor::SetScaleZ( float z )
869 // mNode is being used in a separate thread; queue a message to set the value & base value
870 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeZ, z );
874 void Actor::ScaleBy(const Vector3& relativeScale)
878 // mNode is being used in a separate thread; queue a message to set the value & base value
879 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeRelativeMultiply, relativeScale );
883 const Vector3& Actor::GetCurrentScale() const
887 // mNode is being used in a separate thread; copy the value from the previous update
888 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
894 const Vector3& Actor::GetCurrentWorldScale() const
898 // mNode is being used in a separate thread; copy the value from the previous update
899 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
905 void Actor::SetInheritScale( bool inherit )
907 // non animateable so keep local copy
908 mInheritScale = inherit;
911 // mNode is being used in a separate thread; queue a message to set the value
912 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
916 bool Actor::IsScaleInherited() const
918 return mInheritScale;
921 Matrix Actor::GetCurrentWorldMatrix() const
925 // World matrix is no longer updated unless there is something observing the node.
926 // Need to calculate it from node's world position, orientation and scale:
927 BufferIndex updateBufferIndex = GetEventThreadServices().GetEventBufferIndex();
928 Matrix worldMatrix(false);
929 worldMatrix.SetTransformComponents( mNode->GetWorldScale( updateBufferIndex ),
930 mNode->GetWorldOrientation( updateBufferIndex ),
931 mNode->GetWorldPosition( updateBufferIndex ) );
935 return Matrix::IDENTITY;
938 void Actor::SetVisible( bool visible )
942 // mNode is being used in a separate thread; queue a message to set the value & base value
943 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
947 bool Actor::IsVisible() const
951 // mNode is being used in a separate thread; copy the value from the previous update
952 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
958 void Actor::SetOpacity( float opacity )
962 // mNode is being used in a separate thread; queue a message to set the value & base value
963 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
967 float Actor::GetCurrentOpacity() const
971 // mNode is being used in a separate thread; copy the value from the previous update
972 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
978 const Vector4& Actor::GetCurrentWorldColor() const
982 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
988 void Actor::SetColor( const Vector4& color )
992 // mNode is being used in a separate thread; queue a message to set the value & base value
993 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
997 void Actor::SetColorRed( float red )
1001 // mNode is being used in a separate thread; queue a message to set the value & base value
1002 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1006 void Actor::SetColorGreen( float green )
1010 // mNode is being used in a separate thread; queue a message to set the value & base value
1011 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1015 void Actor::SetColorBlue( float blue )
1019 // mNode is being used in a separate thread; queue a message to set the value & base value
1020 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1024 const Vector4& Actor::GetCurrentColor() const
1028 // mNode is being used in a separate thread; copy the value from the previous update
1029 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1032 return Color::WHITE;
1035 void Actor::SetInheritOrientation( bool inherit )
1037 // non animateable so keep local copy
1038 mInheritOrientation = inherit;
1041 // mNode is being used in a separate thread; queue a message to set the value
1042 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1046 bool Actor::IsOrientationInherited() const
1048 return mInheritOrientation;
1051 void Actor::SetSizeModeFactor( const Vector3& factor )
1053 EnsureRelayoutData();
1055 mRelayoutData->sizeModeFactor = factor;
1058 const Vector3& Actor::GetSizeModeFactor() const
1060 if ( mRelayoutData )
1062 return mRelayoutData->sizeModeFactor;
1065 return GetDefaultSizeModeFactor();
1068 void Actor::SetColorMode( ColorMode colorMode )
1070 // non animateable so keep local copy
1071 mColorMode = colorMode;
1074 // mNode is being used in a separate thread; queue a message to set the value
1075 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1079 ColorMode Actor::GetColorMode() const
1081 // we have cached copy
1085 void Actor::SetSize( float width, float height )
1087 SetSize( Vector2( width, height ) );
1090 void Actor::SetSize( float width, float height, float depth )
1092 SetSize( Vector3( width, height, depth ) );
1095 void Actor::SetSize( const Vector2& size )
1097 SetSize( Vector3( size.width, size.height, 0.f ) );
1100 void Actor::SetSizeInternal( const Vector2& size )
1102 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1105 void Actor::SetSize( const Vector3& size )
1107 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1109 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1110 SetPreferredSize( size.GetVectorXY() );
1114 SetSizeInternal( size );
1118 void Actor::SetSizeInternal( const Vector3& size )
1120 // dont allow recursive loop
1121 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1122 // check that we have a node AND the new size width, height or depth is at least a little bit different from the old one
1123 if( ( NULL != mNode )&&
1124 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1125 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1126 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1130 // mNode is being used in a separate thread; queue a message to set the value & base value
1131 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::Bake, mTargetSize );
1133 // Notification for derived classes
1134 mInsideOnSizeSet = true;
1135 OnSizeSet( mTargetSize );
1136 mInsideOnSizeSet = false;
1138 // Raise a relayout request if the flag is not locked
1139 if( mRelayoutData && !mRelayoutData->insideRelayout )
1146 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1148 mTargetSize = targetSize;
1150 // Notify deriving classes
1151 OnSizeAnimation( animation, mTargetSize );
1154 void Actor::NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property )
1156 if ( Dali::Actor::Property::SIZE_WIDTH == property )
1158 mTargetSize.width = targetSize;
1160 else if ( Dali::Actor::Property::SIZE_HEIGHT == property )
1162 mTargetSize.height = targetSize;
1164 else if ( Dali::Actor::Property::SIZE_DEPTH == property )
1166 mTargetSize.depth = targetSize;
1168 // Notify deriving classes
1169 OnSizeAnimation( animation, mTargetSize );
1172 void Actor::NotifyPositionAnimation( Animation& animation, const Vector3& targetPosition )
1174 mTargetPosition = targetPosition;
1177 void Actor::NotifyPositionAnimation( Animation& animation, float targetPosition, Property::Index property )
1179 if ( Dali::Actor::Property::POSITION_X == property )
1181 mTargetPosition.x = targetPosition;
1183 else if ( Dali::Actor::Property::POSITION_Y == property )
1185 mTargetPosition.y = targetPosition;
1187 else if ( Dali::Actor::Property::POSITION_Z == property )
1189 mTargetPosition.z = targetPosition;
1193 void Actor::SetWidth( float width )
1195 mTargetSize.width = width;
1199 // mNode is being used in a separate thread; queue a message to set the value & base value
1200 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeX, width );
1204 void Actor::SetHeight( float height )
1206 mTargetSize.height = height;
1210 // mNode is being used in a separate thread; queue a message to set the value & base value
1211 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeY, height );
1215 void Actor::SetDepth( float depth )
1217 mTargetSize.depth = depth;
1221 // mNode is being used in a separate thread; queue a message to set the value & base value
1222 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeZ, depth );
1226 const Vector3& Actor::GetTargetSize() const
1231 const Vector3& Actor::GetCurrentSize() const
1235 // mNode is being used in a separate thread; copy the value from the previous update
1236 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1239 return Vector3::ZERO;
1242 Vector3 Actor::GetNaturalSize() const
1244 // It is up to deriving classes to return the appropriate natural size
1245 return Vector3( 0.0f, 0.0f, 0.0f );
1248 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1250 EnsureRelayoutData();
1252 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1254 if( dimension & ( 1 << i ) )
1256 mRelayoutData->resizePolicies[ i ] = policy;
1260 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1262 if( dimension & Dimension::WIDTH )
1264 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1267 if( dimension & Dimension::HEIGHT )
1269 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1273 // If calling SetResizePolicy, assume we want relayout enabled
1274 SetRelayoutEnabled( true );
1276 OnSetResizePolicy( policy, dimension );
1278 // Trigger relayout on this control
1282 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1284 if ( mRelayoutData )
1286 // If more than one dimension is requested, just return the first one found
1287 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1289 if( ( dimension & ( 1 << i ) ) )
1291 return mRelayoutData->resizePolicies[ i ];
1296 return ResizePolicy::DEFAULT;
1299 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1301 EnsureRelayoutData();
1303 mRelayoutData->sizeSetPolicy = policy;
1306 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1308 if ( mRelayoutData )
1310 return mRelayoutData->sizeSetPolicy;
1313 return DEFAULT_SIZE_SCALE_POLICY;
1316 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1318 EnsureRelayoutData();
1320 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1322 if( dimension & ( 1 << i ) )
1324 mRelayoutData->dimensionDependencies[ i ] = dependency;
1329 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1331 if ( mRelayoutData )
1333 // If more than one dimension is requested, just return the first one found
1334 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1336 if( ( dimension & ( 1 << i ) ) )
1338 return mRelayoutData->dimensionDependencies[ i ];
1343 return Dimension::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::Type dimension )
1367 EnsureRelayoutData();
1369 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1371 if( dimension & ( 1 << i ) )
1373 mRelayoutData->dimensionDirty[ i ] = dirty;
1378 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1380 if ( mRelayoutData )
1382 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1384 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1394 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1396 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1399 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1401 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1404 unsigned int Actor::AddRenderer( Renderer& renderer )
1408 mRenderers = new RendererContainer;
1411 unsigned int index = mRenderers->size();
1412 RendererPtr rendererPtr = RendererPtr( &renderer );
1413 mRenderers->push_back( rendererPtr );
1414 AddRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1418 rendererPtr->Connect();
1424 unsigned int Actor::GetRendererCount() const
1426 unsigned int rendererCount(0);
1429 rendererCount = mRenderers->size();
1432 return rendererCount;
1435 RendererPtr Actor::GetRendererAt( unsigned int index )
1437 RendererPtr renderer;
1438 if( index < GetRendererCount() )
1440 renderer = ( *mRenderers )[ index ];
1446 void Actor::RemoveRenderer( Renderer& renderer )
1450 RendererIter end = mRenderers->end();
1451 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1453 if( (*iter).Get() == &renderer )
1455 mRenderers->erase( iter );
1456 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1463 void Actor::RemoveRenderer( unsigned int index )
1465 if( index < GetRendererCount() )
1467 RendererPtr renderer = ( *mRenderers )[ index ];
1468 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.Get()->GetRendererSceneObject() );
1469 mRenderers->erase( mRenderers->begin()+index );
1473 void Actor::SetOverlay( bool enable )
1475 // Setting STENCIL will override OVERLAY_2D
1476 if( DrawMode::STENCIL != mDrawMode )
1478 SetDrawMode( enable ? DrawMode::OVERLAY_2D : DrawMode::NORMAL );
1482 bool Actor::IsOverlay() const
1484 return ( DrawMode::OVERLAY_2D == mDrawMode );
1487 void Actor::SetDrawMode( DrawMode::Type drawMode )
1489 // this flag is not animatable so keep the value
1490 mDrawMode = drawMode;
1493 // mNode is being used in a separate thread; queue a message to set the value
1494 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1498 DrawMode::Type Actor::GetDrawMode() const
1503 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1505 // only valid when on-stage
1506 StagePtr stage = Stage::GetCurrent();
1507 if( stage && OnStage() )
1509 const RenderTaskList& taskList = stage->GetRenderTaskList();
1511 Vector2 converted( screenX, screenY );
1513 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1514 const int taskCount = taskList.GetTaskCount();
1515 for( int i = taskCount - 1; i >= 0; --i )
1517 Dali::RenderTask task = taskList.GetTask( i );
1518 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1520 // found a task where this conversion was ok so return
1528 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1530 bool retval = false;
1531 // only valid when on-stage
1534 CameraActor* camera = renderTask.GetCameraActor();
1538 renderTask.GetViewport( viewport );
1540 // need to translate coordinates to render tasks coordinate space
1541 Vector2 converted( screenX, screenY );
1542 if( renderTask.TranslateCoordinates( converted ) )
1544 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1551 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1553 // Early-out if mNode is NULL
1559 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1561 // Calculate the ModelView matrix
1562 Matrix modelView( false/*don't init*/);
1563 // need to use the components as world matrix is only updated for actors that need it
1564 modelView.SetTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1565 Matrix::Multiply( modelView, modelView, viewMatrix );
1567 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1568 Matrix invertedMvp( false/*don't init*/);
1569 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1570 bool success = invertedMvp.Invert();
1572 // Convert to GL coordinates
1573 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1578 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1585 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1591 if( XyPlaneIntersect( nearPos, farPos, local ) )
1593 Vector3 size = GetCurrentSize();
1594 localX = local.x + size.x * 0.5f;
1595 localY = local.y + size.y * 0.5f;
1606 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1609 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1611 Mathematical Formulation
1613 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1615 ( p - c ) dot ( p - c ) = r^2
1617 Given a ray with a point of origin 'o', and a direction vector 'd':
1619 ray(t) = o + td, t >= 0
1621 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1623 (o + td - c ) dot ( o + td - c ) = r^2
1625 To solve for t we first expand the above into a more recognisable quadratic equation form
1627 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1636 B = 2( o - c ) dot d
1637 C = ( o - c ) dot ( o - c ) - r^2
1639 which can be solved using a standard quadratic formula.
1641 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1643 Practical Simplification
1645 In a renderer, we often differentiate between world space and object space. In the object space
1646 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1647 into object space, the mathematical solution presented above can be simplified significantly.
1649 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1653 and we can find the t at which the (transformed) ray intersects the sphere by
1655 ( o + td ) dot ( o + td ) = r^2
1657 According to the reasoning above, we expand the above quadratic equation into the general form
1661 which now has coefficients:
1668 // Early out if mNode is NULL
1674 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1676 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1677 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1678 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1680 // Compute the radius is not needed, square radius it's enough.
1681 const Vector3& size( mNode->GetSize( bufferIndex ) );
1683 // Scale the sphere.
1684 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1686 const float width = size.width * scale.width;
1687 const float height = size.height * scale.height;
1689 float squareSphereRadius = 0.5f * ( width * width + height * height );
1691 float a = rayDir.Dot( rayDir ); // a
1692 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1693 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1695 return ( b2 * b2 - a * c ) >= 0.f;
1698 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
1705 // Transforms the ray to the local reference system.
1706 // Calculate the inverse of Model matrix
1707 Matrix invModelMatrix( false/*don't init*/);
1709 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1710 // need to use the components as world matrix is only updated for actors that need it
1711 invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1713 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1714 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1716 // Test with the actor's XY plane (Normal = 0 0 1 1).
1718 float a = -rayOriginLocal.z;
1719 float b = rayDirLocal.z;
1721 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1723 // Ray travels distance * rayDirLocal to intersect with plane.
1726 const Vector3& size = mNode->GetSize( bufferIndex );
1728 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1729 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1731 // Test with the actor's geometry.
1732 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1739 void Actor::SetLeaveRequired( bool required )
1741 mLeaveRequired = required;
1744 bool Actor::GetLeaveRequired() const
1746 return mLeaveRequired;
1749 void Actor::SetKeyboardFocusable( bool focusable )
1751 mKeyboardFocusable = focusable;
1754 bool Actor::IsKeyboardFocusable() const
1756 return mKeyboardFocusable;
1759 bool Actor::GetTouchRequired() const
1761 return !mTouchedSignal.Empty() || mDerivedRequiresTouch;
1764 bool Actor::GetHoverRequired() const
1766 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1769 bool Actor::GetWheelEventRequired() const
1771 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1774 bool Actor::IsHittable() const
1776 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1779 ActorGestureData& Actor::GetGestureData()
1781 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1782 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1783 if( NULL == mGestureData )
1785 mGestureData = new ActorGestureData;
1787 return *mGestureData;
1790 bool Actor::IsGestureRequred( Gesture::Type type ) const
1792 return mGestureData && mGestureData->IsGestureRequred( type );
1795 bool Actor::EmitTouchEventSignal( const TouchEvent& event )
1797 bool consumed = false;
1799 if( !mTouchedSignal.Empty() )
1801 Dali::Actor handle( this );
1802 consumed = mTouchedSignal.Emit( handle, event );
1807 // Notification for derived classes
1808 consumed = OnTouchEvent( event );
1814 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1816 bool consumed = false;
1818 if( !mHoveredSignal.Empty() )
1820 Dali::Actor handle( this );
1821 consumed = mHoveredSignal.Emit( handle, event );
1826 // Notification for derived classes
1827 consumed = OnHoverEvent( event );
1833 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1835 bool consumed = false;
1837 if( !mWheelEventSignal.Empty() )
1839 Dali::Actor handle( this );
1840 consumed = mWheelEventSignal.Emit( handle, event );
1845 // Notification for derived classes
1846 consumed = OnWheelEvent( event );
1852 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
1854 return mTouchedSignal;
1857 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
1859 return mHoveredSignal;
1862 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
1864 return mWheelEventSignal;
1867 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
1869 return mOnStageSignal;
1872 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
1874 return mOffStageSignal;
1877 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
1879 return mOnRelayoutSignal;
1882 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1884 bool connected( true );
1885 Actor* actor = dynamic_cast< Actor* >( object );
1887 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1889 actor->TouchedSignal().Connect( tracker, functor );
1891 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1893 actor->HoveredSignal().Connect( tracker, functor );
1895 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1897 actor->WheelEventSignal().Connect( tracker, functor );
1899 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
1901 actor->OnStageSignal().Connect( tracker, functor );
1903 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
1905 actor->OffStageSignal().Connect( tracker, functor );
1907 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
1909 actor->OnRelayoutSignal().Connect( tracker, functor );
1913 // signalName does not match any signal
1920 Actor::Actor( DerivedType derivedType )
1925 mParentOrigin( NULL ),
1926 mAnchorPoint( NULL ),
1927 mRelayoutData( NULL ),
1928 mGestureData( NULL ),
1930 mTargetSize( 0.0f, 0.0f, 0.0f ),
1932 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
1934 mIsRoot( ROOT_LAYER == derivedType ),
1935 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
1936 mIsOnStage( false ),
1938 mLeaveRequired( false ),
1939 mKeyboardFocusable( false ),
1940 mDerivedRequiresTouch( false ),
1941 mDerivedRequiresHover( false ),
1942 mDerivedRequiresWheelEvent( false ),
1943 mOnStageSignalled( false ),
1944 mInsideOnSizeSet( false ),
1945 mInheritPosition( true ),
1946 mInheritOrientation( true ),
1947 mInheritScale( true ),
1948 mDrawMode( DrawMode::NORMAL ),
1949 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
1950 mColorMode( Node::DEFAULT_COLOR_MODE )
1954 void Actor::Initialize()
1957 SceneGraph::Node* node = CreateNode();
1959 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
1960 mNode = node; // Keep raw-pointer to Node
1964 GetEventThreadServices().RegisterObject( this );
1969 // Remove mParent pointers from children even if we're destroying core,
1970 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1973 ActorConstIter endIter = mChildren->end();
1974 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1976 (*iter)->SetParent( NULL );
1982 // Guard to allow handle destruction after Core has been destroyed
1983 if( EventThreadServices::IsCoreRunning() )
1987 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
1988 mNode = NULL; // Node is about to be destroyed
1991 GetEventThreadServices().UnregisterObject( this );
1994 // Cleanup optional gesture data
1995 delete mGestureData;
1997 // Cleanup optional parent origin and anchor
1998 delete mParentOrigin;
1999 delete mAnchorPoint;
2001 // Delete optional relayout data
2004 delete mRelayoutData;
2008 void Actor::ConnectToStage( unsigned int parentDepth )
2010 // This container is used instead of walking the Actor hierarchy.
2011 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
2012 ActorContainer connectionList;
2014 // This stage is atomic i.e. not interrupted by user callbacks.
2015 RecursiveConnectToStage( connectionList, parentDepth + 1 );
2017 // Notify applications about the newly connected actors.
2018 const ActorIter endIter = connectionList.end();
2019 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2021 (*iter)->NotifyStageConnection();
2027 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth )
2029 DALI_ASSERT_ALWAYS( !OnStage() );
2034 ConnectToSceneGraph();
2036 // Notification for internal derived classes
2037 OnStageConnectionInternal();
2039 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2040 connectionList.push_back( ActorPtr( this ) );
2042 // Recursively connect children
2045 ActorConstIter endIter = mChildren->end();
2046 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2048 (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
2054 * This method is called when the Actor is connected to the Stage.
2055 * The parent must have added its Node to the scene-graph.
2056 * The child must connect its Node to the parent's Node.
2057 * This is recursive; the child calls ConnectToStage() for its children.
2059 void Actor::ConnectToSceneGraph()
2061 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2065 // Reparent Node in next Update
2066 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode );
2069 // Notify attachment
2072 mAttachment->Connect();
2075 unsigned int rendererCount( GetRendererCount() );
2076 for( unsigned int i(0); i<rendererCount; ++i )
2078 GetRendererAt(i)->Connect();
2081 // Request relayout on all actors that are added to the scenegraph
2084 // Notification for Object::Observers
2088 void Actor::NotifyStageConnection()
2090 // Actors can be removed (in a callback), before the on-stage stage is reported.
2091 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2092 if( OnStage() && !mOnStageSignalled )
2094 // Notification for external (CustomActor) derived classes
2095 OnStageConnectionExternal( mDepth );
2097 if( !mOnStageSignal.Empty() )
2099 Dali::Actor handle( this );
2100 mOnStageSignal.Emit( handle );
2103 // Guard against Remove during callbacks
2106 mOnStageSignalled = true; // signal required next time Actor is removed
2111 void Actor::DisconnectFromStage()
2113 // This container is used instead of walking the Actor hierachy.
2114 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2115 ActorContainer disconnectionList;
2117 // This stage is atomic i.e. not interrupted by user callbacks
2118 RecursiveDisconnectFromStage( disconnectionList );
2120 // Notify applications about the newly disconnected actors.
2121 const ActorIter endIter = disconnectionList.end();
2122 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2124 (*iter)->NotifyStageDisconnection();
2128 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2130 DALI_ASSERT_ALWAYS( OnStage() );
2132 // Recursively disconnect children
2135 ActorConstIter endIter = mChildren->end();
2136 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2138 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2142 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2143 disconnectionList.push_back( ActorPtr( this ) );
2145 // Notification for internal derived classes
2146 OnStageDisconnectionInternal();
2148 DisconnectFromSceneGraph();
2154 * This method is called by an actor or its parent, before a node removal message is sent.
2155 * This is recursive; the child calls DisconnectFromStage() for its children.
2157 void Actor::DisconnectFromSceneGraph()
2159 // Notification for Object::Observers
2160 OnSceneObjectRemove();
2162 // Notify attachment
2165 mAttachment->Disconnect();
2168 unsigned int rendererCount( GetRendererCount() );
2169 for( unsigned int i(0); i<rendererCount; ++i )
2171 GetRendererAt(i)->Disconnect();
2175 void Actor::NotifyStageDisconnection()
2177 // Actors can be added (in a callback), before the off-stage state is reported.
2178 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2179 // only do this step if there is a stage, i.e. Core is not being shut down
2180 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2182 // Notification for external (CustomeActor) derived classes
2183 OnStageDisconnectionExternal();
2185 if( !mOffStageSignal.Empty() )
2187 Dali::Actor handle( this );
2188 mOffStageSignal.Emit( handle );
2191 // Guard against Add during callbacks
2194 mOnStageSignalled = false; // signal required next time Actor is added
2199 bool Actor::IsNodeConnected() const
2201 bool connected( false );
2203 if( OnStage() && ( NULL != mNode ) )
2205 if( IsRoot() || mNode->GetParent() )
2214 unsigned int Actor::GetDefaultPropertyCount() const
2216 return DEFAULT_PROPERTY_COUNT;
2219 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2221 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2223 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2225 indices.PushBack( i );
2229 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2231 if( index < DEFAULT_PROPERTY_COUNT )
2233 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2239 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2241 Property::Index index = Property::INVALID_INDEX;
2243 // Look for name in default properties
2244 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2246 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2247 if( 0 == name.compare( property->name ) )
2257 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2259 if( index < DEFAULT_PROPERTY_COUNT )
2261 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2267 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2269 if( index < DEFAULT_PROPERTY_COUNT )
2271 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2277 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2279 if( index < DEFAULT_PROPERTY_COUNT )
2281 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2287 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2289 if( index < DEFAULT_PROPERTY_COUNT )
2291 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2294 // index out of range...return Property::NONE
2295 return Property::NONE;
2298 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2302 case Dali::Actor::Property::PARENT_ORIGIN:
2304 SetParentOrigin( property.Get< Vector3 >() );
2308 case Dali::Actor::Property::PARENT_ORIGIN_X:
2310 SetParentOriginX( property.Get< float >() );
2314 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2316 SetParentOriginY( property.Get< float >() );
2320 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2322 SetParentOriginZ( property.Get< float >() );
2326 case Dali::Actor::Property::ANCHOR_POINT:
2328 SetAnchorPoint( property.Get< Vector3 >() );
2332 case Dali::Actor::Property::ANCHOR_POINT_X:
2334 SetAnchorPointX( property.Get< float >() );
2338 case Dali::Actor::Property::ANCHOR_POINT_Y:
2340 SetAnchorPointY( property.Get< float >() );
2344 case Dali::Actor::Property::ANCHOR_POINT_Z:
2346 SetAnchorPointZ( property.Get< float >() );
2350 case Dali::Actor::Property::SIZE:
2352 SetSize( property.Get< Vector3 >() );
2356 case Dali::Actor::Property::SIZE_WIDTH:
2358 SetWidth( property.Get< float >() );
2362 case Dali::Actor::Property::SIZE_HEIGHT:
2364 SetHeight( property.Get< float >() );
2368 case Dali::Actor::Property::SIZE_DEPTH:
2370 SetDepth( property.Get< float >() );
2374 case Dali::Actor::Property::POSITION:
2376 SetPosition( property.Get< Vector3 >() );
2380 case Dali::Actor::Property::POSITION_X:
2382 SetX( property.Get< float >() );
2386 case Dali::Actor::Property::POSITION_Y:
2388 SetY( property.Get< float >() );
2392 case Dali::Actor::Property::POSITION_Z:
2394 SetZ( property.Get< float >() );
2398 case Dali::Actor::Property::ORIENTATION:
2400 SetOrientation( property.Get< Quaternion >() );
2404 case Dali::Actor::Property::SCALE:
2406 SetScale( property.Get< Vector3 >() );
2410 case Dali::Actor::Property::SCALE_X:
2412 SetScaleX( property.Get< float >() );
2416 case Dali::Actor::Property::SCALE_Y:
2418 SetScaleY( property.Get< float >() );
2422 case Dali::Actor::Property::SCALE_Z:
2424 SetScaleZ( property.Get< float >() );
2428 case Dali::Actor::Property::VISIBLE:
2430 SetVisible( property.Get< bool >() );
2434 case Dali::Actor::Property::COLOR:
2436 SetColor( property.Get< Vector4 >() );
2440 case Dali::Actor::Property::COLOR_RED:
2442 SetColorRed( property.Get< float >() );
2446 case Dali::Actor::Property::COLOR_GREEN:
2448 SetColorGreen( property.Get< float >() );
2452 case Dali::Actor::Property::COLOR_BLUE:
2454 SetColorBlue( property.Get< float >() );
2458 case Dali::Actor::Property::COLOR_ALPHA:
2460 SetOpacity( property.Get< float >() );
2464 case Dali::Actor::Property::NAME:
2466 SetName( property.Get< std::string >() );
2470 case Dali::Actor::Property::SENSITIVE:
2472 SetSensitive( property.Get< bool >() );
2476 case Dali::Actor::Property::LEAVE_REQUIRED:
2478 SetLeaveRequired( property.Get< bool >() );
2482 case Dali::Actor::Property::INHERIT_POSITION:
2484 SetInheritPosition( property.Get< bool >() );
2488 case Dali::Actor::Property::INHERIT_ORIENTATION:
2490 SetInheritOrientation( property.Get< bool >() );
2494 case Dali::Actor::Property::INHERIT_SCALE:
2496 SetInheritScale( property.Get< bool >() );
2500 case Dali::Actor::Property::COLOR_MODE:
2502 SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2506 case Dali::Actor::Property::POSITION_INHERITANCE:
2508 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2512 case Dali::Actor::Property::DRAW_MODE:
2514 SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2518 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2520 SetSizeModeFactor( property.Get< Vector3 >() );
2524 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2526 ResizePolicy::Type type;
2527 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2529 SetResizePolicy( type, Dimension::WIDTH );
2534 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2536 ResizePolicy::Type type;
2537 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2539 SetResizePolicy( type, Dimension::HEIGHT );
2544 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2546 SizeScalePolicy::Type type;
2547 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount, type ) )
2549 SetSizeScalePolicy( type );
2554 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2556 if( property.Get< bool >() )
2558 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2563 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2565 if( property.Get< bool >() )
2567 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2572 case Dali::Actor::Property::PADDING:
2574 Vector4 padding = property.Get< Vector4 >();
2575 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2576 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2580 case Dali::Actor::Property::MINIMUM_SIZE:
2582 Vector2 size = property.Get< Vector2 >();
2583 SetMinimumSize( size.x, Dimension::WIDTH );
2584 SetMinimumSize( size.y, Dimension::HEIGHT );
2588 case Dali::Actor::Property::MAXIMUM_SIZE:
2590 Vector2 size = property.Get< Vector2 >();
2591 SetMaximumSize( size.x, Dimension::WIDTH );
2592 SetMaximumSize( size.y, Dimension::HEIGHT );
2598 // this can happen in the case of a non-animatable default property so just do nothing
2604 // TODO: This method needs to be removed
2605 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2607 switch( entry.GetType() )
2609 case Property::BOOLEAN:
2611 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2612 DALI_ASSERT_DEBUG( NULL != property );
2614 // property is being used in a separate thread; queue a message to set the property
2615 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2620 case Property::INTEGER:
2622 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2623 DALI_ASSERT_DEBUG( NULL != property );
2625 // property is being used in a separate thread; queue a message to set the property
2626 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2631 case Property::FLOAT:
2633 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2634 DALI_ASSERT_DEBUG( NULL != property );
2636 // property is being used in a separate thread; queue a message to set the property
2637 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2642 case Property::VECTOR2:
2644 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2645 DALI_ASSERT_DEBUG( NULL != property );
2647 // property is being used in a separate thread; queue a message to set the property
2648 if(entry.componentIndex == 0)
2650 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2652 else if(entry.componentIndex == 1)
2654 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2658 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2664 case Property::VECTOR3:
2666 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2667 DALI_ASSERT_DEBUG( NULL != property );
2669 // property is being used in a separate thread; queue a message to set the property
2670 if(entry.componentIndex == 0)
2672 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2674 else if(entry.componentIndex == 1)
2676 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2678 else if(entry.componentIndex == 2)
2680 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2684 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2690 case Property::VECTOR4:
2692 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2693 DALI_ASSERT_DEBUG( NULL != property );
2695 // property is being used in a separate thread; queue a message to set the property
2696 if(entry.componentIndex == 0)
2698 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
2700 else if(entry.componentIndex == 1)
2702 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
2704 else if(entry.componentIndex == 2)
2706 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
2708 else if(entry.componentIndex == 3)
2710 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
2714 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2720 case Property::ROTATION:
2722 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
2723 DALI_ASSERT_DEBUG( NULL != property );
2725 // property is being used in a separate thread; queue a message to set the property
2726 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
2731 case Property::MATRIX:
2733 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
2734 DALI_ASSERT_DEBUG( NULL != property );
2736 // property is being used in a separate thread; queue a message to set the property
2737 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
2742 case Property::MATRIX3:
2744 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
2745 DALI_ASSERT_DEBUG( NULL != property );
2747 // property is being used in a separate thread; queue a message to set the property
2748 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
2755 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
2761 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
2763 Property::Value value;
2767 case Dali::Actor::Property::PARENT_ORIGIN:
2769 value = GetCurrentParentOrigin();
2773 case Dali::Actor::Property::PARENT_ORIGIN_X:
2775 value = GetCurrentParentOrigin().x;
2779 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2781 value = GetCurrentParentOrigin().y;
2785 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2787 value = GetCurrentParentOrigin().z;
2791 case Dali::Actor::Property::ANCHOR_POINT:
2793 value = GetCurrentAnchorPoint();
2797 case Dali::Actor::Property::ANCHOR_POINT_X:
2799 value = GetCurrentAnchorPoint().x;
2803 case Dali::Actor::Property::ANCHOR_POINT_Y:
2805 value = GetCurrentAnchorPoint().y;
2809 case Dali::Actor::Property::ANCHOR_POINT_Z:
2811 value = GetCurrentAnchorPoint().z;
2815 case Dali::Actor::Property::SIZE:
2817 value = GetTargetSize();
2821 case Dali::Actor::Property::SIZE_WIDTH:
2823 value = GetTargetSize().width;
2827 case Dali::Actor::Property::SIZE_HEIGHT:
2829 value = GetTargetSize().height;
2833 case Dali::Actor::Property::SIZE_DEPTH:
2835 value = GetTargetSize().depth;
2839 case Dali::Actor::Property::POSITION:
2841 value = GetTargetPosition();
2845 case Dali::Actor::Property::POSITION_X:
2847 value = GetTargetPosition().x;
2851 case Dali::Actor::Property::POSITION_Y:
2853 value = GetTargetPosition().y;
2857 case Dali::Actor::Property::POSITION_Z:
2859 value = GetTargetPosition().z;
2863 case Dali::Actor::Property::WORLD_POSITION:
2865 value = GetCurrentWorldPosition();
2869 case Dali::Actor::Property::WORLD_POSITION_X:
2871 value = GetCurrentWorldPosition().x;
2875 case Dali::Actor::Property::WORLD_POSITION_Y:
2877 value = GetCurrentWorldPosition().y;
2881 case Dali::Actor::Property::WORLD_POSITION_Z:
2883 value = GetCurrentWorldPosition().z;
2887 case Dali::Actor::Property::ORIENTATION:
2889 value = GetCurrentOrientation();
2893 case Dali::Actor::Property::WORLD_ORIENTATION:
2895 value = GetCurrentWorldOrientation();
2899 case Dali::Actor::Property::SCALE:
2901 value = GetCurrentScale();
2905 case Dali::Actor::Property::SCALE_X:
2907 value = GetCurrentScale().x;
2911 case Dali::Actor::Property::SCALE_Y:
2913 value = GetCurrentScale().y;
2917 case Dali::Actor::Property::SCALE_Z:
2919 value = GetCurrentScale().z;
2923 case Dali::Actor::Property::WORLD_SCALE:
2925 value = GetCurrentWorldScale();
2929 case Dali::Actor::Property::VISIBLE:
2931 value = IsVisible();
2935 case Dali::Actor::Property::COLOR:
2937 value = GetCurrentColor();
2941 case Dali::Actor::Property::COLOR_RED:
2943 value = GetCurrentColor().r;
2947 case Dali::Actor::Property::COLOR_GREEN:
2949 value = GetCurrentColor().g;
2953 case Dali::Actor::Property::COLOR_BLUE:
2955 value = GetCurrentColor().b;
2959 case Dali::Actor::Property::COLOR_ALPHA:
2961 value = GetCurrentColor().a;
2965 case Dali::Actor::Property::WORLD_COLOR:
2967 value = GetCurrentWorldColor();
2971 case Dali::Actor::Property::WORLD_MATRIX:
2973 value = GetCurrentWorldMatrix();
2977 case Dali::Actor::Property::NAME:
2983 case Dali::Actor::Property::SENSITIVE:
2985 value = IsSensitive();
2989 case Dali::Actor::Property::LEAVE_REQUIRED:
2991 value = GetLeaveRequired();
2995 case Dali::Actor::Property::INHERIT_POSITION:
2997 value = IsPositionInherited();
3001 case Dali::Actor::Property::INHERIT_ORIENTATION:
3003 value = IsOrientationInherited();
3007 case Dali::Actor::Property::INHERIT_SCALE:
3009 value = IsScaleInherited();
3013 case Dali::Actor::Property::COLOR_MODE:
3015 value = Scripting::GetColorMode( GetColorMode() );
3019 case Dali::Actor::Property::POSITION_INHERITANCE:
3021 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
3025 case Dali::Actor::Property::DRAW_MODE:
3027 value = Scripting::GetDrawMode( GetDrawMode() );
3031 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3033 value = GetSizeModeFactor();
3037 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3039 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3043 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3045 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3049 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3051 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3055 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3057 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3061 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3063 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3067 case Dali::Actor::Property::PADDING:
3069 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3070 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3071 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3075 case Dali::Actor::Property::MINIMUM_SIZE:
3077 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3081 case Dali::Actor::Property::MAXIMUM_SIZE:
3083 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3089 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3097 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3102 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3104 // This method should only return an object connected to the scene-graph
3105 return OnStage() ? mNode : NULL;
3108 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3110 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3112 const PropertyBase* property( NULL );
3114 // This method should only return a property of an object connected to the scene-graph
3120 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3122 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3123 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3125 property = animatable->GetSceneGraphProperty();
3127 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3129 CustomPropertyMetadata* custom = FindCustomProperty( index );
3130 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3132 property = custom->GetSceneGraphProperty();
3134 else if( NULL != mNode )
3138 case Dali::Actor::Property::SIZE:
3139 property = &mNode->mSize;
3142 case Dali::Actor::Property::SIZE_WIDTH:
3143 property = &mNode->mSize;
3146 case Dali::Actor::Property::SIZE_HEIGHT:
3147 property = &mNode->mSize;
3150 case Dali::Actor::Property::SIZE_DEPTH:
3151 property = &mNode->mSize;
3154 case Dali::Actor::Property::POSITION:
3155 property = &mNode->mPosition;
3158 case Dali::Actor::Property::POSITION_X:
3159 property = &mNode->mPosition;
3162 case Dali::Actor::Property::POSITION_Y:
3163 property = &mNode->mPosition;
3166 case Dali::Actor::Property::POSITION_Z:
3167 property = &mNode->mPosition;
3170 case Dali::Actor::Property::ORIENTATION:
3171 property = &mNode->mOrientation;
3174 case Dali::Actor::Property::SCALE:
3175 property = &mNode->mScale;
3178 case Dali::Actor::Property::SCALE_X:
3179 property = &mNode->mScale;
3182 case Dali::Actor::Property::SCALE_Y:
3183 property = &mNode->mScale;
3186 case Dali::Actor::Property::SCALE_Z:
3187 property = &mNode->mScale;
3190 case Dali::Actor::Property::VISIBLE:
3191 property = &mNode->mVisible;
3194 case Dali::Actor::Property::COLOR:
3195 property = &mNode->mColor;
3198 case Dali::Actor::Property::COLOR_RED:
3199 property = &mNode->mColor;
3202 case Dali::Actor::Property::COLOR_GREEN:
3203 property = &mNode->mColor;
3206 case Dali::Actor::Property::COLOR_BLUE:
3207 property = &mNode->mColor;
3210 case Dali::Actor::Property::COLOR_ALPHA:
3211 property = &mNode->mColor;
3222 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3224 const PropertyInputImpl* property( NULL );
3226 // This method should only return a property of an object connected to the scene-graph
3232 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3234 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3235 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3237 property = animatable->GetSceneGraphProperty();
3239 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3241 CustomPropertyMetadata* custom = FindCustomProperty( index );
3242 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3243 property = custom->GetSceneGraphProperty();
3245 else if( NULL != mNode )
3249 case Dali::Actor::Property::PARENT_ORIGIN:
3250 property = &mNode->mParentOrigin;
3253 case Dali::Actor::Property::PARENT_ORIGIN_X:
3254 property = &mNode->mParentOrigin;
3257 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3258 property = &mNode->mParentOrigin;
3261 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3262 property = &mNode->mParentOrigin;
3265 case Dali::Actor::Property::ANCHOR_POINT:
3266 property = &mNode->mAnchorPoint;
3269 case Dali::Actor::Property::ANCHOR_POINT_X:
3270 property = &mNode->mAnchorPoint;
3273 case Dali::Actor::Property::ANCHOR_POINT_Y:
3274 property = &mNode->mAnchorPoint;
3277 case Dali::Actor::Property::ANCHOR_POINT_Z:
3278 property = &mNode->mAnchorPoint;
3281 case Dali::Actor::Property::SIZE:
3282 property = &mNode->mSize;
3285 case Dali::Actor::Property::SIZE_WIDTH:
3286 property = &mNode->mSize;
3289 case Dali::Actor::Property::SIZE_HEIGHT:
3290 property = &mNode->mSize;
3293 case Dali::Actor::Property::SIZE_DEPTH:
3294 property = &mNode->mSize;
3297 case Dali::Actor::Property::POSITION:
3298 property = &mNode->mPosition;
3301 case Dali::Actor::Property::POSITION_X:
3302 property = &mNode->mPosition;
3305 case Dali::Actor::Property::POSITION_Y:
3306 property = &mNode->mPosition;
3309 case Dali::Actor::Property::POSITION_Z:
3310 property = &mNode->mPosition;
3313 case Dali::Actor::Property::WORLD_POSITION:
3314 property = &mNode->mWorldPosition;
3317 case Dali::Actor::Property::WORLD_POSITION_X:
3318 property = &mNode->mWorldPosition;
3321 case Dali::Actor::Property::WORLD_POSITION_Y:
3322 property = &mNode->mWorldPosition;
3325 case Dali::Actor::Property::WORLD_POSITION_Z:
3326 property = &mNode->mWorldPosition;
3329 case Dali::Actor::Property::ORIENTATION:
3330 property = &mNode->mOrientation;
3333 case Dali::Actor::Property::WORLD_ORIENTATION:
3334 property = &mNode->mWorldOrientation;
3337 case Dali::Actor::Property::SCALE:
3338 property = &mNode->mScale;
3341 case Dali::Actor::Property::SCALE_X:
3342 property = &mNode->mScale;
3345 case Dali::Actor::Property::SCALE_Y:
3346 property = &mNode->mScale;
3349 case Dali::Actor::Property::SCALE_Z:
3350 property = &mNode->mScale;
3353 case Dali::Actor::Property::WORLD_SCALE:
3354 property = &mNode->mWorldScale;
3357 case Dali::Actor::Property::VISIBLE:
3358 property = &mNode->mVisible;
3361 case Dali::Actor::Property::COLOR:
3362 property = &mNode->mColor;
3365 case Dali::Actor::Property::COLOR_RED:
3366 property = &mNode->mColor;
3369 case Dali::Actor::Property::COLOR_GREEN:
3370 property = &mNode->mColor;
3373 case Dali::Actor::Property::COLOR_BLUE:
3374 property = &mNode->mColor;
3377 case Dali::Actor::Property::COLOR_ALPHA:
3378 property = &mNode->mColor;
3381 case Dali::Actor::Property::WORLD_COLOR:
3382 property = &mNode->mWorldColor;
3385 case Dali::Actor::Property::WORLD_MATRIX:
3386 property = &mNode->mWorldMatrix;
3397 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3399 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3401 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3403 // check whether the animatable property is registered already, if not then register one.
3404 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3405 if( animatableProperty )
3407 componentIndex = animatableProperty->componentIndex;
3414 case Dali::Actor::Property::PARENT_ORIGIN_X:
3415 case Dali::Actor::Property::ANCHOR_POINT_X:
3416 case Dali::Actor::Property::SIZE_WIDTH:
3417 case Dali::Actor::Property::POSITION_X:
3418 case Dali::Actor::Property::WORLD_POSITION_X:
3419 case Dali::Actor::Property::SCALE_X:
3420 case Dali::Actor::Property::COLOR_RED:
3426 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3427 case Dali::Actor::Property::ANCHOR_POINT_Y:
3428 case Dali::Actor::Property::SIZE_HEIGHT:
3429 case Dali::Actor::Property::POSITION_Y:
3430 case Dali::Actor::Property::WORLD_POSITION_Y:
3431 case Dali::Actor::Property::SCALE_Y:
3432 case Dali::Actor::Property::COLOR_GREEN:
3438 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3439 case Dali::Actor::Property::ANCHOR_POINT_Z:
3440 case Dali::Actor::Property::SIZE_DEPTH:
3441 case Dali::Actor::Property::POSITION_Z:
3442 case Dali::Actor::Property::WORLD_POSITION_Z:
3443 case Dali::Actor::Property::SCALE_Z:
3444 case Dali::Actor::Property::COLOR_BLUE:
3450 case Dali::Actor::Property::COLOR_ALPHA:
3464 return componentIndex;
3467 void Actor::SetParent( Actor* parent )
3471 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3475 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3478 // Instruct each actor to create a corresponding node in the scene graph
3479 ConnectToStage( parent->GetHierarchyDepth() );
3482 else // parent being set to NULL
3484 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3488 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3491 DALI_ASSERT_ALWAYS( mNode != NULL );
3495 // Disconnect the Node & its children from the scene-graph.
3496 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3499 // Instruct each actor to discard pointers to the scene-graph
3500 DisconnectFromStage();
3505 SceneGraph::Node* Actor::CreateNode() const
3510 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3513 Actor* actor = dynamic_cast< Actor* >( object );
3517 if( 0 == actionName.compare( ACTION_SHOW ) )
3519 actor->SetVisible( true );
3522 else if( 0 == actionName.compare( ACTION_HIDE ) )
3524 actor->SetVisible( false );
3532 void Actor::EnsureRelayoutData()
3534 // Assign relayout data.
3535 if( !mRelayoutData )
3537 mRelayoutData = new RelayoutData();
3541 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3543 // Check if actor is dependent on parent
3544 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3546 if( ( dimension & ( 1 << i ) ) )
3548 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3549 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3559 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3561 // Check if actor is dependent on children
3562 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3564 if( ( dimension & ( 1 << i ) ) )
3566 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3567 switch( resizePolicy )
3569 case ResizePolicy::FIT_TO_CHILDREN:
3570 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3586 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3588 return Actor::RelayoutDependentOnChildren( dimension );
3591 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3593 // Check each possible dimension and see if it is dependent on the input one
3594 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3596 if( dimension & ( 1 << i ) )
3598 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3605 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3607 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3609 if( dimension & ( 1 << i ) )
3611 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3616 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3618 // If more than one dimension is requested, just return the first one found
3619 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3621 if( ( dimension & ( 1 << i ) ) )
3623 return mRelayoutData->negotiatedDimensions[ i ];
3627 return 0.0f; // Default
3630 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3632 EnsureRelayoutData();
3634 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3636 if( dimension & ( 1 << i ) )
3638 mRelayoutData->dimensionPadding[ i ] = padding;
3643 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3645 if ( mRelayoutData )
3647 // If more than one dimension is requested, just return the first one found
3648 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3650 if( ( dimension & ( 1 << i ) ) )
3652 return mRelayoutData->dimensionPadding[ i ];
3657 return GetDefaultDimensionPadding();
3660 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
3662 EnsureRelayoutData();
3664 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3666 if( dimension & ( 1 << i ) )
3668 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3673 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
3675 if ( mRelayoutData )
3677 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3679 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
3689 float Actor::GetHeightForWidthBase( float width )
3691 float height = 0.0f;
3693 const Vector3 naturalSize = GetNaturalSize();
3694 if( naturalSize.width > 0.0f )
3696 height = naturalSize.height * width / naturalSize.width;
3698 else // we treat 0 as 1:1 aspect ratio
3706 float Actor::GetWidthForHeightBase( float height )
3710 const Vector3 naturalSize = GetNaturalSize();
3711 if( naturalSize.height > 0.0f )
3713 width = naturalSize.width * height / naturalSize.height;
3715 else // we treat 0 as 1:1 aspect ratio
3723 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
3725 // Fill to parent, taking size mode factor into account
3726 switch( child.GetResizePolicy( dimension ) )
3728 case ResizePolicy::FILL_TO_PARENT:
3730 return GetLatestSize( dimension );
3733 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3735 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
3738 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3740 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
3745 return GetLatestSize( dimension );
3750 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
3752 // Can be overridden in derived class
3753 return CalculateChildSizeBase( child, dimension );
3756 float Actor::GetHeightForWidth( float width )
3758 // Can be overridden in derived class
3759 return GetHeightForWidthBase( width );
3762 float Actor::GetWidthForHeight( float height )
3764 // Can be overridden in derived class
3765 return GetWidthForHeightBase( height );
3768 float Actor::GetLatestSize( Dimension::Type dimension ) const
3770 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
3773 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
3775 Vector2 padding = GetPadding( dimension );
3777 return GetLatestSize( dimension ) + padding.x + padding.y;
3780 float Actor::NegotiateFromParent( Dimension::Type dimension )
3782 Actor* parent = GetParent();
3785 Vector2 padding( GetPadding( dimension ) );
3786 Vector2 parentPadding( parent->GetPadding( dimension ) );
3787 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
3793 float Actor::NegotiateFromChildren( Dimension::Type dimension )
3795 float maxDimensionPoint = 0.0f;
3797 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3799 ActorPtr child = GetChildAt( i );
3801 if( !child->RelayoutDependentOnParent( dimension ) )
3803 // Calculate the min and max points that the children range across
3804 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
3805 float dimensionSize = child->GetRelayoutSize( dimension );
3806 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
3810 return maxDimensionPoint;
3813 float Actor::GetSize( Dimension::Type dimension ) const
3815 return GetDimensionValue( GetTargetSize(), dimension );
3818 float Actor::GetNaturalSize( Dimension::Type dimension ) const
3820 return GetDimensionValue( GetNaturalSize(), dimension );
3823 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
3825 switch( GetResizePolicy( dimension ) )
3827 case ResizePolicy::USE_NATURAL_SIZE:
3829 return GetNaturalSize( dimension );
3832 case ResizePolicy::FIXED:
3834 return GetDimensionValue( GetPreferredSize(), dimension );
3837 case ResizePolicy::USE_ASSIGNED_SIZE:
3839 return GetDimensionValue( maximumSize, dimension );
3842 case ResizePolicy::FILL_TO_PARENT:
3843 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3844 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3846 return NegotiateFromParent( dimension );
3849 case ResizePolicy::FIT_TO_CHILDREN:
3851 return NegotiateFromChildren( dimension );
3854 case ResizePolicy::DIMENSION_DEPENDENCY:
3856 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
3859 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
3861 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
3864 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
3866 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
3878 return 0.0f; // Default
3881 float Actor::ClampDimension( float size, Dimension::Type dimension )
3883 const float minSize = GetMinimumSize( dimension );
3884 const float maxSize = GetMaximumSize( dimension );
3886 return std::max( minSize, std::min( size, maxSize ) );
3889 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
3891 // Check if it needs to be negotiated
3892 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
3894 // Check that we havn't gotten into an infinite loop
3895 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
3896 bool recursionFound = false;
3897 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
3899 if( *it == searchActor )
3901 recursionFound = true;
3906 if( !recursionFound )
3908 // Record the path that we have taken
3909 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
3911 // Dimension dependency check
3912 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3914 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
3916 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
3918 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
3922 // Parent dependency check
3923 Actor* parent = GetParent();
3924 if( parent && RelayoutDependentOnParent( dimension ) )
3926 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
3929 // Children dependency check
3930 if( RelayoutDependentOnChildren( dimension ) )
3932 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3934 ActorPtr child = GetChildAt( i );
3936 // Only relayout child first if it is not dependent on this actor
3937 if( !child->RelayoutDependentOnParent( dimension ) )
3939 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
3944 // For deriving classes
3945 OnCalculateRelayoutSize( dimension );
3947 // All dependencies checked, calculate the size and set negotiated flag
3948 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
3950 SetNegotiatedDimension( newSize, dimension );
3951 SetLayoutNegotiated( true, dimension );
3953 // For deriving classes
3954 OnLayoutNegotiated( newSize, dimension );
3956 // This actor has been successfully processed, pop it off the recursion stack
3957 recursionStack.pop_back();
3961 // TODO: Break infinite loop
3962 SetLayoutNegotiated( true, dimension );
3967 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
3969 // Negotiate all dimensions that require it
3970 ActorDimensionStack recursionStack;
3972 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3974 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
3977 NegotiateDimension( dimension, allocatedSize, recursionStack );
3981 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
3983 switch( mRelayoutData->sizeSetPolicy )
3985 case SizeScalePolicy::USE_SIZE_SET:
3990 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
3992 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
3993 const Vector3 naturalSize = GetNaturalSize();
3994 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
3996 const float sizeRatio = size.width / size.height;
3997 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
3999 if( naturalSizeRatio < sizeRatio )
4001 return Vector2( naturalSizeRatio * size.height, size.height );
4003 else if( naturalSizeRatio > sizeRatio )
4005 return Vector2( size.width, size.width / naturalSizeRatio );
4016 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4018 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4019 const Vector3 naturalSize = GetNaturalSize();
4020 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4022 const float sizeRatio = size.width / size.height;
4023 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4025 if( naturalSizeRatio < sizeRatio )
4027 return Vector2( size.width, size.width / naturalSizeRatio );
4029 else if( naturalSizeRatio > sizeRatio )
4031 return Vector2( naturalSizeRatio * size.height, size.height );
4049 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4051 // Do the set actor size
4052 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4054 // Adjust for size set policy
4055 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4057 // Lock the flag to stop recursive relayouts on set size
4058 mRelayoutData->insideRelayout = true;
4059 SetSize( negotiatedSize );
4060 mRelayoutData->insideRelayout = false;
4062 // Clear flags for all dimensions
4063 SetLayoutDirty( false );
4065 // Give deriving classes a chance to respond
4066 OnRelayout( negotiatedSize, container );
4068 if( !mOnRelayoutSignal.Empty() )
4070 Dali::Actor handle( this );
4071 mOnRelayoutSignal.Emit( handle );
4075 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4077 // Do the negotiation
4078 NegotiateDimensions( allocatedSize );
4080 // Set the actor size
4081 SetNegotiatedSize( container );
4083 // Negotiate down to children
4084 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4086 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4088 ActorPtr child = GetChildAt( i );
4090 // Only relayout if required
4091 if( child->RelayoutRequired() )
4093 container.Add( Dali::Actor( child.Get() ), newBounds );
4098 void Actor::RelayoutRequest( Dimension::Type dimension )
4100 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4101 if( relayoutController )
4103 Dali::Actor self( this );
4104 relayoutController->RequestRelayout( self, dimension );
4108 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4112 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4116 void Actor::SetPreferredSize( const Vector2& size )
4118 EnsureRelayoutData();
4120 if( size.width > 0.0f )
4122 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4125 if( size.height > 0.0f )
4127 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4130 mRelayoutData->preferredSize = size;
4135 Vector2 Actor::GetPreferredSize() const
4137 if ( mRelayoutData )
4139 return Vector2( mRelayoutData->preferredSize );
4142 return GetDefaultPreferredSize();
4145 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4147 EnsureRelayoutData();
4149 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4151 if( dimension & ( 1 << i ) )
4153 mRelayoutData->minimumSize[ i ] = size;
4160 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4162 if ( mRelayoutData )
4164 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4166 if( dimension & ( 1 << i ) )
4168 return mRelayoutData->minimumSize[ i ];
4173 return 0.0f; // Default
4176 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4178 EnsureRelayoutData();
4180 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4182 if( dimension & ( 1 << i ) )
4184 mRelayoutData->maximumSize[ i ] = size;
4191 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4193 if ( mRelayoutData )
4195 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4197 if( dimension & ( 1 << i ) )
4199 return mRelayoutData->maximumSize[ i ];
4204 return FLT_MAX; // Default
4207 } // namespace Internal