2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/event/actors/actor-impl.h>
28 #include <dali/public-api/common/dali-common.h>
29 #include <dali/public-api/common/constants.h>
30 #include <dali/public-api/math/vector2.h>
31 #include <dali/public-api/math/vector3.h>
32 #include <dali/public-api/math/radian.h>
33 #include <dali/public-api/object/type-registry.h>
34 #include <dali/devel-api/scripting/scripting.h>
36 #include <dali/internal/common/internal-constants.h>
37 #include <dali/internal/event/common/event-thread-services.h>
38 #include <dali/internal/event/render-tasks/render-task-impl.h>
39 #include <dali/internal/event/actors/camera-actor-impl.h>
40 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
41 #include <dali/internal/event/common/property-helper.h>
42 #include <dali/internal/event/common/stage-impl.h>
43 #include <dali/internal/event/common/type-info-impl.h>
44 #include <dali/internal/event/actor-attachments/actor-attachment-impl.h>
45 #include <dali/internal/event/animation/constraint-impl.h>
46 #include <dali/internal/event/common/projection.h>
47 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
48 #include <dali/internal/update/common/animatable-property.h>
49 #include <dali/internal/update/nodes/node-messages.h>
50 #include <dali/internal/update/nodes/node-declarations.h>
51 #include <dali/internal/update/animation/scene-graph-constraint.h>
52 #include <dali/internal/event/events/actor-gesture-data.h>
53 #include <dali/internal/common/message.h>
54 #include <dali/integration-api/debug.h>
56 using Dali::Internal::SceneGraph::Node;
57 using Dali::Internal::SceneGraph::AnimatableProperty;
58 using Dali::Internal::SceneGraph::PropertyBase;
62 namespace ResizePolicy
67 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )
68 DALI_ENUM_TO_STRING( FIXED )
69 DALI_ENUM_TO_STRING( USE_NATURAL_SIZE )
70 DALI_ENUM_TO_STRING( FILL_TO_PARENT )
71 DALI_ENUM_TO_STRING( SIZE_RELATIVE_TO_PARENT )
72 DALI_ENUM_TO_STRING( SIZE_FIXED_OFFSET_FROM_PARENT )
73 DALI_ENUM_TO_STRING( FIT_TO_CHILDREN )
74 DALI_ENUM_TO_STRING( DIMENSION_DEPENDENCY )
75 DALI_ENUM_TO_STRING( USE_ASSIGNED_SIZE )
76 DALI_ENUM_TO_STRING_TABLE_END( Type )
78 } // unnamed namespace
81 namespace SizeScalePolicy
85 // Enumeration to / from string conversion tables
86 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )
87 DALI_ENUM_TO_STRING( USE_SIZE_SET )
88 DALI_ENUM_TO_STRING( FIT_WITH_ASPECT_RATIO )
89 DALI_ENUM_TO_STRING( FILL_WITH_ASPECT_RATIO )
90 DALI_ENUM_TO_STRING_TABLE_END( Type )
91 } // unnamed namespace
97 unsigned int Actor::mActorCounter = 0;
101 /// Using a function because of library initialisation order. Vector3::ONE may not have been initialised yet.
102 inline const Vector3& GetDefaultSizeModeFactor()
107 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
108 inline const Vector2& GetDefaultPreferredSize()
110 return Vector2::ZERO;
113 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
114 inline const Vector2& GetDefaultDimensionPadding()
116 return Vector2::ZERO;
119 const SizeScalePolicy::Type DEFAULT_SIZE_SCALE_POLICY = SizeScalePolicy::USE_SIZE_SET;
121 } // unnamed namespace
124 * Struct to collect relayout variables
126 struct Actor::RelayoutData
129 : sizeModeFactor( GetDefaultSizeModeFactor() ), preferredSize( GetDefaultPreferredSize() ), sizeSetPolicy( DEFAULT_SIZE_SCALE_POLICY ), relayoutEnabled( false ), insideRelayout( false )
131 // Set size negotiation defaults
132 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
134 resizePolicies[ i ] = ResizePolicy::DEFAULT;
135 negotiatedDimensions[ i ] = 0.0f;
136 dimensionNegotiated[ i ] = false;
137 dimensionDirty[ i ] = false;
138 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
139 dimensionPadding[ i ] = GetDefaultDimensionPadding();
140 minimumSize[ i ] = 0.0f;
141 maximumSize[ i ] = FLT_MAX;
145 ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies
147 Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies
149 Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
151 float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
153 float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be
154 float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be
156 bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated
157 bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
159 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
161 Vector2 preferredSize; ///< The preferred size of the actor
163 SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
165 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
166 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
169 namespace // unnamed namespace
175 * We want to discourage the use of property strings (minimize string comparisons),
176 * particularly for the default properties.
177 * Name Type writable animatable constraint-input enum for index-checking
179 DALI_PROPERTY_TABLE_BEGIN
180 DALI_PROPERTY( "parent-origin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
181 DALI_PROPERTY( "parent-origin-x", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
182 DALI_PROPERTY( "parent-origin-y", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
183 DALI_PROPERTY( "parent-origin-z", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
184 DALI_PROPERTY( "anchor-point", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
185 DALI_PROPERTY( "anchor-point-x", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
186 DALI_PROPERTY( "anchor-point-y", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
187 DALI_PROPERTY( "anchor-point-z", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
188 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
189 DALI_PROPERTY( "size-width", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
190 DALI_PROPERTY( "size-height", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
191 DALI_PROPERTY( "size-depth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
192 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
193 DALI_PROPERTY( "position-x", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
194 DALI_PROPERTY( "position-y", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
195 DALI_PROPERTY( "position-z", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
196 DALI_PROPERTY( "world-position", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
197 DALI_PROPERTY( "world-position-x", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
198 DALI_PROPERTY( "world-position-y", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
199 DALI_PROPERTY( "world-position-z", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
200 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
201 DALI_PROPERTY( "world-orientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
202 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
203 DALI_PROPERTY( "scale-x", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
204 DALI_PROPERTY( "scale-y", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
205 DALI_PROPERTY( "scale-z", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
206 DALI_PROPERTY( "world-scale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
207 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
208 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
209 DALI_PROPERTY( "color-red", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
210 DALI_PROPERTY( "color-green", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
211 DALI_PROPERTY( "color-blue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
212 DALI_PROPERTY( "color-alpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
213 DALI_PROPERTY( "world-color", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
214 DALI_PROPERTY( "world-matrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
215 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
216 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
217 DALI_PROPERTY( "leave-required", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
218 DALI_PROPERTY( "inherit-orientation",BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
219 DALI_PROPERTY( "inherit-scale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
220 DALI_PROPERTY( "color-mode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
221 DALI_PROPERTY( "position-inheritance",STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE )
222 DALI_PROPERTY( "draw-mode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
223 DALI_PROPERTY( "size-mode-factor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
224 DALI_PROPERTY( "width-resize-policy",STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
225 DALI_PROPERTY( "height-resize-policy",STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
226 DALI_PROPERTY( "size-scale-policy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
227 DALI_PROPERTY( "width-for-height", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
228 DALI_PROPERTY( "height-for-width", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
229 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
230 DALI_PROPERTY( "minimum-size", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
231 DALI_PROPERTY( "maximum-size", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
232 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
236 const char* const SIGNAL_TOUCHED = "touched";
237 const char* const SIGNAL_HOVERED = "hovered";
238 const char* const SIGNAL_WHEEL_EVENT = "wheel-event";
239 const char* const SIGNAL_ON_STAGE = "on-stage";
240 const char* const SIGNAL_OFF_STAGE = "off-stage";
244 const char* const ACTION_SHOW = "show";
245 const char* const ACTION_HIDE = "hide";
247 BaseHandle CreateActor()
249 return Dali::Actor::New();
252 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
254 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
255 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
256 SignalConnectorType signalConnector3( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
257 SignalConnectorType signalConnector4( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
259 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
260 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
263 * @brief Extract a given dimension from a Vector2
265 * @param[in] values The values to extract from
266 * @param[in] dimension The dimension to extract
267 * @return Return the value for the dimension
269 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
273 case Dimension::WIDTH:
277 case Dimension::HEIGHT:
279 return values.height;
290 * @brief Extract a given dimension from a Vector3
292 * @param[in] values The values to extract from
293 * @param[in] dimension The dimension to extract
294 * @return Return the value for the dimension
296 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
298 return GetDimensionValue( values.GetVectorXY(), dimension );
302 } // unnamed namespace
304 ActorPtr Actor::New()
306 ActorPtr actor( new Actor( BASIC ) );
308 // Second-phase construction
314 const std::string& Actor::GetName() const
319 void Actor::SetName( const std::string& name )
325 // ATTENTION: string for debug purposes is not thread safe.
326 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
330 unsigned int Actor::GetId() const
335 void Actor::Attach( ActorAttachment& attachment )
337 DALI_ASSERT_DEBUG( !mAttachment && "An Actor can only have one attachment" );
341 attachment.Connect();
344 mAttachment = ActorAttachmentPtr( &attachment );
347 ActorAttachmentPtr Actor::GetAttachment()
352 bool Actor::OnStage() const
357 Dali::Layer Actor::GetLayer()
361 // Short-circuit for Layer derived actors
364 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
367 // Find the immediate Layer parent
368 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
370 if( parent->IsLayer() )
372 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
379 void Actor::Add( Actor& child )
381 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
382 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
386 mChildren = new ActorContainer;
389 Actor* const oldParent( child.mParent );
391 // child might already be ours
392 if( this != oldParent )
394 // if we already have parent, unparent us first
397 oldParent->Remove( child ); // This causes OnChildRemove callback
399 // Old parent may need to readjust to missing child
400 if( oldParent->RelayoutDependentOnChildren() )
402 oldParent->RelayoutRequest();
406 // Guard against Add() during previous OnChildRemove callback
409 // Do this first, since user callbacks from within SetParent() may need to remove child
410 mChildren->push_back( ActorPtr( &child ) );
412 // SetParent asserts that child can be added
413 child.SetParent( this );
415 // Notification for derived classes
418 // Only put in a relayout request if there is a suitable dependency
419 if( RelayoutDependentOnChildren() )
427 void Actor::Remove( Actor& child )
429 if( (this == &child) || (!mChildren) )
431 // no children or removing itself
437 // Find the child in mChildren, and unparent it
438 ActorIter end = mChildren->end();
439 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
441 ActorPtr actor = (*iter);
443 if( actor.Get() == &child )
445 // Keep handle for OnChildRemove notification
448 // Do this first, since user callbacks from within SetParent() may need to add the child
449 mChildren->erase( iter );
451 DALI_ASSERT_DEBUG( actor->GetParent() == this );
452 actor->SetParent( NULL );
460 // Notification for derived classes
461 OnChildRemove( *(removed.Get()) );
463 // Only put in a relayout request if there is a suitable dependency
464 if( RelayoutDependentOnChildren() )
471 void Actor::Unparent()
475 // Remove this actor from the parent. The remove will put a relayout request in for
476 // the parent if required
477 mParent->Remove( *this );
478 // mParent is now NULL!
482 unsigned int Actor::GetChildCount() const
484 return ( NULL != mChildren ) ? mChildren->size() : 0;
487 ActorPtr Actor::GetChildAt( unsigned int index ) const
489 DALI_ASSERT_ALWAYS( index < GetChildCount() );
491 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
494 ActorPtr Actor::FindChildByName( const std::string& actorName )
497 if( actorName == mName )
503 ActorIter end = mChildren->end();
504 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
506 child = (*iter)->FindChildByName( actorName );
517 ActorPtr Actor::FindChildById( const unsigned int id )
526 ActorIter end = mChildren->end();
527 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
529 child = (*iter)->FindChildById( id );
540 void Actor::SetParentOrigin( const Vector3& origin )
544 // mNode is being used in a separate thread; queue a message to set the value & base value
545 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
548 // Cache for event-thread access
551 // not allocated, check if different from default
552 if( ParentOrigin::DEFAULT != origin )
554 mParentOrigin = new Vector3( origin );
559 // check if different from current costs more than just set
560 *mParentOrigin = origin;
564 void Actor::SetParentOriginX( float x )
566 const Vector3& current = GetCurrentParentOrigin();
568 SetParentOrigin( Vector3( x, current.y, current.z ) );
571 void Actor::SetParentOriginY( float y )
573 const Vector3& current = GetCurrentParentOrigin();
575 SetParentOrigin( Vector3( current.x, y, current.z ) );
578 void Actor::SetParentOriginZ( float z )
580 const Vector3& current = GetCurrentParentOrigin();
582 SetParentOrigin( Vector3( current.x, current.y, z ) );
585 const Vector3& Actor::GetCurrentParentOrigin() const
587 // Cached for event-thread access
588 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
591 void Actor::SetAnchorPoint( const Vector3& anchor )
595 // mNode is being used in a separate thread; queue a message to set the value & base value
596 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
599 // Cache for event-thread access
602 // not allocated, check if different from default
603 if( AnchorPoint::DEFAULT != anchor )
605 mAnchorPoint = new Vector3( anchor );
610 // check if different from current costs more than just set
611 *mAnchorPoint = anchor;
615 void Actor::SetAnchorPointX( float x )
617 const Vector3& current = GetCurrentAnchorPoint();
619 SetAnchorPoint( Vector3( x, current.y, current.z ) );
622 void Actor::SetAnchorPointY( float y )
624 const Vector3& current = GetCurrentAnchorPoint();
626 SetAnchorPoint( Vector3( current.x, y, current.z ) );
629 void Actor::SetAnchorPointZ( float z )
631 const Vector3& current = GetCurrentAnchorPoint();
633 SetAnchorPoint( Vector3( current.x, current.y, z ) );
636 const Vector3& Actor::GetCurrentAnchorPoint() const
638 // Cached for event-thread access
639 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
642 void Actor::SetPosition( float x, float y )
644 SetPosition( Vector3( x, y, 0.0f ) );
647 void Actor::SetPosition( float x, float y, float z )
649 SetPosition( Vector3( x, y, z ) );
652 void Actor::SetPosition( const Vector3& position )
654 mTargetPosition = position;
658 // mNode is being used in a separate thread; queue a message to set the value & base value
659 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::Bake, position );
663 void Actor::SetX( float x )
665 mTargetPosition.x = x;
669 // mNode is being used in a separate thread; queue a message to set the value & base value
670 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeX, x );
674 void Actor::SetY( float y )
676 mTargetPosition.y = y;
680 // mNode is being used in a separate thread; queue a message to set the value & base value
681 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeY, y );
685 void Actor::SetZ( float z )
687 mTargetPosition.z = z;
691 // mNode is being used in a separate thread; queue a message to set the value & base value
692 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeZ, z );
696 void Actor::TranslateBy( const Vector3& distance )
698 mTargetPosition += distance;
702 // mNode is being used in a separate thread; queue a message to set the value & base value
703 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeRelative, distance );
707 const Vector3& Actor::GetCurrentPosition() const
711 // mNode is being used in a separate thread; copy the value from the previous update
712 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
715 return Vector3::ZERO;
718 const Vector3& Actor::GetTargetPosition() const
720 return mTargetPosition;
723 const Vector3& Actor::GetCurrentWorldPosition() const
727 // mNode is being used in a separate thread; copy the value from the previous update
728 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
731 return Vector3::ZERO;
734 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
736 // this flag is not animatable so keep the value
737 mPositionInheritanceMode = mode;
740 // mNode is being used in a separate thread; queue a message to set the value
741 SetPositionInheritanceModeMessage( GetEventThreadServices(), *mNode, mode );
745 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
747 // Cached for event-thread access
748 return mPositionInheritanceMode;
751 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
753 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
754 normalizedAxis.Normalize();
756 Quaternion orientation( angle, normalizedAxis );
758 SetOrientation( orientation );
761 void Actor::SetOrientation( const Quaternion& orientation )
765 // mNode is being used in a separate thread; queue a message to set the value & base value
766 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::Bake, orientation );
770 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
774 // mNode is being used in a separate thread; queue a message to set the value & base value
775 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, Quaternion(angle, axis) );
779 void Actor::RotateBy( const Quaternion& relativeRotation )
783 // mNode is being used in a separate thread; queue a message to set the value & base value
784 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, relativeRotation );
788 const Quaternion& Actor::GetCurrentOrientation() const
792 // mNode is being used in a separate thread; copy the value from the previous update
793 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
796 return Quaternion::IDENTITY;
799 const Quaternion& Actor::GetCurrentWorldOrientation() const
803 // mNode is being used in a separate thread; copy the value from the previous update
804 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
807 return Quaternion::IDENTITY;
810 void Actor::SetScale( float scale )
812 SetScale( Vector3( scale, scale, scale ) );
815 void Actor::SetScale( float x, float y, float z )
817 SetScale( Vector3( x, y, z ) );
820 void Actor::SetScale( const Vector3& scale )
824 // mNode is being used in a separate thread; queue a message to set the value & base value
825 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::Bake, scale );
829 void Actor::SetScaleX( float x )
833 // mNode is being used in a separate thread; queue a message to set the value & base value
834 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeX, x );
838 void Actor::SetScaleY( float y )
842 // mNode is being used in a separate thread; queue a message to set the value & base value
843 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeY, y );
847 void Actor::SetScaleZ( float z )
851 // mNode is being used in a separate thread; queue a message to set the value & base value
852 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeZ, z );
856 void Actor::ScaleBy(const Vector3& relativeScale)
860 // mNode is being used in a separate thread; queue a message to set the value & base value
861 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeRelativeMultiply, relativeScale );
865 const Vector3& Actor::GetCurrentScale() const
869 // mNode is being used in a separate thread; copy the value from the previous update
870 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
876 const Vector3& Actor::GetCurrentWorldScale() const
880 // mNode is being used in a separate thread; copy the value from the previous update
881 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
887 void Actor::SetInheritScale( bool inherit )
889 // non animateable so keep local copy
890 mInheritScale = inherit;
893 // mNode is being used in a separate thread; queue a message to set the value
894 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
898 bool Actor::IsScaleInherited() const
900 return mInheritScale;
903 Matrix Actor::GetCurrentWorldMatrix() const
907 // World matrix is no longer updated unless there is something observing the node.
908 // Need to calculate it from node's world position, orientation and scale:
909 BufferIndex updateBufferIndex = GetEventThreadServices().GetEventBufferIndex();
910 Matrix worldMatrix(false);
911 worldMatrix.SetTransformComponents( mNode->GetWorldScale( updateBufferIndex ),
912 mNode->GetWorldOrientation( updateBufferIndex ),
913 mNode->GetWorldPosition( updateBufferIndex ) );
917 return Matrix::IDENTITY;
920 void Actor::SetVisible( bool visible )
924 // mNode is being used in a separate thread; queue a message to set the value & base value
925 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
929 bool Actor::IsVisible() const
933 // mNode is being used in a separate thread; copy the value from the previous update
934 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
940 void Actor::SetOpacity( float opacity )
944 // mNode is being used in a separate thread; queue a message to set the value & base value
945 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
949 float Actor::GetCurrentOpacity() const
953 // mNode is being used in a separate thread; copy the value from the previous update
954 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
960 const Vector4& Actor::GetCurrentWorldColor() const
964 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
970 void Actor::SetColor( const Vector4& color )
974 // mNode is being used in a separate thread; queue a message to set the value & base value
975 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
979 void Actor::SetColorRed( float red )
983 // mNode is being used in a separate thread; queue a message to set the value & base value
984 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
988 void Actor::SetColorGreen( float green )
992 // mNode is being used in a separate thread; queue a message to set the value & base value
993 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
997 void Actor::SetColorBlue( float blue )
1001 // mNode is being used in a separate thread; queue a message to set the value & base value
1002 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1006 const Vector4& Actor::GetCurrentColor() const
1010 // mNode is being used in a separate thread; copy the value from the previous update
1011 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1014 return Color::WHITE;
1017 void Actor::SetInheritOrientation( bool inherit )
1019 // non animateable so keep local copy
1020 mInheritOrientation = inherit;
1023 // mNode is being used in a separate thread; queue a message to set the value
1024 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1028 bool Actor::IsOrientationInherited() const
1030 return mInheritOrientation;
1033 void Actor::SetSizeModeFactor( const Vector3& factor )
1035 EnsureRelayoutData();
1037 mRelayoutData->sizeModeFactor = factor;
1040 const Vector3& Actor::GetSizeModeFactor() const
1042 if ( mRelayoutData )
1044 return mRelayoutData->sizeModeFactor;
1047 return GetDefaultSizeModeFactor();
1050 void Actor::SetColorMode( ColorMode colorMode )
1052 // non animateable so keep local copy
1053 mColorMode = colorMode;
1056 // mNode is being used in a separate thread; queue a message to set the value
1057 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1061 ColorMode Actor::GetColorMode() const
1063 // we have cached copy
1067 void Actor::SetSize( float width, float height )
1069 SetSize( Vector2( width, height ) );
1072 void Actor::SetSize( float width, float height, float depth )
1074 SetSize( Vector3( width, height, depth ) );
1077 void Actor::SetSize( const Vector2& size )
1079 SetSize( Vector3( size.width, size.height, 0.f ) );
1082 void Actor::SetSizeInternal( const Vector2& size )
1084 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1087 void Actor::SetSize( const Vector3& size )
1089 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1091 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1092 SetPreferredSize( size.GetVectorXY() );
1096 SetSizeInternal( size );
1100 void Actor::SetSizeInternal( const Vector3& size )
1102 // dont allow recursive loop
1103 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1104 // 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
1105 if( ( NULL != mNode )&&
1106 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1107 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1108 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1112 // mNode is being used in a separate thread; queue a message to set the value & base value
1113 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::Bake, mTargetSize );
1115 // Notification for derived classes
1116 mInsideOnSizeSet = true;
1117 OnSizeSet( mTargetSize );
1118 mInsideOnSizeSet = false;
1120 // Raise a relayout request if the flag is not locked
1121 if( mRelayoutData && !mRelayoutData->insideRelayout )
1128 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1130 mTargetSize = targetSize;
1132 // Notify deriving classes
1133 OnSizeAnimation( animation, mTargetSize );
1136 void Actor::NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property )
1138 if ( Dali::Actor::Property::SIZE_WIDTH == property )
1140 mTargetSize.width = targetSize;
1142 else if ( Dali::Actor::Property::SIZE_HEIGHT == property )
1144 mTargetSize.height = targetSize;
1146 // Notify deriving classes
1147 OnSizeAnimation( animation, mTargetSize );
1150 void Actor::SetWidth( float width )
1154 // mNode is being used in a separate thread; queue a message to set the value & base value
1155 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeX, width );
1159 void Actor::SetHeight( float height )
1163 // mNode is being used in a separate thread; queue a message to set the value & base value
1164 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeY, height );
1168 void Actor::SetDepth( float depth )
1172 // mNode is being used in a separate thread; queue a message to set the value & base value
1173 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeZ, depth );
1177 const Vector3& Actor::GetTargetSize() const
1182 const Vector3& Actor::GetCurrentSize() const
1186 // mNode is being used in a separate thread; copy the value from the previous update
1187 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1190 return Vector3::ZERO;
1193 Vector3 Actor::GetNaturalSize() const
1195 // It is up to deriving classes to return the appropriate natural size
1196 return Vector3( 0.0f, 0.0f, 0.0f );
1199 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1201 EnsureRelayoutData();
1203 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1205 if( dimension & ( 1 << i ) )
1207 mRelayoutData->resizePolicies[ i ] = policy;
1211 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1213 if( dimension & Dimension::WIDTH )
1215 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1218 if( dimension & Dimension::HEIGHT )
1220 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1224 // If calling SetResizePolicy, assume we want relayout enabled
1225 SetRelayoutEnabled( true );
1227 OnSetResizePolicy( policy, dimension );
1229 // Trigger relayout on this control
1233 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1235 if ( mRelayoutData )
1237 // If more than one dimension is requested, just return the first one found
1238 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1240 if( ( dimension & ( 1 << i ) ) )
1242 return mRelayoutData->resizePolicies[ i ];
1247 return ResizePolicy::DEFAULT;
1250 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1252 EnsureRelayoutData();
1254 mRelayoutData->sizeSetPolicy = policy;
1257 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1259 if ( mRelayoutData )
1261 return mRelayoutData->sizeSetPolicy;
1264 return DEFAULT_SIZE_SCALE_POLICY;
1267 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1269 EnsureRelayoutData();
1271 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1273 if( dimension & ( 1 << i ) )
1275 mRelayoutData->dimensionDependencies[ i ] = dependency;
1280 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1282 if ( mRelayoutData )
1284 // If more than one dimension is requested, just return the first one found
1285 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1287 if( ( dimension & ( 1 << i ) ) )
1289 return mRelayoutData->dimensionDependencies[ i ];
1294 return Dimension::ALL_DIMENSIONS; // Default
1297 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1299 // If relayout data has not been allocated yet and the client is requesting
1300 // to disable it, do nothing
1301 if( mRelayoutData || relayoutEnabled )
1303 EnsureRelayoutData();
1305 mRelayoutData->relayoutEnabled = relayoutEnabled;
1309 bool Actor::IsRelayoutEnabled() const
1311 // Assume that if relayout data has not been allocated yet then
1312 // relayout is disabled
1313 return mRelayoutData && mRelayoutData->relayoutEnabled;
1316 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1318 EnsureRelayoutData();
1320 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1322 if( dimension & ( 1 << i ) )
1324 mRelayoutData->dimensionDirty[ i ] = dirty;
1329 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1331 if ( mRelayoutData )
1333 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1335 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1345 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1347 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1350 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1352 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1355 unsigned int Actor::AddRenderer( Renderer& renderer )
1359 mRenderers = new RendererContainer;
1362 unsigned int index = mRenderers->size();
1363 RendererPtr rendererPtr = RendererPtr( &renderer );
1364 mRenderers->push_back( rendererPtr );
1365 AddRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1369 rendererPtr->Connect();
1375 unsigned int Actor::GetRendererCount() const
1377 unsigned int rendererCount(0);
1380 rendererCount = mRenderers->size();
1383 return rendererCount;
1386 RendererPtr Actor::GetRendererAt( unsigned int index )
1388 RendererPtr renderer;
1389 if( index < GetRendererCount() )
1391 renderer = ( *mRenderers )[ index ];
1397 void Actor::RemoveRenderer( Renderer& renderer )
1401 RendererIter end = mRenderers->end();
1402 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1404 if( (*iter).Get() == &renderer )
1406 mRenderers->erase( iter );
1407 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1414 void Actor::RemoveRenderer( unsigned int index )
1416 if( index < GetRendererCount() )
1418 RendererPtr renderer = ( *mRenderers )[ index ];
1419 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.Get()->GetRendererSceneObject() );
1420 mRenderers->erase( mRenderers->begin()+index );
1424 void Actor::SetOverlay( bool enable )
1426 // Setting STENCIL will override OVERLAY_2D
1427 if( DrawMode::STENCIL != mDrawMode )
1429 SetDrawMode( enable ? DrawMode::OVERLAY_2D : DrawMode::NORMAL );
1433 bool Actor::IsOverlay() const
1435 return ( DrawMode::OVERLAY_2D == mDrawMode );
1438 void Actor::SetDrawMode( DrawMode::Type drawMode )
1440 // this flag is not animatable so keep the value
1441 mDrawMode = drawMode;
1444 // mNode is being used in a separate thread; queue a message to set the value
1445 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1449 DrawMode::Type Actor::GetDrawMode() const
1454 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1456 // only valid when on-stage
1457 StagePtr stage = Stage::GetCurrent();
1458 if( stage && OnStage() )
1460 const RenderTaskList& taskList = stage->GetRenderTaskList();
1462 Vector2 converted( screenX, screenY );
1464 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1465 const int taskCount = taskList.GetTaskCount();
1466 for( int i = taskCount - 1; i >= 0; --i )
1468 Dali::RenderTask task = taskList.GetTask( i );
1469 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1471 // found a task where this conversion was ok so return
1479 bool Actor::ScreenToLocal( RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1481 bool retval = false;
1482 // only valid when on-stage
1485 CameraActor* camera = renderTask.GetCameraActor();
1489 renderTask.GetViewport( viewport );
1491 // need to translate coordinates to render tasks coordinate space
1492 Vector2 converted( screenX, screenY );
1493 if( renderTask.TranslateCoordinates( converted ) )
1495 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1502 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1504 // Early-out if mNode is NULL
1510 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1512 // Calculate the ModelView matrix
1513 Matrix modelView( false/*don't init*/);
1514 // need to use the components as world matrix is only updated for actors that need it
1515 modelView.SetTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1516 Matrix::Multiply( modelView, modelView, viewMatrix );
1518 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1519 Matrix invertedMvp( false/*don't init*/);
1520 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1521 bool success = invertedMvp.Invert();
1523 // Convert to GL coordinates
1524 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1529 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1536 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1542 if( XyPlaneIntersect( nearPos, farPos, local ) )
1544 Vector3 size = GetCurrentSize();
1545 localX = local.x + size.x * 0.5f;
1546 localY = local.y + size.y * 0.5f;
1557 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1560 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1562 Mathematical Formulation
1564 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1566 ( p - c ) dot ( p - c ) = r^2
1568 Given a ray with a point of origin 'o', and a direction vector 'd':
1570 ray(t) = o + td, t >= 0
1572 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1574 (o + td - c ) dot ( o + td - c ) = r^2
1576 To solve for t we first expand the above into a more recognisable quadratic equation form
1578 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1587 B = 2( o - c ) dot d
1588 C = ( o - c ) dot ( o - c ) - r^2
1590 which can be solved using a standard quadratic formula.
1592 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1594 Practical Simplification
1596 In a renderer, we often differentiate between world space and object space. In the object space
1597 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1598 into object space, the mathematical solution presented above can be simplified significantly.
1600 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1604 and we can find the t at which the (transformed) ray intersects the sphere by
1606 ( o + td ) dot ( o + td ) = r^2
1608 According to the reasoning above, we expand the above quadratic equation into the general form
1612 which now has coefficients:
1619 // Early out if mNode is NULL
1625 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1627 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1628 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1629 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1631 // Compute the radius is not needed, square radius it's enough.
1632 const Vector3& size( mNode->GetSize( bufferIndex ) );
1634 // Scale the sphere.
1635 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1637 const float width = size.width * scale.width;
1638 const float height = size.height * scale.height;
1640 float squareSphereRadius = 0.5f * ( width * width + height * height );
1642 float a = rayDir.Dot( rayDir ); // a
1643 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1644 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1646 return ( b2 * b2 - a * c ) >= 0.f;
1649 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
1656 // Transforms the ray to the local reference system.
1657 // Calculate the inverse of Model matrix
1658 Matrix invModelMatrix( false/*don't init*/);
1660 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1661 // need to use the components as world matrix is only updated for actors that need it
1662 invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1664 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1665 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1667 // Test with the actor's XY plane (Normal = 0 0 1 1).
1669 float a = -rayOriginLocal.z;
1670 float b = rayDirLocal.z;
1672 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1674 // Ray travels distance * rayDirLocal to intersect with plane.
1677 const Vector3& size = mNode->GetSize( bufferIndex );
1679 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1680 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1682 // Test with the actor's geometry.
1683 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1690 void Actor::SetLeaveRequired( bool required )
1692 mLeaveRequired = required;
1695 bool Actor::GetLeaveRequired() const
1697 return mLeaveRequired;
1700 void Actor::SetKeyboardFocusable( bool focusable )
1702 mKeyboardFocusable = focusable;
1705 bool Actor::IsKeyboardFocusable() const
1707 return mKeyboardFocusable;
1710 bool Actor::GetTouchRequired() const
1712 return !mTouchedSignal.Empty() || mDerivedRequiresTouch;
1715 bool Actor::GetHoverRequired() const
1717 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1720 bool Actor::GetWheelEventRequired() const
1722 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1725 bool Actor::IsHittable() const
1727 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1730 ActorGestureData& Actor::GetGestureData()
1732 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1733 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1734 if( NULL == mGestureData )
1736 mGestureData = new ActorGestureData;
1738 return *mGestureData;
1741 bool Actor::IsGestureRequred( Gesture::Type type ) const
1743 return mGestureData && mGestureData->IsGestureRequred( type );
1746 bool Actor::EmitTouchEventSignal( const TouchEvent& event )
1748 bool consumed = false;
1750 if( !mTouchedSignal.Empty() )
1752 Dali::Actor handle( this );
1753 consumed = mTouchedSignal.Emit( handle, event );
1758 // Notification for derived classes
1759 consumed = OnTouchEvent( event );
1765 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1767 bool consumed = false;
1769 if( !mHoveredSignal.Empty() )
1771 Dali::Actor handle( this );
1772 consumed = mHoveredSignal.Emit( handle, event );
1777 // Notification for derived classes
1778 consumed = OnHoverEvent( event );
1784 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1786 bool consumed = false;
1788 if( !mWheelEventSignal.Empty() )
1790 Dali::Actor handle( this );
1791 consumed = mWheelEventSignal.Emit( handle, event );
1796 // Notification for derived classes
1797 consumed = OnWheelEvent( event );
1803 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
1805 return mTouchedSignal;
1808 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
1810 return mHoveredSignal;
1813 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
1815 return mWheelEventSignal;
1818 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
1820 return mOnStageSignal;
1823 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
1825 return mOffStageSignal;
1828 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
1830 return mOnRelayoutSignal;
1833 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1835 bool connected( true );
1836 Actor* actor = dynamic_cast< Actor* >( object );
1838 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1840 actor->TouchedSignal().Connect( tracker, functor );
1842 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1844 actor->HoveredSignal().Connect( tracker, functor );
1846 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1848 actor->WheelEventSignal().Connect( tracker, functor );
1850 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
1852 actor->OnStageSignal().Connect( tracker, functor );
1854 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
1856 actor->OffStageSignal().Connect( tracker, functor );
1860 // signalName does not match any signal
1867 Actor::Actor( DerivedType derivedType )
1872 mParentOrigin( NULL ),
1873 mAnchorPoint( NULL ),
1874 mRelayoutData( NULL ),
1875 mGestureData( NULL ),
1877 mTargetSize( 0.0f, 0.0f, 0.0f ),
1879 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
1881 mIsRoot( ROOT_LAYER == derivedType ),
1882 mIsRenderable( RENDERABLE == derivedType ),
1883 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
1884 mIsOnStage( false ),
1886 mLeaveRequired( false ),
1887 mKeyboardFocusable( false ),
1888 mDerivedRequiresTouch( false ),
1889 mDerivedRequiresHover( false ),
1890 mDerivedRequiresWheelEvent( false ),
1891 mOnStageSignalled( false ),
1892 mInsideOnSizeSet( false ),
1893 mInheritOrientation( true ),
1894 mInheritScale( true ),
1895 mDrawMode( DrawMode::NORMAL ),
1896 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
1897 mColorMode( Node::DEFAULT_COLOR_MODE )
1901 void Actor::Initialize()
1904 SceneGraph::Node* node = CreateNode();
1906 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
1907 mNode = node; // Keep raw-pointer to Node
1911 GetEventThreadServices().RegisterObject( this );
1916 // Remove mParent pointers from children even if we're destroying core,
1917 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1920 ActorConstIter endIter = mChildren->end();
1921 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1923 (*iter)->SetParent( NULL );
1929 // Guard to allow handle destruction after Core has been destroyed
1930 if( EventThreadServices::IsCoreRunning() )
1934 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
1935 mNode = NULL; // Node is about to be destroyed
1938 GetEventThreadServices().UnregisterObject( this );
1941 // Cleanup optional gesture data
1942 delete mGestureData;
1944 // Cleanup optional parent origin and anchor
1945 delete mParentOrigin;
1946 delete mAnchorPoint;
1948 // Delete optional relayout data
1951 delete mRelayoutData;
1955 void Actor::ConnectToStage( unsigned int parentDepth )
1957 // This container is used instead of walking the Actor hierarchy.
1958 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
1959 ActorContainer connectionList;
1961 // This stage is atomic i.e. not interrupted by user callbacks.
1962 RecursiveConnectToStage( connectionList, parentDepth + 1 );
1964 // Notify applications about the newly connected actors.
1965 const ActorIter endIter = connectionList.end();
1966 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
1968 (*iter)->NotifyStageConnection();
1974 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth )
1976 DALI_ASSERT_ALWAYS( !OnStage() );
1981 ConnectToSceneGraph();
1983 // Notification for internal derived classes
1984 OnStageConnectionInternal();
1986 // This stage is atomic; avoid emitting callbacks until all Actors are connected
1987 connectionList.push_back( ActorPtr( this ) );
1989 // Recursively connect children
1992 ActorConstIter endIter = mChildren->end();
1993 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1995 (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
2001 * This method is called when the Actor is connected to the Stage.
2002 * The parent must have added its Node to the scene-graph.
2003 * The child must connect its Node to the parent's Node.
2004 * This is recursive; the child calls ConnectToStage() for its children.
2006 void Actor::ConnectToSceneGraph()
2008 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2012 // Reparent Node in next Update
2013 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode );
2016 // Notify attachment
2019 mAttachment->Connect();
2022 unsigned int rendererCount( GetRendererCount() );
2023 for( unsigned int i(0); i<rendererCount; ++i )
2025 GetRendererAt(i)->Connect();
2028 // Request relayout on all actors that are added to the scenegraph
2031 // Notification for Object::Observers
2035 void Actor::NotifyStageConnection()
2037 // Actors can be removed (in a callback), before the on-stage stage is reported.
2038 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2039 if( OnStage() && !mOnStageSignalled )
2041 // Notification for external (CustomActor) derived classes
2042 OnStageConnectionExternal( mDepth );
2044 if( !mOnStageSignal.Empty() )
2046 Dali::Actor handle( this );
2047 mOnStageSignal.Emit( handle );
2050 // Guard against Remove during callbacks
2053 mOnStageSignalled = true; // signal required next time Actor is removed
2058 void Actor::DisconnectFromStage()
2060 // This container is used instead of walking the Actor hierachy.
2061 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2062 ActorContainer disconnectionList;
2064 // This stage is atomic i.e. not interrupted by user callbacks
2065 RecursiveDisconnectFromStage( disconnectionList );
2067 // Notify applications about the newly disconnected actors.
2068 const ActorIter endIter = disconnectionList.end();
2069 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2071 (*iter)->NotifyStageDisconnection();
2075 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2077 DALI_ASSERT_ALWAYS( OnStage() );
2079 // Recursively disconnect children
2082 ActorConstIter endIter = mChildren->end();
2083 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2085 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2089 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2090 disconnectionList.push_back( ActorPtr( this ) );
2092 // Notification for internal derived classes
2093 OnStageDisconnectionInternal();
2095 DisconnectFromSceneGraph();
2101 * This method is called by an actor or its parent, before a node removal message is sent.
2102 * This is recursive; the child calls DisconnectFromStage() for its children.
2104 void Actor::DisconnectFromSceneGraph()
2106 // Notification for Object::Observers
2107 OnSceneObjectRemove();
2109 // Notify attachment
2112 mAttachment->Disconnect();
2115 unsigned int rendererCount( GetRendererCount() );
2116 for( unsigned int i(0); i<rendererCount; ++i )
2118 GetRendererAt(i)->Disconnect();
2122 void Actor::NotifyStageDisconnection()
2124 // Actors can be added (in a callback), before the off-stage state is reported.
2125 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2126 // only do this step if there is a stage, i.e. Core is not being shut down
2127 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2129 // Notification for external (CustomeActor) derived classes
2130 OnStageDisconnectionExternal();
2132 if( !mOffStageSignal.Empty() )
2134 Dali::Actor handle( this );
2135 mOffStageSignal.Emit( handle );
2138 // Guard against Add during callbacks
2141 mOnStageSignalled = false; // signal required next time Actor is added
2146 bool Actor::IsNodeConnected() const
2148 bool connected( false );
2150 if( OnStage() && ( NULL != mNode ) )
2152 if( IsRoot() || mNode->GetParent() )
2161 unsigned int Actor::GetDefaultPropertyCount() const
2163 return DEFAULT_PROPERTY_COUNT;
2166 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2168 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2170 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2172 indices.PushBack( i );
2176 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2178 if( index < DEFAULT_PROPERTY_COUNT )
2180 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2186 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2188 Property::Index index = Property::INVALID_INDEX;
2190 // Look for name in default properties
2191 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2193 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2194 if( 0 == name.compare( property->name ) )
2204 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2206 if( index < DEFAULT_PROPERTY_COUNT )
2208 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2214 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2216 if( index < DEFAULT_PROPERTY_COUNT )
2218 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2224 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2226 if( index < DEFAULT_PROPERTY_COUNT )
2228 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2234 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2236 if( index < DEFAULT_PROPERTY_COUNT )
2238 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2241 // index out of range...return Property::NONE
2242 return Property::NONE;
2245 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2249 case Dali::Actor::Property::PARENT_ORIGIN:
2251 SetParentOrigin( property.Get< Vector3 >() );
2255 case Dali::Actor::Property::PARENT_ORIGIN_X:
2257 SetParentOriginX( property.Get< float >() );
2261 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2263 SetParentOriginY( property.Get< float >() );
2267 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2269 SetParentOriginZ( property.Get< float >() );
2273 case Dali::Actor::Property::ANCHOR_POINT:
2275 SetAnchorPoint( property.Get< Vector3 >() );
2279 case Dali::Actor::Property::ANCHOR_POINT_X:
2281 SetAnchorPointX( property.Get< float >() );
2285 case Dali::Actor::Property::ANCHOR_POINT_Y:
2287 SetAnchorPointY( property.Get< float >() );
2291 case Dali::Actor::Property::ANCHOR_POINT_Z:
2293 SetAnchorPointZ( property.Get< float >() );
2297 case Dali::Actor::Property::SIZE:
2299 SetSize( property.Get< Vector3 >() );
2303 case Dali::Actor::Property::SIZE_WIDTH:
2305 SetWidth( property.Get< float >() );
2309 case Dali::Actor::Property::SIZE_HEIGHT:
2311 SetHeight( property.Get< float >() );
2315 case Dali::Actor::Property::SIZE_DEPTH:
2317 SetDepth( property.Get< float >() );
2321 case Dali::Actor::Property::POSITION:
2323 SetPosition( property.Get< Vector3 >() );
2327 case Dali::Actor::Property::POSITION_X:
2329 SetX( property.Get< float >() );
2333 case Dali::Actor::Property::POSITION_Y:
2335 SetY( property.Get< float >() );
2339 case Dali::Actor::Property::POSITION_Z:
2341 SetZ( property.Get< float >() );
2345 case Dali::Actor::Property::ORIENTATION:
2347 SetOrientation( property.Get< Quaternion >() );
2351 case Dali::Actor::Property::SCALE:
2353 SetScale( property.Get< Vector3 >() );
2357 case Dali::Actor::Property::SCALE_X:
2359 SetScaleX( property.Get< float >() );
2363 case Dali::Actor::Property::SCALE_Y:
2365 SetScaleY( property.Get< float >() );
2369 case Dali::Actor::Property::SCALE_Z:
2371 SetScaleZ( property.Get< float >() );
2375 case Dali::Actor::Property::VISIBLE:
2377 SetVisible( property.Get< bool >() );
2381 case Dali::Actor::Property::COLOR:
2383 SetColor( property.Get< Vector4 >() );
2387 case Dali::Actor::Property::COLOR_RED:
2389 SetColorRed( property.Get< float >() );
2393 case Dali::Actor::Property::COLOR_GREEN:
2395 SetColorGreen( property.Get< float >() );
2399 case Dali::Actor::Property::COLOR_BLUE:
2401 SetColorBlue( property.Get< float >() );
2405 case Dali::Actor::Property::COLOR_ALPHA:
2407 SetOpacity( property.Get< float >() );
2411 case Dali::Actor::Property::NAME:
2413 SetName( property.Get< std::string >() );
2417 case Dali::Actor::Property::SENSITIVE:
2419 SetSensitive( property.Get< bool >() );
2423 case Dali::Actor::Property::LEAVE_REQUIRED:
2425 SetLeaveRequired( property.Get< bool >() );
2429 case Dali::Actor::Property::INHERIT_ORIENTATION:
2431 SetInheritOrientation( property.Get< bool >() );
2435 case Dali::Actor::Property::INHERIT_SCALE:
2437 SetInheritScale( property.Get< bool >() );
2441 case Dali::Actor::Property::COLOR_MODE:
2443 SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2447 case Dali::Actor::Property::POSITION_INHERITANCE:
2449 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2453 case Dali::Actor::Property::DRAW_MODE:
2455 SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2459 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2461 SetSizeModeFactor( property.Get< Vector3 >() );
2465 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2467 ResizePolicy::Type type;
2468 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2470 SetResizePolicy( type, Dimension::WIDTH );
2475 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2477 ResizePolicy::Type type;
2478 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2480 SetResizePolicy( type, Dimension::HEIGHT );
2485 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2487 SizeScalePolicy::Type type;
2488 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount, type ) )
2490 SetSizeScalePolicy( type );
2495 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2497 if( property.Get< bool >() )
2499 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2504 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2506 if( property.Get< bool >() )
2508 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2513 case Dali::Actor::Property::PADDING:
2515 Vector4 padding = property.Get< Vector4 >();
2516 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2517 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2521 case Dali::Actor::Property::MINIMUM_SIZE:
2523 Vector2 size = property.Get< Vector2 >();
2524 SetMinimumSize( size.x, Dimension::WIDTH );
2525 SetMinimumSize( size.y, Dimension::HEIGHT );
2529 case Dali::Actor::Property::MAXIMUM_SIZE:
2531 Vector2 size = property.Get< Vector2 >();
2532 SetMaximumSize( size.x, Dimension::WIDTH );
2533 SetMaximumSize( size.y, Dimension::HEIGHT );
2539 // this can happen in the case of a non-animatable default property so just do nothing
2545 // TODO: This method needs to be removed
2546 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2548 switch( entry.type )
2550 case Property::BOOLEAN:
2552 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2553 DALI_ASSERT_DEBUG( NULL != property );
2555 // property is being used in a separate thread; queue a message to set the property
2556 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2561 case Property::INTEGER:
2563 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2564 DALI_ASSERT_DEBUG( NULL != property );
2566 // property is being used in a separate thread; queue a message to set the property
2567 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2572 case Property::FLOAT:
2574 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2575 DALI_ASSERT_DEBUG( NULL != property );
2577 // property is being used in a separate thread; queue a message to set the property
2578 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2583 case Property::VECTOR2:
2585 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2586 DALI_ASSERT_DEBUG( NULL != property );
2588 // property is being used in a separate thread; queue a message to set the property
2589 if(entry.componentIndex == 0)
2591 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2593 else if(entry.componentIndex == 1)
2595 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2599 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2605 case Property::VECTOR3:
2607 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2608 DALI_ASSERT_DEBUG( NULL != property );
2610 // property is being used in a separate thread; queue a message to set the property
2611 if(entry.componentIndex == 0)
2613 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2615 else if(entry.componentIndex == 1)
2617 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2619 else if(entry.componentIndex == 2)
2621 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2625 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2631 case Property::VECTOR4:
2633 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2634 DALI_ASSERT_DEBUG( NULL != property );
2636 // property is being used in a separate thread; queue a message to set the property
2637 if(entry.componentIndex == 0)
2639 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
2641 else if(entry.componentIndex == 1)
2643 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
2645 else if(entry.componentIndex == 2)
2647 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
2649 else if(entry.componentIndex == 3)
2651 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
2655 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2661 case Property::ROTATION:
2663 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
2664 DALI_ASSERT_DEBUG( NULL != property );
2666 // property is being used in a separate thread; queue a message to set the property
2667 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
2672 case Property::MATRIX:
2674 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
2675 DALI_ASSERT_DEBUG( NULL != property );
2677 // property is being used in a separate thread; queue a message to set the property
2678 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
2683 case Property::MATRIX3:
2685 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
2686 DALI_ASSERT_DEBUG( NULL != property );
2688 // property is being used in a separate thread; queue a message to set the property
2689 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
2696 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
2702 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
2704 Property::Value value;
2708 case Dali::Actor::Property::PARENT_ORIGIN:
2710 value = GetCurrentParentOrigin();
2714 case Dali::Actor::Property::PARENT_ORIGIN_X:
2716 value = GetCurrentParentOrigin().x;
2720 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2722 value = GetCurrentParentOrigin().y;
2726 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2728 value = GetCurrentParentOrigin().z;
2732 case Dali::Actor::Property::ANCHOR_POINT:
2734 value = GetCurrentAnchorPoint();
2738 case Dali::Actor::Property::ANCHOR_POINT_X:
2740 value = GetCurrentAnchorPoint().x;
2744 case Dali::Actor::Property::ANCHOR_POINT_Y:
2746 value = GetCurrentAnchorPoint().y;
2750 case Dali::Actor::Property::ANCHOR_POINT_Z:
2752 value = GetCurrentAnchorPoint().z;
2756 case Dali::Actor::Property::SIZE:
2758 value = GetCurrentSize();
2762 case Dali::Actor::Property::SIZE_WIDTH:
2764 value = GetCurrentSize().width;
2768 case Dali::Actor::Property::SIZE_HEIGHT:
2770 value = GetCurrentSize().height;
2774 case Dali::Actor::Property::SIZE_DEPTH:
2776 value = GetCurrentSize().depth;
2780 case Dali::Actor::Property::POSITION:
2782 value = GetCurrentPosition();
2786 case Dali::Actor::Property::POSITION_X:
2788 value = GetCurrentPosition().x;
2792 case Dali::Actor::Property::POSITION_Y:
2794 value = GetCurrentPosition().y;
2798 case Dali::Actor::Property::POSITION_Z:
2800 value = GetCurrentPosition().z;
2804 case Dali::Actor::Property::WORLD_POSITION:
2806 value = GetCurrentWorldPosition();
2810 case Dali::Actor::Property::WORLD_POSITION_X:
2812 value = GetCurrentWorldPosition().x;
2816 case Dali::Actor::Property::WORLD_POSITION_Y:
2818 value = GetCurrentWorldPosition().y;
2822 case Dali::Actor::Property::WORLD_POSITION_Z:
2824 value = GetCurrentWorldPosition().z;
2828 case Dali::Actor::Property::ORIENTATION:
2830 value = GetCurrentOrientation();
2834 case Dali::Actor::Property::WORLD_ORIENTATION:
2836 value = GetCurrentWorldOrientation();
2840 case Dali::Actor::Property::SCALE:
2842 value = GetCurrentScale();
2846 case Dali::Actor::Property::SCALE_X:
2848 value = GetCurrentScale().x;
2852 case Dali::Actor::Property::SCALE_Y:
2854 value = GetCurrentScale().y;
2858 case Dali::Actor::Property::SCALE_Z:
2860 value = GetCurrentScale().z;
2864 case Dali::Actor::Property::WORLD_SCALE:
2866 value = GetCurrentWorldScale();
2870 case Dali::Actor::Property::VISIBLE:
2872 value = IsVisible();
2876 case Dali::Actor::Property::COLOR:
2878 value = GetCurrentColor();
2882 case Dali::Actor::Property::COLOR_RED:
2884 value = GetCurrentColor().r;
2888 case Dali::Actor::Property::COLOR_GREEN:
2890 value = GetCurrentColor().g;
2894 case Dali::Actor::Property::COLOR_BLUE:
2896 value = GetCurrentColor().b;
2900 case Dali::Actor::Property::COLOR_ALPHA:
2902 value = GetCurrentColor().a;
2906 case Dali::Actor::Property::WORLD_COLOR:
2908 value = GetCurrentWorldColor();
2912 case Dali::Actor::Property::WORLD_MATRIX:
2914 value = GetCurrentWorldMatrix();
2918 case Dali::Actor::Property::NAME:
2924 case Dali::Actor::Property::SENSITIVE:
2926 value = IsSensitive();
2930 case Dali::Actor::Property::LEAVE_REQUIRED:
2932 value = GetLeaveRequired();
2936 case Dali::Actor::Property::INHERIT_ORIENTATION:
2938 value = IsOrientationInherited();
2942 case Dali::Actor::Property::INHERIT_SCALE:
2944 value = IsScaleInherited();
2948 case Dali::Actor::Property::COLOR_MODE:
2950 value = Scripting::GetColorMode( GetColorMode() );
2954 case Dali::Actor::Property::POSITION_INHERITANCE:
2956 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
2960 case Dali::Actor::Property::DRAW_MODE:
2962 value = Scripting::GetDrawMode( GetDrawMode() );
2966 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2968 value = GetSizeModeFactor();
2972 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2974 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
2978 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2980 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
2984 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2986 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
2990 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2992 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
2996 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2998 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3002 case Dali::Actor::Property::PADDING:
3004 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3005 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3006 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3010 case Dali::Actor::Property::MINIMUM_SIZE:
3012 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3016 case Dali::Actor::Property::MAXIMUM_SIZE:
3018 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3024 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3032 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3037 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3039 // This method should only return an object connected to the scene-graph
3040 return OnStage() ? mNode : NULL;
3043 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3045 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3047 const PropertyBase* property( NULL );
3049 // This method should only return a property of an object connected to the scene-graph
3055 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3057 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3058 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3060 property = animatable->GetSceneGraphProperty();
3062 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3064 CustomPropertyMetadata* custom = FindCustomProperty( index );
3065 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3067 property = custom->GetSceneGraphProperty();
3069 else if( NULL != mNode )
3073 case Dali::Actor::Property::SIZE:
3074 property = &mNode->mSize;
3077 case Dali::Actor::Property::SIZE_WIDTH:
3078 property = &mNode->mSize;
3081 case Dali::Actor::Property::SIZE_HEIGHT:
3082 property = &mNode->mSize;
3085 case Dali::Actor::Property::SIZE_DEPTH:
3086 property = &mNode->mSize;
3089 case Dali::Actor::Property::POSITION:
3090 property = &mNode->mPosition;
3093 case Dali::Actor::Property::POSITION_X:
3094 property = &mNode->mPosition;
3097 case Dali::Actor::Property::POSITION_Y:
3098 property = &mNode->mPosition;
3101 case Dali::Actor::Property::POSITION_Z:
3102 property = &mNode->mPosition;
3105 case Dali::Actor::Property::ORIENTATION:
3106 property = &mNode->mOrientation;
3109 case Dali::Actor::Property::SCALE:
3110 property = &mNode->mScale;
3113 case Dali::Actor::Property::SCALE_X:
3114 property = &mNode->mScale;
3117 case Dali::Actor::Property::SCALE_Y:
3118 property = &mNode->mScale;
3121 case Dali::Actor::Property::SCALE_Z:
3122 property = &mNode->mScale;
3125 case Dali::Actor::Property::VISIBLE:
3126 property = &mNode->mVisible;
3129 case Dali::Actor::Property::COLOR:
3130 property = &mNode->mColor;
3133 case Dali::Actor::Property::COLOR_RED:
3134 property = &mNode->mColor;
3137 case Dali::Actor::Property::COLOR_GREEN:
3138 property = &mNode->mColor;
3141 case Dali::Actor::Property::COLOR_BLUE:
3142 property = &mNode->mColor;
3145 case Dali::Actor::Property::COLOR_ALPHA:
3146 property = &mNode->mColor;
3157 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3159 const PropertyInputImpl* property( NULL );
3161 // This method should only return a property of an object connected to the scene-graph
3167 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3169 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3170 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3172 property = animatable->GetSceneGraphProperty();
3174 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3176 CustomPropertyMetadata* custom = FindCustomProperty( index );
3177 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3178 property = custom->GetSceneGraphProperty();
3180 else if( NULL != mNode )
3184 case Dali::Actor::Property::PARENT_ORIGIN:
3185 property = &mNode->mParentOrigin;
3188 case Dali::Actor::Property::PARENT_ORIGIN_X:
3189 property = &mNode->mParentOrigin;
3192 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3193 property = &mNode->mParentOrigin;
3196 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3197 property = &mNode->mParentOrigin;
3200 case Dali::Actor::Property::ANCHOR_POINT:
3201 property = &mNode->mAnchorPoint;
3204 case Dali::Actor::Property::ANCHOR_POINT_X:
3205 property = &mNode->mAnchorPoint;
3208 case Dali::Actor::Property::ANCHOR_POINT_Y:
3209 property = &mNode->mAnchorPoint;
3212 case Dali::Actor::Property::ANCHOR_POINT_Z:
3213 property = &mNode->mAnchorPoint;
3216 case Dali::Actor::Property::SIZE:
3217 property = &mNode->mSize;
3220 case Dali::Actor::Property::SIZE_WIDTH:
3221 property = &mNode->mSize;
3224 case Dali::Actor::Property::SIZE_HEIGHT:
3225 property = &mNode->mSize;
3228 case Dali::Actor::Property::SIZE_DEPTH:
3229 property = &mNode->mSize;
3232 case Dali::Actor::Property::POSITION:
3233 property = &mNode->mPosition;
3236 case Dali::Actor::Property::POSITION_X:
3237 property = &mNode->mPosition;
3240 case Dali::Actor::Property::POSITION_Y:
3241 property = &mNode->mPosition;
3244 case Dali::Actor::Property::POSITION_Z:
3245 property = &mNode->mPosition;
3248 case Dali::Actor::Property::WORLD_POSITION:
3249 property = &mNode->mWorldPosition;
3252 case Dali::Actor::Property::WORLD_POSITION_X:
3253 property = &mNode->mWorldPosition;
3256 case Dali::Actor::Property::WORLD_POSITION_Y:
3257 property = &mNode->mWorldPosition;
3260 case Dali::Actor::Property::WORLD_POSITION_Z:
3261 property = &mNode->mWorldPosition;
3264 case Dali::Actor::Property::ORIENTATION:
3265 property = &mNode->mOrientation;
3268 case Dali::Actor::Property::WORLD_ORIENTATION:
3269 property = &mNode->mWorldOrientation;
3272 case Dali::Actor::Property::SCALE:
3273 property = &mNode->mScale;
3276 case Dali::Actor::Property::SCALE_X:
3277 property = &mNode->mScale;
3280 case Dali::Actor::Property::SCALE_Y:
3281 property = &mNode->mScale;
3284 case Dali::Actor::Property::SCALE_Z:
3285 property = &mNode->mScale;
3288 case Dali::Actor::Property::WORLD_SCALE:
3289 property = &mNode->mWorldScale;
3292 case Dali::Actor::Property::VISIBLE:
3293 property = &mNode->mVisible;
3296 case Dali::Actor::Property::COLOR:
3297 property = &mNode->mColor;
3300 case Dali::Actor::Property::COLOR_RED:
3301 property = &mNode->mColor;
3304 case Dali::Actor::Property::COLOR_GREEN:
3305 property = &mNode->mColor;
3308 case Dali::Actor::Property::COLOR_BLUE:
3309 property = &mNode->mColor;
3312 case Dali::Actor::Property::COLOR_ALPHA:
3313 property = &mNode->mColor;
3316 case Dali::Actor::Property::WORLD_COLOR:
3317 property = &mNode->mWorldColor;
3320 case Dali::Actor::Property::WORLD_MATRIX:
3321 property = &mNode->mWorldMatrix;
3332 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3334 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3336 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3338 // check whether the animatable property is registered already, if not then register one.
3339 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3340 if( animatableProperty )
3342 componentIndex = animatableProperty->componentIndex;
3349 case Dali::Actor::Property::PARENT_ORIGIN_X:
3350 case Dali::Actor::Property::ANCHOR_POINT_X:
3351 case Dali::Actor::Property::SIZE_WIDTH:
3352 case Dali::Actor::Property::POSITION_X:
3353 case Dali::Actor::Property::WORLD_POSITION_X:
3354 case Dali::Actor::Property::SCALE_X:
3355 case Dali::Actor::Property::COLOR_RED:
3361 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3362 case Dali::Actor::Property::ANCHOR_POINT_Y:
3363 case Dali::Actor::Property::SIZE_HEIGHT:
3364 case Dali::Actor::Property::POSITION_Y:
3365 case Dali::Actor::Property::WORLD_POSITION_Y:
3366 case Dali::Actor::Property::SCALE_Y:
3367 case Dali::Actor::Property::COLOR_GREEN:
3373 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3374 case Dali::Actor::Property::ANCHOR_POINT_Z:
3375 case Dali::Actor::Property::SIZE_DEPTH:
3376 case Dali::Actor::Property::POSITION_Z:
3377 case Dali::Actor::Property::WORLD_POSITION_Z:
3378 case Dali::Actor::Property::SCALE_Z:
3379 case Dali::Actor::Property::COLOR_BLUE:
3385 case Dali::Actor::Property::COLOR_ALPHA:
3399 return componentIndex;
3402 void Actor::SetParent( Actor* parent )
3406 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3410 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3413 // Instruct each actor to create a corresponding node in the scene graph
3414 ConnectToStage( parent->GetHierarchyDepth() );
3417 else // parent being set to NULL
3419 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3423 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3426 DALI_ASSERT_ALWAYS( mNode != NULL );
3430 // Disconnect the Node & its children from the scene-graph.
3431 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3434 // Instruct each actor to discard pointers to the scene-graph
3435 DisconnectFromStage();
3440 SceneGraph::Node* Actor::CreateNode() const
3445 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3448 Actor* actor = dynamic_cast< Actor* >( object );
3452 if( 0 == actionName.compare( ACTION_SHOW ) )
3454 actor->SetVisible( true );
3457 else if( 0 == actionName.compare( ACTION_HIDE ) )
3459 actor->SetVisible( false );
3467 void Actor::EnsureRelayoutData()
3469 // Assign relayout data.
3470 if( !mRelayoutData )
3472 mRelayoutData = new RelayoutData();
3476 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3478 // Check if actor is dependent on parent
3479 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3481 if( ( dimension & ( 1 << i ) ) )
3483 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3484 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3494 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3496 // Check if actor is dependent on children
3497 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3499 if( ( dimension & ( 1 << i ) ) )
3501 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3502 switch( resizePolicy )
3504 case ResizePolicy::FIT_TO_CHILDREN:
3505 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3521 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3523 return Actor::RelayoutDependentOnChildren( dimension );
3526 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3528 // Check each possible dimension and see if it is dependent on the input one
3529 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3531 if( dimension & ( 1 << i ) )
3533 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3540 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3542 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3544 if( dimension & ( 1 << i ) )
3546 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3551 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3553 // If more than one dimension is requested, just return the first one found
3554 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3556 if( ( dimension & ( 1 << i ) ) )
3558 return mRelayoutData->negotiatedDimensions[ i ];
3562 return 0.0f; // Default
3565 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3567 EnsureRelayoutData();
3569 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3571 if( dimension & ( 1 << i ) )
3573 mRelayoutData->dimensionPadding[ i ] = padding;
3578 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3580 if ( mRelayoutData )
3582 // If more than one dimension is requested, just return the first one found
3583 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3585 if( ( dimension & ( 1 << i ) ) )
3587 return mRelayoutData->dimensionPadding[ i ];
3592 return GetDefaultDimensionPadding();
3595 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
3597 EnsureRelayoutData();
3599 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3601 if( dimension & ( 1 << i ) )
3603 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3608 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
3610 if ( mRelayoutData )
3612 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3614 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
3624 float Actor::GetHeightForWidthBase( float width )
3626 float height = 0.0f;
3628 const Vector3 naturalSize = GetNaturalSize();
3629 if( naturalSize.width > 0.0f )
3631 height = naturalSize.height * width / naturalSize.width;
3633 else // we treat 0 as 1:1 aspect ratio
3641 float Actor::GetWidthForHeightBase( float height )
3645 const Vector3 naturalSize = GetNaturalSize();
3646 if( naturalSize.height > 0.0f )
3648 width = naturalSize.width * height / naturalSize.height;
3650 else // we treat 0 as 1:1 aspect ratio
3658 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
3660 // Fill to parent, taking size mode factor into account
3661 switch( child.GetResizePolicy( dimension ) )
3663 case ResizePolicy::FILL_TO_PARENT:
3665 return GetLatestSize( dimension );
3668 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3670 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
3673 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3675 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
3680 return GetLatestSize( dimension );
3685 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
3687 // Can be overridden in derived class
3688 return CalculateChildSizeBase( child, dimension );
3691 float Actor::GetHeightForWidth( float width )
3693 // Can be overridden in derived class
3694 return GetHeightForWidthBase( width );
3697 float Actor::GetWidthForHeight( float height )
3699 // Can be overridden in derived class
3700 return GetWidthForHeightBase( height );
3703 float Actor::GetLatestSize( Dimension::Type dimension ) const
3705 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
3708 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
3710 Vector2 padding = GetPadding( dimension );
3712 return GetLatestSize( dimension ) + padding.x + padding.y;
3715 float Actor::NegotiateFromParent( Dimension::Type dimension )
3717 Actor* parent = GetParent();
3720 Vector2 padding( GetPadding( dimension ) );
3721 Vector2 parentPadding( parent->GetPadding( dimension ) );
3722 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
3728 float Actor::NegotiateFromChildren( Dimension::Type dimension )
3730 float maxDimensionPoint = 0.0f;
3732 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3734 ActorPtr child = GetChildAt( i );
3736 if( !child->RelayoutDependentOnParent( dimension ) )
3738 // Calculate the min and max points that the children range across
3739 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
3740 float dimensionSize = child->GetRelayoutSize( dimension );
3741 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
3745 return maxDimensionPoint;
3748 float Actor::GetSize( Dimension::Type dimension ) const
3750 return GetDimensionValue( GetTargetSize(), dimension );
3753 float Actor::GetNaturalSize( Dimension::Type dimension ) const
3755 return GetDimensionValue( GetNaturalSize(), dimension );
3758 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
3760 switch( GetResizePolicy( dimension ) )
3762 case ResizePolicy::USE_NATURAL_SIZE:
3764 return GetNaturalSize( dimension );
3767 case ResizePolicy::FIXED:
3769 return GetDimensionValue( GetPreferredSize(), dimension );
3772 case ResizePolicy::USE_ASSIGNED_SIZE:
3774 return GetDimensionValue( maximumSize, dimension );
3777 case ResizePolicy::FILL_TO_PARENT:
3778 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3779 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3781 return NegotiateFromParent( dimension );
3784 case ResizePolicy::FIT_TO_CHILDREN:
3786 return NegotiateFromChildren( dimension );
3789 case ResizePolicy::DIMENSION_DEPENDENCY:
3791 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
3794 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
3796 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
3799 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
3801 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
3813 return 0.0f; // Default
3816 float Actor::ClampDimension( float size, Dimension::Type dimension )
3818 const float minSize = GetMinimumSize( dimension );
3819 const float maxSize = GetMaximumSize( dimension );
3821 return std::max( minSize, std::min( size, maxSize ) );
3824 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
3826 // Check if it needs to be negotiated
3827 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
3829 // Check that we havn't gotten into an infinite loop
3830 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
3831 bool recursionFound = false;
3832 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
3834 if( *it == searchActor )
3836 recursionFound = true;
3841 if( !recursionFound )
3843 // Record the path that we have taken
3844 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
3846 // Dimension dependency check
3847 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3849 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
3851 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
3853 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
3857 // Parent dependency check
3858 Actor* parent = GetParent();
3859 if( parent && RelayoutDependentOnParent( dimension ) )
3861 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
3864 // Children dependency check
3865 if( RelayoutDependentOnChildren( dimension ) )
3867 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3869 ActorPtr child = GetChildAt( i );
3871 // Only relayout child first if it is not dependent on this actor
3872 if( !child->RelayoutDependentOnParent( dimension ) )
3874 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
3879 // For deriving classes
3880 OnCalculateRelayoutSize( dimension );
3882 // All dependencies checked, calculate the size and set negotiated flag
3883 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
3885 SetNegotiatedDimension( newSize, dimension );
3886 SetLayoutNegotiated( true, dimension );
3888 // For deriving classes
3889 OnLayoutNegotiated( newSize, dimension );
3891 // This actor has been successfully processed, pop it off the recursion stack
3892 recursionStack.pop_back();
3896 // TODO: Break infinite loop
3897 SetLayoutNegotiated( true, dimension );
3902 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
3904 // Negotiate all dimensions that require it
3905 ActorDimensionStack recursionStack;
3907 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3909 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
3912 NegotiateDimension( dimension, allocatedSize, recursionStack );
3916 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
3918 switch( mRelayoutData->sizeSetPolicy )
3920 case SizeScalePolicy::USE_SIZE_SET:
3925 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
3927 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
3928 const Vector3 naturalSize = GetNaturalSize();
3929 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
3931 const float sizeRatio = size.width / size.height;
3932 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
3934 if( naturalSizeRatio < sizeRatio )
3936 return Vector2( naturalSizeRatio * size.height, size.height );
3938 else if( naturalSizeRatio > sizeRatio )
3940 return Vector2( size.width, size.width / naturalSizeRatio );
3951 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
3953 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
3954 const Vector3 naturalSize = GetNaturalSize();
3955 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
3957 const float sizeRatio = size.width / size.height;
3958 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
3960 if( naturalSizeRatio < sizeRatio )
3962 return Vector2( size.width, size.width / naturalSizeRatio );
3964 else if( naturalSizeRatio > sizeRatio )
3966 return Vector2( naturalSizeRatio * size.height, size.height );
3984 void Actor::SetNegotiatedSize( RelayoutContainer& container )
3986 // Do the set actor size
3987 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
3989 // Adjust for size set policy
3990 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
3992 // Lock the flag to stop recursive relayouts on set size
3993 mRelayoutData->insideRelayout = true;
3994 SetSize( negotiatedSize );
3995 mRelayoutData->insideRelayout = false;
3997 // Clear flags for all dimensions
3998 SetLayoutDirty( false );
4000 // Give deriving classes a chance to respond
4001 OnRelayout( negotiatedSize, container );
4003 if( !mOnRelayoutSignal.Empty() )
4005 Dali::Actor handle( this );
4006 mOnRelayoutSignal.Emit( handle );
4010 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4012 // Do the negotiation
4013 NegotiateDimensions( allocatedSize );
4015 // Set the actor size
4016 SetNegotiatedSize( container );
4018 // Negotiate down to children
4019 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4021 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4023 ActorPtr child = GetChildAt( i );
4025 // Only relayout if required
4026 if( child->RelayoutRequired() )
4028 container.Add( Dali::Actor( child.Get() ), newBounds );
4033 void Actor::RelayoutRequest( Dimension::Type dimension )
4035 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4036 if( relayoutController )
4038 Dali::Actor self( this );
4039 relayoutController->RequestRelayout( self, dimension );
4043 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4047 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4051 void Actor::SetPreferredSize( const Vector2& size )
4053 EnsureRelayoutData();
4055 if( size.width > 0.0f )
4057 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4060 if( size.height > 0.0f )
4062 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4065 mRelayoutData->preferredSize = size;
4070 Vector2 Actor::GetPreferredSize() const
4072 if ( mRelayoutData )
4074 return Vector2( mRelayoutData->preferredSize );
4077 return GetDefaultPreferredSize();
4080 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4082 EnsureRelayoutData();
4084 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4086 if( dimension & ( 1 << i ) )
4088 mRelayoutData->minimumSize[ i ] = size;
4095 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4097 if ( mRelayoutData )
4099 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4101 if( dimension & ( 1 << i ) )
4103 return mRelayoutData->minimumSize[ i ];
4108 return 0.0f; // Default
4111 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4113 EnsureRelayoutData();
4115 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4117 if( dimension & ( 1 << i ) )
4119 mRelayoutData->maximumSize[ i ] = size;
4126 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4128 if ( mRelayoutData )
4130 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4132 if( dimension & ( 1 << i ) )
4134 return mRelayoutData->maximumSize[ i ];
4139 return FLT_MAX; // Default
4142 } // namespace Internal