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_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
236 const char* const SIGNAL_TOUCHED = "touched";
237 const char* const SIGNAL_HOVERED = "hovered";
238 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
239 const char* const SIGNAL_ON_STAGE = "onStage";
240 const char* const SIGNAL_OFF_STAGE = "offStage";
241 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
245 const char* const ACTION_SHOW = "show";
246 const char* const ACTION_HIDE = "hide";
248 BaseHandle CreateActor()
250 return Dali::Actor::New();
253 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
255 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
256 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
257 SignalConnectorType signalConnector3( mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal );
258 SignalConnectorType signalConnector4( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
259 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
260 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
262 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
263 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
266 * @brief Extract a given dimension from a Vector2
268 * @param[in] values The values to extract from
269 * @param[in] dimension The dimension to extract
270 * @return Return the value for the dimension
272 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
276 case Dimension::WIDTH:
280 case Dimension::HEIGHT:
282 return values.height;
293 * @brief Extract a given dimension from a Vector3
295 * @param[in] values The values to extract from
296 * @param[in] dimension The dimension to extract
297 * @return Return the value for the dimension
299 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
301 return GetDimensionValue( values.GetVectorXY(), dimension );
305 } // unnamed namespace
307 ActorPtr Actor::New()
309 ActorPtr actor( new Actor( BASIC ) );
311 // Second-phase construction
317 const std::string& Actor::GetName() const
322 void Actor::SetName( const std::string& name )
328 // ATTENTION: string for debug purposes is not thread safe.
329 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
333 unsigned int Actor::GetId() const
338 void Actor::Attach( ActorAttachment& attachment )
340 DALI_ASSERT_DEBUG( !mAttachment && "An Actor can only have one attachment" );
344 attachment.Connect();
347 mAttachment = ActorAttachmentPtr( &attachment );
350 ActorAttachmentPtr Actor::GetAttachment()
355 bool Actor::OnStage() const
360 Dali::Layer Actor::GetLayer()
364 // Short-circuit for Layer derived actors
367 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
370 // Find the immediate Layer parent
371 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
373 if( parent->IsLayer() )
375 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
382 void Actor::Add( Actor& child )
384 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
385 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
389 mChildren = new ActorContainer;
392 Actor* const oldParent( child.mParent );
394 // child might already be ours
395 if( this != oldParent )
397 // if we already have parent, unparent us first
400 oldParent->Remove( child ); // This causes OnChildRemove callback
402 // Old parent may need to readjust to missing child
403 if( oldParent->RelayoutDependentOnChildren() )
405 oldParent->RelayoutRequest();
409 // Guard against Add() during previous OnChildRemove callback
412 // Do this first, since user callbacks from within SetParent() may need to remove child
413 mChildren->push_back( ActorPtr( &child ) );
415 // SetParent asserts that child can be added
416 child.SetParent( this );
418 // Notification for derived classes
421 // Only put in a relayout request if there is a suitable dependency
422 if( RelayoutDependentOnChildren() )
430 void Actor::Remove( Actor& child )
432 if( (this == &child) || (!mChildren) )
434 // no children or removing itself
440 // Find the child in mChildren, and unparent it
441 ActorIter end = mChildren->end();
442 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
444 ActorPtr actor = (*iter);
446 if( actor.Get() == &child )
448 // Keep handle for OnChildRemove notification
451 // Do this first, since user callbacks from within SetParent() may need to add the child
452 mChildren->erase( iter );
454 DALI_ASSERT_DEBUG( actor->GetParent() == this );
455 actor->SetParent( NULL );
463 // Notification for derived classes
464 OnChildRemove( *(removed.Get()) );
466 // Only put in a relayout request if there is a suitable dependency
467 if( RelayoutDependentOnChildren() )
474 void Actor::Unparent()
478 // Remove this actor from the parent. The remove will put a relayout request in for
479 // the parent if required
480 mParent->Remove( *this );
481 // mParent is now NULL!
485 unsigned int Actor::GetChildCount() const
487 return ( NULL != mChildren ) ? mChildren->size() : 0;
490 ActorPtr Actor::GetChildAt( unsigned int index ) const
492 DALI_ASSERT_ALWAYS( index < GetChildCount() );
494 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
497 ActorPtr Actor::FindChildByName( const std::string& actorName )
500 if( actorName == mName )
506 ActorIter end = mChildren->end();
507 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
509 child = (*iter)->FindChildByName( actorName );
520 ActorPtr Actor::FindChildById( const unsigned int id )
529 ActorIter end = mChildren->end();
530 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
532 child = (*iter)->FindChildById( id );
543 void Actor::SetParentOrigin( const Vector3& origin )
547 // mNode is being used in a separate thread; queue a message to set the value & base value
548 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
551 // Cache for event-thread access
554 // not allocated, check if different from default
555 if( ParentOrigin::DEFAULT != origin )
557 mParentOrigin = new Vector3( origin );
562 // check if different from current costs more than just set
563 *mParentOrigin = origin;
567 void Actor::SetParentOriginX( float x )
569 const Vector3& current = GetCurrentParentOrigin();
571 SetParentOrigin( Vector3( x, current.y, current.z ) );
574 void Actor::SetParentOriginY( float y )
576 const Vector3& current = GetCurrentParentOrigin();
578 SetParentOrigin( Vector3( current.x, y, current.z ) );
581 void Actor::SetParentOriginZ( float z )
583 const Vector3& current = GetCurrentParentOrigin();
585 SetParentOrigin( Vector3( current.x, current.y, z ) );
588 const Vector3& Actor::GetCurrentParentOrigin() const
590 // Cached for event-thread access
591 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
594 void Actor::SetAnchorPoint( const Vector3& anchor )
598 // mNode is being used in a separate thread; queue a message to set the value & base value
599 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
602 // Cache for event-thread access
605 // not allocated, check if different from default
606 if( AnchorPoint::DEFAULT != anchor )
608 mAnchorPoint = new Vector3( anchor );
613 // check if different from current costs more than just set
614 *mAnchorPoint = anchor;
618 void Actor::SetAnchorPointX( float x )
620 const Vector3& current = GetCurrentAnchorPoint();
622 SetAnchorPoint( Vector3( x, current.y, current.z ) );
625 void Actor::SetAnchorPointY( float y )
627 const Vector3& current = GetCurrentAnchorPoint();
629 SetAnchorPoint( Vector3( current.x, y, current.z ) );
632 void Actor::SetAnchorPointZ( float z )
634 const Vector3& current = GetCurrentAnchorPoint();
636 SetAnchorPoint( Vector3( current.x, current.y, z ) );
639 const Vector3& Actor::GetCurrentAnchorPoint() const
641 // Cached for event-thread access
642 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
645 void Actor::SetPosition( float x, float y )
647 SetPosition( Vector3( x, y, 0.0f ) );
650 void Actor::SetPosition( float x, float y, float z )
652 SetPosition( Vector3( x, y, z ) );
655 void Actor::SetPosition( const Vector3& position )
657 mTargetPosition = position;
661 // mNode is being used in a separate thread; queue a message to set the value & base value
662 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::Bake, position );
666 void Actor::SetX( float x )
668 mTargetPosition.x = x;
672 // mNode is being used in a separate thread; queue a message to set the value & base value
673 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeX, x );
677 void Actor::SetY( float y )
679 mTargetPosition.y = y;
683 // mNode is being used in a separate thread; queue a message to set the value & base value
684 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeY, y );
688 void Actor::SetZ( float z )
690 mTargetPosition.z = z;
694 // mNode is being used in a separate thread; queue a message to set the value & base value
695 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeZ, z );
699 void Actor::TranslateBy( const Vector3& distance )
701 mTargetPosition += distance;
705 // mNode is being used in a separate thread; queue a message to set the value & base value
706 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeRelative, distance );
710 const Vector3& Actor::GetCurrentPosition() const
714 // mNode is being used in a separate thread; copy the value from the previous update
715 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
718 return Vector3::ZERO;
721 const Vector3& Actor::GetTargetPosition() const
723 return mTargetPosition;
726 const Vector3& Actor::GetCurrentWorldPosition() const
730 // mNode is being used in a separate thread; copy the value from the previous update
731 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
734 return Vector3::ZERO;
737 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
739 // this flag is not animatable so keep the value
740 mPositionInheritanceMode = mode;
743 // mNode is being used in a separate thread; queue a message to set the value
744 SetPositionInheritanceModeMessage( GetEventThreadServices(), *mNode, mode );
748 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
750 // Cached for event-thread access
751 return mPositionInheritanceMode;
754 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
756 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
757 normalizedAxis.Normalize();
759 Quaternion orientation( angle, normalizedAxis );
761 SetOrientation( orientation );
764 void Actor::SetOrientation( const Quaternion& orientation )
768 // mNode is being used in a separate thread; queue a message to set the value & base value
769 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::Bake, orientation );
773 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
777 // mNode is being used in a separate thread; queue a message to set the value & base value
778 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, Quaternion(angle, axis) );
782 void Actor::RotateBy( const Quaternion& relativeRotation )
786 // mNode is being used in a separate thread; queue a message to set the value & base value
787 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, relativeRotation );
791 const Quaternion& Actor::GetCurrentOrientation() const
795 // mNode is being used in a separate thread; copy the value from the previous update
796 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
799 return Quaternion::IDENTITY;
802 const Quaternion& Actor::GetCurrentWorldOrientation() const
806 // mNode is being used in a separate thread; copy the value from the previous update
807 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
810 return Quaternion::IDENTITY;
813 void Actor::SetScale( float scale )
815 SetScale( Vector3( scale, scale, scale ) );
818 void Actor::SetScale( float x, float y, float z )
820 SetScale( Vector3( x, y, z ) );
823 void Actor::SetScale( const Vector3& scale )
827 // mNode is being used in a separate thread; queue a message to set the value & base value
828 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::Bake, scale );
832 void Actor::SetScaleX( float x )
836 // mNode is being used in a separate thread; queue a message to set the value & base value
837 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeX, x );
841 void Actor::SetScaleY( float y )
845 // mNode is being used in a separate thread; queue a message to set the value & base value
846 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeY, y );
850 void Actor::SetScaleZ( float z )
854 // mNode is being used in a separate thread; queue a message to set the value & base value
855 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeZ, z );
859 void Actor::ScaleBy(const Vector3& relativeScale)
863 // mNode is being used in a separate thread; queue a message to set the value & base value
864 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeRelativeMultiply, relativeScale );
868 const Vector3& Actor::GetCurrentScale() const
872 // mNode is being used in a separate thread; copy the value from the previous update
873 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
879 const Vector3& Actor::GetCurrentWorldScale() const
883 // mNode is being used in a separate thread; copy the value from the previous update
884 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
890 void Actor::SetInheritScale( bool inherit )
892 // non animateable so keep local copy
893 mInheritScale = inherit;
896 // mNode is being used in a separate thread; queue a message to set the value
897 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
901 bool Actor::IsScaleInherited() const
903 return mInheritScale;
906 Matrix Actor::GetCurrentWorldMatrix() const
910 // World matrix is no longer updated unless there is something observing the node.
911 // Need to calculate it from node's world position, orientation and scale:
912 BufferIndex updateBufferIndex = GetEventThreadServices().GetEventBufferIndex();
913 Matrix worldMatrix(false);
914 worldMatrix.SetTransformComponents( mNode->GetWorldScale( updateBufferIndex ),
915 mNode->GetWorldOrientation( updateBufferIndex ),
916 mNode->GetWorldPosition( updateBufferIndex ) );
920 return Matrix::IDENTITY;
923 void Actor::SetVisible( bool visible )
927 // mNode is being used in a separate thread; queue a message to set the value & base value
928 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
932 bool Actor::IsVisible() const
936 // mNode is being used in a separate thread; copy the value from the previous update
937 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
943 void Actor::SetOpacity( float opacity )
947 // mNode is being used in a separate thread; queue a message to set the value & base value
948 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
952 float Actor::GetCurrentOpacity() const
956 // mNode is being used in a separate thread; copy the value from the previous update
957 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
963 const Vector4& Actor::GetCurrentWorldColor() const
967 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
973 void Actor::SetColor( const Vector4& color )
977 // mNode is being used in a separate thread; queue a message to set the value & base value
978 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
982 void Actor::SetColorRed( float red )
986 // mNode is being used in a separate thread; queue a message to set the value & base value
987 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
991 void Actor::SetColorGreen( float green )
995 // mNode is being used in a separate thread; queue a message to set the value & base value
996 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1000 void Actor::SetColorBlue( float blue )
1004 // mNode is being used in a separate thread; queue a message to set the value & base value
1005 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1009 const Vector4& Actor::GetCurrentColor() const
1013 // mNode is being used in a separate thread; copy the value from the previous update
1014 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1017 return Color::WHITE;
1020 void Actor::SetInheritOrientation( bool inherit )
1022 // non animateable so keep local copy
1023 mInheritOrientation = inherit;
1026 // mNode is being used in a separate thread; queue a message to set the value
1027 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1031 bool Actor::IsOrientationInherited() const
1033 return mInheritOrientation;
1036 void Actor::SetSizeModeFactor( const Vector3& factor )
1038 EnsureRelayoutData();
1040 mRelayoutData->sizeModeFactor = factor;
1043 const Vector3& Actor::GetSizeModeFactor() const
1045 if ( mRelayoutData )
1047 return mRelayoutData->sizeModeFactor;
1050 return GetDefaultSizeModeFactor();
1053 void Actor::SetColorMode( ColorMode colorMode )
1055 // non animateable so keep local copy
1056 mColorMode = colorMode;
1059 // mNode is being used in a separate thread; queue a message to set the value
1060 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1064 ColorMode Actor::GetColorMode() const
1066 // we have cached copy
1070 void Actor::SetSize( float width, float height )
1072 SetSize( Vector2( width, height ) );
1075 void Actor::SetSize( float width, float height, float depth )
1077 SetSize( Vector3( width, height, depth ) );
1080 void Actor::SetSize( const Vector2& size )
1082 SetSize( Vector3( size.width, size.height, 0.f ) );
1085 void Actor::SetSizeInternal( const Vector2& size )
1087 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1090 void Actor::SetSize( const Vector3& size )
1092 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1094 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1095 SetPreferredSize( size.GetVectorXY() );
1099 SetSizeInternal( size );
1103 void Actor::SetSizeInternal( const Vector3& size )
1105 // dont allow recursive loop
1106 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1107 // 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
1108 if( ( NULL != mNode )&&
1109 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1110 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1111 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1115 // mNode is being used in a separate thread; queue a message to set the value & base value
1116 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::Bake, mTargetSize );
1118 // Notification for derived classes
1119 mInsideOnSizeSet = true;
1120 OnSizeSet( mTargetSize );
1121 mInsideOnSizeSet = false;
1123 // Raise a relayout request if the flag is not locked
1124 if( mRelayoutData && !mRelayoutData->insideRelayout )
1131 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1133 mTargetSize = targetSize;
1135 // Notify deriving classes
1136 OnSizeAnimation( animation, mTargetSize );
1139 void Actor::NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property )
1141 if ( Dali::Actor::Property::SIZE_WIDTH == property )
1143 mTargetSize.width = targetSize;
1145 else if ( Dali::Actor::Property::SIZE_HEIGHT == property )
1147 mTargetSize.height = targetSize;
1149 else if ( Dali::Actor::Property::SIZE_DEPTH == property )
1151 mTargetSize.depth = targetSize;
1153 // Notify deriving classes
1154 OnSizeAnimation( animation, mTargetSize );
1157 void Actor::NotifyPositionAnimation( Animation& animation, const Vector3& targetPosition )
1159 mTargetPosition = targetPosition;
1162 void Actor::NotifyPositionAnimation( Animation& animation, float targetPosition, Property::Index property )
1164 if ( Dali::Actor::Property::POSITION_X == property )
1166 mTargetPosition.x = targetPosition;
1168 else if ( Dali::Actor::Property::POSITION_Y == property )
1170 mTargetPosition.y = targetPosition;
1172 else if ( Dali::Actor::Property::POSITION_Z == property )
1174 mTargetPosition.z = targetPosition;
1178 void Actor::SetWidth( float width )
1180 mTargetSize.width = width;
1184 // mNode is being used in a separate thread; queue a message to set the value & base value
1185 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeX, width );
1189 void Actor::SetHeight( float height )
1191 mTargetSize.height = height;
1195 // mNode is being used in a separate thread; queue a message to set the value & base value
1196 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeY, height );
1200 void Actor::SetDepth( float depth )
1202 mTargetSize.depth = depth;
1206 // mNode is being used in a separate thread; queue a message to set the value & base value
1207 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeZ, depth );
1211 const Vector3& Actor::GetTargetSize() const
1216 const Vector3& Actor::GetCurrentSize() const
1220 // mNode is being used in a separate thread; copy the value from the previous update
1221 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1224 return Vector3::ZERO;
1227 Vector3 Actor::GetNaturalSize() const
1229 // It is up to deriving classes to return the appropriate natural size
1230 return Vector3( 0.0f, 0.0f, 0.0f );
1233 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1235 EnsureRelayoutData();
1237 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1239 if( dimension & ( 1 << i ) )
1241 mRelayoutData->resizePolicies[ i ] = policy;
1245 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1247 if( dimension & Dimension::WIDTH )
1249 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1252 if( dimension & Dimension::HEIGHT )
1254 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1258 // If calling SetResizePolicy, assume we want relayout enabled
1259 SetRelayoutEnabled( true );
1261 OnSetResizePolicy( policy, dimension );
1263 // Trigger relayout on this control
1267 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1269 if ( mRelayoutData )
1271 // If more than one dimension is requested, just return the first one found
1272 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1274 if( ( dimension & ( 1 << i ) ) )
1276 return mRelayoutData->resizePolicies[ i ];
1281 return ResizePolicy::DEFAULT;
1284 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1286 EnsureRelayoutData();
1288 mRelayoutData->sizeSetPolicy = policy;
1291 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1293 if ( mRelayoutData )
1295 return mRelayoutData->sizeSetPolicy;
1298 return DEFAULT_SIZE_SCALE_POLICY;
1301 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1303 EnsureRelayoutData();
1305 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1307 if( dimension & ( 1 << i ) )
1309 mRelayoutData->dimensionDependencies[ i ] = dependency;
1314 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1316 if ( mRelayoutData )
1318 // If more than one dimension is requested, just return the first one found
1319 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1321 if( ( dimension & ( 1 << i ) ) )
1323 return mRelayoutData->dimensionDependencies[ i ];
1328 return Dimension::ALL_DIMENSIONS; // Default
1331 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1333 // If relayout data has not been allocated yet and the client is requesting
1334 // to disable it, do nothing
1335 if( mRelayoutData || relayoutEnabled )
1337 EnsureRelayoutData();
1339 mRelayoutData->relayoutEnabled = relayoutEnabled;
1343 bool Actor::IsRelayoutEnabled() const
1345 // Assume that if relayout data has not been allocated yet then
1346 // relayout is disabled
1347 return mRelayoutData && mRelayoutData->relayoutEnabled;
1350 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1352 EnsureRelayoutData();
1354 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1356 if( dimension & ( 1 << i ) )
1358 mRelayoutData->dimensionDirty[ i ] = dirty;
1363 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1365 if ( mRelayoutData )
1367 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1369 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1379 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1381 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1384 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1386 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1389 unsigned int Actor::AddRenderer( Renderer& renderer )
1393 mRenderers = new RendererContainer;
1396 unsigned int index = mRenderers->size();
1397 RendererPtr rendererPtr = RendererPtr( &renderer );
1398 mRenderers->push_back( rendererPtr );
1399 AddRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1403 rendererPtr->Connect();
1409 unsigned int Actor::GetRendererCount() const
1411 unsigned int rendererCount(0);
1414 rendererCount = mRenderers->size();
1417 return rendererCount;
1420 RendererPtr Actor::GetRendererAt( unsigned int index )
1422 RendererPtr renderer;
1423 if( index < GetRendererCount() )
1425 renderer = ( *mRenderers )[ index ];
1431 void Actor::RemoveRenderer( Renderer& renderer )
1435 RendererIter end = mRenderers->end();
1436 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1438 if( (*iter).Get() == &renderer )
1440 mRenderers->erase( iter );
1441 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1448 void Actor::RemoveRenderer( unsigned int index )
1450 if( index < GetRendererCount() )
1452 RendererPtr renderer = ( *mRenderers )[ index ];
1453 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.Get()->GetRendererSceneObject() );
1454 mRenderers->erase( mRenderers->begin()+index );
1458 void Actor::SetOverlay( bool enable )
1460 // Setting STENCIL will override OVERLAY_2D
1461 if( DrawMode::STENCIL != mDrawMode )
1463 SetDrawMode( enable ? DrawMode::OVERLAY_2D : DrawMode::NORMAL );
1467 bool Actor::IsOverlay() const
1469 return ( DrawMode::OVERLAY_2D == mDrawMode );
1472 void Actor::SetDrawMode( DrawMode::Type drawMode )
1474 // this flag is not animatable so keep the value
1475 mDrawMode = drawMode;
1478 // mNode is being used in a separate thread; queue a message to set the value
1479 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1483 DrawMode::Type Actor::GetDrawMode() const
1488 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1490 // only valid when on-stage
1491 StagePtr stage = Stage::GetCurrent();
1492 if( stage && OnStage() )
1494 const RenderTaskList& taskList = stage->GetRenderTaskList();
1496 Vector2 converted( screenX, screenY );
1498 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1499 const int taskCount = taskList.GetTaskCount();
1500 for( int i = taskCount - 1; i >= 0; --i )
1502 Dali::RenderTask task = taskList.GetTask( i );
1503 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1505 // found a task where this conversion was ok so return
1513 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1515 bool retval = false;
1516 // only valid when on-stage
1519 CameraActor* camera = renderTask.GetCameraActor();
1523 renderTask.GetViewport( viewport );
1525 // need to translate coordinates to render tasks coordinate space
1526 Vector2 converted( screenX, screenY );
1527 if( renderTask.TranslateCoordinates( converted ) )
1529 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1536 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1538 // Early-out if mNode is NULL
1544 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1546 // Calculate the ModelView matrix
1547 Matrix modelView( false/*don't init*/);
1548 // need to use the components as world matrix is only updated for actors that need it
1549 modelView.SetTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1550 Matrix::Multiply( modelView, modelView, viewMatrix );
1552 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1553 Matrix invertedMvp( false/*don't init*/);
1554 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1555 bool success = invertedMvp.Invert();
1557 // Convert to GL coordinates
1558 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1563 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1570 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1576 if( XyPlaneIntersect( nearPos, farPos, local ) )
1578 Vector3 size = GetCurrentSize();
1579 localX = local.x + size.x * 0.5f;
1580 localY = local.y + size.y * 0.5f;
1591 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1594 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1596 Mathematical Formulation
1598 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1600 ( p - c ) dot ( p - c ) = r^2
1602 Given a ray with a point of origin 'o', and a direction vector 'd':
1604 ray(t) = o + td, t >= 0
1606 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1608 (o + td - c ) dot ( o + td - c ) = r^2
1610 To solve for t we first expand the above into a more recognisable quadratic equation form
1612 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1621 B = 2( o - c ) dot d
1622 C = ( o - c ) dot ( o - c ) - r^2
1624 which can be solved using a standard quadratic formula.
1626 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1628 Practical Simplification
1630 In a renderer, we often differentiate between world space and object space. In the object space
1631 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1632 into object space, the mathematical solution presented above can be simplified significantly.
1634 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1638 and we can find the t at which the (transformed) ray intersects the sphere by
1640 ( o + td ) dot ( o + td ) = r^2
1642 According to the reasoning above, we expand the above quadratic equation into the general form
1646 which now has coefficients:
1653 // Early out if mNode is NULL
1659 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1661 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1662 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1663 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1665 // Compute the radius is not needed, square radius it's enough.
1666 const Vector3& size( mNode->GetSize( bufferIndex ) );
1668 // Scale the sphere.
1669 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1671 const float width = size.width * scale.width;
1672 const float height = size.height * scale.height;
1674 float squareSphereRadius = 0.5f * ( width * width + height * height );
1676 float a = rayDir.Dot( rayDir ); // a
1677 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1678 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1680 return ( b2 * b2 - a * c ) >= 0.f;
1683 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
1690 // Transforms the ray to the local reference system.
1691 // Calculate the inverse of Model matrix
1692 Matrix invModelMatrix( false/*don't init*/);
1694 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1695 // need to use the components as world matrix is only updated for actors that need it
1696 invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1698 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1699 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1701 // Test with the actor's XY plane (Normal = 0 0 1 1).
1703 float a = -rayOriginLocal.z;
1704 float b = rayDirLocal.z;
1706 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1708 // Ray travels distance * rayDirLocal to intersect with plane.
1711 const Vector3& size = mNode->GetSize( bufferIndex );
1713 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1714 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1716 // Test with the actor's geometry.
1717 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1724 void Actor::SetLeaveRequired( bool required )
1726 mLeaveRequired = required;
1729 bool Actor::GetLeaveRequired() const
1731 return mLeaveRequired;
1734 void Actor::SetKeyboardFocusable( bool focusable )
1736 mKeyboardFocusable = focusable;
1739 bool Actor::IsKeyboardFocusable() const
1741 return mKeyboardFocusable;
1744 bool Actor::GetTouchRequired() const
1746 return !mTouchedSignal.Empty() || mDerivedRequiresTouch;
1749 bool Actor::GetHoverRequired() const
1751 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1754 bool Actor::GetWheelEventRequired() const
1756 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1759 bool Actor::IsHittable() const
1761 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1764 ActorGestureData& Actor::GetGestureData()
1766 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1767 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1768 if( NULL == mGestureData )
1770 mGestureData = new ActorGestureData;
1772 return *mGestureData;
1775 bool Actor::IsGestureRequred( Gesture::Type type ) const
1777 return mGestureData && mGestureData->IsGestureRequred( type );
1780 bool Actor::EmitTouchEventSignal( const TouchEvent& event )
1782 bool consumed = false;
1784 if( !mTouchedSignal.Empty() )
1786 Dali::Actor handle( this );
1787 consumed = mTouchedSignal.Emit( handle, event );
1792 // Notification for derived classes
1793 consumed = OnTouchEvent( event );
1799 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1801 bool consumed = false;
1803 if( !mHoveredSignal.Empty() )
1805 Dali::Actor handle( this );
1806 consumed = mHoveredSignal.Emit( handle, event );
1811 // Notification for derived classes
1812 consumed = OnHoverEvent( event );
1818 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1820 bool consumed = false;
1822 if( !mWheelEventSignal.Empty() )
1824 Dali::Actor handle( this );
1825 consumed = mWheelEventSignal.Emit( handle, event );
1830 // Notification for derived classes
1831 consumed = OnWheelEvent( event );
1837 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
1839 return mTouchedSignal;
1842 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
1844 return mHoveredSignal;
1847 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
1849 return mWheelEventSignal;
1852 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
1854 return mOnStageSignal;
1857 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
1859 return mOffStageSignal;
1862 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
1864 return mOnRelayoutSignal;
1867 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1869 bool connected( true );
1870 Actor* actor = dynamic_cast< Actor* >( object );
1872 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1874 actor->TouchedSignal().Connect( tracker, functor );
1876 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1878 actor->HoveredSignal().Connect( tracker, functor );
1880 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1882 actor->WheelEventSignal().Connect( tracker, functor );
1884 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
1886 actor->OnStageSignal().Connect( tracker, functor );
1888 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
1890 actor->OffStageSignal().Connect( tracker, functor );
1892 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
1894 actor->OnRelayoutSignal().Connect( tracker, functor );
1898 // signalName does not match any signal
1905 Actor::Actor( DerivedType derivedType )
1910 mParentOrigin( NULL ),
1911 mAnchorPoint( NULL ),
1912 mRelayoutData( NULL ),
1913 mGestureData( NULL ),
1915 mTargetSize( 0.0f, 0.0f, 0.0f ),
1917 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
1919 mIsRoot( ROOT_LAYER == derivedType ),
1920 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
1921 mIsOnStage( false ),
1923 mLeaveRequired( false ),
1924 mKeyboardFocusable( false ),
1925 mDerivedRequiresTouch( false ),
1926 mDerivedRequiresHover( false ),
1927 mDerivedRequiresWheelEvent( false ),
1928 mOnStageSignalled( false ),
1929 mInsideOnSizeSet( false ),
1930 mInheritOrientation( true ),
1931 mInheritScale( true ),
1932 mDrawMode( DrawMode::NORMAL ),
1933 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
1934 mColorMode( Node::DEFAULT_COLOR_MODE )
1938 void Actor::Initialize()
1941 SceneGraph::Node* node = CreateNode();
1943 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
1944 mNode = node; // Keep raw-pointer to Node
1948 GetEventThreadServices().RegisterObject( this );
1953 // Remove mParent pointers from children even if we're destroying core,
1954 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1957 ActorConstIter endIter = mChildren->end();
1958 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1960 (*iter)->SetParent( NULL );
1966 // Guard to allow handle destruction after Core has been destroyed
1967 if( EventThreadServices::IsCoreRunning() )
1971 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
1972 mNode = NULL; // Node is about to be destroyed
1975 GetEventThreadServices().UnregisterObject( this );
1978 // Cleanup optional gesture data
1979 delete mGestureData;
1981 // Cleanup optional parent origin and anchor
1982 delete mParentOrigin;
1983 delete mAnchorPoint;
1985 // Delete optional relayout data
1988 delete mRelayoutData;
1992 void Actor::ConnectToStage( unsigned int parentDepth )
1994 // This container is used instead of walking the Actor hierarchy.
1995 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
1996 ActorContainer connectionList;
1998 // This stage is atomic i.e. not interrupted by user callbacks.
1999 RecursiveConnectToStage( connectionList, parentDepth + 1 );
2001 // Notify applications about the newly connected actors.
2002 const ActorIter endIter = connectionList.end();
2003 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2005 (*iter)->NotifyStageConnection();
2011 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth )
2013 DALI_ASSERT_ALWAYS( !OnStage() );
2018 ConnectToSceneGraph();
2020 // Notification for internal derived classes
2021 OnStageConnectionInternal();
2023 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2024 connectionList.push_back( ActorPtr( this ) );
2026 // Recursively connect children
2029 ActorConstIter endIter = mChildren->end();
2030 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2032 (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
2038 * This method is called when the Actor is connected to the Stage.
2039 * The parent must have added its Node to the scene-graph.
2040 * The child must connect its Node to the parent's Node.
2041 * This is recursive; the child calls ConnectToStage() for its children.
2043 void Actor::ConnectToSceneGraph()
2045 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2049 // Reparent Node in next Update
2050 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode );
2053 // Notify attachment
2056 mAttachment->Connect();
2059 unsigned int rendererCount( GetRendererCount() );
2060 for( unsigned int i(0); i<rendererCount; ++i )
2062 GetRendererAt(i)->Connect();
2065 // Request relayout on all actors that are added to the scenegraph
2068 // Notification for Object::Observers
2072 void Actor::NotifyStageConnection()
2074 // Actors can be removed (in a callback), before the on-stage stage is reported.
2075 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2076 if( OnStage() && !mOnStageSignalled )
2078 // Notification for external (CustomActor) derived classes
2079 OnStageConnectionExternal( mDepth );
2081 if( !mOnStageSignal.Empty() )
2083 Dali::Actor handle( this );
2084 mOnStageSignal.Emit( handle );
2087 // Guard against Remove during callbacks
2090 mOnStageSignalled = true; // signal required next time Actor is removed
2095 void Actor::DisconnectFromStage()
2097 // This container is used instead of walking the Actor hierachy.
2098 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2099 ActorContainer disconnectionList;
2101 // This stage is atomic i.e. not interrupted by user callbacks
2102 RecursiveDisconnectFromStage( disconnectionList );
2104 // Notify applications about the newly disconnected actors.
2105 const ActorIter endIter = disconnectionList.end();
2106 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2108 (*iter)->NotifyStageDisconnection();
2112 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2114 DALI_ASSERT_ALWAYS( OnStage() );
2116 // Recursively disconnect children
2119 ActorConstIter endIter = mChildren->end();
2120 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2122 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2126 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2127 disconnectionList.push_back( ActorPtr( this ) );
2129 // Notification for internal derived classes
2130 OnStageDisconnectionInternal();
2132 DisconnectFromSceneGraph();
2138 * This method is called by an actor or its parent, before a node removal message is sent.
2139 * This is recursive; the child calls DisconnectFromStage() for its children.
2141 void Actor::DisconnectFromSceneGraph()
2143 // Notification for Object::Observers
2144 OnSceneObjectRemove();
2146 // Notify attachment
2149 mAttachment->Disconnect();
2152 unsigned int rendererCount( GetRendererCount() );
2153 for( unsigned int i(0); i<rendererCount; ++i )
2155 GetRendererAt(i)->Disconnect();
2159 void Actor::NotifyStageDisconnection()
2161 // Actors can be added (in a callback), before the off-stage state is reported.
2162 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2163 // only do this step if there is a stage, i.e. Core is not being shut down
2164 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2166 // Notification for external (CustomeActor) derived classes
2167 OnStageDisconnectionExternal();
2169 if( !mOffStageSignal.Empty() )
2171 Dali::Actor handle( this );
2172 mOffStageSignal.Emit( handle );
2175 // Guard against Add during callbacks
2178 mOnStageSignalled = false; // signal required next time Actor is added
2183 bool Actor::IsNodeConnected() const
2185 bool connected( false );
2187 if( OnStage() && ( NULL != mNode ) )
2189 if( IsRoot() || mNode->GetParent() )
2198 unsigned int Actor::GetDefaultPropertyCount() const
2200 return DEFAULT_PROPERTY_COUNT;
2203 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2205 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2207 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2209 indices.PushBack( i );
2213 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2215 if( index < DEFAULT_PROPERTY_COUNT )
2217 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2223 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2225 Property::Index index = Property::INVALID_INDEX;
2227 // Look for name in default properties
2228 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2230 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2231 if( 0 == name.compare( property->name ) )
2241 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2243 if( index < DEFAULT_PROPERTY_COUNT )
2245 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2251 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2253 if( index < DEFAULT_PROPERTY_COUNT )
2255 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2261 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2263 if( index < DEFAULT_PROPERTY_COUNT )
2265 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2271 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2273 if( index < DEFAULT_PROPERTY_COUNT )
2275 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2278 // index out of range...return Property::NONE
2279 return Property::NONE;
2282 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2286 case Dali::Actor::Property::PARENT_ORIGIN:
2288 SetParentOrigin( property.Get< Vector3 >() );
2292 case Dali::Actor::Property::PARENT_ORIGIN_X:
2294 SetParentOriginX( property.Get< float >() );
2298 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2300 SetParentOriginY( property.Get< float >() );
2304 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2306 SetParentOriginZ( property.Get< float >() );
2310 case Dali::Actor::Property::ANCHOR_POINT:
2312 SetAnchorPoint( property.Get< Vector3 >() );
2316 case Dali::Actor::Property::ANCHOR_POINT_X:
2318 SetAnchorPointX( property.Get< float >() );
2322 case Dali::Actor::Property::ANCHOR_POINT_Y:
2324 SetAnchorPointY( property.Get< float >() );
2328 case Dali::Actor::Property::ANCHOR_POINT_Z:
2330 SetAnchorPointZ( property.Get< float >() );
2334 case Dali::Actor::Property::SIZE:
2336 SetSize( property.Get< Vector3 >() );
2340 case Dali::Actor::Property::SIZE_WIDTH:
2342 SetWidth( property.Get< float >() );
2346 case Dali::Actor::Property::SIZE_HEIGHT:
2348 SetHeight( property.Get< float >() );
2352 case Dali::Actor::Property::SIZE_DEPTH:
2354 SetDepth( property.Get< float >() );
2358 case Dali::Actor::Property::POSITION:
2360 SetPosition( property.Get< Vector3 >() );
2364 case Dali::Actor::Property::POSITION_X:
2366 SetX( property.Get< float >() );
2370 case Dali::Actor::Property::POSITION_Y:
2372 SetY( property.Get< float >() );
2376 case Dali::Actor::Property::POSITION_Z:
2378 SetZ( property.Get< float >() );
2382 case Dali::Actor::Property::ORIENTATION:
2384 SetOrientation( property.Get< Quaternion >() );
2388 case Dali::Actor::Property::SCALE:
2390 SetScale( property.Get< Vector3 >() );
2394 case Dali::Actor::Property::SCALE_X:
2396 SetScaleX( property.Get< float >() );
2400 case Dali::Actor::Property::SCALE_Y:
2402 SetScaleY( property.Get< float >() );
2406 case Dali::Actor::Property::SCALE_Z:
2408 SetScaleZ( property.Get< float >() );
2412 case Dali::Actor::Property::VISIBLE:
2414 SetVisible( property.Get< bool >() );
2418 case Dali::Actor::Property::COLOR:
2420 SetColor( property.Get< Vector4 >() );
2424 case Dali::Actor::Property::COLOR_RED:
2426 SetColorRed( property.Get< float >() );
2430 case Dali::Actor::Property::COLOR_GREEN:
2432 SetColorGreen( property.Get< float >() );
2436 case Dali::Actor::Property::COLOR_BLUE:
2438 SetColorBlue( property.Get< float >() );
2442 case Dali::Actor::Property::COLOR_ALPHA:
2444 SetOpacity( property.Get< float >() );
2448 case Dali::Actor::Property::NAME:
2450 SetName( property.Get< std::string >() );
2454 case Dali::Actor::Property::SENSITIVE:
2456 SetSensitive( property.Get< bool >() );
2460 case Dali::Actor::Property::LEAVE_REQUIRED:
2462 SetLeaveRequired( property.Get< bool >() );
2466 case Dali::Actor::Property::INHERIT_ORIENTATION:
2468 SetInheritOrientation( property.Get< bool >() );
2472 case Dali::Actor::Property::INHERIT_SCALE:
2474 SetInheritScale( property.Get< bool >() );
2478 case Dali::Actor::Property::COLOR_MODE:
2480 SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2484 case Dali::Actor::Property::POSITION_INHERITANCE:
2486 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2490 case Dali::Actor::Property::DRAW_MODE:
2492 SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2496 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2498 SetSizeModeFactor( property.Get< Vector3 >() );
2502 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2504 ResizePolicy::Type type;
2505 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2507 SetResizePolicy( type, Dimension::WIDTH );
2512 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2514 ResizePolicy::Type type;
2515 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2517 SetResizePolicy( type, Dimension::HEIGHT );
2522 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2524 SizeScalePolicy::Type type;
2525 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount, type ) )
2527 SetSizeScalePolicy( type );
2532 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2534 if( property.Get< bool >() )
2536 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2541 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2543 if( property.Get< bool >() )
2545 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2550 case Dali::Actor::Property::PADDING:
2552 Vector4 padding = property.Get< Vector4 >();
2553 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2554 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2558 case Dali::Actor::Property::MINIMUM_SIZE:
2560 Vector2 size = property.Get< Vector2 >();
2561 SetMinimumSize( size.x, Dimension::WIDTH );
2562 SetMinimumSize( size.y, Dimension::HEIGHT );
2566 case Dali::Actor::Property::MAXIMUM_SIZE:
2568 Vector2 size = property.Get< Vector2 >();
2569 SetMaximumSize( size.x, Dimension::WIDTH );
2570 SetMaximumSize( size.y, Dimension::HEIGHT );
2576 // this can happen in the case of a non-animatable default property so just do nothing
2582 // TODO: This method needs to be removed
2583 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2585 switch( entry.GetType() )
2587 case Property::BOOLEAN:
2589 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2590 DALI_ASSERT_DEBUG( NULL != property );
2592 // property is being used in a separate thread; queue a message to set the property
2593 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2598 case Property::INTEGER:
2600 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2601 DALI_ASSERT_DEBUG( NULL != property );
2603 // property is being used in a separate thread; queue a message to set the property
2604 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2609 case Property::FLOAT:
2611 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( 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<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2620 case Property::VECTOR2:
2622 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( 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 if(entry.componentIndex == 0)
2628 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2630 else if(entry.componentIndex == 1)
2632 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2636 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2642 case Property::VECTOR3:
2644 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( 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<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2652 else if(entry.componentIndex == 1)
2654 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2656 else if(entry.componentIndex == 2)
2658 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2662 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2668 case Property::VECTOR4:
2670 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2671 DALI_ASSERT_DEBUG( NULL != property );
2673 // property is being used in a separate thread; queue a message to set the property
2674 if(entry.componentIndex == 0)
2676 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
2678 else if(entry.componentIndex == 1)
2680 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
2682 else if(entry.componentIndex == 2)
2684 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
2686 else if(entry.componentIndex == 3)
2688 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
2692 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2698 case Property::ROTATION:
2700 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
2701 DALI_ASSERT_DEBUG( NULL != property );
2703 // property is being used in a separate thread; queue a message to set the property
2704 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
2709 case Property::MATRIX:
2711 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
2712 DALI_ASSERT_DEBUG( NULL != property );
2714 // property is being used in a separate thread; queue a message to set the property
2715 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
2720 case Property::MATRIX3:
2722 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( 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<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
2733 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
2739 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
2741 Property::Value value;
2745 case Dali::Actor::Property::PARENT_ORIGIN:
2747 value = GetCurrentParentOrigin();
2751 case Dali::Actor::Property::PARENT_ORIGIN_X:
2753 value = GetCurrentParentOrigin().x;
2757 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2759 value = GetCurrentParentOrigin().y;
2763 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2765 value = GetCurrentParentOrigin().z;
2769 case Dali::Actor::Property::ANCHOR_POINT:
2771 value = GetCurrentAnchorPoint();
2775 case Dali::Actor::Property::ANCHOR_POINT_X:
2777 value = GetCurrentAnchorPoint().x;
2781 case Dali::Actor::Property::ANCHOR_POINT_Y:
2783 value = GetCurrentAnchorPoint().y;
2787 case Dali::Actor::Property::ANCHOR_POINT_Z:
2789 value = GetCurrentAnchorPoint().z;
2793 case Dali::Actor::Property::SIZE:
2795 value = GetTargetSize();
2799 case Dali::Actor::Property::SIZE_WIDTH:
2801 value = GetTargetSize().width;
2805 case Dali::Actor::Property::SIZE_HEIGHT:
2807 value = GetTargetSize().height;
2811 case Dali::Actor::Property::SIZE_DEPTH:
2813 value = GetTargetSize().depth;
2817 case Dali::Actor::Property::POSITION:
2819 value = GetTargetPosition();
2823 case Dali::Actor::Property::POSITION_X:
2825 value = GetTargetPosition().x;
2829 case Dali::Actor::Property::POSITION_Y:
2831 value = GetTargetPosition().y;
2835 case Dali::Actor::Property::POSITION_Z:
2837 value = GetTargetPosition().z;
2841 case Dali::Actor::Property::WORLD_POSITION:
2843 value = GetCurrentWorldPosition();
2847 case Dali::Actor::Property::WORLD_POSITION_X:
2849 value = GetCurrentWorldPosition().x;
2853 case Dali::Actor::Property::WORLD_POSITION_Y:
2855 value = GetCurrentWorldPosition().y;
2859 case Dali::Actor::Property::WORLD_POSITION_Z:
2861 value = GetCurrentWorldPosition().z;
2865 case Dali::Actor::Property::ORIENTATION:
2867 value = GetCurrentOrientation();
2871 case Dali::Actor::Property::WORLD_ORIENTATION:
2873 value = GetCurrentWorldOrientation();
2877 case Dali::Actor::Property::SCALE:
2879 value = GetCurrentScale();
2883 case Dali::Actor::Property::SCALE_X:
2885 value = GetCurrentScale().x;
2889 case Dali::Actor::Property::SCALE_Y:
2891 value = GetCurrentScale().y;
2895 case Dali::Actor::Property::SCALE_Z:
2897 value = GetCurrentScale().z;
2901 case Dali::Actor::Property::WORLD_SCALE:
2903 value = GetCurrentWorldScale();
2907 case Dali::Actor::Property::VISIBLE:
2909 value = IsVisible();
2913 case Dali::Actor::Property::COLOR:
2915 value = GetCurrentColor();
2919 case Dali::Actor::Property::COLOR_RED:
2921 value = GetCurrentColor().r;
2925 case Dali::Actor::Property::COLOR_GREEN:
2927 value = GetCurrentColor().g;
2931 case Dali::Actor::Property::COLOR_BLUE:
2933 value = GetCurrentColor().b;
2937 case Dali::Actor::Property::COLOR_ALPHA:
2939 value = GetCurrentColor().a;
2943 case Dali::Actor::Property::WORLD_COLOR:
2945 value = GetCurrentWorldColor();
2949 case Dali::Actor::Property::WORLD_MATRIX:
2951 value = GetCurrentWorldMatrix();
2955 case Dali::Actor::Property::NAME:
2961 case Dali::Actor::Property::SENSITIVE:
2963 value = IsSensitive();
2967 case Dali::Actor::Property::LEAVE_REQUIRED:
2969 value = GetLeaveRequired();
2973 case Dali::Actor::Property::INHERIT_ORIENTATION:
2975 value = IsOrientationInherited();
2979 case Dali::Actor::Property::INHERIT_SCALE:
2981 value = IsScaleInherited();
2985 case Dali::Actor::Property::COLOR_MODE:
2987 value = Scripting::GetColorMode( GetColorMode() );
2991 case Dali::Actor::Property::POSITION_INHERITANCE:
2993 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
2997 case Dali::Actor::Property::DRAW_MODE:
2999 value = Scripting::GetDrawMode( GetDrawMode() );
3003 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3005 value = GetSizeModeFactor();
3009 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3011 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3015 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3017 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3021 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3023 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3027 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3029 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3033 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3035 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3039 case Dali::Actor::Property::PADDING:
3041 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3042 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3043 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3047 case Dali::Actor::Property::MINIMUM_SIZE:
3049 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3053 case Dali::Actor::Property::MAXIMUM_SIZE:
3055 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3061 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3069 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3074 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3076 // This method should only return an object connected to the scene-graph
3077 return OnStage() ? mNode : NULL;
3080 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3082 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3084 const PropertyBase* property( NULL );
3086 // This method should only return a property of an object connected to the scene-graph
3092 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3094 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3095 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3097 property = animatable->GetSceneGraphProperty();
3099 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3101 CustomPropertyMetadata* custom = FindCustomProperty( index );
3102 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3104 property = custom->GetSceneGraphProperty();
3106 else if( NULL != mNode )
3110 case Dali::Actor::Property::SIZE:
3111 property = &mNode->mSize;
3114 case Dali::Actor::Property::SIZE_WIDTH:
3115 property = &mNode->mSize;
3118 case Dali::Actor::Property::SIZE_HEIGHT:
3119 property = &mNode->mSize;
3122 case Dali::Actor::Property::SIZE_DEPTH:
3123 property = &mNode->mSize;
3126 case Dali::Actor::Property::POSITION:
3127 property = &mNode->mPosition;
3130 case Dali::Actor::Property::POSITION_X:
3131 property = &mNode->mPosition;
3134 case Dali::Actor::Property::POSITION_Y:
3135 property = &mNode->mPosition;
3138 case Dali::Actor::Property::POSITION_Z:
3139 property = &mNode->mPosition;
3142 case Dali::Actor::Property::ORIENTATION:
3143 property = &mNode->mOrientation;
3146 case Dali::Actor::Property::SCALE:
3147 property = &mNode->mScale;
3150 case Dali::Actor::Property::SCALE_X:
3151 property = &mNode->mScale;
3154 case Dali::Actor::Property::SCALE_Y:
3155 property = &mNode->mScale;
3158 case Dali::Actor::Property::SCALE_Z:
3159 property = &mNode->mScale;
3162 case Dali::Actor::Property::VISIBLE:
3163 property = &mNode->mVisible;
3166 case Dali::Actor::Property::COLOR:
3167 property = &mNode->mColor;
3170 case Dali::Actor::Property::COLOR_RED:
3171 property = &mNode->mColor;
3174 case Dali::Actor::Property::COLOR_GREEN:
3175 property = &mNode->mColor;
3178 case Dali::Actor::Property::COLOR_BLUE:
3179 property = &mNode->mColor;
3182 case Dali::Actor::Property::COLOR_ALPHA:
3183 property = &mNode->mColor;
3194 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3196 const PropertyInputImpl* property( NULL );
3198 // This method should only return a property of an object connected to the scene-graph
3204 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3206 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3207 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3209 property = animatable->GetSceneGraphProperty();
3211 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3213 CustomPropertyMetadata* custom = FindCustomProperty( index );
3214 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3215 property = custom->GetSceneGraphProperty();
3217 else if( NULL != mNode )
3221 case Dali::Actor::Property::PARENT_ORIGIN:
3222 property = &mNode->mParentOrigin;
3225 case Dali::Actor::Property::PARENT_ORIGIN_X:
3226 property = &mNode->mParentOrigin;
3229 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3230 property = &mNode->mParentOrigin;
3233 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3234 property = &mNode->mParentOrigin;
3237 case Dali::Actor::Property::ANCHOR_POINT:
3238 property = &mNode->mAnchorPoint;
3241 case Dali::Actor::Property::ANCHOR_POINT_X:
3242 property = &mNode->mAnchorPoint;
3245 case Dali::Actor::Property::ANCHOR_POINT_Y:
3246 property = &mNode->mAnchorPoint;
3249 case Dali::Actor::Property::ANCHOR_POINT_Z:
3250 property = &mNode->mAnchorPoint;
3253 case Dali::Actor::Property::SIZE:
3254 property = &mNode->mSize;
3257 case Dali::Actor::Property::SIZE_WIDTH:
3258 property = &mNode->mSize;
3261 case Dali::Actor::Property::SIZE_HEIGHT:
3262 property = &mNode->mSize;
3265 case Dali::Actor::Property::SIZE_DEPTH:
3266 property = &mNode->mSize;
3269 case Dali::Actor::Property::POSITION:
3270 property = &mNode->mPosition;
3273 case Dali::Actor::Property::POSITION_X:
3274 property = &mNode->mPosition;
3277 case Dali::Actor::Property::POSITION_Y:
3278 property = &mNode->mPosition;
3281 case Dali::Actor::Property::POSITION_Z:
3282 property = &mNode->mPosition;
3285 case Dali::Actor::Property::WORLD_POSITION:
3286 property = &mNode->mWorldPosition;
3289 case Dali::Actor::Property::WORLD_POSITION_X:
3290 property = &mNode->mWorldPosition;
3293 case Dali::Actor::Property::WORLD_POSITION_Y:
3294 property = &mNode->mWorldPosition;
3297 case Dali::Actor::Property::WORLD_POSITION_Z:
3298 property = &mNode->mWorldPosition;
3301 case Dali::Actor::Property::ORIENTATION:
3302 property = &mNode->mOrientation;
3305 case Dali::Actor::Property::WORLD_ORIENTATION:
3306 property = &mNode->mWorldOrientation;
3309 case Dali::Actor::Property::SCALE:
3310 property = &mNode->mScale;
3313 case Dali::Actor::Property::SCALE_X:
3314 property = &mNode->mScale;
3317 case Dali::Actor::Property::SCALE_Y:
3318 property = &mNode->mScale;
3321 case Dali::Actor::Property::SCALE_Z:
3322 property = &mNode->mScale;
3325 case Dali::Actor::Property::WORLD_SCALE:
3326 property = &mNode->mWorldScale;
3329 case Dali::Actor::Property::VISIBLE:
3330 property = &mNode->mVisible;
3333 case Dali::Actor::Property::COLOR:
3334 property = &mNode->mColor;
3337 case Dali::Actor::Property::COLOR_RED:
3338 property = &mNode->mColor;
3341 case Dali::Actor::Property::COLOR_GREEN:
3342 property = &mNode->mColor;
3345 case Dali::Actor::Property::COLOR_BLUE:
3346 property = &mNode->mColor;
3349 case Dali::Actor::Property::COLOR_ALPHA:
3350 property = &mNode->mColor;
3353 case Dali::Actor::Property::WORLD_COLOR:
3354 property = &mNode->mWorldColor;
3357 case Dali::Actor::Property::WORLD_MATRIX:
3358 property = &mNode->mWorldMatrix;
3369 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3371 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3373 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3375 // check whether the animatable property is registered already, if not then register one.
3376 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3377 if( animatableProperty )
3379 componentIndex = animatableProperty->componentIndex;
3386 case Dali::Actor::Property::PARENT_ORIGIN_X:
3387 case Dali::Actor::Property::ANCHOR_POINT_X:
3388 case Dali::Actor::Property::SIZE_WIDTH:
3389 case Dali::Actor::Property::POSITION_X:
3390 case Dali::Actor::Property::WORLD_POSITION_X:
3391 case Dali::Actor::Property::SCALE_X:
3392 case Dali::Actor::Property::COLOR_RED:
3398 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3399 case Dali::Actor::Property::ANCHOR_POINT_Y:
3400 case Dali::Actor::Property::SIZE_HEIGHT:
3401 case Dali::Actor::Property::POSITION_Y:
3402 case Dali::Actor::Property::WORLD_POSITION_Y:
3403 case Dali::Actor::Property::SCALE_Y:
3404 case Dali::Actor::Property::COLOR_GREEN:
3410 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3411 case Dali::Actor::Property::ANCHOR_POINT_Z:
3412 case Dali::Actor::Property::SIZE_DEPTH:
3413 case Dali::Actor::Property::POSITION_Z:
3414 case Dali::Actor::Property::WORLD_POSITION_Z:
3415 case Dali::Actor::Property::SCALE_Z:
3416 case Dali::Actor::Property::COLOR_BLUE:
3422 case Dali::Actor::Property::COLOR_ALPHA:
3436 return componentIndex;
3439 void Actor::SetParent( Actor* parent )
3443 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3447 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3450 // Instruct each actor to create a corresponding node in the scene graph
3451 ConnectToStage( parent->GetHierarchyDepth() );
3454 else // parent being set to NULL
3456 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3460 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3463 DALI_ASSERT_ALWAYS( mNode != NULL );
3467 // Disconnect the Node & its children from the scene-graph.
3468 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3471 // Instruct each actor to discard pointers to the scene-graph
3472 DisconnectFromStage();
3477 SceneGraph::Node* Actor::CreateNode() const
3482 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3485 Actor* actor = dynamic_cast< Actor* >( object );
3489 if( 0 == actionName.compare( ACTION_SHOW ) )
3491 actor->SetVisible( true );
3494 else if( 0 == actionName.compare( ACTION_HIDE ) )
3496 actor->SetVisible( false );
3504 void Actor::EnsureRelayoutData()
3506 // Assign relayout data.
3507 if( !mRelayoutData )
3509 mRelayoutData = new RelayoutData();
3513 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3515 // Check if actor is dependent on parent
3516 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3518 if( ( dimension & ( 1 << i ) ) )
3520 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3521 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3531 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3533 // Check if actor is dependent on children
3534 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3536 if( ( dimension & ( 1 << i ) ) )
3538 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3539 switch( resizePolicy )
3541 case ResizePolicy::FIT_TO_CHILDREN:
3542 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3558 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3560 return Actor::RelayoutDependentOnChildren( dimension );
3563 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3565 // Check each possible dimension and see if it is dependent on the input one
3566 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3568 if( dimension & ( 1 << i ) )
3570 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3577 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3579 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3581 if( dimension & ( 1 << i ) )
3583 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3588 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3590 // If more than one dimension is requested, just return the first one found
3591 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3593 if( ( dimension & ( 1 << i ) ) )
3595 return mRelayoutData->negotiatedDimensions[ i ];
3599 return 0.0f; // Default
3602 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3604 EnsureRelayoutData();
3606 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3608 if( dimension & ( 1 << i ) )
3610 mRelayoutData->dimensionPadding[ i ] = padding;
3615 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3617 if ( mRelayoutData )
3619 // If more than one dimension is requested, just return the first one found
3620 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3622 if( ( dimension & ( 1 << i ) ) )
3624 return mRelayoutData->dimensionPadding[ i ];
3629 return GetDefaultDimensionPadding();
3632 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
3634 EnsureRelayoutData();
3636 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3638 if( dimension & ( 1 << i ) )
3640 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3645 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
3647 if ( mRelayoutData )
3649 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3651 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
3661 float Actor::GetHeightForWidthBase( float width )
3663 float height = 0.0f;
3665 const Vector3 naturalSize = GetNaturalSize();
3666 if( naturalSize.width > 0.0f )
3668 height = naturalSize.height * width / naturalSize.width;
3670 else // we treat 0 as 1:1 aspect ratio
3678 float Actor::GetWidthForHeightBase( float height )
3682 const Vector3 naturalSize = GetNaturalSize();
3683 if( naturalSize.height > 0.0f )
3685 width = naturalSize.width * height / naturalSize.height;
3687 else // we treat 0 as 1:1 aspect ratio
3695 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
3697 // Fill to parent, taking size mode factor into account
3698 switch( child.GetResizePolicy( dimension ) )
3700 case ResizePolicy::FILL_TO_PARENT:
3702 return GetLatestSize( dimension );
3705 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3707 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
3710 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3712 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
3717 return GetLatestSize( dimension );
3722 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
3724 // Can be overridden in derived class
3725 return CalculateChildSizeBase( child, dimension );
3728 float Actor::GetHeightForWidth( float width )
3730 // Can be overridden in derived class
3731 return GetHeightForWidthBase( width );
3734 float Actor::GetWidthForHeight( float height )
3736 // Can be overridden in derived class
3737 return GetWidthForHeightBase( height );
3740 float Actor::GetLatestSize( Dimension::Type dimension ) const
3742 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
3745 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
3747 Vector2 padding = GetPadding( dimension );
3749 return GetLatestSize( dimension ) + padding.x + padding.y;
3752 float Actor::NegotiateFromParent( Dimension::Type dimension )
3754 Actor* parent = GetParent();
3757 Vector2 padding( GetPadding( dimension ) );
3758 Vector2 parentPadding( parent->GetPadding( dimension ) );
3759 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
3765 float Actor::NegotiateFromChildren( Dimension::Type dimension )
3767 float maxDimensionPoint = 0.0f;
3769 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3771 ActorPtr child = GetChildAt( i );
3773 if( !child->RelayoutDependentOnParent( dimension ) )
3775 // Calculate the min and max points that the children range across
3776 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
3777 float dimensionSize = child->GetRelayoutSize( dimension );
3778 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
3782 return maxDimensionPoint;
3785 float Actor::GetSize( Dimension::Type dimension ) const
3787 return GetDimensionValue( GetTargetSize(), dimension );
3790 float Actor::GetNaturalSize( Dimension::Type dimension ) const
3792 return GetDimensionValue( GetNaturalSize(), dimension );
3795 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
3797 switch( GetResizePolicy( dimension ) )
3799 case ResizePolicy::USE_NATURAL_SIZE:
3801 return GetNaturalSize( dimension );
3804 case ResizePolicy::FIXED:
3806 return GetDimensionValue( GetPreferredSize(), dimension );
3809 case ResizePolicy::USE_ASSIGNED_SIZE:
3811 return GetDimensionValue( maximumSize, dimension );
3814 case ResizePolicy::FILL_TO_PARENT:
3815 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3816 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3818 return NegotiateFromParent( dimension );
3821 case ResizePolicy::FIT_TO_CHILDREN:
3823 return NegotiateFromChildren( dimension );
3826 case ResizePolicy::DIMENSION_DEPENDENCY:
3828 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
3831 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
3833 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
3836 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
3838 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
3850 return 0.0f; // Default
3853 float Actor::ClampDimension( float size, Dimension::Type dimension )
3855 const float minSize = GetMinimumSize( dimension );
3856 const float maxSize = GetMaximumSize( dimension );
3858 return std::max( minSize, std::min( size, maxSize ) );
3861 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
3863 // Check if it needs to be negotiated
3864 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
3866 // Check that we havn't gotten into an infinite loop
3867 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
3868 bool recursionFound = false;
3869 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
3871 if( *it == searchActor )
3873 recursionFound = true;
3878 if( !recursionFound )
3880 // Record the path that we have taken
3881 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
3883 // Dimension dependency check
3884 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3886 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
3888 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
3890 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
3894 // Parent dependency check
3895 Actor* parent = GetParent();
3896 if( parent && RelayoutDependentOnParent( dimension ) )
3898 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
3901 // Children dependency check
3902 if( RelayoutDependentOnChildren( dimension ) )
3904 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3906 ActorPtr child = GetChildAt( i );
3908 // Only relayout child first if it is not dependent on this actor
3909 if( !child->RelayoutDependentOnParent( dimension ) )
3911 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
3916 // For deriving classes
3917 OnCalculateRelayoutSize( dimension );
3919 // All dependencies checked, calculate the size and set negotiated flag
3920 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
3922 SetNegotiatedDimension( newSize, dimension );
3923 SetLayoutNegotiated( true, dimension );
3925 // For deriving classes
3926 OnLayoutNegotiated( newSize, dimension );
3928 // This actor has been successfully processed, pop it off the recursion stack
3929 recursionStack.pop_back();
3933 // TODO: Break infinite loop
3934 SetLayoutNegotiated( true, dimension );
3939 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
3941 // Negotiate all dimensions that require it
3942 ActorDimensionStack recursionStack;
3944 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3946 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
3949 NegotiateDimension( dimension, allocatedSize, recursionStack );
3953 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
3955 switch( mRelayoutData->sizeSetPolicy )
3957 case SizeScalePolicy::USE_SIZE_SET:
3962 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
3964 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
3965 const Vector3 naturalSize = GetNaturalSize();
3966 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
3968 const float sizeRatio = size.width / size.height;
3969 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
3971 if( naturalSizeRatio < sizeRatio )
3973 return Vector2( naturalSizeRatio * size.height, size.height );
3975 else if( naturalSizeRatio > sizeRatio )
3977 return Vector2( size.width, size.width / naturalSizeRatio );
3988 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
3990 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
3991 const Vector3 naturalSize = GetNaturalSize();
3992 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
3994 const float sizeRatio = size.width / size.height;
3995 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
3997 if( naturalSizeRatio < sizeRatio )
3999 return Vector2( size.width, size.width / naturalSizeRatio );
4001 else if( naturalSizeRatio > sizeRatio )
4003 return Vector2( naturalSizeRatio * size.height, size.height );
4021 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4023 // Do the set actor size
4024 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4026 // Adjust for size set policy
4027 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4029 // Lock the flag to stop recursive relayouts on set size
4030 mRelayoutData->insideRelayout = true;
4031 SetSize( negotiatedSize );
4032 mRelayoutData->insideRelayout = false;
4034 // Clear flags for all dimensions
4035 SetLayoutDirty( false );
4037 // Give deriving classes a chance to respond
4038 OnRelayout( negotiatedSize, container );
4040 if( !mOnRelayoutSignal.Empty() )
4042 Dali::Actor handle( this );
4043 mOnRelayoutSignal.Emit( handle );
4047 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4049 // Do the negotiation
4050 NegotiateDimensions( allocatedSize );
4052 // Set the actor size
4053 SetNegotiatedSize( container );
4055 // Negotiate down to children
4056 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4058 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4060 ActorPtr child = GetChildAt( i );
4062 // Only relayout if required
4063 if( child->RelayoutRequired() )
4065 container.Add( Dali::Actor( child.Get() ), newBounds );
4070 void Actor::RelayoutRequest( Dimension::Type dimension )
4072 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4073 if( relayoutController )
4075 Dali::Actor self( this );
4076 relayoutController->RequestRelayout( self, dimension );
4080 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4084 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4088 void Actor::SetPreferredSize( const Vector2& size )
4090 EnsureRelayoutData();
4092 if( size.width > 0.0f )
4094 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4097 if( size.height > 0.0f )
4099 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4102 mRelayoutData->preferredSize = size;
4107 Vector2 Actor::GetPreferredSize() const
4109 if ( mRelayoutData )
4111 return Vector2( mRelayoutData->preferredSize );
4114 return GetDefaultPreferredSize();
4117 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4119 EnsureRelayoutData();
4121 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4123 if( dimension & ( 1 << i ) )
4125 mRelayoutData->minimumSize[ i ] = size;
4132 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4134 if ( mRelayoutData )
4136 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4138 if( dimension & ( 1 << i ) )
4140 return mRelayoutData->minimumSize[ i ];
4145 return 0.0f; // Default
4148 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4150 EnsureRelayoutData();
4152 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4154 if( dimension & ( 1 << i ) )
4156 mRelayoutData->maximumSize[ i ] = size;
4163 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4165 if ( mRelayoutData )
4167 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4169 if( dimension & ( 1 << i ) )
4171 return mRelayoutData->maximumSize[ i ];
4176 return FLT_MAX; // Default
4179 } // namespace Internal