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/actor-attachments/renderer-attachment-impl.h>
46 #include <dali/internal/event/animation/constraint-impl.h>
47 #include <dali/internal/event/common/projection.h>
48 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
49 #include <dali/internal/update/common/animatable-property.h>
50 #include <dali/internal/update/nodes/node-messages.h>
51 #include <dali/internal/update/nodes/node-declarations.h>
52 #include <dali/internal/update/animation/scene-graph-constraint.h>
53 #include <dali/internal/event/events/actor-gesture-data.h>
54 #include <dali/internal/common/message.h>
55 #include <dali/integration-api/debug.h>
57 using Dali::Internal::SceneGraph::Node;
58 using Dali::Internal::SceneGraph::AnimatableProperty;
59 using Dali::Internal::SceneGraph::PropertyBase;
63 namespace ResizePolicy
68 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )
69 DALI_ENUM_TO_STRING( FIXED )
70 DALI_ENUM_TO_STRING( USE_NATURAL_SIZE )
71 DALI_ENUM_TO_STRING( FILL_TO_PARENT )
72 DALI_ENUM_TO_STRING( SIZE_RELATIVE_TO_PARENT )
73 DALI_ENUM_TO_STRING( SIZE_FIXED_OFFSET_FROM_PARENT )
74 DALI_ENUM_TO_STRING( FIT_TO_CHILDREN )
75 DALI_ENUM_TO_STRING( DIMENSION_DEPENDENCY )
76 DALI_ENUM_TO_STRING( USE_ASSIGNED_SIZE )
77 DALI_ENUM_TO_STRING_TABLE_END( Type )
79 } // unnamed namespace
82 namespace SizeScalePolicy
86 // Enumeration to / from string conversion tables
87 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )
88 DALI_ENUM_TO_STRING( USE_SIZE_SET )
89 DALI_ENUM_TO_STRING( FIT_WITH_ASPECT_RATIO )
90 DALI_ENUM_TO_STRING( FILL_WITH_ASPECT_RATIO )
91 DALI_ENUM_TO_STRING_TABLE_END( Type )
92 } // unnamed namespace
98 unsigned int Actor::mActorCounter = 0;
102 /// Using a function because of library initialisation order. Vector3::ONE may not have been initialised yet.
103 inline const Vector3& GetDefaultSizeModeFactor()
108 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
109 inline const Vector2& GetDefaultPreferredSize()
111 return Vector2::ZERO;
114 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
115 inline const Vector2& GetDefaultDimensionPadding()
117 return Vector2::ZERO;
120 const SizeScalePolicy::Type DEFAULT_SIZE_SCALE_POLICY = SizeScalePolicy::USE_SIZE_SET;
122 } // unnamed namespace
125 * Struct to collect relayout variables
127 struct Actor::RelayoutData
130 : sizeModeFactor( GetDefaultSizeModeFactor() ), preferredSize( GetDefaultPreferredSize() ), sizeSetPolicy( DEFAULT_SIZE_SCALE_POLICY ), relayoutEnabled( false ), insideRelayout( false )
132 // Set size negotiation defaults
133 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
135 resizePolicies[ i ] = ResizePolicy::DEFAULT;
136 negotiatedDimensions[ i ] = 0.0f;
137 dimensionNegotiated[ i ] = false;
138 dimensionDirty[ i ] = false;
139 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
140 dimensionPadding[ i ] = GetDefaultDimensionPadding();
141 minimumSize[ i ] = 0.0f;
142 maximumSize[ i ] = FLT_MAX;
146 ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies
148 Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies
150 Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
152 float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
154 float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be
155 float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be
157 bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated
158 bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
160 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
162 Vector2 preferredSize; ///< The preferred size of the actor
164 SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
166 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
167 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
170 namespace // unnamed namespace
176 * We want to discourage the use of property strings (minimize string comparisons),
177 * particularly for the default properties.
178 * Name Type writable animatable constraint-input enum for index-checking
180 DALI_PROPERTY_TABLE_BEGIN
181 DALI_PROPERTY( "parent-origin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
182 DALI_PROPERTY( "parent-origin-x", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
183 DALI_PROPERTY( "parent-origin-y", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
184 DALI_PROPERTY( "parent-origin-z", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
185 DALI_PROPERTY( "anchor-point", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
186 DALI_PROPERTY( "anchor-point-x", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
187 DALI_PROPERTY( "anchor-point-y", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
188 DALI_PROPERTY( "anchor-point-z", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
189 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
190 DALI_PROPERTY( "size-width", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
191 DALI_PROPERTY( "size-height", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
192 DALI_PROPERTY( "size-depth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
193 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
194 DALI_PROPERTY( "position-x", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
195 DALI_PROPERTY( "position-y", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
196 DALI_PROPERTY( "position-z", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
197 DALI_PROPERTY( "world-position", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
198 DALI_PROPERTY( "world-position-x", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
199 DALI_PROPERTY( "world-position-y", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
200 DALI_PROPERTY( "world-position-z", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
201 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
202 DALI_PROPERTY( "world-orientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
203 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
204 DALI_PROPERTY( "scale-x", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
205 DALI_PROPERTY( "scale-y", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
206 DALI_PROPERTY( "scale-z", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
207 DALI_PROPERTY( "world-scale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
208 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
209 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
210 DALI_PROPERTY( "color-red", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
211 DALI_PROPERTY( "color-green", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
212 DALI_PROPERTY( "color-blue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
213 DALI_PROPERTY( "color-alpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
214 DALI_PROPERTY( "world-color", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
215 DALI_PROPERTY( "world-matrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
216 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
217 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
218 DALI_PROPERTY( "leave-required", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
219 DALI_PROPERTY( "inherit-orientation",BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
220 DALI_PROPERTY( "inherit-scale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
221 DALI_PROPERTY( "color-mode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
222 DALI_PROPERTY( "position-inheritance",STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE )
223 DALI_PROPERTY( "draw-mode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
224 DALI_PROPERTY( "size-mode-factor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
225 DALI_PROPERTY( "width-resize-policy",STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
226 DALI_PROPERTY( "height-resize-policy",STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
227 DALI_PROPERTY( "size-scale-policy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
228 DALI_PROPERTY( "width-for-height", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
229 DALI_PROPERTY( "height-for-width", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
230 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
231 DALI_PROPERTY( "minimum-size", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
232 DALI_PROPERTY( "maximum-size", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
233 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
237 const char* const SIGNAL_TOUCHED = "touched";
238 const char* const SIGNAL_HOVERED = "hovered";
239 const char* const SIGNAL_WHEEL_EVENT = "wheel-event";
240 const char* const SIGNAL_ON_STAGE = "on-stage";
241 const char* const SIGNAL_OFF_STAGE = "off-stage";
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_ON_STAGE, &Actor::DoConnectSignal );
258 SignalConnectorType signalConnector4( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
260 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
261 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
264 * @brief Extract a given dimension from a Vector2
266 * @param[in] values The values to extract from
267 * @param[in] dimension The dimension to extract
268 * @return Return the value for the dimension
270 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
274 case Dimension::WIDTH:
278 case Dimension::HEIGHT:
280 return values.height;
291 * @brief Extract a given dimension from a Vector3
293 * @param[in] values The values to extract from
294 * @param[in] dimension The dimension to extract
295 * @return Return the value for the dimension
297 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
299 return GetDimensionValue( values.GetVectorXY(), dimension );
303 } // unnamed namespace
305 ActorPtr Actor::New()
307 ActorPtr actor( new Actor( BASIC ) );
309 // Second-phase construction
315 const std::string& Actor::GetName() const
320 void Actor::SetName( const std::string& name )
326 // ATTENTION: string for debug purposes is not thread safe.
327 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
331 unsigned int Actor::GetId() const
336 void Actor::Attach( ActorAttachment& attachment )
338 DALI_ASSERT_DEBUG( !mAttachment && "An Actor can only have one attachment" );
342 attachment.Connect();
345 mAttachment = ActorAttachmentPtr( &attachment );
348 ActorAttachmentPtr Actor::GetAttachment()
353 bool Actor::OnStage() const
358 Dali::Layer Actor::GetLayer()
362 // Short-circuit for Layer derived actors
365 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
368 // Find the immediate Layer parent
369 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
371 if( parent->IsLayer() )
373 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
380 void Actor::Add( Actor& child )
382 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
383 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
387 mChildren = new ActorContainer;
390 Actor* const oldParent( child.mParent );
392 // child might already be ours
393 if( this != oldParent )
395 // if we already have parent, unparent us first
398 oldParent->Remove( child ); // This causes OnChildRemove callback
400 // Old parent may need to readjust to missing child
401 if( oldParent->RelayoutDependentOnChildren() )
403 oldParent->RelayoutRequest();
407 // Guard against Add() during previous OnChildRemove callback
410 // Do this first, since user callbacks from within SetParent() may need to remove child
411 mChildren->push_back( ActorPtr( &child ) );
413 // SetParent asserts that child can be added
414 child.SetParent( this );
416 // Notification for derived classes
419 // Only put in a relayout request if there is a suitable dependency
420 if( RelayoutDependentOnChildren() )
428 void Actor::Insert( unsigned int index, Actor& child )
430 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
431 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
435 mChildren = new ActorContainer;
438 Actor* const oldParent( child.mParent );
440 // since an explicit position has been given, always insert, even if already a child
443 oldParent->Remove( child ); // This causes OnChildRemove callback
445 // Old parent may need to readjust to missing child
446 if( oldParent->RelayoutDependentOnChildren() )
448 oldParent->RelayoutRequest();
452 // Guard against Add() during previous OnChildRemove callback
455 // Do this first, since user callbacks from within SetParent() may need to remove child
456 if( index < GetChildCount() )
458 ActorIter it = mChildren->begin();
459 std::advance( it, index );
460 mChildren->insert( it, ActorPtr( &child ) );
464 mChildren->push_back( ActorPtr( &child ) );
466 // SetParent asserts that child can be added
467 child.SetParent( this, index );
469 // Notification for derived classes
472 // Only put in a relayout request if there is a suitable dependency
473 if( RelayoutDependentOnChildren() )
478 if( child.RelayoutDependentOnParent() )
480 child.RelayoutRequest();
485 void Actor::Remove( Actor& child )
487 if( (this == &child) || (!mChildren) )
489 // no children or removing itself
495 // Find the child in mChildren, and unparent it
496 ActorIter end = mChildren->end();
497 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
499 ActorPtr actor = (*iter);
501 if( actor.Get() == &child )
503 // Keep handle for OnChildRemove notification
506 // Do this first, since user callbacks from within SetParent() may need to add the child
507 mChildren->erase( iter );
509 DALI_ASSERT_DEBUG( actor->GetParent() == this );
510 actor->SetParent( NULL );
518 // Notification for derived classes
519 OnChildRemove( *(removed.Get()) );
521 // Only put in a relayout request if there is a suitable dependency
522 if( RelayoutDependentOnChildren() )
529 void Actor::Unparent()
533 // Remove this actor from the parent. The remove will put a relayout request in for
534 // the parent if required
535 mParent->Remove( *this );
536 // mParent is now NULL!
540 unsigned int Actor::GetChildCount() const
542 return ( NULL != mChildren ) ? mChildren->size() : 0;
545 ActorPtr Actor::GetChildAt( unsigned int index ) const
547 DALI_ASSERT_ALWAYS( index < GetChildCount() );
549 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
552 ActorPtr Actor::FindChildByName( const std::string& actorName )
555 if( actorName == mName )
561 ActorIter end = mChildren->end();
562 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
564 child = (*iter)->FindChildByName( actorName );
575 ActorPtr Actor::FindChildById( const unsigned int id )
584 ActorIter end = mChildren->end();
585 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
587 child = (*iter)->FindChildById( id );
598 void Actor::SetParentOrigin( const Vector3& origin )
602 // mNode is being used in a separate thread; queue a message to set the value & base value
603 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
606 // Cache for event-thread access
609 // not allocated, check if different from default
610 if( ParentOrigin::DEFAULT != origin )
612 mParentOrigin = new Vector3( origin );
617 // check if different from current costs more than just set
618 *mParentOrigin = origin;
622 void Actor::SetParentOriginX( float x )
624 const Vector3& current = GetCurrentParentOrigin();
626 SetParentOrigin( Vector3( x, current.y, current.z ) );
629 void Actor::SetParentOriginY( float y )
631 const Vector3& current = GetCurrentParentOrigin();
633 SetParentOrigin( Vector3( current.x, y, current.z ) );
636 void Actor::SetParentOriginZ( float z )
638 const Vector3& current = GetCurrentParentOrigin();
640 SetParentOrigin( Vector3( current.x, current.y, z ) );
643 const Vector3& Actor::GetCurrentParentOrigin() const
645 // Cached for event-thread access
646 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
649 void Actor::SetAnchorPoint( const Vector3& anchor )
653 // mNode is being used in a separate thread; queue a message to set the value & base value
654 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
657 // Cache for event-thread access
660 // not allocated, check if different from default
661 if( AnchorPoint::DEFAULT != anchor )
663 mAnchorPoint = new Vector3( anchor );
668 // check if different from current costs more than just set
669 *mAnchorPoint = anchor;
673 void Actor::SetAnchorPointX( float x )
675 const Vector3& current = GetCurrentAnchorPoint();
677 SetAnchorPoint( Vector3( x, current.y, current.z ) );
680 void Actor::SetAnchorPointY( float y )
682 const Vector3& current = GetCurrentAnchorPoint();
684 SetAnchorPoint( Vector3( current.x, y, current.z ) );
687 void Actor::SetAnchorPointZ( float z )
689 const Vector3& current = GetCurrentAnchorPoint();
691 SetAnchorPoint( Vector3( current.x, current.y, z ) );
694 const Vector3& Actor::GetCurrentAnchorPoint() const
696 // Cached for event-thread access
697 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
700 void Actor::SetPosition( float x, float y )
702 SetPosition( Vector3( x, y, 0.0f ) );
705 void Actor::SetPosition( float x, float y, float z )
707 SetPosition( Vector3( x, y, z ) );
710 void Actor::SetPosition( const Vector3& position )
712 mTargetPosition = position;
716 // mNode is being used in a separate thread; queue a message to set the value & base value
717 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::Bake, position );
721 void Actor::SetX( float x )
723 mTargetPosition.x = x;
727 // mNode is being used in a separate thread; queue a message to set the value & base value
728 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeX, x );
732 void Actor::SetY( float y )
734 mTargetPosition.y = y;
738 // mNode is being used in a separate thread; queue a message to set the value & base value
739 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeY, y );
743 void Actor::SetZ( float z )
745 mTargetPosition.z = z;
749 // mNode is being used in a separate thread; queue a message to set the value & base value
750 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeZ, z );
754 void Actor::TranslateBy( const Vector3& distance )
756 mTargetPosition += distance;
760 // mNode is being used in a separate thread; queue a message to set the value & base value
761 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeRelative, distance );
765 const Vector3& Actor::GetCurrentPosition() const
769 // mNode is being used in a separate thread; copy the value from the previous update
770 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
773 return Vector3::ZERO;
776 const Vector3& Actor::GetTargetPosition() const
778 return mTargetPosition;
781 const Vector3& Actor::GetCurrentWorldPosition() const
785 // mNode is being used in a separate thread; copy the value from the previous update
786 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
789 return Vector3::ZERO;
792 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
794 // this flag is not animatable so keep the value
795 mPositionInheritanceMode = mode;
798 // mNode is being used in a separate thread; queue a message to set the value
799 SetPositionInheritanceModeMessage( GetEventThreadServices(), *mNode, mode );
803 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
805 // Cached for event-thread access
806 return mPositionInheritanceMode;
809 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
811 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
812 normalizedAxis.Normalize();
814 Quaternion orientation( angle, normalizedAxis );
816 SetOrientation( orientation );
819 void Actor::SetOrientation( const Quaternion& orientation )
823 // mNode is being used in a separate thread; queue a message to set the value & base value
824 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::Bake, orientation );
828 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
832 // mNode is being used in a separate thread; queue a message to set the value & base value
833 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, Quaternion(angle, axis) );
837 void Actor::RotateBy( const Quaternion& relativeRotation )
841 // mNode is being used in a separate thread; queue a message to set the value & base value
842 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, relativeRotation );
846 const Quaternion& Actor::GetCurrentOrientation() const
850 // mNode is being used in a separate thread; copy the value from the previous update
851 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
854 return Quaternion::IDENTITY;
857 const Quaternion& Actor::GetCurrentWorldOrientation() const
861 // mNode is being used in a separate thread; copy the value from the previous update
862 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
865 return Quaternion::IDENTITY;
868 void Actor::SetScale( float scale )
870 SetScale( Vector3( scale, scale, scale ) );
873 void Actor::SetScale( float x, float y, float z )
875 SetScale( Vector3( x, y, z ) );
878 void Actor::SetScale( const Vector3& scale )
882 // mNode is being used in a separate thread; queue a message to set the value & base value
883 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::Bake, scale );
887 void Actor::SetScaleX( float x )
891 // mNode is being used in a separate thread; queue a message to set the value & base value
892 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeX, x );
896 void Actor::SetScaleY( float y )
900 // mNode is being used in a separate thread; queue a message to set the value & base value
901 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeY, y );
905 void Actor::SetScaleZ( float z )
909 // mNode is being used in a separate thread; queue a message to set the value & base value
910 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeZ, z );
914 void Actor::ScaleBy(const Vector3& relativeScale)
918 // mNode is being used in a separate thread; queue a message to set the value & base value
919 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeRelativeMultiply, relativeScale );
923 const Vector3& Actor::GetCurrentScale() const
927 // mNode is being used in a separate thread; copy the value from the previous update
928 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
934 const Vector3& Actor::GetCurrentWorldScale() const
938 // mNode is being used in a separate thread; copy the value from the previous update
939 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
945 void Actor::SetInheritScale( bool inherit )
947 // non animateable so keep local copy
948 mInheritScale = inherit;
951 // mNode is being used in a separate thread; queue a message to set the value
952 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
956 bool Actor::IsScaleInherited() const
958 return mInheritScale;
961 Matrix Actor::GetCurrentWorldMatrix() const
965 // World matrix is no longer updated unless there is something observing the node.
966 // Need to calculate it from node's world position, orientation and scale:
967 BufferIndex updateBufferIndex = GetEventThreadServices().GetEventBufferIndex();
968 Matrix worldMatrix(false);
969 worldMatrix.SetTransformComponents( mNode->GetWorldScale( updateBufferIndex ),
970 mNode->GetWorldOrientation( updateBufferIndex ),
971 mNode->GetWorldPosition( updateBufferIndex ) );
975 return Matrix::IDENTITY;
978 void Actor::SetVisible( bool visible )
982 // mNode is being used in a separate thread; queue a message to set the value & base value
983 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
987 bool Actor::IsVisible() const
991 // mNode is being used in a separate thread; copy the value from the previous update
992 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
998 void Actor::SetOpacity( float opacity )
1002 // mNode is being used in a separate thread; queue a message to set the value & base value
1003 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
1007 float Actor::GetCurrentOpacity() const
1011 // mNode is being used in a separate thread; copy the value from the previous update
1012 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1018 const Vector4& Actor::GetCurrentWorldColor() const
1022 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1025 return Color::WHITE;
1028 void Actor::SetColor( const Vector4& color )
1032 // mNode is being used in a separate thread; queue a message to set the value & base value
1033 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1037 void Actor::SetColorRed( float red )
1041 // mNode is being used in a separate thread; queue a message to set the value & base value
1042 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1046 void Actor::SetColorGreen( float green )
1050 // mNode is being used in a separate thread; queue a message to set the value & base value
1051 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1055 void Actor::SetColorBlue( float blue )
1059 // mNode is being used in a separate thread; queue a message to set the value & base value
1060 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1064 const Vector4& Actor::GetCurrentColor() const
1068 // mNode is being used in a separate thread; copy the value from the previous update
1069 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1072 return Color::WHITE;
1075 void Actor::SetInheritOrientation( bool inherit )
1077 // non animateable so keep local copy
1078 mInheritOrientation = inherit;
1081 // mNode is being used in a separate thread; queue a message to set the value
1082 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1086 bool Actor::IsOrientationInherited() const
1088 return mInheritOrientation;
1091 void Actor::SetSizeModeFactor( const Vector3& factor )
1093 EnsureRelayoutData();
1095 mRelayoutData->sizeModeFactor = factor;
1098 const Vector3& Actor::GetSizeModeFactor() const
1100 if ( mRelayoutData )
1102 return mRelayoutData->sizeModeFactor;
1105 return GetDefaultSizeModeFactor();
1108 void Actor::SetColorMode( ColorMode colorMode )
1110 // non animateable so keep local copy
1111 mColorMode = colorMode;
1114 // mNode is being used in a separate thread; queue a message to set the value
1115 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1119 ColorMode Actor::GetColorMode() const
1121 // we have cached copy
1125 void Actor::SetSize( float width, float height )
1127 SetSize( Vector2( width, height ) );
1130 void Actor::SetSize( float width, float height, float depth )
1132 SetSize( Vector3( width, height, depth ) );
1135 void Actor::SetSize( const Vector2& size )
1137 SetSize( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1140 void Actor::SetSizeInternal( const Vector2& size )
1142 SetSizeInternal( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1145 float Actor::CalculateSizeZ( const Vector2& size ) const
1147 return std::min( size.width, size.height );
1150 void Actor::SetSize( const Vector3& size )
1152 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1154 SetPreferredSize( size.GetVectorXY() );
1158 SetSizeInternal( size );
1162 void Actor::SetSizeInternal( const Vector3& size )
1164 // dont allow recursive loop
1165 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1166 // 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
1167 if( ( NULL != mNode )&&
1168 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1169 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1170 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1174 // mNode is being used in a separate thread; queue a message to set the value & base value
1175 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::Bake, mTargetSize );
1177 // Notification for derived classes
1178 mInsideOnSizeSet = true;
1179 OnSizeSet( mTargetSize );
1180 mInsideOnSizeSet = false;
1182 // Raise a relayout request if the flag is not locked
1183 if( mRelayoutData && !mRelayoutData->insideRelayout )
1190 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1192 mTargetSize = targetSize;
1194 // Notify deriving classes
1195 OnSizeAnimation( animation, mTargetSize );
1198 void Actor::NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property )
1200 if ( Dali::Actor::Property::SIZE_WIDTH == property )
1202 mTargetSize.width = targetSize;
1204 else if ( Dali::Actor::Property::SIZE_HEIGHT == property )
1206 mTargetSize.height = targetSize;
1208 // Notify deriving classes
1209 OnSizeAnimation( animation, mTargetSize );
1212 void Actor::SetWidth( float width )
1216 // mNode is being used in a separate thread; queue a message to set the value & base value
1217 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeX, width );
1221 void Actor::SetHeight( float height )
1225 // mNode is being used in a separate thread; queue a message to set the value & base value
1226 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeY, height );
1230 void Actor::SetDepth( float depth )
1234 // mNode is being used in a separate thread; queue a message to set the value & base value
1235 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeZ, depth );
1239 const Vector3& Actor::GetTargetSize() const
1244 const Vector3& Actor::GetCurrentSize() const
1248 // mNode is being used in a separate thread; copy the value from the previous update
1249 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1252 return Vector3::ZERO;
1255 Vector3 Actor::GetNaturalSize() const
1257 // It is up to deriving classes to return the appropriate natural size
1258 return Vector3( 0.0f, 0.0f, 0.0f );
1261 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1263 EnsureRelayoutData();
1265 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1267 if( dimension & ( 1 << i ) )
1269 mRelayoutData->resizePolicies[ i ] = policy;
1273 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1275 if( dimension & Dimension::WIDTH )
1277 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1280 if( dimension & Dimension::HEIGHT )
1282 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1286 // If calling SetResizePolicy, assume we want relayout enabled
1287 SetRelayoutEnabled( true );
1289 OnSetResizePolicy( policy, dimension );
1291 // Trigger relayout on this control
1295 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1297 if ( mRelayoutData )
1299 // If more than one dimension is requested, just return the first one found
1300 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1302 if( ( dimension & ( 1 << i ) ) )
1304 return mRelayoutData->resizePolicies[ i ];
1309 return ResizePolicy::DEFAULT;
1312 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1314 EnsureRelayoutData();
1316 mRelayoutData->sizeSetPolicy = policy;
1319 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1321 if ( mRelayoutData )
1323 return mRelayoutData->sizeSetPolicy;
1326 return DEFAULT_SIZE_SCALE_POLICY;
1329 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1331 EnsureRelayoutData();
1333 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1335 if( dimension & ( 1 << i ) )
1337 mRelayoutData->dimensionDependencies[ i ] = dependency;
1342 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1344 if ( mRelayoutData )
1346 // If more than one dimension is requested, just return the first one found
1347 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1349 if( ( dimension & ( 1 << i ) ) )
1351 return mRelayoutData->dimensionDependencies[ i ];
1356 return Dimension::ALL_DIMENSIONS; // Default
1359 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1361 // If relayout data has not been allocated yet and the client is requesting
1362 // to disable it, do nothing
1363 if( mRelayoutData || relayoutEnabled )
1365 EnsureRelayoutData();
1367 mRelayoutData->relayoutEnabled = relayoutEnabled;
1371 bool Actor::IsRelayoutEnabled() const
1373 // Assume that if relayout data has not been allocated yet then
1374 // relayout is disabled
1375 return mRelayoutData && mRelayoutData->relayoutEnabled;
1378 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1380 EnsureRelayoutData();
1382 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1384 if( dimension & ( 1 << i ) )
1386 mRelayoutData->dimensionDirty[ i ] = dirty;
1391 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1393 if ( mRelayoutData )
1395 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1397 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1407 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1409 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1412 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1414 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1417 unsigned int Actor::AddRenderer( Renderer& renderer )
1419 //TODO: MESH_REWORK : Add support for multiple renderers
1420 if ( ! mAttachment )
1422 mAttachment = RendererAttachment::New( GetEventThreadServices(), *mNode, renderer );
1428 unsigned int Actor::GetRendererCount() const
1430 //TODO: MESH_REWORK : Add support for multiple renderers
1431 RendererAttachment* attachment = dynamic_cast<RendererAttachment*>(mAttachment.Get());
1432 return attachment ? 1u : 0u;
1435 Renderer& Actor::GetRendererAt( unsigned int index )
1437 //TODO: MESH_REWORK : Add support for multiple renderers
1438 DALI_ASSERT_DEBUG( index == 0 && "Only one renderer is supported." );
1440 //TODO: MESH_REWORK : Temporary code
1441 RendererAttachment* attachment = dynamic_cast<RendererAttachment*>(mAttachment.Get());
1442 DALI_ASSERT_ALWAYS( attachment && "Actor doesn't have a renderer" );
1444 return attachment->GetRenderer();
1447 void Actor::RemoveRenderer( Renderer& renderer )
1449 //TODO: MESH_REWORK : Add support for multiple renderers
1453 void Actor::RemoveRenderer( unsigned int index )
1455 //TODO: MESH_REWORK : Add support for multiple renderers
1459 void Actor::SetOverlay( bool enable )
1461 // Setting STENCIL will override OVERLAY
1462 if( DrawMode::STENCIL != mDrawMode )
1464 SetDrawMode( enable ? DrawMode::OVERLAY : DrawMode::NORMAL );
1468 bool Actor::IsOverlay() const
1470 return ( DrawMode::OVERLAY == mDrawMode );
1473 void Actor::SetDrawMode( DrawMode::Type drawMode )
1475 // this flag is not animatable so keep the value
1476 mDrawMode = drawMode;
1479 // mNode is being used in a separate thread; queue a message to set the value
1480 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1484 DrawMode::Type Actor::GetDrawMode() const
1489 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1491 // only valid when on-stage
1492 StagePtr stage = Stage::GetCurrent();
1493 if( stage && OnStage() )
1495 const RenderTaskList& taskList = stage->GetRenderTaskList();
1497 Vector2 converted( screenX, screenY );
1499 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1500 const int taskCount = taskList.GetTaskCount();
1501 for( int i = taskCount - 1; i >= 0; --i )
1503 Dali::RenderTask task = taskList.GetTask( i );
1504 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1506 // found a task where this conversion was ok so return
1514 bool Actor::ScreenToLocal( RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1516 bool retval = false;
1517 // only valid when on-stage
1520 CameraActor* camera = renderTask.GetCameraActor();
1524 renderTask.GetViewport( viewport );
1526 // need to translate coordinates to render tasks coordinate space
1527 Vector2 converted( screenX, screenY );
1528 if( renderTask.TranslateCoordinates( converted ) )
1530 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1537 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1539 // Early-out if mNode is NULL
1545 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1547 // Calculate the ModelView matrix
1548 Matrix modelView( false/*don't init*/);
1549 // need to use the components as world matrix is only updated for actors that need it
1550 modelView.SetTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1551 Matrix::Multiply( modelView, modelView, viewMatrix );
1553 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1554 Matrix invertedMvp( false/*don't init*/);
1555 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1556 bool success = invertedMvp.Invert();
1558 // Convert to GL coordinates
1559 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1564 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1571 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1577 if( XyPlaneIntersect( nearPos, farPos, local ) )
1579 Vector3 size = GetCurrentSize();
1580 localX = local.x + size.x * 0.5f;
1581 localY = local.y + size.y * 0.5f;
1592 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1595 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1597 Mathematical Formulation
1599 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1601 ( p - c ) dot ( p - c ) = r^2
1603 Given a ray with a point of origin 'o', and a direction vector 'd':
1605 ray(t) = o + td, t >= 0
1607 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1609 (o + td - c ) dot ( o + td - c ) = r^2
1611 To solve for t we first expand the above into a more recognisable quadratic equation form
1613 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1622 B = 2( o - c ) dot d
1623 C = ( o - c ) dot ( o - c ) - r^2
1625 which can be solved using a standard quadratic formula.
1627 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1629 Practical Simplification
1631 In a renderer, we often differentiate between world space and object space. In the object space
1632 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1633 into object space, the mathematical solution presented above can be simplified significantly.
1635 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1639 and we can find the t at which the (transformed) ray intersects the sphere by
1641 ( o + td ) dot ( o + td ) = r^2
1643 According to the reasoning above, we expand the above quadratic equation into the general form
1647 which now has coefficients:
1654 // Early out if mNode is NULL
1660 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1662 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1663 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1664 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1666 // Compute the radius is not needed, square radius it's enough.
1667 const Vector3& size( mNode->GetSize( bufferIndex ) );
1669 // Scale the sphere.
1670 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1672 const float width = size.width * scale.width;
1673 const float height = size.height * scale.height;
1675 float squareSphereRadius = 0.5f * ( width * width + height * height );
1677 float a = rayDir.Dot( rayDir ); // a
1678 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1679 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1681 return ( b2 * b2 - a * c ) >= 0.f;
1684 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
1691 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1693 // Transforms the ray to the local reference system.
1695 // Calculate the inverse of Model matrix
1696 Matrix invModelMatrix( false/*don't init*/);
1697 // need to use the components as world matrix is only updated for actors that need it
1698 invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1700 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1701 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1703 // Test with the actor's XY plane (Normal = 0 0 1 1).
1705 float a = -rayOriginLocal.z;
1706 float b = rayDirLocal.z;
1708 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1710 // Ray travels distance * rayDirLocal to intersect with plane.
1713 const Vector3& size = mNode->GetSize( bufferIndex );
1715 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1716 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1718 // Test with the actor's geometry.
1719 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1726 void Actor::SetLeaveRequired( bool required )
1728 mLeaveRequired = required;
1731 bool Actor::GetLeaveRequired() const
1733 return mLeaveRequired;
1736 void Actor::SetKeyboardFocusable( bool focusable )
1738 mKeyboardFocusable = focusable;
1741 bool Actor::IsKeyboardFocusable() const
1743 return mKeyboardFocusable;
1746 bool Actor::GetTouchRequired() const
1748 return !mTouchedSignal.Empty() || mDerivedRequiresTouch;
1751 bool Actor::GetHoverRequired() const
1753 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1756 bool Actor::GetWheelEventRequired() const
1758 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1761 bool Actor::IsHittable() const
1763 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1766 ActorGestureData& Actor::GetGestureData()
1768 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1769 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1770 if( NULL == mGestureData )
1772 mGestureData = new ActorGestureData;
1774 return *mGestureData;
1777 bool Actor::IsGestureRequred( Gesture::Type type ) const
1779 return mGestureData && mGestureData->IsGestureRequred( type );
1782 bool Actor::EmitTouchEventSignal( const TouchEvent& event )
1784 bool consumed = false;
1786 if( !mTouchedSignal.Empty() )
1788 Dali::Actor handle( this );
1789 consumed = mTouchedSignal.Emit( handle, event );
1794 // Notification for derived classes
1795 consumed = OnTouchEvent( event );
1801 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1803 bool consumed = false;
1805 if( !mHoveredSignal.Empty() )
1807 Dali::Actor handle( this );
1808 consumed = mHoveredSignal.Emit( handle, event );
1813 // Notification for derived classes
1814 consumed = OnHoverEvent( event );
1820 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1822 bool consumed = false;
1824 if( !mWheelEventSignal.Empty() )
1826 Dali::Actor handle( this );
1827 consumed = mWheelEventSignal.Emit( handle, event );
1832 // Notification for derived classes
1833 consumed = OnWheelEvent( event );
1839 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
1841 return mTouchedSignal;
1844 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
1846 return mHoveredSignal;
1849 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
1851 return mWheelEventSignal;
1854 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
1856 return mOnStageSignal;
1859 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
1861 return mOffStageSignal;
1864 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
1866 return mOnRelayoutSignal;
1869 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1871 bool connected( true );
1872 Actor* actor = dynamic_cast< Actor* >( object );
1874 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1876 actor->TouchedSignal().Connect( tracker, functor );
1878 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1880 actor->HoveredSignal().Connect( tracker, functor );
1882 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1884 actor->WheelEventSignal().Connect( tracker, functor );
1886 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
1888 actor->OnStageSignal().Connect( tracker, functor );
1890 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
1892 actor->OffStageSignal().Connect( tracker, functor );
1896 // signalName does not match any signal
1903 Actor::Actor( DerivedType derivedType )
1907 mParentOrigin( NULL ),
1908 mAnchorPoint( NULL ),
1909 mRelayoutData( NULL ),
1910 mGestureData( NULL ),
1912 mTargetSize( 0.0f, 0.0f, 0.0f ),
1914 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
1916 mIsRoot( ROOT_LAYER == derivedType ),
1917 mIsRenderable( RENDERABLE == derivedType ),
1918 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
1919 mIsOnStage( false ),
1921 mLeaveRequired( false ),
1922 mKeyboardFocusable( false ),
1923 mDerivedRequiresTouch( false ),
1924 mDerivedRequiresHover( false ),
1925 mDerivedRequiresWheelEvent( false ),
1926 mOnStageSignalled( false ),
1927 mInsideOnSizeSet( false ),
1928 mInheritOrientation( true ),
1929 mInheritScale( true ),
1930 mDrawMode( DrawMode::NORMAL ),
1931 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
1932 mColorMode( Node::DEFAULT_COLOR_MODE )
1936 void Actor::Initialize()
1939 SceneGraph::Node* node = CreateNode();
1941 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
1942 mNode = node; // Keep raw-pointer to Node
1946 GetEventThreadServices().RegisterObject( this );
1951 // Remove mParent pointers from children even if we're destroying core,
1952 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1955 ActorConstIter endIter = mChildren->end();
1956 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1958 (*iter)->SetParent( NULL );
1963 // Guard to allow handle destruction after Core has been destroyed
1964 if( EventThreadServices::IsCoreRunning() )
1968 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
1969 mNode = NULL; // Node is about to be destroyed
1972 GetEventThreadServices().UnregisterObject( this );
1975 // Cleanup optional gesture data
1976 delete mGestureData;
1978 // Cleanup optional parent origin and anchor
1979 delete mParentOrigin;
1980 delete mAnchorPoint;
1982 // Delete optional relayout data
1985 delete mRelayoutData;
1989 void Actor::ConnectToStage( unsigned int parentDepth, int index )
1991 // This container is used instead of walking the Actor hierachy.
1992 // It protects us when the Actor hierachy is modified during OnStageConnectionExternal callbacks.
1993 ActorContainer connectionList;
1996 // This stage is atomic i.e. not interrupted by user callbacks
1997 RecursiveConnectToStage( connectionList, parentDepth+1, index );
1999 // Notify applications about the newly connected actors.
2000 const ActorIter endIter = connectionList.end();
2001 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2003 (*iter)->NotifyStageConnection();
2009 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth, int index )
2011 DALI_ASSERT_ALWAYS( !OnStage() );
2016 ConnectToSceneGraph( index );
2018 // Notification for internal derived classes
2019 OnStageConnectionInternal();
2021 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2022 connectionList.push_back( ActorPtr( this ) );
2024 // Recursively connect children
2027 ActorConstIter endIter = mChildren->end();
2028 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2030 (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
2036 * This method is called when the Actor is connected to the Stage.
2037 * The parent must have added its Node to the scene-graph.
2038 * The child must connect its Node to the parent's Node.
2039 * This is resursive; the child calls ConnectToStage() for its children.
2041 void Actor::ConnectToSceneGraph( int index )
2043 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2047 // Reparent Node in next Update
2048 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode, index );
2051 // Notify attachment
2054 mAttachment->Connect();
2057 // Request relayout on all actors that are added to the scenegraph
2060 // Notification for Object::Observers
2064 void Actor::NotifyStageConnection()
2066 // Actors can be removed (in a callback), before the on-stage stage is reported.
2067 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2068 if( OnStage() && !mOnStageSignalled )
2070 // Notification for external (CustomActor) derived classes
2071 OnStageConnectionExternal( mDepth );
2073 if( !mOnStageSignal.Empty() )
2075 Dali::Actor handle( this );
2076 mOnStageSignal.Emit( handle );
2079 // Guard against Remove during callbacks
2082 mOnStageSignalled = true; // signal required next time Actor is removed
2087 void Actor::DisconnectFromStage()
2089 // This container is used instead of walking the Actor hierachy.
2090 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2091 ActorContainer disconnectionList;
2093 // This stage is atomic i.e. not interrupted by user callbacks
2094 RecursiveDisconnectFromStage( disconnectionList );
2096 // Notify applications about the newly disconnected actors.
2097 const ActorIter endIter = disconnectionList.end();
2098 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2100 (*iter)->NotifyStageDisconnection();
2104 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2106 DALI_ASSERT_ALWAYS( OnStage() );
2108 // Recursively disconnect children
2111 ActorConstIter endIter = mChildren->end();
2112 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2114 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2118 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2119 disconnectionList.push_back( ActorPtr( this ) );
2121 // Notification for internal derived classes
2122 OnStageDisconnectionInternal();
2124 DisconnectFromSceneGraph();
2130 * This method is called by an actor or its parent, before a node removal message is sent.
2131 * This is recursive; the child calls DisconnectFromStage() for its children.
2133 void Actor::DisconnectFromSceneGraph()
2135 // Notification for Object::Observers
2136 OnSceneObjectRemove();
2138 // Notify attachment
2141 mAttachment->Disconnect();
2145 void Actor::NotifyStageDisconnection()
2147 // Actors can be added (in a callback), before the off-stage state is reported.
2148 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2149 // only do this step if there is a stage, i.e. Core is not being shut down
2150 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2152 // Notification for external (CustomeActor) derived classes
2153 OnStageDisconnectionExternal();
2155 if( !mOffStageSignal.Empty() )
2157 Dali::Actor handle( this );
2158 mOffStageSignal.Emit( handle );
2161 // Guard against Add during callbacks
2164 mOnStageSignalled = false; // signal required next time Actor is added
2169 bool Actor::IsNodeConnected() const
2171 bool connected( false );
2176 if( mNode->IsRoot() || mNode->GetParent() )
2185 unsigned int Actor::GetDefaultPropertyCount() const
2187 return DEFAULT_PROPERTY_COUNT;
2190 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2192 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2194 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2196 indices.PushBack( i );
2200 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2202 if( index < DEFAULT_PROPERTY_COUNT )
2204 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2210 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2212 Property::Index index = Property::INVALID_INDEX;
2214 // Look for name in default properties
2215 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2217 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2218 if( 0 == name.compare( property->name ) )
2228 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2230 if( index < DEFAULT_PROPERTY_COUNT )
2232 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2238 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2240 if( index < DEFAULT_PROPERTY_COUNT )
2242 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2248 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2250 if( index < DEFAULT_PROPERTY_COUNT )
2252 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2258 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2260 if( index < DEFAULT_PROPERTY_COUNT )
2262 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2265 // index out of range...return Property::NONE
2266 return Property::NONE;
2269 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2273 case Dali::Actor::Property::PARENT_ORIGIN:
2275 SetParentOrigin( property.Get< Vector3 >() );
2279 case Dali::Actor::Property::PARENT_ORIGIN_X:
2281 SetParentOriginX( property.Get< float >() );
2285 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2287 SetParentOriginY( property.Get< float >() );
2291 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2293 SetParentOriginZ( property.Get< float >() );
2297 case Dali::Actor::Property::ANCHOR_POINT:
2299 SetAnchorPoint( property.Get< Vector3 >() );
2303 case Dali::Actor::Property::ANCHOR_POINT_X:
2305 SetAnchorPointX( property.Get< float >() );
2309 case Dali::Actor::Property::ANCHOR_POINT_Y:
2311 SetAnchorPointY( property.Get< float >() );
2315 case Dali::Actor::Property::ANCHOR_POINT_Z:
2317 SetAnchorPointZ( property.Get< float >() );
2321 case Dali::Actor::Property::SIZE:
2323 SetSize( property.Get< Vector3 >() );
2327 case Dali::Actor::Property::SIZE_WIDTH:
2329 SetWidth( property.Get< float >() );
2333 case Dali::Actor::Property::SIZE_HEIGHT:
2335 SetHeight( property.Get< float >() );
2339 case Dali::Actor::Property::SIZE_DEPTH:
2341 SetDepth( property.Get< float >() );
2345 case Dali::Actor::Property::POSITION:
2347 SetPosition( property.Get< Vector3 >() );
2351 case Dali::Actor::Property::POSITION_X:
2353 SetX( property.Get< float >() );
2357 case Dali::Actor::Property::POSITION_Y:
2359 SetY( property.Get< float >() );
2363 case Dali::Actor::Property::POSITION_Z:
2365 SetZ( property.Get< float >() );
2369 case Dali::Actor::Property::ORIENTATION:
2371 SetOrientation( property.Get< Quaternion >() );
2375 case Dali::Actor::Property::SCALE:
2377 SetScale( property.Get< Vector3 >() );
2381 case Dali::Actor::Property::SCALE_X:
2383 SetScaleX( property.Get< float >() );
2387 case Dali::Actor::Property::SCALE_Y:
2389 SetScaleY( property.Get< float >() );
2393 case Dali::Actor::Property::SCALE_Z:
2395 SetScaleZ( property.Get< float >() );
2399 case Dali::Actor::Property::VISIBLE:
2401 SetVisible( property.Get< bool >() );
2405 case Dali::Actor::Property::COLOR:
2407 SetColor( property.Get< Vector4 >() );
2411 case Dali::Actor::Property::COLOR_RED:
2413 SetColorRed( property.Get< float >() );
2417 case Dali::Actor::Property::COLOR_GREEN:
2419 SetColorGreen( property.Get< float >() );
2423 case Dali::Actor::Property::COLOR_BLUE:
2425 SetColorBlue( property.Get< float >() );
2429 case Dali::Actor::Property::COLOR_ALPHA:
2431 SetOpacity( property.Get< float >() );
2435 case Dali::Actor::Property::NAME:
2437 SetName( property.Get< std::string >() );
2441 case Dali::Actor::Property::SENSITIVE:
2443 SetSensitive( property.Get< bool >() );
2447 case Dali::Actor::Property::LEAVE_REQUIRED:
2449 SetLeaveRequired( property.Get< bool >() );
2453 case Dali::Actor::Property::INHERIT_ORIENTATION:
2455 SetInheritOrientation( property.Get< bool >() );
2459 case Dali::Actor::Property::INHERIT_SCALE:
2461 SetInheritScale( property.Get< bool >() );
2465 case Dali::Actor::Property::COLOR_MODE:
2467 SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2471 case Dali::Actor::Property::POSITION_INHERITANCE:
2473 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2477 case Dali::Actor::Property::DRAW_MODE:
2479 SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2483 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2485 SetSizeModeFactor( property.Get< Vector3 >() );
2489 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2491 ResizePolicy::Type type;
2492 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2494 SetResizePolicy( type, Dimension::WIDTH );
2499 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2501 ResizePolicy::Type type;
2502 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2504 SetResizePolicy( type, Dimension::HEIGHT );
2509 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2511 SizeScalePolicy::Type type;
2512 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount, type ) )
2514 SetSizeScalePolicy( type );
2519 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2521 if( property.Get< bool >() )
2523 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2528 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2530 if( property.Get< bool >() )
2532 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2537 case Dali::Actor::Property::PADDING:
2539 Vector4 padding = property.Get< Vector4 >();
2540 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2541 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2545 case Dali::Actor::Property::MINIMUM_SIZE:
2547 Vector2 size = property.Get< Vector2 >();
2548 SetMinimumSize( size.x, Dimension::WIDTH );
2549 SetMinimumSize( size.y, Dimension::HEIGHT );
2553 case Dali::Actor::Property::MAXIMUM_SIZE:
2555 Vector2 size = property.Get< Vector2 >();
2556 SetMaximumSize( size.x, Dimension::WIDTH );
2557 SetMaximumSize( size.y, Dimension::HEIGHT );
2563 // this can happen in the case of a non-animatable default property so just do nothing
2569 // TODO: This method needs to be removed
2570 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2572 switch( entry.type )
2574 case Property::BOOLEAN:
2576 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2577 DALI_ASSERT_DEBUG( NULL != property );
2579 // property is being used in a separate thread; queue a message to set the property
2580 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2585 case Property::INTEGER:
2587 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2588 DALI_ASSERT_DEBUG( NULL != property );
2590 // property is being used in a separate thread; queue a message to set the property
2591 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2596 case Property::FLOAT:
2598 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2599 DALI_ASSERT_DEBUG( NULL != property );
2601 // property is being used in a separate thread; queue a message to set the property
2602 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2607 case Property::VECTOR2:
2609 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2610 DALI_ASSERT_DEBUG( NULL != property );
2612 // property is being used in a separate thread; queue a message to set the property
2613 if(entry.componentIndex == 0)
2615 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2617 else if(entry.componentIndex == 1)
2619 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2623 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2629 case Property::VECTOR3:
2631 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2632 DALI_ASSERT_DEBUG( NULL != property );
2634 // property is being used in a separate thread; queue a message to set the property
2635 if(entry.componentIndex == 0)
2637 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2639 else if(entry.componentIndex == 1)
2641 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2643 else if(entry.componentIndex == 2)
2645 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2649 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2655 case Property::VECTOR4:
2657 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2658 DALI_ASSERT_DEBUG( NULL != property );
2660 // property is being used in a separate thread; queue a message to set the property
2661 if(entry.componentIndex == 0)
2663 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
2665 else if(entry.componentIndex == 1)
2667 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
2669 else if(entry.componentIndex == 2)
2671 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
2673 else if(entry.componentIndex == 3)
2675 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
2679 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2685 case Property::ROTATION:
2687 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
2688 DALI_ASSERT_DEBUG( NULL != property );
2690 // property is being used in a separate thread; queue a message to set the property
2691 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
2696 case Property::MATRIX:
2698 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
2699 DALI_ASSERT_DEBUG( NULL != property );
2701 // property is being used in a separate thread; queue a message to set the property
2702 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
2707 case Property::MATRIX3:
2709 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
2710 DALI_ASSERT_DEBUG( NULL != property );
2712 // property is being used in a separate thread; queue a message to set the property
2713 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
2720 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
2726 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
2728 Property::Value value;
2732 case Dali::Actor::Property::PARENT_ORIGIN:
2734 value = GetCurrentParentOrigin();
2738 case Dali::Actor::Property::PARENT_ORIGIN_X:
2740 value = GetCurrentParentOrigin().x;
2744 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2746 value = GetCurrentParentOrigin().y;
2750 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2752 value = GetCurrentParentOrigin().z;
2756 case Dali::Actor::Property::ANCHOR_POINT:
2758 value = GetCurrentAnchorPoint();
2762 case Dali::Actor::Property::ANCHOR_POINT_X:
2764 value = GetCurrentAnchorPoint().x;
2768 case Dali::Actor::Property::ANCHOR_POINT_Y:
2770 value = GetCurrentAnchorPoint().y;
2774 case Dali::Actor::Property::ANCHOR_POINT_Z:
2776 value = GetCurrentAnchorPoint().z;
2780 case Dali::Actor::Property::SIZE:
2782 value = GetCurrentSize();
2786 case Dali::Actor::Property::SIZE_WIDTH:
2788 value = GetCurrentSize().width;
2792 case Dali::Actor::Property::SIZE_HEIGHT:
2794 value = GetCurrentSize().height;
2798 case Dali::Actor::Property::SIZE_DEPTH:
2800 value = GetCurrentSize().depth;
2804 case Dali::Actor::Property::POSITION:
2806 value = GetCurrentPosition();
2810 case Dali::Actor::Property::POSITION_X:
2812 value = GetCurrentPosition().x;
2816 case Dali::Actor::Property::POSITION_Y:
2818 value = GetCurrentPosition().y;
2822 case Dali::Actor::Property::POSITION_Z:
2824 value = GetCurrentPosition().z;
2828 case Dali::Actor::Property::WORLD_POSITION:
2830 value = GetCurrentWorldPosition();
2834 case Dali::Actor::Property::WORLD_POSITION_X:
2836 value = GetCurrentWorldPosition().x;
2840 case Dali::Actor::Property::WORLD_POSITION_Y:
2842 value = GetCurrentWorldPosition().y;
2846 case Dali::Actor::Property::WORLD_POSITION_Z:
2848 value = GetCurrentWorldPosition().z;
2852 case Dali::Actor::Property::ORIENTATION:
2854 value = GetCurrentOrientation();
2858 case Dali::Actor::Property::WORLD_ORIENTATION:
2860 value = GetCurrentWorldOrientation();
2864 case Dali::Actor::Property::SCALE:
2866 value = GetCurrentScale();
2870 case Dali::Actor::Property::SCALE_X:
2872 value = GetCurrentScale().x;
2876 case Dali::Actor::Property::SCALE_Y:
2878 value = GetCurrentScale().y;
2882 case Dali::Actor::Property::SCALE_Z:
2884 value = GetCurrentScale().z;
2888 case Dali::Actor::Property::WORLD_SCALE:
2890 value = GetCurrentWorldScale();
2894 case Dali::Actor::Property::VISIBLE:
2896 value = IsVisible();
2900 case Dali::Actor::Property::COLOR:
2902 value = GetCurrentColor();
2906 case Dali::Actor::Property::COLOR_RED:
2908 value = GetCurrentColor().r;
2912 case Dali::Actor::Property::COLOR_GREEN:
2914 value = GetCurrentColor().g;
2918 case Dali::Actor::Property::COLOR_BLUE:
2920 value = GetCurrentColor().b;
2924 case Dali::Actor::Property::COLOR_ALPHA:
2926 value = GetCurrentColor().a;
2930 case Dali::Actor::Property::WORLD_COLOR:
2932 value = GetCurrentWorldColor();
2936 case Dali::Actor::Property::WORLD_MATRIX:
2938 value = GetCurrentWorldMatrix();
2942 case Dali::Actor::Property::NAME:
2948 case Dali::Actor::Property::SENSITIVE:
2950 value = IsSensitive();
2954 case Dali::Actor::Property::LEAVE_REQUIRED:
2956 value = GetLeaveRequired();
2960 case Dali::Actor::Property::INHERIT_ORIENTATION:
2962 value = IsOrientationInherited();
2966 case Dali::Actor::Property::INHERIT_SCALE:
2968 value = IsScaleInherited();
2972 case Dali::Actor::Property::COLOR_MODE:
2974 value = Scripting::GetColorMode( GetColorMode() );
2978 case Dali::Actor::Property::POSITION_INHERITANCE:
2980 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
2984 case Dali::Actor::Property::DRAW_MODE:
2986 value = Scripting::GetDrawMode( GetDrawMode() );
2990 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2992 value = GetSizeModeFactor();
2996 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2998 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3002 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3004 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3008 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3010 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3014 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3016 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3020 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3022 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3026 case Dali::Actor::Property::PADDING:
3028 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3029 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3030 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3034 case Dali::Actor::Property::MINIMUM_SIZE:
3036 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3040 case Dali::Actor::Property::MAXIMUM_SIZE:
3042 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3048 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3056 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3061 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3063 // This method should only return an object connected to the scene-graph
3064 return OnStage() ? mNode : NULL;
3067 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3069 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3071 const PropertyBase* property( NULL );
3073 // This method should only return a property of an object connected to the scene-graph
3079 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3081 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3082 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3084 property = animatable->GetSceneGraphProperty();
3086 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3088 CustomPropertyMetadata* custom = FindCustomProperty( index );
3089 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3091 property = custom->GetSceneGraphProperty();
3093 else if( NULL != mNode )
3097 case Dali::Actor::Property::SIZE:
3098 property = &mNode->mSize;
3101 case Dali::Actor::Property::SIZE_WIDTH:
3102 property = &mNode->mSize;
3105 case Dali::Actor::Property::SIZE_HEIGHT:
3106 property = &mNode->mSize;
3109 case Dali::Actor::Property::SIZE_DEPTH:
3110 property = &mNode->mSize;
3113 case Dali::Actor::Property::POSITION:
3114 property = &mNode->mPosition;
3117 case Dali::Actor::Property::POSITION_X:
3118 property = &mNode->mPosition;
3121 case Dali::Actor::Property::POSITION_Y:
3122 property = &mNode->mPosition;
3125 case Dali::Actor::Property::POSITION_Z:
3126 property = &mNode->mPosition;
3129 case Dali::Actor::Property::ORIENTATION:
3130 property = &mNode->mOrientation;
3133 case Dali::Actor::Property::SCALE:
3134 property = &mNode->mScale;
3137 case Dali::Actor::Property::SCALE_X:
3138 property = &mNode->mScale;
3141 case Dali::Actor::Property::SCALE_Y:
3142 property = &mNode->mScale;
3145 case Dali::Actor::Property::SCALE_Z:
3146 property = &mNode->mScale;
3149 case Dali::Actor::Property::VISIBLE:
3150 property = &mNode->mVisible;
3153 case Dali::Actor::Property::COLOR:
3154 property = &mNode->mColor;
3157 case Dali::Actor::Property::COLOR_RED:
3158 property = &mNode->mColor;
3161 case Dali::Actor::Property::COLOR_GREEN:
3162 property = &mNode->mColor;
3165 case Dali::Actor::Property::COLOR_BLUE:
3166 property = &mNode->mColor;
3169 case Dali::Actor::Property::COLOR_ALPHA:
3170 property = &mNode->mColor;
3181 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3183 const PropertyInputImpl* property( NULL );
3185 // This method should only return a property of an object connected to the scene-graph
3191 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3193 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3194 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3196 property = animatable->GetSceneGraphProperty();
3198 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3200 CustomPropertyMetadata* custom = FindCustomProperty( index );
3201 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3202 property = custom->GetSceneGraphProperty();
3204 else if( NULL != mNode )
3208 case Dali::Actor::Property::PARENT_ORIGIN:
3209 property = &mNode->mParentOrigin;
3212 case Dali::Actor::Property::PARENT_ORIGIN_X:
3213 property = &mNode->mParentOrigin;
3216 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3217 property = &mNode->mParentOrigin;
3220 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3221 property = &mNode->mParentOrigin;
3224 case Dali::Actor::Property::ANCHOR_POINT:
3225 property = &mNode->mAnchorPoint;
3228 case Dali::Actor::Property::ANCHOR_POINT_X:
3229 property = &mNode->mAnchorPoint;
3232 case Dali::Actor::Property::ANCHOR_POINT_Y:
3233 property = &mNode->mAnchorPoint;
3236 case Dali::Actor::Property::ANCHOR_POINT_Z:
3237 property = &mNode->mAnchorPoint;
3240 case Dali::Actor::Property::SIZE:
3241 property = &mNode->mSize;
3244 case Dali::Actor::Property::SIZE_WIDTH:
3245 property = &mNode->mSize;
3248 case Dali::Actor::Property::SIZE_HEIGHT:
3249 property = &mNode->mSize;
3252 case Dali::Actor::Property::SIZE_DEPTH:
3253 property = &mNode->mSize;
3256 case Dali::Actor::Property::POSITION:
3257 property = &mNode->mPosition;
3260 case Dali::Actor::Property::POSITION_X:
3261 property = &mNode->mPosition;
3264 case Dali::Actor::Property::POSITION_Y:
3265 property = &mNode->mPosition;
3268 case Dali::Actor::Property::POSITION_Z:
3269 property = &mNode->mPosition;
3272 case Dali::Actor::Property::WORLD_POSITION:
3273 property = &mNode->mWorldPosition;
3276 case Dali::Actor::Property::WORLD_POSITION_X:
3277 property = &mNode->mWorldPosition;
3280 case Dali::Actor::Property::WORLD_POSITION_Y:
3281 property = &mNode->mWorldPosition;
3284 case Dali::Actor::Property::WORLD_POSITION_Z:
3285 property = &mNode->mWorldPosition;
3288 case Dali::Actor::Property::ORIENTATION:
3289 property = &mNode->mOrientation;
3292 case Dali::Actor::Property::WORLD_ORIENTATION:
3293 property = &mNode->mWorldOrientation;
3296 case Dali::Actor::Property::SCALE:
3297 property = &mNode->mScale;
3300 case Dali::Actor::Property::SCALE_X:
3301 property = &mNode->mScale;
3304 case Dali::Actor::Property::SCALE_Y:
3305 property = &mNode->mScale;
3308 case Dali::Actor::Property::SCALE_Z:
3309 property = &mNode->mScale;
3312 case Dali::Actor::Property::WORLD_SCALE:
3313 property = &mNode->mWorldScale;
3316 case Dali::Actor::Property::VISIBLE:
3317 property = &mNode->mVisible;
3320 case Dali::Actor::Property::COLOR:
3321 property = &mNode->mColor;
3324 case Dali::Actor::Property::COLOR_RED:
3325 property = &mNode->mColor;
3328 case Dali::Actor::Property::COLOR_GREEN:
3329 property = &mNode->mColor;
3332 case Dali::Actor::Property::COLOR_BLUE:
3333 property = &mNode->mColor;
3336 case Dali::Actor::Property::COLOR_ALPHA:
3337 property = &mNode->mColor;
3340 case Dali::Actor::Property::WORLD_COLOR:
3341 property = &mNode->mWorldColor;
3344 case Dali::Actor::Property::WORLD_MATRIX:
3345 property = &mNode->mWorldMatrix;
3356 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3358 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3360 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3362 // check whether the animatable property is registered already, if not then register one.
3363 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3364 if( animatableProperty )
3366 componentIndex = animatableProperty->componentIndex;
3373 case Dali::Actor::Property::PARENT_ORIGIN_X:
3374 case Dali::Actor::Property::ANCHOR_POINT_X:
3375 case Dali::Actor::Property::SIZE_WIDTH:
3376 case Dali::Actor::Property::POSITION_X:
3377 case Dali::Actor::Property::WORLD_POSITION_X:
3378 case Dali::Actor::Property::SCALE_X:
3379 case Dali::Actor::Property::COLOR_RED:
3385 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3386 case Dali::Actor::Property::ANCHOR_POINT_Y:
3387 case Dali::Actor::Property::SIZE_HEIGHT:
3388 case Dali::Actor::Property::POSITION_Y:
3389 case Dali::Actor::Property::WORLD_POSITION_Y:
3390 case Dali::Actor::Property::SCALE_Y:
3391 case Dali::Actor::Property::COLOR_GREEN:
3397 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3398 case Dali::Actor::Property::ANCHOR_POINT_Z:
3399 case Dali::Actor::Property::SIZE_DEPTH:
3400 case Dali::Actor::Property::POSITION_Z:
3401 case Dali::Actor::Property::WORLD_POSITION_Z:
3402 case Dali::Actor::Property::SCALE_Z:
3403 case Dali::Actor::Property::COLOR_BLUE:
3409 case Dali::Actor::Property::COLOR_ALPHA:
3423 return componentIndex;
3426 void Actor::SetParent( Actor* parent, int index )
3430 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3434 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3437 // Instruct each actor to create a corresponding node in the scene graph
3438 ConnectToStage( parent->GetHierarchyDepth(), index );
3441 else // parent being set to NULL
3443 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3447 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3450 DALI_ASSERT_ALWAYS( mNode != NULL );
3454 // Disconnect the Node & its children from the scene-graph.
3455 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3458 // Instruct each actor to discard pointers to the scene-graph
3459 DisconnectFromStage();
3464 SceneGraph::Node* Actor::CreateNode() const
3469 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3472 Actor* actor = dynamic_cast< Actor* >( object );
3476 if( 0 == actionName.compare( ACTION_SHOW ) )
3478 actor->SetVisible( true );
3481 else if( 0 == actionName.compare( ACTION_HIDE ) )
3483 actor->SetVisible( false );
3491 void Actor::EnsureRelayoutData()
3493 // Assign relayout data.
3494 if( !mRelayoutData )
3496 mRelayoutData = new RelayoutData();
3500 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3502 // Check if actor is dependent on parent
3503 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3505 if( ( dimension & ( 1 << i ) ) )
3507 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3508 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3518 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3520 // Check if actor is dependent on children
3521 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3523 if( ( dimension & ( 1 << i ) ) )
3525 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3526 switch( resizePolicy )
3528 case ResizePolicy::FIT_TO_CHILDREN:
3529 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3545 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3547 return Actor::RelayoutDependentOnChildren( dimension );
3550 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3552 // Check each possible dimension and see if it is dependent on the input one
3553 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3555 if( dimension & ( 1 << i ) )
3557 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3564 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3566 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3568 if( dimension & ( 1 << i ) )
3570 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3575 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3577 // If more than one dimension is requested, just return the first one found
3578 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3580 if( ( dimension & ( 1 << i ) ) )
3582 return mRelayoutData->negotiatedDimensions[ i ];
3586 return 0.0f; // Default
3589 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3591 EnsureRelayoutData();
3593 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3595 if( dimension & ( 1 << i ) )
3597 mRelayoutData->dimensionPadding[ i ] = padding;
3602 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3604 if ( mRelayoutData )
3606 // If more than one dimension is requested, just return the first one found
3607 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3609 if( ( dimension & ( 1 << i ) ) )
3611 return mRelayoutData->dimensionPadding[ i ];
3616 return GetDefaultDimensionPadding();
3619 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
3621 EnsureRelayoutData();
3623 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3625 if( dimension & ( 1 << i ) )
3627 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3632 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
3634 if ( mRelayoutData )
3636 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3638 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
3648 float Actor::GetHeightForWidthBase( float width )
3650 float height = 0.0f;
3652 const Vector3 naturalSize = GetNaturalSize();
3653 if( naturalSize.width > 0.0f )
3655 height = naturalSize.height * width / naturalSize.width;
3657 else // we treat 0 as 1:1 aspect ratio
3665 float Actor::GetWidthForHeightBase( float height )
3669 const Vector3 naturalSize = GetNaturalSize();
3670 if( naturalSize.height > 0.0f )
3672 width = naturalSize.width * height / naturalSize.height;
3674 else // we treat 0 as 1:1 aspect ratio
3682 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
3684 // Fill to parent, taking size mode factor into account
3685 switch( child.GetResizePolicy( dimension ) )
3687 case ResizePolicy::FILL_TO_PARENT:
3689 return GetLatestSize( dimension );
3692 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3694 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
3697 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3699 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
3704 return GetLatestSize( dimension );
3709 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
3711 // Can be overridden in derived class
3712 return CalculateChildSizeBase( child, dimension );
3715 float Actor::GetHeightForWidth( float width )
3717 // Can be overridden in derived class
3718 return GetHeightForWidthBase( width );
3721 float Actor::GetWidthForHeight( float height )
3723 // Can be overridden in derived class
3724 return GetWidthForHeightBase( height );
3727 float Actor::GetLatestSize( Dimension::Type dimension ) const
3729 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
3732 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
3734 Vector2 padding = GetPadding( dimension );
3736 return GetLatestSize( dimension ) + padding.x + padding.y;
3739 float Actor::NegotiateFromParent( Dimension::Type dimension )
3741 Actor* parent = GetParent();
3744 Vector2 padding( GetPadding( dimension ) );
3745 Vector2 parentPadding( parent->GetPadding( dimension ) );
3746 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
3752 float Actor::NegotiateFromChildren( Dimension::Type dimension )
3754 float maxDimensionPoint = 0.0f;
3756 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3758 ActorPtr child = GetChildAt( i );
3760 if( !child->RelayoutDependentOnParent( dimension ) )
3762 // Calculate the min and max points that the children range across
3763 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
3764 float dimensionSize = child->GetRelayoutSize( dimension );
3765 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
3769 return maxDimensionPoint;
3772 float Actor::GetSize( Dimension::Type dimension ) const
3774 return GetDimensionValue( GetTargetSize(), dimension );
3777 float Actor::GetNaturalSize( Dimension::Type dimension ) const
3779 return GetDimensionValue( GetNaturalSize(), dimension );
3782 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
3784 switch( GetResizePolicy( dimension ) )
3786 case ResizePolicy::USE_NATURAL_SIZE:
3788 return GetNaturalSize( dimension );
3791 case ResizePolicy::FIXED:
3793 return GetDimensionValue( GetPreferredSize(), dimension );
3796 case ResizePolicy::USE_ASSIGNED_SIZE:
3798 return GetDimensionValue( maximumSize, dimension );
3801 case ResizePolicy::FILL_TO_PARENT:
3802 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3803 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3805 return NegotiateFromParent( dimension );
3808 case ResizePolicy::FIT_TO_CHILDREN:
3810 return NegotiateFromChildren( dimension );
3813 case ResizePolicy::DIMENSION_DEPENDENCY:
3815 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
3818 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
3820 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
3823 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
3825 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
3837 return 0.0f; // Default
3840 float Actor::ClampDimension( float size, Dimension::Type dimension )
3842 const float minSize = GetMinimumSize( dimension );
3843 const float maxSize = GetMaximumSize( dimension );
3845 return std::max( minSize, std::min( size, maxSize ) );
3848 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
3850 // Check if it needs to be negotiated
3851 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
3853 // Check that we havn't gotten into an infinite loop
3854 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
3855 bool recursionFound = false;
3856 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
3858 if( *it == searchActor )
3860 recursionFound = true;
3865 if( !recursionFound )
3867 // Record the path that we have taken
3868 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
3870 // Dimension dependency check
3871 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3873 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
3875 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
3877 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
3881 // Parent dependency check
3882 Actor* parent = GetParent();
3883 if( parent && RelayoutDependentOnParent( dimension ) )
3885 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
3888 // Children dependency check
3889 if( RelayoutDependentOnChildren( dimension ) )
3891 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3893 ActorPtr child = GetChildAt( i );
3895 // Only relayout child first if it is not dependent on this actor
3896 if( !child->RelayoutDependentOnParent( dimension ) )
3898 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
3903 // For deriving classes
3904 OnCalculateRelayoutSize( dimension );
3906 // All dependencies checked, calculate the size and set negotiated flag
3907 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
3909 SetNegotiatedDimension( newSize, dimension );
3910 SetLayoutNegotiated( true, dimension );
3912 // For deriving classes
3913 OnLayoutNegotiated( newSize, dimension );
3915 // This actor has been successfully processed, pop it off the recursion stack
3916 recursionStack.pop_back();
3920 // TODO: Break infinite loop
3921 SetLayoutNegotiated( true, dimension );
3926 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
3928 // Negotiate all dimensions that require it
3929 ActorDimensionStack recursionStack;
3931 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3933 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
3936 NegotiateDimension( dimension, allocatedSize, recursionStack );
3940 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
3942 switch( mRelayoutData->sizeSetPolicy )
3944 case SizeScalePolicy::USE_SIZE_SET:
3949 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
3951 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
3952 const Vector3 naturalSize = GetNaturalSize();
3953 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
3955 const float sizeRatio = size.width / size.height;
3956 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
3958 if( naturalSizeRatio < sizeRatio )
3960 return Vector2( naturalSizeRatio * size.height, size.height );
3962 else if( naturalSizeRatio > sizeRatio )
3964 return Vector2( size.width, size.width / naturalSizeRatio );
3975 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
3977 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
3978 const Vector3 naturalSize = GetNaturalSize();
3979 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
3981 const float sizeRatio = size.width / size.height;
3982 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
3984 if( naturalSizeRatio < sizeRatio )
3986 return Vector2( size.width, size.width / naturalSizeRatio );
3988 else if( naturalSizeRatio > sizeRatio )
3990 return Vector2( naturalSizeRatio * size.height, size.height );
4008 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4010 // Do the set actor size
4011 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4013 // Adjust for size set policy
4014 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4016 // Lock the flag to stop recursive relayouts on set size
4017 mRelayoutData->insideRelayout = true;
4018 SetSize( negotiatedSize );
4019 mRelayoutData->insideRelayout = false;
4021 // Clear flags for all dimensions
4022 SetLayoutDirty( false );
4024 // Give deriving classes a chance to respond
4025 OnRelayout( negotiatedSize, container );
4027 if( !mOnRelayoutSignal.Empty() )
4029 Dali::Actor handle( this );
4030 mOnRelayoutSignal.Emit( handle );
4034 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4036 // Do the negotiation
4037 NegotiateDimensions( allocatedSize );
4039 // Set the actor size
4040 SetNegotiatedSize( container );
4042 // Negotiate down to children
4043 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4045 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4047 ActorPtr child = GetChildAt( i );
4049 // Only relayout if required
4050 if( child->RelayoutRequired() )
4052 container.Add( Dali::Actor( child.Get() ), newBounds );
4057 void Actor::RelayoutRequest( Dimension::Type dimension )
4059 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4060 if( relayoutController )
4062 Dali::Actor self( this );
4063 relayoutController->RequestRelayout( self, dimension );
4067 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4071 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4075 void Actor::SetPreferredSize( const Vector2& size )
4077 EnsureRelayoutData();
4079 if( size.width > 0.0f )
4081 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4084 if( size.height > 0.0f )
4086 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4089 mRelayoutData->preferredSize = size;
4094 Vector2 Actor::GetPreferredSize() const
4096 if ( mRelayoutData )
4098 return mRelayoutData->preferredSize;
4101 return GetDefaultPreferredSize();
4104 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4106 EnsureRelayoutData();
4108 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4110 if( dimension & ( 1 << i ) )
4112 mRelayoutData->minimumSize[ i ] = size;
4119 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4121 if ( mRelayoutData )
4123 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4125 if( dimension & ( 1 << i ) )
4127 return mRelayoutData->minimumSize[ i ];
4132 return 0.0f; // Default
4135 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4137 EnsureRelayoutData();
4139 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4141 if( dimension & ( 1 << i ) )
4143 mRelayoutData->maximumSize[ i ] = size;
4150 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4152 if ( mRelayoutData )
4154 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4156 if( dimension & ( 1 << i ) )
4158 return mRelayoutData->maximumSize[ i ];
4163 return FLT_MAX; // Default
4166 } // namespace Internal