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 );
1425 mAttachment->Connect();
1432 unsigned int Actor::GetRendererCount() const
1434 //TODO: MESH_REWORK : Add support for multiple renderers
1435 RendererAttachment* attachment = dynamic_cast<RendererAttachment*>(mAttachment.Get());
1436 return attachment ? 1u : 0u;
1439 Renderer& Actor::GetRendererAt( unsigned int index )
1441 //TODO: MESH_REWORK : Add support for multiple renderers
1442 DALI_ASSERT_DEBUG( index == 0 && "Only one renderer is supported." );
1444 //TODO: MESH_REWORK : Temporary code
1445 RendererAttachment* attachment = dynamic_cast<RendererAttachment*>(mAttachment.Get());
1446 DALI_ASSERT_ALWAYS( attachment && "Actor doesn't have a renderer" );
1448 return attachment->GetRenderer();
1451 void Actor::RemoveRenderer( Renderer& renderer )
1453 //TODO: MESH_REWORK : Add support for multiple renderers
1457 void Actor::RemoveRenderer( unsigned int index )
1459 //TODO: MESH_REWORK : Add support for multiple renderers
1463 void Actor::SetOverlay( bool enable )
1465 // Setting STENCIL will override OVERLAY_2D
1466 if( DrawMode::STENCIL != mDrawMode )
1468 SetDrawMode( enable ? DrawMode::OVERLAY_2D : DrawMode::NORMAL );
1472 bool Actor::IsOverlay() const
1474 return ( DrawMode::OVERLAY_2D == mDrawMode );
1477 void Actor::SetDrawMode( DrawMode::Type drawMode )
1479 // this flag is not animatable so keep the value
1480 mDrawMode = drawMode;
1483 // mNode is being used in a separate thread; queue a message to set the value
1484 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1488 DrawMode::Type Actor::GetDrawMode() const
1493 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1495 // only valid when on-stage
1496 StagePtr stage = Stage::GetCurrent();
1497 if( stage && OnStage() )
1499 const RenderTaskList& taskList = stage->GetRenderTaskList();
1501 Vector2 converted( screenX, screenY );
1503 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1504 const int taskCount = taskList.GetTaskCount();
1505 for( int i = taskCount - 1; i >= 0; --i )
1507 Dali::RenderTask task = taskList.GetTask( i );
1508 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1510 // found a task where this conversion was ok so return
1518 bool Actor::ScreenToLocal( RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1520 bool retval = false;
1521 // only valid when on-stage
1524 CameraActor* camera = renderTask.GetCameraActor();
1528 renderTask.GetViewport( viewport );
1530 // need to translate coordinates to render tasks coordinate space
1531 Vector2 converted( screenX, screenY );
1532 if( renderTask.TranslateCoordinates( converted ) )
1534 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1541 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1543 // Early-out if mNode is NULL
1549 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1551 // Calculate the ModelView matrix
1552 Matrix modelView( false/*don't init*/);
1553 // need to use the components as world matrix is only updated for actors that need it
1554 modelView.SetTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1555 Matrix::Multiply( modelView, modelView, viewMatrix );
1557 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1558 Matrix invertedMvp( false/*don't init*/);
1559 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1560 bool success = invertedMvp.Invert();
1562 // Convert to GL coordinates
1563 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1568 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1575 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1581 if( XyPlaneIntersect( nearPos, farPos, local ) )
1583 Vector3 size = GetCurrentSize();
1584 localX = local.x + size.x * 0.5f;
1585 localY = local.y + size.y * 0.5f;
1596 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1599 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1601 Mathematical Formulation
1603 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1605 ( p - c ) dot ( p - c ) = r^2
1607 Given a ray with a point of origin 'o', and a direction vector 'd':
1609 ray(t) = o + td, t >= 0
1611 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1613 (o + td - c ) dot ( o + td - c ) = r^2
1615 To solve for t we first expand the above into a more recognisable quadratic equation form
1617 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1626 B = 2( o - c ) dot d
1627 C = ( o - c ) dot ( o - c ) - r^2
1629 which can be solved using a standard quadratic formula.
1631 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1633 Practical Simplification
1635 In a renderer, we often differentiate between world space and object space. In the object space
1636 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1637 into object space, the mathematical solution presented above can be simplified significantly.
1639 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1643 and we can find the t at which the (transformed) ray intersects the sphere by
1645 ( o + td ) dot ( o + td ) = r^2
1647 According to the reasoning above, we expand the above quadratic equation into the general form
1651 which now has coefficients:
1658 // Early out if mNode is NULL
1664 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1666 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1667 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1668 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1670 // Compute the radius is not needed, square radius it's enough.
1671 const Vector3& size( mNode->GetSize( bufferIndex ) );
1673 // Scale the sphere.
1674 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1676 const float width = size.width * scale.width;
1677 const float height = size.height * scale.height;
1679 float squareSphereRadius = 0.5f * ( width * width + height * height );
1681 float a = rayDir.Dot( rayDir ); // a
1682 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1683 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1685 return ( b2 * b2 - a * c ) >= 0.f;
1688 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
1695 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1697 // Transforms the ray to the local reference system.
1699 // Calculate the inverse of Model matrix
1700 Matrix invModelMatrix( false/*don't init*/);
1701 // need to use the components as world matrix is only updated for actors that need it
1702 invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1704 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1705 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1707 // Test with the actor's XY plane (Normal = 0 0 1 1).
1709 float a = -rayOriginLocal.z;
1710 float b = rayDirLocal.z;
1712 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1714 // Ray travels distance * rayDirLocal to intersect with plane.
1717 const Vector3& size = mNode->GetSize( bufferIndex );
1719 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1720 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1722 // Test with the actor's geometry.
1723 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1730 void Actor::SetLeaveRequired( bool required )
1732 mLeaveRequired = required;
1735 bool Actor::GetLeaveRequired() const
1737 return mLeaveRequired;
1740 void Actor::SetKeyboardFocusable( bool focusable )
1742 mKeyboardFocusable = focusable;
1745 bool Actor::IsKeyboardFocusable() const
1747 return mKeyboardFocusable;
1750 bool Actor::GetTouchRequired() const
1752 return !mTouchedSignal.Empty() || mDerivedRequiresTouch;
1755 bool Actor::GetHoverRequired() const
1757 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1760 bool Actor::GetWheelEventRequired() const
1762 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1765 bool Actor::IsHittable() const
1767 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1770 ActorGestureData& Actor::GetGestureData()
1772 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1773 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1774 if( NULL == mGestureData )
1776 mGestureData = new ActorGestureData;
1778 return *mGestureData;
1781 bool Actor::IsGestureRequred( Gesture::Type type ) const
1783 return mGestureData && mGestureData->IsGestureRequred( type );
1786 bool Actor::EmitTouchEventSignal( const TouchEvent& event )
1788 bool consumed = false;
1790 if( !mTouchedSignal.Empty() )
1792 Dali::Actor handle( this );
1793 consumed = mTouchedSignal.Emit( handle, event );
1798 // Notification for derived classes
1799 consumed = OnTouchEvent( event );
1805 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1807 bool consumed = false;
1809 if( !mHoveredSignal.Empty() )
1811 Dali::Actor handle( this );
1812 consumed = mHoveredSignal.Emit( handle, event );
1817 // Notification for derived classes
1818 consumed = OnHoverEvent( event );
1824 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1826 bool consumed = false;
1828 if( !mWheelEventSignal.Empty() )
1830 Dali::Actor handle( this );
1831 consumed = mWheelEventSignal.Emit( handle, event );
1836 // Notification for derived classes
1837 consumed = OnWheelEvent( event );
1843 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
1845 return mTouchedSignal;
1848 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
1850 return mHoveredSignal;
1853 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
1855 return mWheelEventSignal;
1858 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
1860 return mOnStageSignal;
1863 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
1865 return mOffStageSignal;
1868 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
1870 return mOnRelayoutSignal;
1873 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1875 bool connected( true );
1876 Actor* actor = dynamic_cast< Actor* >( object );
1878 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1880 actor->TouchedSignal().Connect( tracker, functor );
1882 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1884 actor->HoveredSignal().Connect( tracker, functor );
1886 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1888 actor->WheelEventSignal().Connect( tracker, functor );
1890 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
1892 actor->OnStageSignal().Connect( tracker, functor );
1894 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
1896 actor->OffStageSignal().Connect( tracker, functor );
1900 // signalName does not match any signal
1907 Actor::Actor( DerivedType derivedType )
1911 mParentOrigin( NULL ),
1912 mAnchorPoint( NULL ),
1913 mRelayoutData( NULL ),
1914 mGestureData( NULL ),
1916 mTargetSize( 0.0f, 0.0f, 0.0f ),
1918 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
1920 mIsRoot( ROOT_LAYER == derivedType ),
1921 mIsRenderable( RENDERABLE == derivedType ),
1922 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
1923 mIsOnStage( false ),
1925 mLeaveRequired( false ),
1926 mKeyboardFocusable( false ),
1927 mDerivedRequiresTouch( false ),
1928 mDerivedRequiresHover( false ),
1929 mDerivedRequiresWheelEvent( false ),
1930 mOnStageSignalled( false ),
1931 mInsideOnSizeSet( false ),
1932 mInheritOrientation( true ),
1933 mInheritScale( true ),
1934 mDrawMode( DrawMode::NORMAL ),
1935 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
1936 mColorMode( Node::DEFAULT_COLOR_MODE )
1940 void Actor::Initialize()
1943 SceneGraph::Node* node = CreateNode();
1945 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
1946 mNode = node; // Keep raw-pointer to Node
1950 GetEventThreadServices().RegisterObject( this );
1955 // Remove mParent pointers from children even if we're destroying core,
1956 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1959 ActorConstIter endIter = mChildren->end();
1960 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1962 (*iter)->SetParent( NULL );
1967 // Guard to allow handle destruction after Core has been destroyed
1968 if( EventThreadServices::IsCoreRunning() )
1972 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
1973 mNode = NULL; // Node is about to be destroyed
1976 GetEventThreadServices().UnregisterObject( this );
1979 // Cleanup optional gesture data
1980 delete mGestureData;
1982 // Cleanup optional parent origin and anchor
1983 delete mParentOrigin;
1984 delete mAnchorPoint;
1986 // Delete optional relayout data
1989 delete mRelayoutData;
1993 void Actor::ConnectToStage( unsigned int parentDepth, int index )
1995 // This container is used instead of walking the Actor hierachy.
1996 // It protects us when the Actor hierachy is modified during OnStageConnectionExternal callbacks.
1997 ActorContainer connectionList;
2000 // This stage is atomic i.e. not interrupted by user callbacks
2001 RecursiveConnectToStage( connectionList, parentDepth+1, index );
2003 // Notify applications about the newly connected actors.
2004 const ActorIter endIter = connectionList.end();
2005 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2007 (*iter)->NotifyStageConnection();
2013 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth, int index )
2015 DALI_ASSERT_ALWAYS( !OnStage() );
2020 ConnectToSceneGraph( index );
2022 // Notification for internal derived classes
2023 OnStageConnectionInternal();
2025 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2026 connectionList.push_back( ActorPtr( this ) );
2028 // Recursively connect children
2031 ActorConstIter endIter = mChildren->end();
2032 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2034 (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
2040 * This method is called when the Actor is connected to the Stage.
2041 * The parent must have added its Node to the scene-graph.
2042 * The child must connect its Node to the parent's Node.
2043 * This is resursive; the child calls ConnectToStage() for its children.
2045 void Actor::ConnectToSceneGraph( int index )
2047 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2051 // Reparent Node in next Update
2052 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode, index );
2055 // Notify attachment
2058 mAttachment->Connect();
2061 // Request relayout on all actors that are added to the scenegraph
2064 // Notification for Object::Observers
2068 void Actor::NotifyStageConnection()
2070 // Actors can be removed (in a callback), before the on-stage stage is reported.
2071 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2072 if( OnStage() && !mOnStageSignalled )
2074 // Notification for external (CustomActor) derived classes
2075 OnStageConnectionExternal( mDepth );
2077 if( !mOnStageSignal.Empty() )
2079 Dali::Actor handle( this );
2080 mOnStageSignal.Emit( handle );
2083 // Guard against Remove during callbacks
2086 mOnStageSignalled = true; // signal required next time Actor is removed
2091 void Actor::DisconnectFromStage()
2093 // This container is used instead of walking the Actor hierachy.
2094 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2095 ActorContainer disconnectionList;
2097 // This stage is atomic i.e. not interrupted by user callbacks
2098 RecursiveDisconnectFromStage( disconnectionList );
2100 // Notify applications about the newly disconnected actors.
2101 const ActorIter endIter = disconnectionList.end();
2102 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2104 (*iter)->NotifyStageDisconnection();
2108 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2110 DALI_ASSERT_ALWAYS( OnStage() );
2112 // Recursively disconnect children
2115 ActorConstIter endIter = mChildren->end();
2116 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2118 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2122 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2123 disconnectionList.push_back( ActorPtr( this ) );
2125 // Notification for internal derived classes
2126 OnStageDisconnectionInternal();
2128 DisconnectFromSceneGraph();
2134 * This method is called by an actor or its parent, before a node removal message is sent.
2135 * This is recursive; the child calls DisconnectFromStage() for its children.
2137 void Actor::DisconnectFromSceneGraph()
2139 // Notification for Object::Observers
2140 OnSceneObjectRemove();
2142 // Notify attachment
2145 mAttachment->Disconnect();
2149 void Actor::NotifyStageDisconnection()
2151 // Actors can be added (in a callback), before the off-stage state is reported.
2152 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2153 // only do this step if there is a stage, i.e. Core is not being shut down
2154 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2156 // Notification for external (CustomeActor) derived classes
2157 OnStageDisconnectionExternal();
2159 if( !mOffStageSignal.Empty() )
2161 Dali::Actor handle( this );
2162 mOffStageSignal.Emit( handle );
2165 // Guard against Add during callbacks
2168 mOnStageSignalled = false; // signal required next time Actor is added
2173 bool Actor::IsNodeConnected() const
2175 bool connected( false );
2180 if( mNode->IsRoot() || mNode->GetParent() )
2189 unsigned int Actor::GetDefaultPropertyCount() const
2191 return DEFAULT_PROPERTY_COUNT;
2194 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2196 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2198 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2200 indices.PushBack( i );
2204 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2206 if( index < DEFAULT_PROPERTY_COUNT )
2208 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2214 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2216 Property::Index index = Property::INVALID_INDEX;
2218 // Look for name in default properties
2219 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2221 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2222 if( 0 == name.compare( property->name ) )
2232 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2234 if( index < DEFAULT_PROPERTY_COUNT )
2236 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2242 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2244 if( index < DEFAULT_PROPERTY_COUNT )
2246 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2252 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2254 if( index < DEFAULT_PROPERTY_COUNT )
2256 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2262 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2264 if( index < DEFAULT_PROPERTY_COUNT )
2266 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2269 // index out of range...return Property::NONE
2270 return Property::NONE;
2273 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2277 case Dali::Actor::Property::PARENT_ORIGIN:
2279 SetParentOrigin( property.Get< Vector3 >() );
2283 case Dali::Actor::Property::PARENT_ORIGIN_X:
2285 SetParentOriginX( property.Get< float >() );
2289 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2291 SetParentOriginY( property.Get< float >() );
2295 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2297 SetParentOriginZ( property.Get< float >() );
2301 case Dali::Actor::Property::ANCHOR_POINT:
2303 SetAnchorPoint( property.Get< Vector3 >() );
2307 case Dali::Actor::Property::ANCHOR_POINT_X:
2309 SetAnchorPointX( property.Get< float >() );
2313 case Dali::Actor::Property::ANCHOR_POINT_Y:
2315 SetAnchorPointY( property.Get< float >() );
2319 case Dali::Actor::Property::ANCHOR_POINT_Z:
2321 SetAnchorPointZ( property.Get< float >() );
2325 case Dali::Actor::Property::SIZE:
2327 SetSize( property.Get< Vector3 >() );
2331 case Dali::Actor::Property::SIZE_WIDTH:
2333 SetWidth( property.Get< float >() );
2337 case Dali::Actor::Property::SIZE_HEIGHT:
2339 SetHeight( property.Get< float >() );
2343 case Dali::Actor::Property::SIZE_DEPTH:
2345 SetDepth( property.Get< float >() );
2349 case Dali::Actor::Property::POSITION:
2351 SetPosition( property.Get< Vector3 >() );
2355 case Dali::Actor::Property::POSITION_X:
2357 SetX( property.Get< float >() );
2361 case Dali::Actor::Property::POSITION_Y:
2363 SetY( property.Get< float >() );
2367 case Dali::Actor::Property::POSITION_Z:
2369 SetZ( property.Get< float >() );
2373 case Dali::Actor::Property::ORIENTATION:
2375 SetOrientation( property.Get< Quaternion >() );
2379 case Dali::Actor::Property::SCALE:
2381 SetScale( property.Get< Vector3 >() );
2385 case Dali::Actor::Property::SCALE_X:
2387 SetScaleX( property.Get< float >() );
2391 case Dali::Actor::Property::SCALE_Y:
2393 SetScaleY( property.Get< float >() );
2397 case Dali::Actor::Property::SCALE_Z:
2399 SetScaleZ( property.Get< float >() );
2403 case Dali::Actor::Property::VISIBLE:
2405 SetVisible( property.Get< bool >() );
2409 case Dali::Actor::Property::COLOR:
2411 SetColor( property.Get< Vector4 >() );
2415 case Dali::Actor::Property::COLOR_RED:
2417 SetColorRed( property.Get< float >() );
2421 case Dali::Actor::Property::COLOR_GREEN:
2423 SetColorGreen( property.Get< float >() );
2427 case Dali::Actor::Property::COLOR_BLUE:
2429 SetColorBlue( property.Get< float >() );
2433 case Dali::Actor::Property::COLOR_ALPHA:
2435 SetOpacity( property.Get< float >() );
2439 case Dali::Actor::Property::NAME:
2441 SetName( property.Get< std::string >() );
2445 case Dali::Actor::Property::SENSITIVE:
2447 SetSensitive( property.Get< bool >() );
2451 case Dali::Actor::Property::LEAVE_REQUIRED:
2453 SetLeaveRequired( property.Get< bool >() );
2457 case Dali::Actor::Property::INHERIT_ORIENTATION:
2459 SetInheritOrientation( property.Get< bool >() );
2463 case Dali::Actor::Property::INHERIT_SCALE:
2465 SetInheritScale( property.Get< bool >() );
2469 case Dali::Actor::Property::COLOR_MODE:
2471 SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2475 case Dali::Actor::Property::POSITION_INHERITANCE:
2477 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2481 case Dali::Actor::Property::DRAW_MODE:
2483 SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2487 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2489 SetSizeModeFactor( property.Get< Vector3 >() );
2493 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2495 ResizePolicy::Type type;
2496 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2498 SetResizePolicy( type, Dimension::WIDTH );
2503 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2505 ResizePolicy::Type type;
2506 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2508 SetResizePolicy( type, Dimension::HEIGHT );
2513 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2515 SizeScalePolicy::Type type;
2516 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount, type ) )
2518 SetSizeScalePolicy( type );
2523 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2525 if( property.Get< bool >() )
2527 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2532 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2534 if( property.Get< bool >() )
2536 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2541 case Dali::Actor::Property::PADDING:
2543 Vector4 padding = property.Get< Vector4 >();
2544 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2545 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2549 case Dali::Actor::Property::MINIMUM_SIZE:
2551 Vector2 size = property.Get< Vector2 >();
2552 SetMinimumSize( size.x, Dimension::WIDTH );
2553 SetMinimumSize( size.y, Dimension::HEIGHT );
2557 case Dali::Actor::Property::MAXIMUM_SIZE:
2559 Vector2 size = property.Get< Vector2 >();
2560 SetMaximumSize( size.x, Dimension::WIDTH );
2561 SetMaximumSize( size.y, Dimension::HEIGHT );
2567 // this can happen in the case of a non-animatable default property so just do nothing
2573 // TODO: This method needs to be removed
2574 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2576 switch( entry.type )
2578 case Property::BOOLEAN:
2580 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2581 DALI_ASSERT_DEBUG( NULL != property );
2583 // property is being used in a separate thread; queue a message to set the property
2584 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2589 case Property::INTEGER:
2591 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2592 DALI_ASSERT_DEBUG( NULL != property );
2594 // property is being used in a separate thread; queue a message to set the property
2595 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2600 case Property::FLOAT:
2602 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2603 DALI_ASSERT_DEBUG( NULL != property );
2605 // property is being used in a separate thread; queue a message to set the property
2606 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2611 case Property::VECTOR2:
2613 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2614 DALI_ASSERT_DEBUG( NULL != property );
2616 // property is being used in a separate thread; queue a message to set the property
2617 if(entry.componentIndex == 0)
2619 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2621 else if(entry.componentIndex == 1)
2623 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2627 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2633 case Property::VECTOR3:
2635 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2636 DALI_ASSERT_DEBUG( NULL != property );
2638 // property is being used in a separate thread; queue a message to set the property
2639 if(entry.componentIndex == 0)
2641 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2643 else if(entry.componentIndex == 1)
2645 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2647 else if(entry.componentIndex == 2)
2649 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2653 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2659 case Property::VECTOR4:
2661 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2662 DALI_ASSERT_DEBUG( NULL != property );
2664 // property is being used in a separate thread; queue a message to set the property
2665 if(entry.componentIndex == 0)
2667 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
2669 else if(entry.componentIndex == 1)
2671 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
2673 else if(entry.componentIndex == 2)
2675 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
2677 else if(entry.componentIndex == 3)
2679 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
2683 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2689 case Property::ROTATION:
2691 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
2692 DALI_ASSERT_DEBUG( NULL != property );
2694 // property is being used in a separate thread; queue a message to set the property
2695 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
2700 case Property::MATRIX:
2702 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
2703 DALI_ASSERT_DEBUG( NULL != property );
2705 // property is being used in a separate thread; queue a message to set the property
2706 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
2711 case Property::MATRIX3:
2713 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
2714 DALI_ASSERT_DEBUG( NULL != property );
2716 // property is being used in a separate thread; queue a message to set the property
2717 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
2724 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
2730 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
2732 Property::Value value;
2736 case Dali::Actor::Property::PARENT_ORIGIN:
2738 value = GetCurrentParentOrigin();
2742 case Dali::Actor::Property::PARENT_ORIGIN_X:
2744 value = GetCurrentParentOrigin().x;
2748 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2750 value = GetCurrentParentOrigin().y;
2754 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2756 value = GetCurrentParentOrigin().z;
2760 case Dali::Actor::Property::ANCHOR_POINT:
2762 value = GetCurrentAnchorPoint();
2766 case Dali::Actor::Property::ANCHOR_POINT_X:
2768 value = GetCurrentAnchorPoint().x;
2772 case Dali::Actor::Property::ANCHOR_POINT_Y:
2774 value = GetCurrentAnchorPoint().y;
2778 case Dali::Actor::Property::ANCHOR_POINT_Z:
2780 value = GetCurrentAnchorPoint().z;
2784 case Dali::Actor::Property::SIZE:
2786 value = GetCurrentSize();
2790 case Dali::Actor::Property::SIZE_WIDTH:
2792 value = GetCurrentSize().width;
2796 case Dali::Actor::Property::SIZE_HEIGHT:
2798 value = GetCurrentSize().height;
2802 case Dali::Actor::Property::SIZE_DEPTH:
2804 value = GetCurrentSize().depth;
2808 case Dali::Actor::Property::POSITION:
2810 value = GetCurrentPosition();
2814 case Dali::Actor::Property::POSITION_X:
2816 value = GetCurrentPosition().x;
2820 case Dali::Actor::Property::POSITION_Y:
2822 value = GetCurrentPosition().y;
2826 case Dali::Actor::Property::POSITION_Z:
2828 value = GetCurrentPosition().z;
2832 case Dali::Actor::Property::WORLD_POSITION:
2834 value = GetCurrentWorldPosition();
2838 case Dali::Actor::Property::WORLD_POSITION_X:
2840 value = GetCurrentWorldPosition().x;
2844 case Dali::Actor::Property::WORLD_POSITION_Y:
2846 value = GetCurrentWorldPosition().y;
2850 case Dali::Actor::Property::WORLD_POSITION_Z:
2852 value = GetCurrentWorldPosition().z;
2856 case Dali::Actor::Property::ORIENTATION:
2858 value = GetCurrentOrientation();
2862 case Dali::Actor::Property::WORLD_ORIENTATION:
2864 value = GetCurrentWorldOrientation();
2868 case Dali::Actor::Property::SCALE:
2870 value = GetCurrentScale();
2874 case Dali::Actor::Property::SCALE_X:
2876 value = GetCurrentScale().x;
2880 case Dali::Actor::Property::SCALE_Y:
2882 value = GetCurrentScale().y;
2886 case Dali::Actor::Property::SCALE_Z:
2888 value = GetCurrentScale().z;
2892 case Dali::Actor::Property::WORLD_SCALE:
2894 value = GetCurrentWorldScale();
2898 case Dali::Actor::Property::VISIBLE:
2900 value = IsVisible();
2904 case Dali::Actor::Property::COLOR:
2906 value = GetCurrentColor();
2910 case Dali::Actor::Property::COLOR_RED:
2912 value = GetCurrentColor().r;
2916 case Dali::Actor::Property::COLOR_GREEN:
2918 value = GetCurrentColor().g;
2922 case Dali::Actor::Property::COLOR_BLUE:
2924 value = GetCurrentColor().b;
2928 case Dali::Actor::Property::COLOR_ALPHA:
2930 value = GetCurrentColor().a;
2934 case Dali::Actor::Property::WORLD_COLOR:
2936 value = GetCurrentWorldColor();
2940 case Dali::Actor::Property::WORLD_MATRIX:
2942 value = GetCurrentWorldMatrix();
2946 case Dali::Actor::Property::NAME:
2952 case Dali::Actor::Property::SENSITIVE:
2954 value = IsSensitive();
2958 case Dali::Actor::Property::LEAVE_REQUIRED:
2960 value = GetLeaveRequired();
2964 case Dali::Actor::Property::INHERIT_ORIENTATION:
2966 value = IsOrientationInherited();
2970 case Dali::Actor::Property::INHERIT_SCALE:
2972 value = IsScaleInherited();
2976 case Dali::Actor::Property::COLOR_MODE:
2978 value = Scripting::GetColorMode( GetColorMode() );
2982 case Dali::Actor::Property::POSITION_INHERITANCE:
2984 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
2988 case Dali::Actor::Property::DRAW_MODE:
2990 value = Scripting::GetDrawMode( GetDrawMode() );
2994 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2996 value = GetSizeModeFactor();
3000 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3002 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3006 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3008 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3012 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3014 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3018 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3020 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3024 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3026 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3030 case Dali::Actor::Property::PADDING:
3032 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3033 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3034 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3038 case Dali::Actor::Property::MINIMUM_SIZE:
3040 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3044 case Dali::Actor::Property::MAXIMUM_SIZE:
3046 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3052 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3060 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3065 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3067 // This method should only return an object connected to the scene-graph
3068 return OnStage() ? mNode : NULL;
3071 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3073 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3075 const PropertyBase* property( NULL );
3077 // This method should only return a property of an object connected to the scene-graph
3083 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3085 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3086 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3088 property = animatable->GetSceneGraphProperty();
3090 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3092 CustomPropertyMetadata* custom = FindCustomProperty( index );
3093 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3095 property = custom->GetSceneGraphProperty();
3097 else if( NULL != mNode )
3101 case Dali::Actor::Property::SIZE:
3102 property = &mNode->mSize;
3105 case Dali::Actor::Property::SIZE_WIDTH:
3106 property = &mNode->mSize;
3109 case Dali::Actor::Property::SIZE_HEIGHT:
3110 property = &mNode->mSize;
3113 case Dali::Actor::Property::SIZE_DEPTH:
3114 property = &mNode->mSize;
3117 case Dali::Actor::Property::POSITION:
3118 property = &mNode->mPosition;
3121 case Dali::Actor::Property::POSITION_X:
3122 property = &mNode->mPosition;
3125 case Dali::Actor::Property::POSITION_Y:
3126 property = &mNode->mPosition;
3129 case Dali::Actor::Property::POSITION_Z:
3130 property = &mNode->mPosition;
3133 case Dali::Actor::Property::ORIENTATION:
3134 property = &mNode->mOrientation;
3137 case Dali::Actor::Property::SCALE:
3138 property = &mNode->mScale;
3141 case Dali::Actor::Property::SCALE_X:
3142 property = &mNode->mScale;
3145 case Dali::Actor::Property::SCALE_Y:
3146 property = &mNode->mScale;
3149 case Dali::Actor::Property::SCALE_Z:
3150 property = &mNode->mScale;
3153 case Dali::Actor::Property::VISIBLE:
3154 property = &mNode->mVisible;
3157 case Dali::Actor::Property::COLOR:
3158 property = &mNode->mColor;
3161 case Dali::Actor::Property::COLOR_RED:
3162 property = &mNode->mColor;
3165 case Dali::Actor::Property::COLOR_GREEN:
3166 property = &mNode->mColor;
3169 case Dali::Actor::Property::COLOR_BLUE:
3170 property = &mNode->mColor;
3173 case Dali::Actor::Property::COLOR_ALPHA:
3174 property = &mNode->mColor;
3185 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3187 const PropertyInputImpl* property( NULL );
3189 // This method should only return a property of an object connected to the scene-graph
3195 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3197 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3198 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3200 property = animatable->GetSceneGraphProperty();
3202 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3204 CustomPropertyMetadata* custom = FindCustomProperty( index );
3205 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3206 property = custom->GetSceneGraphProperty();
3208 else if( NULL != mNode )
3212 case Dali::Actor::Property::PARENT_ORIGIN:
3213 property = &mNode->mParentOrigin;
3216 case Dali::Actor::Property::PARENT_ORIGIN_X:
3217 property = &mNode->mParentOrigin;
3220 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3221 property = &mNode->mParentOrigin;
3224 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3225 property = &mNode->mParentOrigin;
3228 case Dali::Actor::Property::ANCHOR_POINT:
3229 property = &mNode->mAnchorPoint;
3232 case Dali::Actor::Property::ANCHOR_POINT_X:
3233 property = &mNode->mAnchorPoint;
3236 case Dali::Actor::Property::ANCHOR_POINT_Y:
3237 property = &mNode->mAnchorPoint;
3240 case Dali::Actor::Property::ANCHOR_POINT_Z:
3241 property = &mNode->mAnchorPoint;
3244 case Dali::Actor::Property::SIZE:
3245 property = &mNode->mSize;
3248 case Dali::Actor::Property::SIZE_WIDTH:
3249 property = &mNode->mSize;
3252 case Dali::Actor::Property::SIZE_HEIGHT:
3253 property = &mNode->mSize;
3256 case Dali::Actor::Property::SIZE_DEPTH:
3257 property = &mNode->mSize;
3260 case Dali::Actor::Property::POSITION:
3261 property = &mNode->mPosition;
3264 case Dali::Actor::Property::POSITION_X:
3265 property = &mNode->mPosition;
3268 case Dali::Actor::Property::POSITION_Y:
3269 property = &mNode->mPosition;
3272 case Dali::Actor::Property::POSITION_Z:
3273 property = &mNode->mPosition;
3276 case Dali::Actor::Property::WORLD_POSITION:
3277 property = &mNode->mWorldPosition;
3280 case Dali::Actor::Property::WORLD_POSITION_X:
3281 property = &mNode->mWorldPosition;
3284 case Dali::Actor::Property::WORLD_POSITION_Y:
3285 property = &mNode->mWorldPosition;
3288 case Dali::Actor::Property::WORLD_POSITION_Z:
3289 property = &mNode->mWorldPosition;
3292 case Dali::Actor::Property::ORIENTATION:
3293 property = &mNode->mOrientation;
3296 case Dali::Actor::Property::WORLD_ORIENTATION:
3297 property = &mNode->mWorldOrientation;
3300 case Dali::Actor::Property::SCALE:
3301 property = &mNode->mScale;
3304 case Dali::Actor::Property::SCALE_X:
3305 property = &mNode->mScale;
3308 case Dali::Actor::Property::SCALE_Y:
3309 property = &mNode->mScale;
3312 case Dali::Actor::Property::SCALE_Z:
3313 property = &mNode->mScale;
3316 case Dali::Actor::Property::WORLD_SCALE:
3317 property = &mNode->mWorldScale;
3320 case Dali::Actor::Property::VISIBLE:
3321 property = &mNode->mVisible;
3324 case Dali::Actor::Property::COLOR:
3325 property = &mNode->mColor;
3328 case Dali::Actor::Property::COLOR_RED:
3329 property = &mNode->mColor;
3332 case Dali::Actor::Property::COLOR_GREEN:
3333 property = &mNode->mColor;
3336 case Dali::Actor::Property::COLOR_BLUE:
3337 property = &mNode->mColor;
3340 case Dali::Actor::Property::COLOR_ALPHA:
3341 property = &mNode->mColor;
3344 case Dali::Actor::Property::WORLD_COLOR:
3345 property = &mNode->mWorldColor;
3348 case Dali::Actor::Property::WORLD_MATRIX:
3349 property = &mNode->mWorldMatrix;
3360 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3362 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3364 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3366 // check whether the animatable property is registered already, if not then register one.
3367 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3368 if( animatableProperty )
3370 componentIndex = animatableProperty->componentIndex;
3377 case Dali::Actor::Property::PARENT_ORIGIN_X:
3378 case Dali::Actor::Property::ANCHOR_POINT_X:
3379 case Dali::Actor::Property::SIZE_WIDTH:
3380 case Dali::Actor::Property::POSITION_X:
3381 case Dali::Actor::Property::WORLD_POSITION_X:
3382 case Dali::Actor::Property::SCALE_X:
3383 case Dali::Actor::Property::COLOR_RED:
3389 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3390 case Dali::Actor::Property::ANCHOR_POINT_Y:
3391 case Dali::Actor::Property::SIZE_HEIGHT:
3392 case Dali::Actor::Property::POSITION_Y:
3393 case Dali::Actor::Property::WORLD_POSITION_Y:
3394 case Dali::Actor::Property::SCALE_Y:
3395 case Dali::Actor::Property::COLOR_GREEN:
3401 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3402 case Dali::Actor::Property::ANCHOR_POINT_Z:
3403 case Dali::Actor::Property::SIZE_DEPTH:
3404 case Dali::Actor::Property::POSITION_Z:
3405 case Dali::Actor::Property::WORLD_POSITION_Z:
3406 case Dali::Actor::Property::SCALE_Z:
3407 case Dali::Actor::Property::COLOR_BLUE:
3413 case Dali::Actor::Property::COLOR_ALPHA:
3427 return componentIndex;
3430 void Actor::SetParent( Actor* parent, int index )
3434 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3438 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3441 // Instruct each actor to create a corresponding node in the scene graph
3442 ConnectToStage( parent->GetHierarchyDepth(), index );
3445 else // parent being set to NULL
3447 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3451 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3454 DALI_ASSERT_ALWAYS( mNode != NULL );
3458 // Disconnect the Node & its children from the scene-graph.
3459 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3462 // Instruct each actor to discard pointers to the scene-graph
3463 DisconnectFromStage();
3468 SceneGraph::Node* Actor::CreateNode() const
3473 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3476 Actor* actor = dynamic_cast< Actor* >( object );
3480 if( 0 == actionName.compare( ACTION_SHOW ) )
3482 actor->SetVisible( true );
3485 else if( 0 == actionName.compare( ACTION_HIDE ) )
3487 actor->SetVisible( false );
3495 void Actor::EnsureRelayoutData()
3497 // Assign relayout data.
3498 if( !mRelayoutData )
3500 mRelayoutData = new RelayoutData();
3504 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3506 // Check if actor is dependent on parent
3507 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3509 if( ( dimension & ( 1 << i ) ) )
3511 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3512 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3522 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3524 // Check if actor is dependent on children
3525 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3527 if( ( dimension & ( 1 << i ) ) )
3529 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3530 switch( resizePolicy )
3532 case ResizePolicy::FIT_TO_CHILDREN:
3533 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3549 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3551 return Actor::RelayoutDependentOnChildren( dimension );
3554 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3556 // Check each possible dimension and see if it is dependent on the input one
3557 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3559 if( dimension & ( 1 << i ) )
3561 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3568 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3570 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3572 if( dimension & ( 1 << i ) )
3574 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3579 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3581 // If more than one dimension is requested, just return the first one found
3582 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3584 if( ( dimension & ( 1 << i ) ) )
3586 return mRelayoutData->negotiatedDimensions[ i ];
3590 return 0.0f; // Default
3593 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3595 EnsureRelayoutData();
3597 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3599 if( dimension & ( 1 << i ) )
3601 mRelayoutData->dimensionPadding[ i ] = padding;
3606 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3608 if ( mRelayoutData )
3610 // If more than one dimension is requested, just return the first one found
3611 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3613 if( ( dimension & ( 1 << i ) ) )
3615 return mRelayoutData->dimensionPadding[ i ];
3620 return GetDefaultDimensionPadding();
3623 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
3625 EnsureRelayoutData();
3627 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3629 if( dimension & ( 1 << i ) )
3631 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3636 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
3638 if ( mRelayoutData )
3640 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3642 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
3652 float Actor::GetHeightForWidthBase( float width )
3654 float height = 0.0f;
3656 const Vector3 naturalSize = GetNaturalSize();
3657 if( naturalSize.width > 0.0f )
3659 height = naturalSize.height * width / naturalSize.width;
3661 else // we treat 0 as 1:1 aspect ratio
3669 float Actor::GetWidthForHeightBase( float height )
3673 const Vector3 naturalSize = GetNaturalSize();
3674 if( naturalSize.height > 0.0f )
3676 width = naturalSize.width * height / naturalSize.height;
3678 else // we treat 0 as 1:1 aspect ratio
3686 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
3688 // Fill to parent, taking size mode factor into account
3689 switch( child.GetResizePolicy( dimension ) )
3691 case ResizePolicy::FILL_TO_PARENT:
3693 return GetLatestSize( dimension );
3696 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3698 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
3701 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3703 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
3708 return GetLatestSize( dimension );
3713 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
3715 // Can be overridden in derived class
3716 return CalculateChildSizeBase( child, dimension );
3719 float Actor::GetHeightForWidth( float width )
3721 // Can be overridden in derived class
3722 return GetHeightForWidthBase( width );
3725 float Actor::GetWidthForHeight( float height )
3727 // Can be overridden in derived class
3728 return GetWidthForHeightBase( height );
3731 float Actor::GetLatestSize( Dimension::Type dimension ) const
3733 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
3736 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
3738 Vector2 padding = GetPadding( dimension );
3740 return GetLatestSize( dimension ) + padding.x + padding.y;
3743 float Actor::NegotiateFromParent( Dimension::Type dimension )
3745 Actor* parent = GetParent();
3748 Vector2 padding( GetPadding( dimension ) );
3749 Vector2 parentPadding( parent->GetPadding( dimension ) );
3750 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
3756 float Actor::NegotiateFromChildren( Dimension::Type dimension )
3758 float maxDimensionPoint = 0.0f;
3760 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3762 ActorPtr child = GetChildAt( i );
3764 if( !child->RelayoutDependentOnParent( dimension ) )
3766 // Calculate the min and max points that the children range across
3767 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
3768 float dimensionSize = child->GetRelayoutSize( dimension );
3769 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
3773 return maxDimensionPoint;
3776 float Actor::GetSize( Dimension::Type dimension ) const
3778 return GetDimensionValue( GetTargetSize(), dimension );
3781 float Actor::GetNaturalSize( Dimension::Type dimension ) const
3783 return GetDimensionValue( GetNaturalSize(), dimension );
3786 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
3788 switch( GetResizePolicy( dimension ) )
3790 case ResizePolicy::USE_NATURAL_SIZE:
3792 return GetNaturalSize( dimension );
3795 case ResizePolicy::FIXED:
3797 return GetDimensionValue( GetPreferredSize(), dimension );
3800 case ResizePolicy::USE_ASSIGNED_SIZE:
3802 return GetDimensionValue( maximumSize, dimension );
3805 case ResizePolicy::FILL_TO_PARENT:
3806 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3807 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3809 return NegotiateFromParent( dimension );
3812 case ResizePolicy::FIT_TO_CHILDREN:
3814 return NegotiateFromChildren( dimension );
3817 case ResizePolicy::DIMENSION_DEPENDENCY:
3819 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
3822 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
3824 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
3827 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
3829 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
3841 return 0.0f; // Default
3844 float Actor::ClampDimension( float size, Dimension::Type dimension )
3846 const float minSize = GetMinimumSize( dimension );
3847 const float maxSize = GetMaximumSize( dimension );
3849 return std::max( minSize, std::min( size, maxSize ) );
3852 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
3854 // Check if it needs to be negotiated
3855 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
3857 // Check that we havn't gotten into an infinite loop
3858 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
3859 bool recursionFound = false;
3860 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
3862 if( *it == searchActor )
3864 recursionFound = true;
3869 if( !recursionFound )
3871 // Record the path that we have taken
3872 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
3874 // Dimension dependency check
3875 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3877 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
3879 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
3881 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
3885 // Parent dependency check
3886 Actor* parent = GetParent();
3887 if( parent && RelayoutDependentOnParent( dimension ) )
3889 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
3892 // Children dependency check
3893 if( RelayoutDependentOnChildren( dimension ) )
3895 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3897 ActorPtr child = GetChildAt( i );
3899 // Only relayout child first if it is not dependent on this actor
3900 if( !child->RelayoutDependentOnParent( dimension ) )
3902 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
3907 // For deriving classes
3908 OnCalculateRelayoutSize( dimension );
3910 // All dependencies checked, calculate the size and set negotiated flag
3911 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
3913 SetNegotiatedDimension( newSize, dimension );
3914 SetLayoutNegotiated( true, dimension );
3916 // For deriving classes
3917 OnLayoutNegotiated( newSize, dimension );
3919 // This actor has been successfully processed, pop it off the recursion stack
3920 recursionStack.pop_back();
3924 // TODO: Break infinite loop
3925 SetLayoutNegotiated( true, dimension );
3930 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
3932 // Negotiate all dimensions that require it
3933 ActorDimensionStack recursionStack;
3935 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3937 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
3940 NegotiateDimension( dimension, allocatedSize, recursionStack );
3944 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
3946 switch( mRelayoutData->sizeSetPolicy )
3948 case SizeScalePolicy::USE_SIZE_SET:
3953 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
3955 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
3956 const Vector3 naturalSize = GetNaturalSize();
3957 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
3959 const float sizeRatio = size.width / size.height;
3960 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
3962 if( naturalSizeRatio < sizeRatio )
3964 return Vector2( naturalSizeRatio * size.height, size.height );
3966 else if( naturalSizeRatio > sizeRatio )
3968 return Vector2( size.width, size.width / naturalSizeRatio );
3979 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
3981 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
3982 const Vector3 naturalSize = GetNaturalSize();
3983 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
3985 const float sizeRatio = size.width / size.height;
3986 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
3988 if( naturalSizeRatio < sizeRatio )
3990 return Vector2( size.width, size.width / naturalSizeRatio );
3992 else if( naturalSizeRatio > sizeRatio )
3994 return Vector2( naturalSizeRatio * size.height, size.height );
4012 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4014 // Do the set actor size
4015 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4017 // Adjust for size set policy
4018 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4020 // Lock the flag to stop recursive relayouts on set size
4021 mRelayoutData->insideRelayout = true;
4022 SetSize( negotiatedSize );
4023 mRelayoutData->insideRelayout = false;
4025 // Clear flags for all dimensions
4026 SetLayoutDirty( false );
4028 // Give deriving classes a chance to respond
4029 OnRelayout( negotiatedSize, container );
4031 if( !mOnRelayoutSignal.Empty() )
4033 Dali::Actor handle( this );
4034 mOnRelayoutSignal.Emit( handle );
4038 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4040 // Do the negotiation
4041 NegotiateDimensions( allocatedSize );
4043 // Set the actor size
4044 SetNegotiatedSize( container );
4046 // Negotiate down to children
4047 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4049 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4051 ActorPtr child = GetChildAt( i );
4053 // Only relayout if required
4054 if( child->RelayoutRequired() )
4056 container.Add( Dali::Actor( child.Get() ), newBounds );
4061 void Actor::RelayoutRequest( Dimension::Type dimension )
4063 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4064 if( relayoutController )
4066 Dali::Actor self( this );
4067 relayoutController->RequestRelayout( self, dimension );
4071 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4075 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4079 void Actor::SetPreferredSize( const Vector2& size )
4081 EnsureRelayoutData();
4083 if( size.width > 0.0f )
4085 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4088 if( size.height > 0.0f )
4090 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4093 mRelayoutData->preferredSize = size;
4098 Vector2 Actor::GetPreferredSize() const
4100 if ( mRelayoutData )
4102 return mRelayoutData->preferredSize;
4105 return GetDefaultPreferredSize();
4108 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4110 EnsureRelayoutData();
4112 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4114 if( dimension & ( 1 << i ) )
4116 mRelayoutData->minimumSize[ i ] = size;
4123 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4125 if ( mRelayoutData )
4127 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4129 if( dimension & ( 1 << i ) )
4131 return mRelayoutData->minimumSize[ i ];
4136 return 0.0f; // Default
4139 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4141 EnsureRelayoutData();
4143 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4145 if( dimension & ( 1 << i ) )
4147 mRelayoutData->maximumSize[ i ] = size;
4154 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4156 if ( mRelayoutData )
4158 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4160 if( dimension & ( 1 << i ) )
4162 return mRelayoutData->maximumSize[ i ];
4167 return FLT_MAX; // Default
4170 } // namespace Internal