2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/event/actors/actor-impl.h>
28 #include <dali/public-api/common/dali-common.h>
29 #include <dali/public-api/common/constants.h>
30 #include <dali/public-api/math/vector2.h>
31 #include <dali/public-api/math/vector3.h>
32 #include <dali/public-api/math/radian.h>
33 #include <dali/public-api/object/type-registry.h>
34 #include <dali/devel-api/scripting/scripting.h>
36 #include <dali/internal/common/internal-constants.h>
37 #include <dali/internal/event/common/event-thread-services.h>
38 #include <dali/internal/event/render-tasks/render-task-impl.h>
39 #include <dali/internal/event/actors/camera-actor-impl.h>
40 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
41 #include <dali/internal/event/common/property-helper.h>
42 #include <dali/internal/event/common/stage-impl.h>
43 #include <dali/internal/event/common/type-info-impl.h>
44 #include <dali/internal/event/actor-attachments/actor-attachment-impl.h>
45 #include <dali/internal/event/actor-attachments/renderer-attachment-impl.h>
46 #include <dali/internal/event/animation/constraint-impl.h>
47 #include <dali/internal/event/common/projection.h>
48 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
49 #include <dali/internal/update/common/animatable-property.h>
50 #include <dali/internal/update/nodes/node-messages.h>
51 #include <dali/internal/update/nodes/node-declarations.h>
52 #include <dali/internal/update/animation/scene-graph-constraint.h>
53 #include <dali/internal/event/events/actor-gesture-data.h>
54 #include <dali/internal/common/message.h>
55 #include <dali/integration-api/debug.h>
57 using Dali::Internal::SceneGraph::Node;
58 using Dali::Internal::SceneGraph::AnimatableProperty;
59 using Dali::Internal::SceneGraph::PropertyBase;
63 namespace ResizePolicy
68 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )
69 DALI_ENUM_TO_STRING( FIXED )
70 DALI_ENUM_TO_STRING( USE_NATURAL_SIZE )
71 DALI_ENUM_TO_STRING( FILL_TO_PARENT )
72 DALI_ENUM_TO_STRING( SIZE_RELATIVE_TO_PARENT )
73 DALI_ENUM_TO_STRING( SIZE_FIXED_OFFSET_FROM_PARENT )
74 DALI_ENUM_TO_STRING( FIT_TO_CHILDREN )
75 DALI_ENUM_TO_STRING( DIMENSION_DEPENDENCY )
76 DALI_ENUM_TO_STRING( USE_ASSIGNED_SIZE )
77 DALI_ENUM_TO_STRING_TABLE_END( Type )
79 } // unnamed namespace
82 namespace SizeScalePolicy
86 // Enumeration to / from string conversion tables
87 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )
88 DALI_ENUM_TO_STRING( USE_SIZE_SET )
89 DALI_ENUM_TO_STRING( FIT_WITH_ASPECT_RATIO )
90 DALI_ENUM_TO_STRING( FILL_WITH_ASPECT_RATIO )
91 DALI_ENUM_TO_STRING_TABLE_END( Type )
92 } // unnamed namespace
98 unsigned int Actor::mActorCounter = 0;
102 /// Using a function because of library initialisation order. Vector3::ONE may not have been initialised yet.
103 inline const Vector3& GetDefaultSizeModeFactor()
108 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
109 inline const Vector2& GetDefaultPreferredSize()
111 return Vector2::ZERO;
114 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
115 inline const Vector2& GetDefaultDimensionPadding()
117 return Vector2::ZERO;
120 const SizeScalePolicy::Type DEFAULT_SIZE_SCALE_POLICY = SizeScalePolicy::USE_SIZE_SET;
122 } // unnamed namespace
125 * Struct to collect relayout variables
127 struct Actor::RelayoutData
130 : sizeModeFactor( GetDefaultSizeModeFactor() ), preferredSize( GetDefaultPreferredSize() ), sizeSetPolicy( DEFAULT_SIZE_SCALE_POLICY ), relayoutEnabled( false ), insideRelayout( false )
132 // Set size negotiation defaults
133 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
135 resizePolicies[ i ] = ResizePolicy::DEFAULT;
136 negotiatedDimensions[ i ] = 0.0f;
137 dimensionNegotiated[ i ] = false;
138 dimensionDirty[ i ] = false;
139 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
140 dimensionPadding[ i ] = GetDefaultDimensionPadding();
141 minimumSize[ i ] = 0.0f;
142 maximumSize[ i ] = FLT_MAX;
146 ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies
148 Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies
150 Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
152 float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
154 float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be
155 float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be
157 bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated
158 bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
160 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
162 Vector2 preferredSize; ///< The preferred size of the actor
164 SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
166 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
167 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
170 namespace // unnamed namespace
176 * We want to discourage the use of property strings (minimize string comparisons),
177 * particularly for the default properties.
178 * Name Type writable animatable constraint-input enum for index-checking
180 DALI_PROPERTY_TABLE_BEGIN
181 DALI_PROPERTY( "parent-origin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
182 DALI_PROPERTY( "parent-origin-x", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
183 DALI_PROPERTY( "parent-origin-y", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
184 DALI_PROPERTY( "parent-origin-z", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
185 DALI_PROPERTY( "anchor-point", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
186 DALI_PROPERTY( "anchor-point-x", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
187 DALI_PROPERTY( "anchor-point-y", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
188 DALI_PROPERTY( "anchor-point-z", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
189 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
190 DALI_PROPERTY( "size-width", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
191 DALI_PROPERTY( "size-height", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
192 DALI_PROPERTY( "size-depth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
193 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
194 DALI_PROPERTY( "position-x", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
195 DALI_PROPERTY( "position-y", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
196 DALI_PROPERTY( "position-z", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
197 DALI_PROPERTY( "world-position", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
198 DALI_PROPERTY( "world-position-x", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
199 DALI_PROPERTY( "world-position-y", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
200 DALI_PROPERTY( "world-position-z", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
201 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
202 DALI_PROPERTY( "world-orientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
203 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
204 DALI_PROPERTY( "scale-x", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
205 DALI_PROPERTY( "scale-y", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
206 DALI_PROPERTY( "scale-z", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
207 DALI_PROPERTY( "world-scale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
208 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
209 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
210 DALI_PROPERTY( "color-red", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
211 DALI_PROPERTY( "color-green", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
212 DALI_PROPERTY( "color-blue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
213 DALI_PROPERTY( "color-alpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
214 DALI_PROPERTY( "world-color", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
215 DALI_PROPERTY( "world-matrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
216 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
217 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
218 DALI_PROPERTY( "leave-required", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
219 DALI_PROPERTY( "inherit-orientation",BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
220 DALI_PROPERTY( "inherit-scale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
221 DALI_PROPERTY( "color-mode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
222 DALI_PROPERTY( "position-inheritance",STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE )
223 DALI_PROPERTY( "draw-mode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
224 DALI_PROPERTY( "size-mode-factor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
225 DALI_PROPERTY( "width-resize-policy",STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
226 DALI_PROPERTY( "height-resize-policy",STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
227 DALI_PROPERTY( "size-scale-policy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
228 DALI_PROPERTY( "width-for-height", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
229 DALI_PROPERTY( "height-for-width", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
230 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
231 DALI_PROPERTY( "minimum-size", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
232 DALI_PROPERTY( "maximum-size", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
233 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
237 const char* const SIGNAL_TOUCHED = "touched";
238 const char* const SIGNAL_HOVERED = "hovered";
239 const char* const SIGNAL_WHEEL_EVENT = "wheel-event";
240 const char* const SIGNAL_ON_STAGE = "on-stage";
241 const char* const SIGNAL_OFF_STAGE = "off-stage";
245 const char* const ACTION_SHOW = "show";
246 const char* const ACTION_HIDE = "hide";
248 BaseHandle CreateActor()
250 return Dali::Actor::New();
253 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
255 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
256 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
257 SignalConnectorType signalConnector3( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
258 SignalConnectorType signalConnector4( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
260 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
261 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
264 * @brief Extract a given dimension from a Vector2
266 * @param[in] values The values to extract from
267 * @param[in] dimension The dimension to extract
268 * @return Return the value for the dimension
270 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
274 case Dimension::WIDTH:
278 case Dimension::HEIGHT:
280 return values.height;
291 * @brief Extract a given dimension from a Vector3
293 * @param[in] values The values to extract from
294 * @param[in] dimension The dimension to extract
295 * @return Return the value for the dimension
297 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
299 return GetDimensionValue( values.GetVectorXY(), dimension );
303 } // unnamed namespace
305 ActorPtr Actor::New()
307 ActorPtr actor( new Actor( BASIC ) );
309 // Second-phase construction
315 const std::string& Actor::GetName() const
320 void Actor::SetName( const std::string& name )
326 // ATTENTION: string for debug purposes is not thread safe.
327 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
331 unsigned int Actor::GetId() const
336 void Actor::Attach( ActorAttachment& attachment )
338 DALI_ASSERT_DEBUG( !mAttachment && "An Actor can only have one attachment" );
342 attachment.Connect();
345 mAttachment = ActorAttachmentPtr( &attachment );
348 ActorAttachmentPtr Actor::GetAttachment()
353 bool Actor::OnStage() const
358 Dali::Layer Actor::GetLayer()
362 // Short-circuit for Layer derived actors
365 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
368 // Find the immediate Layer parent
369 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
371 if( parent->IsLayer() )
373 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
380 void Actor::Add( Actor& child )
382 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
383 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
387 mChildren = new ActorContainer;
390 Actor* const oldParent( child.mParent );
392 // child might already be ours
393 if( this != oldParent )
395 // if we already have parent, unparent us first
398 oldParent->Remove( child ); // This causes OnChildRemove callback
400 // Old parent may need to readjust to missing child
401 if( oldParent->RelayoutDependentOnChildren() )
403 oldParent->RelayoutRequest();
407 // Guard against Add() during previous OnChildRemove callback
410 // Do this first, since user callbacks from within SetParent() may need to remove child
411 mChildren->push_back( ActorPtr( &child ) );
413 // SetParent asserts that child can be added
414 child.SetParent( this );
416 // Notification for derived classes
419 // Only put in a relayout request if there is a suitable dependency
420 if( RelayoutDependentOnChildren() )
428 void Actor::Remove( Actor& child )
430 if( (this == &child) || (!mChildren) )
432 // no children or removing itself
438 // Find the child in mChildren, and unparent it
439 ActorIter end = mChildren->end();
440 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
442 ActorPtr actor = (*iter);
444 if( actor.Get() == &child )
446 // Keep handle for OnChildRemove notification
449 // Do this first, since user callbacks from within SetParent() may need to add the child
450 mChildren->erase( iter );
452 DALI_ASSERT_DEBUG( actor->GetParent() == this );
453 actor->SetParent( NULL );
461 // Notification for derived classes
462 OnChildRemove( *(removed.Get()) );
464 // Only put in a relayout request if there is a suitable dependency
465 if( RelayoutDependentOnChildren() )
472 void Actor::Unparent()
476 // Remove this actor from the parent. The remove will put a relayout request in for
477 // the parent if required
478 mParent->Remove( *this );
479 // mParent is now NULL!
483 unsigned int Actor::GetChildCount() const
485 return ( NULL != mChildren ) ? mChildren->size() : 0;
488 ActorPtr Actor::GetChildAt( unsigned int index ) const
490 DALI_ASSERT_ALWAYS( index < GetChildCount() );
492 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
495 ActorPtr Actor::FindChildByName( const std::string& actorName )
498 if( actorName == mName )
504 ActorIter end = mChildren->end();
505 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
507 child = (*iter)->FindChildByName( actorName );
518 ActorPtr Actor::FindChildById( const unsigned int id )
527 ActorIter end = mChildren->end();
528 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
530 child = (*iter)->FindChildById( id );
541 void Actor::SetParentOrigin( const Vector3& origin )
545 // mNode is being used in a separate thread; queue a message to set the value & base value
546 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
549 // Cache for event-thread access
552 // not allocated, check if different from default
553 if( ParentOrigin::DEFAULT != origin )
555 mParentOrigin = new Vector3( origin );
560 // check if different from current costs more than just set
561 *mParentOrigin = origin;
565 void Actor::SetParentOriginX( float x )
567 const Vector3& current = GetCurrentParentOrigin();
569 SetParentOrigin( Vector3( x, current.y, current.z ) );
572 void Actor::SetParentOriginY( float y )
574 const Vector3& current = GetCurrentParentOrigin();
576 SetParentOrigin( Vector3( current.x, y, current.z ) );
579 void Actor::SetParentOriginZ( float z )
581 const Vector3& current = GetCurrentParentOrigin();
583 SetParentOrigin( Vector3( current.x, current.y, z ) );
586 const Vector3& Actor::GetCurrentParentOrigin() const
588 // Cached for event-thread access
589 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
592 void Actor::SetAnchorPoint( const Vector3& anchor )
596 // mNode is being used in a separate thread; queue a message to set the value & base value
597 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
600 // Cache for event-thread access
603 // not allocated, check if different from default
604 if( AnchorPoint::DEFAULT != anchor )
606 mAnchorPoint = new Vector3( anchor );
611 // check if different from current costs more than just set
612 *mAnchorPoint = anchor;
616 void Actor::SetAnchorPointX( float x )
618 const Vector3& current = GetCurrentAnchorPoint();
620 SetAnchorPoint( Vector3( x, current.y, current.z ) );
623 void Actor::SetAnchorPointY( float y )
625 const Vector3& current = GetCurrentAnchorPoint();
627 SetAnchorPoint( Vector3( current.x, y, current.z ) );
630 void Actor::SetAnchorPointZ( float z )
632 const Vector3& current = GetCurrentAnchorPoint();
634 SetAnchorPoint( Vector3( current.x, current.y, z ) );
637 const Vector3& Actor::GetCurrentAnchorPoint() const
639 // Cached for event-thread access
640 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
643 void Actor::SetPosition( float x, float y )
645 SetPosition( Vector3( x, y, 0.0f ) );
648 void Actor::SetPosition( float x, float y, float z )
650 SetPosition( Vector3( x, y, z ) );
653 void Actor::SetPosition( const Vector3& position )
655 mTargetPosition = position;
659 // mNode is being used in a separate thread; queue a message to set the value & base value
660 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::Bake, position );
664 void Actor::SetX( float x )
666 mTargetPosition.x = x;
670 // mNode is being used in a separate thread; queue a message to set the value & base value
671 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeX, x );
675 void Actor::SetY( float y )
677 mTargetPosition.y = y;
681 // mNode is being used in a separate thread; queue a message to set the value & base value
682 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeY, y );
686 void Actor::SetZ( float z )
688 mTargetPosition.z = z;
692 // mNode is being used in a separate thread; queue a message to set the value & base value
693 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeZ, z );
697 void Actor::TranslateBy( const Vector3& distance )
699 mTargetPosition += distance;
703 // mNode is being used in a separate thread; queue a message to set the value & base value
704 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeRelative, distance );
708 const Vector3& Actor::GetCurrentPosition() const
712 // mNode is being used in a separate thread; copy the value from the previous update
713 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
716 return Vector3::ZERO;
719 const Vector3& Actor::GetTargetPosition() const
721 return mTargetPosition;
724 const Vector3& Actor::GetCurrentWorldPosition() const
728 // mNode is being used in a separate thread; copy the value from the previous update
729 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
732 return Vector3::ZERO;
735 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
737 // this flag is not animatable so keep the value
738 mPositionInheritanceMode = mode;
741 // mNode is being used in a separate thread; queue a message to set the value
742 SetPositionInheritanceModeMessage( GetEventThreadServices(), *mNode, mode );
746 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
748 // Cached for event-thread access
749 return mPositionInheritanceMode;
752 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
754 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
755 normalizedAxis.Normalize();
757 Quaternion orientation( angle, normalizedAxis );
759 SetOrientation( orientation );
762 void Actor::SetOrientation( const Quaternion& orientation )
766 // mNode is being used in a separate thread; queue a message to set the value & base value
767 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::Bake, orientation );
771 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
775 // mNode is being used in a separate thread; queue a message to set the value & base value
776 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, Quaternion(angle, axis) );
780 void Actor::RotateBy( const Quaternion& relativeRotation )
784 // mNode is being used in a separate thread; queue a message to set the value & base value
785 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, relativeRotation );
789 const Quaternion& Actor::GetCurrentOrientation() const
793 // mNode is being used in a separate thread; copy the value from the previous update
794 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
797 return Quaternion::IDENTITY;
800 const Quaternion& Actor::GetCurrentWorldOrientation() const
804 // mNode is being used in a separate thread; copy the value from the previous update
805 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
808 return Quaternion::IDENTITY;
811 void Actor::SetScale( float scale )
813 SetScale( Vector3( scale, scale, scale ) );
816 void Actor::SetScale( float x, float y, float z )
818 SetScale( Vector3( x, y, z ) );
821 void Actor::SetScale( const Vector3& scale )
825 // mNode is being used in a separate thread; queue a message to set the value & base value
826 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::Bake, scale );
830 void Actor::SetScaleX( float x )
834 // mNode is being used in a separate thread; queue a message to set the value & base value
835 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeX, x );
839 void Actor::SetScaleY( float y )
843 // mNode is being used in a separate thread; queue a message to set the value & base value
844 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeY, y );
848 void Actor::SetScaleZ( float z )
852 // mNode is being used in a separate thread; queue a message to set the value & base value
853 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeZ, z );
857 void Actor::ScaleBy(const Vector3& relativeScale)
861 // mNode is being used in a separate thread; queue a message to set the value & base value
862 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeRelativeMultiply, relativeScale );
866 const Vector3& Actor::GetCurrentScale() const
870 // mNode is being used in a separate thread; copy the value from the previous update
871 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
877 const Vector3& Actor::GetCurrentWorldScale() const
881 // mNode is being used in a separate thread; copy the value from the previous update
882 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
888 void Actor::SetInheritScale( bool inherit )
890 // non animateable so keep local copy
891 mInheritScale = inherit;
894 // mNode is being used in a separate thread; queue a message to set the value
895 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
899 bool Actor::IsScaleInherited() const
901 return mInheritScale;
904 Matrix Actor::GetCurrentWorldMatrix() const
908 // World matrix is no longer updated unless there is something observing the node.
909 // Need to calculate it from node's world position, orientation and scale:
910 BufferIndex updateBufferIndex = GetEventThreadServices().GetEventBufferIndex();
911 Matrix worldMatrix(false);
912 worldMatrix.SetTransformComponents( mNode->GetWorldScale( updateBufferIndex ),
913 mNode->GetWorldOrientation( updateBufferIndex ),
914 mNode->GetWorldPosition( updateBufferIndex ) );
918 return Matrix::IDENTITY;
921 void Actor::SetVisible( bool visible )
925 // mNode is being used in a separate thread; queue a message to set the value & base value
926 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
930 bool Actor::IsVisible() const
934 // mNode is being used in a separate thread; copy the value from the previous update
935 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
941 void Actor::SetOpacity( float opacity )
945 // mNode is being used in a separate thread; queue a message to set the value & base value
946 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
950 float Actor::GetCurrentOpacity() const
954 // mNode is being used in a separate thread; copy the value from the previous update
955 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
961 const Vector4& Actor::GetCurrentWorldColor() const
965 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
971 void Actor::SetColor( const Vector4& color )
975 // mNode is being used in a separate thread; queue a message to set the value & base value
976 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
980 void Actor::SetColorRed( float red )
984 // mNode is being used in a separate thread; queue a message to set the value & base value
985 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
989 void Actor::SetColorGreen( float green )
993 // mNode is being used in a separate thread; queue a message to set the value & base value
994 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
998 void Actor::SetColorBlue( float blue )
1002 // mNode is being used in a separate thread; queue a message to set the value & base value
1003 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1007 const Vector4& Actor::GetCurrentColor() const
1011 // mNode is being used in a separate thread; copy the value from the previous update
1012 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1015 return Color::WHITE;
1018 void Actor::SetInheritOrientation( bool inherit )
1020 // non animateable so keep local copy
1021 mInheritOrientation = inherit;
1024 // mNode is being used in a separate thread; queue a message to set the value
1025 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1029 bool Actor::IsOrientationInherited() const
1031 return mInheritOrientation;
1034 void Actor::SetSizeModeFactor( const Vector3& factor )
1036 EnsureRelayoutData();
1038 mRelayoutData->sizeModeFactor = factor;
1041 const Vector3& Actor::GetSizeModeFactor() const
1043 if ( mRelayoutData )
1045 return mRelayoutData->sizeModeFactor;
1048 return GetDefaultSizeModeFactor();
1051 void Actor::SetColorMode( ColorMode colorMode )
1053 // non animateable so keep local copy
1054 mColorMode = colorMode;
1057 // mNode is being used in a separate thread; queue a message to set the value
1058 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1062 ColorMode Actor::GetColorMode() const
1064 // we have cached copy
1068 void Actor::SetSize( float width, float height )
1070 SetSize( Vector2( width, height ) );
1073 void Actor::SetSize( float width, float height, float depth )
1075 SetSize( Vector3( width, height, depth ) );
1078 void Actor::SetSize( const Vector2& size )
1080 SetSize( Vector3( size.width, size.height, 0.f ) );
1083 void Actor::SetSizeInternal( const Vector2& size )
1085 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1088 void Actor::SetSize( const Vector3& size )
1090 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1092 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1093 SetPreferredSize( size.GetVectorXY() );
1097 SetSizeInternal( size );
1101 void Actor::SetSizeInternal( const Vector3& size )
1103 // dont allow recursive loop
1104 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1105 // 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
1106 if( ( NULL != mNode )&&
1107 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1108 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1109 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1113 // mNode is being used in a separate thread; queue a message to set the value & base value
1114 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::Bake, mTargetSize );
1116 // Notification for derived classes
1117 mInsideOnSizeSet = true;
1118 OnSizeSet( mTargetSize );
1119 mInsideOnSizeSet = false;
1121 // Raise a relayout request if the flag is not locked
1122 if( mRelayoutData && !mRelayoutData->insideRelayout )
1129 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1131 mTargetSize = targetSize;
1133 // Notify deriving classes
1134 OnSizeAnimation( animation, mTargetSize );
1137 void Actor::NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property )
1139 if ( Dali::Actor::Property::SIZE_WIDTH == property )
1141 mTargetSize.width = targetSize;
1143 else if ( Dali::Actor::Property::SIZE_HEIGHT == property )
1145 mTargetSize.height = targetSize;
1147 // Notify deriving classes
1148 OnSizeAnimation( animation, mTargetSize );
1151 void Actor::SetWidth( float width )
1155 // mNode is being used in a separate thread; queue a message to set the value & base value
1156 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeX, width );
1160 void Actor::SetHeight( float height )
1164 // mNode is being used in a separate thread; queue a message to set the value & base value
1165 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeY, height );
1169 void Actor::SetDepth( float depth )
1173 // mNode is being used in a separate thread; queue a message to set the value & base value
1174 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeZ, depth );
1178 const Vector3& Actor::GetTargetSize() const
1183 const Vector3& Actor::GetCurrentSize() const
1187 // mNode is being used in a separate thread; copy the value from the previous update
1188 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1191 return Vector3::ZERO;
1194 Vector3 Actor::GetNaturalSize() const
1196 // It is up to deriving classes to return the appropriate natural size
1197 return Vector3( 0.0f, 0.0f, 0.0f );
1200 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1202 EnsureRelayoutData();
1204 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1206 if( dimension & ( 1 << i ) )
1208 mRelayoutData->resizePolicies[ i ] = policy;
1212 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1214 if( dimension & Dimension::WIDTH )
1216 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1219 if( dimension & Dimension::HEIGHT )
1221 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1225 // If calling SetResizePolicy, assume we want relayout enabled
1226 SetRelayoutEnabled( true );
1228 OnSetResizePolicy( policy, dimension );
1230 // Trigger relayout on this control
1234 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1236 if ( mRelayoutData )
1238 // If more than one dimension is requested, just return the first one found
1239 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1241 if( ( dimension & ( 1 << i ) ) )
1243 return mRelayoutData->resizePolicies[ i ];
1248 return ResizePolicy::DEFAULT;
1251 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1253 EnsureRelayoutData();
1255 mRelayoutData->sizeSetPolicy = policy;
1258 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1260 if ( mRelayoutData )
1262 return mRelayoutData->sizeSetPolicy;
1265 return DEFAULT_SIZE_SCALE_POLICY;
1268 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1270 EnsureRelayoutData();
1272 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1274 if( dimension & ( 1 << i ) )
1276 mRelayoutData->dimensionDependencies[ i ] = dependency;
1281 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1283 if ( mRelayoutData )
1285 // If more than one dimension is requested, just return the first one found
1286 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1288 if( ( dimension & ( 1 << i ) ) )
1290 return mRelayoutData->dimensionDependencies[ i ];
1295 return Dimension::ALL_DIMENSIONS; // Default
1298 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1300 // If relayout data has not been allocated yet and the client is requesting
1301 // to disable it, do nothing
1302 if( mRelayoutData || relayoutEnabled )
1304 EnsureRelayoutData();
1306 mRelayoutData->relayoutEnabled = relayoutEnabled;
1310 bool Actor::IsRelayoutEnabled() const
1312 // Assume that if relayout data has not been allocated yet then
1313 // relayout is disabled
1314 return mRelayoutData && mRelayoutData->relayoutEnabled;
1317 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1319 EnsureRelayoutData();
1321 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1323 if( dimension & ( 1 << i ) )
1325 mRelayoutData->dimensionDirty[ i ] = dirty;
1330 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1332 if ( mRelayoutData )
1334 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1336 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1346 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1348 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1351 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1353 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1356 unsigned int Actor::AddRenderer( Renderer& renderer )
1358 //TODO: MESH_REWORK : Add support for multiple renderers
1359 if ( ! mAttachment )
1361 mAttachment = RendererAttachment::New( GetEventThreadServices(), *mNode, renderer );
1364 mAttachment->Connect();
1371 unsigned int Actor::GetRendererCount() const
1373 //TODO: MESH_REWORK : Add support for multiple renderers
1374 RendererAttachment* attachment = dynamic_cast<RendererAttachment*>(mAttachment.Get());
1375 return attachment ? 1u : 0u;
1378 Renderer& Actor::GetRendererAt( unsigned int index )
1380 //TODO: MESH_REWORK : Add support for multiple renderers
1381 DALI_ASSERT_DEBUG( index == 0 && "Only one renderer is supported." );
1383 //TODO: MESH_REWORK : Temporary code
1384 RendererAttachment* attachment = dynamic_cast<RendererAttachment*>(mAttachment.Get());
1385 DALI_ASSERT_ALWAYS( attachment && "Actor doesn't have a renderer" );
1387 return attachment->GetRenderer();
1390 void Actor::RemoveRenderer( Renderer& renderer )
1392 //TODO: MESH_REWORK : Add support for multiple renderers
1396 void Actor::RemoveRenderer( unsigned int index )
1398 //TODO: MESH_REWORK : Add support for multiple renderers
1402 void Actor::SetOverlay( bool enable )
1404 // Setting STENCIL will override OVERLAY_2D
1405 if( DrawMode::STENCIL != mDrawMode )
1407 SetDrawMode( enable ? DrawMode::OVERLAY_2D : DrawMode::NORMAL );
1411 bool Actor::IsOverlay() const
1413 return ( DrawMode::OVERLAY_2D == mDrawMode );
1416 void Actor::SetDrawMode( DrawMode::Type drawMode )
1418 // this flag is not animatable so keep the value
1419 mDrawMode = drawMode;
1422 // mNode is being used in a separate thread; queue a message to set the value
1423 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1427 DrawMode::Type Actor::GetDrawMode() const
1432 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1434 // only valid when on-stage
1435 StagePtr stage = Stage::GetCurrent();
1436 if( stage && OnStage() )
1438 const RenderTaskList& taskList = stage->GetRenderTaskList();
1440 Vector2 converted( screenX, screenY );
1442 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1443 const int taskCount = taskList.GetTaskCount();
1444 for( int i = taskCount - 1; i >= 0; --i )
1446 Dali::RenderTask task = taskList.GetTask( i );
1447 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1449 // found a task where this conversion was ok so return
1457 bool Actor::ScreenToLocal( RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1459 bool retval = false;
1460 // only valid when on-stage
1463 CameraActor* camera = renderTask.GetCameraActor();
1467 renderTask.GetViewport( viewport );
1469 // need to translate coordinates to render tasks coordinate space
1470 Vector2 converted( screenX, screenY );
1471 if( renderTask.TranslateCoordinates( converted ) )
1473 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1480 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1482 // Early-out if mNode is NULL
1488 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1490 // Calculate the ModelView matrix
1491 Matrix modelView( false/*don't init*/);
1492 // need to use the components as world matrix is only updated for actors that need it
1493 modelView.SetTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1494 Matrix::Multiply( modelView, modelView, viewMatrix );
1496 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1497 Matrix invertedMvp( false/*don't init*/);
1498 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1499 bool success = invertedMvp.Invert();
1501 // Convert to GL coordinates
1502 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1507 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1514 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1520 if( XyPlaneIntersect( nearPos, farPos, local ) )
1522 Vector3 size = GetCurrentSize();
1523 localX = local.x + size.x * 0.5f;
1524 localY = local.y + size.y * 0.5f;
1535 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1538 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1540 Mathematical Formulation
1542 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1544 ( p - c ) dot ( p - c ) = r^2
1546 Given a ray with a point of origin 'o', and a direction vector 'd':
1548 ray(t) = o + td, t >= 0
1550 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1552 (o + td - c ) dot ( o + td - c ) = r^2
1554 To solve for t we first expand the above into a more recognisable quadratic equation form
1556 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1565 B = 2( o - c ) dot d
1566 C = ( o - c ) dot ( o - c ) - r^2
1568 which can be solved using a standard quadratic formula.
1570 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1572 Practical Simplification
1574 In a renderer, we often differentiate between world space and object space. In the object space
1575 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1576 into object space, the mathematical solution presented above can be simplified significantly.
1578 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1582 and we can find the t at which the (transformed) ray intersects the sphere by
1584 ( o + td ) dot ( o + td ) = r^2
1586 According to the reasoning above, we expand the above quadratic equation into the general form
1590 which now has coefficients:
1597 // Early out if mNode is NULL
1603 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1605 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1606 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1607 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1609 // Compute the radius is not needed, square radius it's enough.
1610 const Vector3& size( mNode->GetSize( bufferIndex ) );
1612 // Scale the sphere.
1613 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1615 const float width = size.width * scale.width;
1616 const float height = size.height * scale.height;
1618 float squareSphereRadius = 0.5f * ( width * width + height * height );
1620 float a = rayDir.Dot( rayDir ); // a
1621 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1622 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1624 return ( b2 * b2 - a * c ) >= 0.f;
1627 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
1634 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1636 // Transforms the ray to the local reference system.
1638 // Calculate the inverse of Model matrix
1639 Matrix invModelMatrix( false/*don't init*/);
1640 // need to use the components as world matrix is only updated for actors that need it
1641 invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1643 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1644 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1646 // Test with the actor's XY plane (Normal = 0 0 1 1).
1648 float a = -rayOriginLocal.z;
1649 float b = rayDirLocal.z;
1651 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1653 // Ray travels distance * rayDirLocal to intersect with plane.
1656 const Vector3& size = mNode->GetSize( bufferIndex );
1658 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1659 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1661 // Test with the actor's geometry.
1662 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1669 void Actor::SetLeaveRequired( bool required )
1671 mLeaveRequired = required;
1674 bool Actor::GetLeaveRequired() const
1676 return mLeaveRequired;
1679 void Actor::SetKeyboardFocusable( bool focusable )
1681 mKeyboardFocusable = focusable;
1684 bool Actor::IsKeyboardFocusable() const
1686 return mKeyboardFocusable;
1689 bool Actor::GetTouchRequired() const
1691 return !mTouchedSignal.Empty() || mDerivedRequiresTouch;
1694 bool Actor::GetHoverRequired() const
1696 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1699 bool Actor::GetWheelEventRequired() const
1701 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1704 bool Actor::IsHittable() const
1706 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1709 ActorGestureData& Actor::GetGestureData()
1711 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1712 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1713 if( NULL == mGestureData )
1715 mGestureData = new ActorGestureData;
1717 return *mGestureData;
1720 bool Actor::IsGestureRequred( Gesture::Type type ) const
1722 return mGestureData && mGestureData->IsGestureRequred( type );
1725 bool Actor::EmitTouchEventSignal( const TouchEvent& event )
1727 bool consumed = false;
1729 if( !mTouchedSignal.Empty() )
1731 Dali::Actor handle( this );
1732 consumed = mTouchedSignal.Emit( handle, event );
1737 // Notification for derived classes
1738 consumed = OnTouchEvent( event );
1744 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1746 bool consumed = false;
1748 if( !mHoveredSignal.Empty() )
1750 Dali::Actor handle( this );
1751 consumed = mHoveredSignal.Emit( handle, event );
1756 // Notification for derived classes
1757 consumed = OnHoverEvent( event );
1763 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1765 bool consumed = false;
1767 if( !mWheelEventSignal.Empty() )
1769 Dali::Actor handle( this );
1770 consumed = mWheelEventSignal.Emit( handle, event );
1775 // Notification for derived classes
1776 consumed = OnWheelEvent( event );
1782 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
1784 return mTouchedSignal;
1787 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
1789 return mHoveredSignal;
1792 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
1794 return mWheelEventSignal;
1797 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
1799 return mOnStageSignal;
1802 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
1804 return mOffStageSignal;
1807 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
1809 return mOnRelayoutSignal;
1812 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1814 bool connected( true );
1815 Actor* actor = dynamic_cast< Actor* >( object );
1817 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1819 actor->TouchedSignal().Connect( tracker, functor );
1821 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1823 actor->HoveredSignal().Connect( tracker, functor );
1825 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1827 actor->WheelEventSignal().Connect( tracker, functor );
1829 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
1831 actor->OnStageSignal().Connect( tracker, functor );
1833 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
1835 actor->OffStageSignal().Connect( tracker, functor );
1839 // signalName does not match any signal
1846 Actor::Actor( DerivedType derivedType )
1850 mParentOrigin( NULL ),
1851 mAnchorPoint( NULL ),
1852 mRelayoutData( NULL ),
1853 mGestureData( NULL ),
1855 mTargetSize( 0.0f, 0.0f, 0.0f ),
1857 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
1859 mIsRoot( ROOT_LAYER == derivedType ),
1860 mIsRenderable( RENDERABLE == derivedType ),
1861 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
1862 mIsOnStage( false ),
1864 mLeaveRequired( false ),
1865 mKeyboardFocusable( false ),
1866 mDerivedRequiresTouch( false ),
1867 mDerivedRequiresHover( false ),
1868 mDerivedRequiresWheelEvent( false ),
1869 mOnStageSignalled( false ),
1870 mInsideOnSizeSet( false ),
1871 mInheritOrientation( true ),
1872 mInheritScale( true ),
1873 mDrawMode( DrawMode::NORMAL ),
1874 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
1875 mColorMode( Node::DEFAULT_COLOR_MODE )
1879 void Actor::Initialize()
1882 SceneGraph::Node* node = CreateNode();
1884 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
1885 mNode = node; // Keep raw-pointer to Node
1889 GetEventThreadServices().RegisterObject( this );
1894 // Remove mParent pointers from children even if we're destroying core,
1895 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1898 ActorConstIter endIter = mChildren->end();
1899 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1901 (*iter)->SetParent( NULL );
1906 // Guard to allow handle destruction after Core has been destroyed
1907 if( EventThreadServices::IsCoreRunning() )
1911 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
1912 mNode = NULL; // Node is about to be destroyed
1915 GetEventThreadServices().UnregisterObject( this );
1918 // Cleanup optional gesture data
1919 delete mGestureData;
1921 // Cleanup optional parent origin and anchor
1922 delete mParentOrigin;
1923 delete mAnchorPoint;
1925 // Delete optional relayout data
1928 delete mRelayoutData;
1932 void Actor::ConnectToStage( unsigned int parentDepth )
1934 // This container is used instead of walking the Actor hierarchy.
1935 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
1936 ActorContainer connectionList;
1938 // This stage is atomic i.e. not interrupted by user callbacks.
1939 RecursiveConnectToStage( connectionList, parentDepth + 1 );
1941 // Notify applications about the newly connected actors.
1942 const ActorIter endIter = connectionList.end();
1943 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
1945 (*iter)->NotifyStageConnection();
1951 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth )
1953 DALI_ASSERT_ALWAYS( !OnStage() );
1958 ConnectToSceneGraph();
1960 // Notification for internal derived classes
1961 OnStageConnectionInternal();
1963 // This stage is atomic; avoid emitting callbacks until all Actors are connected
1964 connectionList.push_back( ActorPtr( this ) );
1966 // Recursively connect children
1969 ActorConstIter endIter = mChildren->end();
1970 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1972 (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
1978 * This method is called when the Actor is connected to the Stage.
1979 * The parent must have added its Node to the scene-graph.
1980 * The child must connect its Node to the parent's Node.
1981 * This is recursive; the child calls ConnectToStage() for its children.
1983 void Actor::ConnectToSceneGraph()
1985 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
1989 // Reparent Node in next Update
1990 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode );
1993 // Notify attachment
1996 mAttachment->Connect();
1999 // Request relayout on all actors that are added to the scenegraph
2002 // Notification for Object::Observers
2006 void Actor::NotifyStageConnection()
2008 // Actors can be removed (in a callback), before the on-stage stage is reported.
2009 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2010 if( OnStage() && !mOnStageSignalled )
2012 // Notification for external (CustomActor) derived classes
2013 OnStageConnectionExternal( mDepth );
2015 if( !mOnStageSignal.Empty() )
2017 Dali::Actor handle( this );
2018 mOnStageSignal.Emit( handle );
2021 // Guard against Remove during callbacks
2024 mOnStageSignalled = true; // signal required next time Actor is removed
2029 void Actor::DisconnectFromStage()
2031 // This container is used instead of walking the Actor hierachy.
2032 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2033 ActorContainer disconnectionList;
2035 // This stage is atomic i.e. not interrupted by user callbacks
2036 RecursiveDisconnectFromStage( disconnectionList );
2038 // Notify applications about the newly disconnected actors.
2039 const ActorIter endIter = disconnectionList.end();
2040 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2042 (*iter)->NotifyStageDisconnection();
2046 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2048 DALI_ASSERT_ALWAYS( OnStage() );
2050 // Recursively disconnect children
2053 ActorConstIter endIter = mChildren->end();
2054 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2056 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2060 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2061 disconnectionList.push_back( ActorPtr( this ) );
2063 // Notification for internal derived classes
2064 OnStageDisconnectionInternal();
2066 DisconnectFromSceneGraph();
2072 * This method is called by an actor or its parent, before a node removal message is sent.
2073 * This is recursive; the child calls DisconnectFromStage() for its children.
2075 void Actor::DisconnectFromSceneGraph()
2077 // Notification for Object::Observers
2078 OnSceneObjectRemove();
2080 // Notify attachment
2083 mAttachment->Disconnect();
2087 void Actor::NotifyStageDisconnection()
2089 // Actors can be added (in a callback), before the off-stage state is reported.
2090 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2091 // only do this step if there is a stage, i.e. Core is not being shut down
2092 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2094 // Notification for external (CustomeActor) derived classes
2095 OnStageDisconnectionExternal();
2097 if( !mOffStageSignal.Empty() )
2099 Dali::Actor handle( this );
2100 mOffStageSignal.Emit( handle );
2103 // Guard against Add during callbacks
2106 mOnStageSignalled = false; // signal required next time Actor is added
2111 bool Actor::IsNodeConnected() const
2113 bool connected( false );
2118 if( mNode->IsRoot() || mNode->GetParent() )
2127 unsigned int Actor::GetDefaultPropertyCount() const
2129 return DEFAULT_PROPERTY_COUNT;
2132 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2134 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2136 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2138 indices.PushBack( i );
2142 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2144 if( index < DEFAULT_PROPERTY_COUNT )
2146 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2152 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2154 Property::Index index = Property::INVALID_INDEX;
2156 // Look for name in default properties
2157 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2159 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2160 if( 0 == name.compare( property->name ) )
2170 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2172 if( index < DEFAULT_PROPERTY_COUNT )
2174 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2180 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2182 if( index < DEFAULT_PROPERTY_COUNT )
2184 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2190 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2192 if( index < DEFAULT_PROPERTY_COUNT )
2194 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2200 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2202 if( index < DEFAULT_PROPERTY_COUNT )
2204 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2207 // index out of range...return Property::NONE
2208 return Property::NONE;
2211 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2215 case Dali::Actor::Property::PARENT_ORIGIN:
2217 SetParentOrigin( property.Get< Vector3 >() );
2221 case Dali::Actor::Property::PARENT_ORIGIN_X:
2223 SetParentOriginX( property.Get< float >() );
2227 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2229 SetParentOriginY( property.Get< float >() );
2233 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2235 SetParentOriginZ( property.Get< float >() );
2239 case Dali::Actor::Property::ANCHOR_POINT:
2241 SetAnchorPoint( property.Get< Vector3 >() );
2245 case Dali::Actor::Property::ANCHOR_POINT_X:
2247 SetAnchorPointX( property.Get< float >() );
2251 case Dali::Actor::Property::ANCHOR_POINT_Y:
2253 SetAnchorPointY( property.Get< float >() );
2257 case Dali::Actor::Property::ANCHOR_POINT_Z:
2259 SetAnchorPointZ( property.Get< float >() );
2263 case Dali::Actor::Property::SIZE:
2265 SetSize( property.Get< Vector3 >() );
2269 case Dali::Actor::Property::SIZE_WIDTH:
2271 SetWidth( property.Get< float >() );
2275 case Dali::Actor::Property::SIZE_HEIGHT:
2277 SetHeight( property.Get< float >() );
2281 case Dali::Actor::Property::SIZE_DEPTH:
2283 SetDepth( property.Get< float >() );
2287 case Dali::Actor::Property::POSITION:
2289 SetPosition( property.Get< Vector3 >() );
2293 case Dali::Actor::Property::POSITION_X:
2295 SetX( property.Get< float >() );
2299 case Dali::Actor::Property::POSITION_Y:
2301 SetY( property.Get< float >() );
2305 case Dali::Actor::Property::POSITION_Z:
2307 SetZ( property.Get< float >() );
2311 case Dali::Actor::Property::ORIENTATION:
2313 SetOrientation( property.Get< Quaternion >() );
2317 case Dali::Actor::Property::SCALE:
2319 SetScale( property.Get< Vector3 >() );
2323 case Dali::Actor::Property::SCALE_X:
2325 SetScaleX( property.Get< float >() );
2329 case Dali::Actor::Property::SCALE_Y:
2331 SetScaleY( property.Get< float >() );
2335 case Dali::Actor::Property::SCALE_Z:
2337 SetScaleZ( property.Get< float >() );
2341 case Dali::Actor::Property::VISIBLE:
2343 SetVisible( property.Get< bool >() );
2347 case Dali::Actor::Property::COLOR:
2349 SetColor( property.Get< Vector4 >() );
2353 case Dali::Actor::Property::COLOR_RED:
2355 SetColorRed( property.Get< float >() );
2359 case Dali::Actor::Property::COLOR_GREEN:
2361 SetColorGreen( property.Get< float >() );
2365 case Dali::Actor::Property::COLOR_BLUE:
2367 SetColorBlue( property.Get< float >() );
2371 case Dali::Actor::Property::COLOR_ALPHA:
2373 SetOpacity( property.Get< float >() );
2377 case Dali::Actor::Property::NAME:
2379 SetName( property.Get< std::string >() );
2383 case Dali::Actor::Property::SENSITIVE:
2385 SetSensitive( property.Get< bool >() );
2389 case Dali::Actor::Property::LEAVE_REQUIRED:
2391 SetLeaveRequired( property.Get< bool >() );
2395 case Dali::Actor::Property::INHERIT_ORIENTATION:
2397 SetInheritOrientation( property.Get< bool >() );
2401 case Dali::Actor::Property::INHERIT_SCALE:
2403 SetInheritScale( property.Get< bool >() );
2407 case Dali::Actor::Property::COLOR_MODE:
2409 SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2413 case Dali::Actor::Property::POSITION_INHERITANCE:
2415 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2419 case Dali::Actor::Property::DRAW_MODE:
2421 SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2425 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2427 SetSizeModeFactor( property.Get< Vector3 >() );
2431 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2433 ResizePolicy::Type type;
2434 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2436 SetResizePolicy( type, Dimension::WIDTH );
2441 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2443 ResizePolicy::Type type;
2444 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2446 SetResizePolicy( type, Dimension::HEIGHT );
2451 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2453 SizeScalePolicy::Type type;
2454 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount, type ) )
2456 SetSizeScalePolicy( type );
2461 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2463 if( property.Get< bool >() )
2465 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2470 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2472 if( property.Get< bool >() )
2474 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2479 case Dali::Actor::Property::PADDING:
2481 Vector4 padding = property.Get< Vector4 >();
2482 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2483 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2487 case Dali::Actor::Property::MINIMUM_SIZE:
2489 Vector2 size = property.Get< Vector2 >();
2490 SetMinimumSize( size.x, Dimension::WIDTH );
2491 SetMinimumSize( size.y, Dimension::HEIGHT );
2495 case Dali::Actor::Property::MAXIMUM_SIZE:
2497 Vector2 size = property.Get< Vector2 >();
2498 SetMaximumSize( size.x, Dimension::WIDTH );
2499 SetMaximumSize( size.y, Dimension::HEIGHT );
2505 // this can happen in the case of a non-animatable default property so just do nothing
2511 // TODO: This method needs to be removed
2512 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2514 switch( entry.type )
2516 case Property::BOOLEAN:
2518 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2519 DALI_ASSERT_DEBUG( NULL != property );
2521 // property is being used in a separate thread; queue a message to set the property
2522 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2527 case Property::INTEGER:
2529 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2530 DALI_ASSERT_DEBUG( NULL != property );
2532 // property is being used in a separate thread; queue a message to set the property
2533 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2538 case Property::FLOAT:
2540 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2541 DALI_ASSERT_DEBUG( NULL != property );
2543 // property is being used in a separate thread; queue a message to set the property
2544 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2549 case Property::VECTOR2:
2551 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2552 DALI_ASSERT_DEBUG( NULL != property );
2554 // property is being used in a separate thread; queue a message to set the property
2555 if(entry.componentIndex == 0)
2557 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2559 else if(entry.componentIndex == 1)
2561 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2565 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2571 case Property::VECTOR3:
2573 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2574 DALI_ASSERT_DEBUG( NULL != property );
2576 // property is being used in a separate thread; queue a message to set the property
2577 if(entry.componentIndex == 0)
2579 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2581 else if(entry.componentIndex == 1)
2583 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2585 else if(entry.componentIndex == 2)
2587 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2591 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2597 case Property::VECTOR4:
2599 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2600 DALI_ASSERT_DEBUG( NULL != property );
2602 // property is being used in a separate thread; queue a message to set the property
2603 if(entry.componentIndex == 0)
2605 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
2607 else if(entry.componentIndex == 1)
2609 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
2611 else if(entry.componentIndex == 2)
2613 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
2615 else if(entry.componentIndex == 3)
2617 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
2621 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2627 case Property::ROTATION:
2629 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
2630 DALI_ASSERT_DEBUG( NULL != property );
2632 // property is being used in a separate thread; queue a message to set the property
2633 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
2638 case Property::MATRIX:
2640 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
2641 DALI_ASSERT_DEBUG( NULL != property );
2643 // property is being used in a separate thread; queue a message to set the property
2644 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
2649 case Property::MATRIX3:
2651 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
2652 DALI_ASSERT_DEBUG( NULL != property );
2654 // property is being used in a separate thread; queue a message to set the property
2655 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
2662 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
2668 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
2670 Property::Value value;
2674 case Dali::Actor::Property::PARENT_ORIGIN:
2676 value = GetCurrentParentOrigin();
2680 case Dali::Actor::Property::PARENT_ORIGIN_X:
2682 value = GetCurrentParentOrigin().x;
2686 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2688 value = GetCurrentParentOrigin().y;
2692 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2694 value = GetCurrentParentOrigin().z;
2698 case Dali::Actor::Property::ANCHOR_POINT:
2700 value = GetCurrentAnchorPoint();
2704 case Dali::Actor::Property::ANCHOR_POINT_X:
2706 value = GetCurrentAnchorPoint().x;
2710 case Dali::Actor::Property::ANCHOR_POINT_Y:
2712 value = GetCurrentAnchorPoint().y;
2716 case Dali::Actor::Property::ANCHOR_POINT_Z:
2718 value = GetCurrentAnchorPoint().z;
2722 case Dali::Actor::Property::SIZE:
2724 value = GetCurrentSize();
2728 case Dali::Actor::Property::SIZE_WIDTH:
2730 value = GetCurrentSize().width;
2734 case Dali::Actor::Property::SIZE_HEIGHT:
2736 value = GetCurrentSize().height;
2740 case Dali::Actor::Property::SIZE_DEPTH:
2742 value = GetCurrentSize().depth;
2746 case Dali::Actor::Property::POSITION:
2748 value = GetCurrentPosition();
2752 case Dali::Actor::Property::POSITION_X:
2754 value = GetCurrentPosition().x;
2758 case Dali::Actor::Property::POSITION_Y:
2760 value = GetCurrentPosition().y;
2764 case Dali::Actor::Property::POSITION_Z:
2766 value = GetCurrentPosition().z;
2770 case Dali::Actor::Property::WORLD_POSITION:
2772 value = GetCurrentWorldPosition();
2776 case Dali::Actor::Property::WORLD_POSITION_X:
2778 value = GetCurrentWorldPosition().x;
2782 case Dali::Actor::Property::WORLD_POSITION_Y:
2784 value = GetCurrentWorldPosition().y;
2788 case Dali::Actor::Property::WORLD_POSITION_Z:
2790 value = GetCurrentWorldPosition().z;
2794 case Dali::Actor::Property::ORIENTATION:
2796 value = GetCurrentOrientation();
2800 case Dali::Actor::Property::WORLD_ORIENTATION:
2802 value = GetCurrentWorldOrientation();
2806 case Dali::Actor::Property::SCALE:
2808 value = GetCurrentScale();
2812 case Dali::Actor::Property::SCALE_X:
2814 value = GetCurrentScale().x;
2818 case Dali::Actor::Property::SCALE_Y:
2820 value = GetCurrentScale().y;
2824 case Dali::Actor::Property::SCALE_Z:
2826 value = GetCurrentScale().z;
2830 case Dali::Actor::Property::WORLD_SCALE:
2832 value = GetCurrentWorldScale();
2836 case Dali::Actor::Property::VISIBLE:
2838 value = IsVisible();
2842 case Dali::Actor::Property::COLOR:
2844 value = GetCurrentColor();
2848 case Dali::Actor::Property::COLOR_RED:
2850 value = GetCurrentColor().r;
2854 case Dali::Actor::Property::COLOR_GREEN:
2856 value = GetCurrentColor().g;
2860 case Dali::Actor::Property::COLOR_BLUE:
2862 value = GetCurrentColor().b;
2866 case Dali::Actor::Property::COLOR_ALPHA:
2868 value = GetCurrentColor().a;
2872 case Dali::Actor::Property::WORLD_COLOR:
2874 value = GetCurrentWorldColor();
2878 case Dali::Actor::Property::WORLD_MATRIX:
2880 value = GetCurrentWorldMatrix();
2884 case Dali::Actor::Property::NAME:
2890 case Dali::Actor::Property::SENSITIVE:
2892 value = IsSensitive();
2896 case Dali::Actor::Property::LEAVE_REQUIRED:
2898 value = GetLeaveRequired();
2902 case Dali::Actor::Property::INHERIT_ORIENTATION:
2904 value = IsOrientationInherited();
2908 case Dali::Actor::Property::INHERIT_SCALE:
2910 value = IsScaleInherited();
2914 case Dali::Actor::Property::COLOR_MODE:
2916 value = Scripting::GetColorMode( GetColorMode() );
2920 case Dali::Actor::Property::POSITION_INHERITANCE:
2922 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
2926 case Dali::Actor::Property::DRAW_MODE:
2928 value = Scripting::GetDrawMode( GetDrawMode() );
2932 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2934 value = GetSizeModeFactor();
2938 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2940 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
2944 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2946 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
2950 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2952 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
2956 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2958 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
2962 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2964 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
2968 case Dali::Actor::Property::PADDING:
2970 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
2971 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
2972 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
2976 case Dali::Actor::Property::MINIMUM_SIZE:
2978 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
2982 case Dali::Actor::Property::MAXIMUM_SIZE:
2984 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
2990 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
2998 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3003 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3005 // This method should only return an object connected to the scene-graph
3006 return OnStage() ? mNode : NULL;
3009 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3011 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3013 const PropertyBase* property( NULL );
3015 // This method should only return a property of an object connected to the scene-graph
3021 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3023 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3024 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3026 property = animatable->GetSceneGraphProperty();
3028 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3030 CustomPropertyMetadata* custom = FindCustomProperty( index );
3031 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3033 property = custom->GetSceneGraphProperty();
3035 else if( NULL != mNode )
3039 case Dali::Actor::Property::SIZE:
3040 property = &mNode->mSize;
3043 case Dali::Actor::Property::SIZE_WIDTH:
3044 property = &mNode->mSize;
3047 case Dali::Actor::Property::SIZE_HEIGHT:
3048 property = &mNode->mSize;
3051 case Dali::Actor::Property::SIZE_DEPTH:
3052 property = &mNode->mSize;
3055 case Dali::Actor::Property::POSITION:
3056 property = &mNode->mPosition;
3059 case Dali::Actor::Property::POSITION_X:
3060 property = &mNode->mPosition;
3063 case Dali::Actor::Property::POSITION_Y:
3064 property = &mNode->mPosition;
3067 case Dali::Actor::Property::POSITION_Z:
3068 property = &mNode->mPosition;
3071 case Dali::Actor::Property::ORIENTATION:
3072 property = &mNode->mOrientation;
3075 case Dali::Actor::Property::SCALE:
3076 property = &mNode->mScale;
3079 case Dali::Actor::Property::SCALE_X:
3080 property = &mNode->mScale;
3083 case Dali::Actor::Property::SCALE_Y:
3084 property = &mNode->mScale;
3087 case Dali::Actor::Property::SCALE_Z:
3088 property = &mNode->mScale;
3091 case Dali::Actor::Property::VISIBLE:
3092 property = &mNode->mVisible;
3095 case Dali::Actor::Property::COLOR:
3096 property = &mNode->mColor;
3099 case Dali::Actor::Property::COLOR_RED:
3100 property = &mNode->mColor;
3103 case Dali::Actor::Property::COLOR_GREEN:
3104 property = &mNode->mColor;
3107 case Dali::Actor::Property::COLOR_BLUE:
3108 property = &mNode->mColor;
3111 case Dali::Actor::Property::COLOR_ALPHA:
3112 property = &mNode->mColor;
3123 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3125 const PropertyInputImpl* property( NULL );
3127 // This method should only return a property of an object connected to the scene-graph
3133 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3135 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3136 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3138 property = animatable->GetSceneGraphProperty();
3140 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3142 CustomPropertyMetadata* custom = FindCustomProperty( index );
3143 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3144 property = custom->GetSceneGraphProperty();
3146 else if( NULL != mNode )
3150 case Dali::Actor::Property::PARENT_ORIGIN:
3151 property = &mNode->mParentOrigin;
3154 case Dali::Actor::Property::PARENT_ORIGIN_X:
3155 property = &mNode->mParentOrigin;
3158 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3159 property = &mNode->mParentOrigin;
3162 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3163 property = &mNode->mParentOrigin;
3166 case Dali::Actor::Property::ANCHOR_POINT:
3167 property = &mNode->mAnchorPoint;
3170 case Dali::Actor::Property::ANCHOR_POINT_X:
3171 property = &mNode->mAnchorPoint;
3174 case Dali::Actor::Property::ANCHOR_POINT_Y:
3175 property = &mNode->mAnchorPoint;
3178 case Dali::Actor::Property::ANCHOR_POINT_Z:
3179 property = &mNode->mAnchorPoint;
3182 case Dali::Actor::Property::SIZE:
3183 property = &mNode->mSize;
3186 case Dali::Actor::Property::SIZE_WIDTH:
3187 property = &mNode->mSize;
3190 case Dali::Actor::Property::SIZE_HEIGHT:
3191 property = &mNode->mSize;
3194 case Dali::Actor::Property::SIZE_DEPTH:
3195 property = &mNode->mSize;
3198 case Dali::Actor::Property::POSITION:
3199 property = &mNode->mPosition;
3202 case Dali::Actor::Property::POSITION_X:
3203 property = &mNode->mPosition;
3206 case Dali::Actor::Property::POSITION_Y:
3207 property = &mNode->mPosition;
3210 case Dali::Actor::Property::POSITION_Z:
3211 property = &mNode->mPosition;
3214 case Dali::Actor::Property::WORLD_POSITION:
3215 property = &mNode->mWorldPosition;
3218 case Dali::Actor::Property::WORLD_POSITION_X:
3219 property = &mNode->mWorldPosition;
3222 case Dali::Actor::Property::WORLD_POSITION_Y:
3223 property = &mNode->mWorldPosition;
3226 case Dali::Actor::Property::WORLD_POSITION_Z:
3227 property = &mNode->mWorldPosition;
3230 case Dali::Actor::Property::ORIENTATION:
3231 property = &mNode->mOrientation;
3234 case Dali::Actor::Property::WORLD_ORIENTATION:
3235 property = &mNode->mWorldOrientation;
3238 case Dali::Actor::Property::SCALE:
3239 property = &mNode->mScale;
3242 case Dali::Actor::Property::SCALE_X:
3243 property = &mNode->mScale;
3246 case Dali::Actor::Property::SCALE_Y:
3247 property = &mNode->mScale;
3250 case Dali::Actor::Property::SCALE_Z:
3251 property = &mNode->mScale;
3254 case Dali::Actor::Property::WORLD_SCALE:
3255 property = &mNode->mWorldScale;
3258 case Dali::Actor::Property::VISIBLE:
3259 property = &mNode->mVisible;
3262 case Dali::Actor::Property::COLOR:
3263 property = &mNode->mColor;
3266 case Dali::Actor::Property::COLOR_RED:
3267 property = &mNode->mColor;
3270 case Dali::Actor::Property::COLOR_GREEN:
3271 property = &mNode->mColor;
3274 case Dali::Actor::Property::COLOR_BLUE:
3275 property = &mNode->mColor;
3278 case Dali::Actor::Property::COLOR_ALPHA:
3279 property = &mNode->mColor;
3282 case Dali::Actor::Property::WORLD_COLOR:
3283 property = &mNode->mWorldColor;
3286 case Dali::Actor::Property::WORLD_MATRIX:
3287 property = &mNode->mWorldMatrix;
3298 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3300 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3302 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3304 // check whether the animatable property is registered already, if not then register one.
3305 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3306 if( animatableProperty )
3308 componentIndex = animatableProperty->componentIndex;
3315 case Dali::Actor::Property::PARENT_ORIGIN_X:
3316 case Dali::Actor::Property::ANCHOR_POINT_X:
3317 case Dali::Actor::Property::SIZE_WIDTH:
3318 case Dali::Actor::Property::POSITION_X:
3319 case Dali::Actor::Property::WORLD_POSITION_X:
3320 case Dali::Actor::Property::SCALE_X:
3321 case Dali::Actor::Property::COLOR_RED:
3327 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3328 case Dali::Actor::Property::ANCHOR_POINT_Y:
3329 case Dali::Actor::Property::SIZE_HEIGHT:
3330 case Dali::Actor::Property::POSITION_Y:
3331 case Dali::Actor::Property::WORLD_POSITION_Y:
3332 case Dali::Actor::Property::SCALE_Y:
3333 case Dali::Actor::Property::COLOR_GREEN:
3339 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3340 case Dali::Actor::Property::ANCHOR_POINT_Z:
3341 case Dali::Actor::Property::SIZE_DEPTH:
3342 case Dali::Actor::Property::POSITION_Z:
3343 case Dali::Actor::Property::WORLD_POSITION_Z:
3344 case Dali::Actor::Property::SCALE_Z:
3345 case Dali::Actor::Property::COLOR_BLUE:
3351 case Dali::Actor::Property::COLOR_ALPHA:
3365 return componentIndex;
3368 void Actor::SetParent( Actor* parent )
3372 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3376 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3379 // Instruct each actor to create a corresponding node in the scene graph
3380 ConnectToStage( parent->GetHierarchyDepth() );
3383 else // parent being set to NULL
3385 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3389 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3392 DALI_ASSERT_ALWAYS( mNode != NULL );
3396 // Disconnect the Node & its children from the scene-graph.
3397 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3400 // Instruct each actor to discard pointers to the scene-graph
3401 DisconnectFromStage();
3406 SceneGraph::Node* Actor::CreateNode() const
3411 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3414 Actor* actor = dynamic_cast< Actor* >( object );
3418 if( 0 == actionName.compare( ACTION_SHOW ) )
3420 actor->SetVisible( true );
3423 else if( 0 == actionName.compare( ACTION_HIDE ) )
3425 actor->SetVisible( false );
3433 void Actor::EnsureRelayoutData()
3435 // Assign relayout data.
3436 if( !mRelayoutData )
3438 mRelayoutData = new RelayoutData();
3442 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3444 // Check if actor is dependent on parent
3445 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3447 if( ( dimension & ( 1 << i ) ) )
3449 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3450 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3460 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3462 // Check if actor is dependent on children
3463 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3465 if( ( dimension & ( 1 << i ) ) )
3467 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3468 switch( resizePolicy )
3470 case ResizePolicy::FIT_TO_CHILDREN:
3471 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3487 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3489 return Actor::RelayoutDependentOnChildren( dimension );
3492 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3494 // Check each possible dimension and see if it is dependent on the input one
3495 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3497 if( dimension & ( 1 << i ) )
3499 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3506 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3508 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3510 if( dimension & ( 1 << i ) )
3512 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3517 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3519 // If more than one dimension is requested, just return the first one found
3520 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3522 if( ( dimension & ( 1 << i ) ) )
3524 return mRelayoutData->negotiatedDimensions[ i ];
3528 return 0.0f; // Default
3531 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3533 EnsureRelayoutData();
3535 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3537 if( dimension & ( 1 << i ) )
3539 mRelayoutData->dimensionPadding[ i ] = padding;
3544 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3546 if ( mRelayoutData )
3548 // If more than one dimension is requested, just return the first one found
3549 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3551 if( ( dimension & ( 1 << i ) ) )
3553 return mRelayoutData->dimensionPadding[ i ];
3558 return GetDefaultDimensionPadding();
3561 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
3563 EnsureRelayoutData();
3565 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3567 if( dimension & ( 1 << i ) )
3569 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3574 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
3576 if ( mRelayoutData )
3578 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3580 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
3590 float Actor::GetHeightForWidthBase( float width )
3592 float height = 0.0f;
3594 const Vector3 naturalSize = GetNaturalSize();
3595 if( naturalSize.width > 0.0f )
3597 height = naturalSize.height * width / naturalSize.width;
3599 else // we treat 0 as 1:1 aspect ratio
3607 float Actor::GetWidthForHeightBase( float height )
3611 const Vector3 naturalSize = GetNaturalSize();
3612 if( naturalSize.height > 0.0f )
3614 width = naturalSize.width * height / naturalSize.height;
3616 else // we treat 0 as 1:1 aspect ratio
3624 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
3626 // Fill to parent, taking size mode factor into account
3627 switch( child.GetResizePolicy( dimension ) )
3629 case ResizePolicy::FILL_TO_PARENT:
3631 return GetLatestSize( dimension );
3634 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3636 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
3639 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3641 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
3646 return GetLatestSize( dimension );
3651 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
3653 // Can be overridden in derived class
3654 return CalculateChildSizeBase( child, dimension );
3657 float Actor::GetHeightForWidth( float width )
3659 // Can be overridden in derived class
3660 return GetHeightForWidthBase( width );
3663 float Actor::GetWidthForHeight( float height )
3665 // Can be overridden in derived class
3666 return GetWidthForHeightBase( height );
3669 float Actor::GetLatestSize( Dimension::Type dimension ) const
3671 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
3674 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
3676 Vector2 padding = GetPadding( dimension );
3678 return GetLatestSize( dimension ) + padding.x + padding.y;
3681 float Actor::NegotiateFromParent( Dimension::Type dimension )
3683 Actor* parent = GetParent();
3686 Vector2 padding( GetPadding( dimension ) );
3687 Vector2 parentPadding( parent->GetPadding( dimension ) );
3688 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
3694 float Actor::NegotiateFromChildren( Dimension::Type dimension )
3696 float maxDimensionPoint = 0.0f;
3698 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3700 ActorPtr child = GetChildAt( i );
3702 if( !child->RelayoutDependentOnParent( dimension ) )
3704 // Calculate the min and max points that the children range across
3705 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
3706 float dimensionSize = child->GetRelayoutSize( dimension );
3707 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
3711 return maxDimensionPoint;
3714 float Actor::GetSize( Dimension::Type dimension ) const
3716 return GetDimensionValue( GetTargetSize(), dimension );
3719 float Actor::GetNaturalSize( Dimension::Type dimension ) const
3721 return GetDimensionValue( GetNaturalSize(), dimension );
3724 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
3726 switch( GetResizePolicy( dimension ) )
3728 case ResizePolicy::USE_NATURAL_SIZE:
3730 return GetNaturalSize( dimension );
3733 case ResizePolicy::FIXED:
3735 return GetDimensionValue( GetPreferredSize(), dimension );
3738 case ResizePolicy::USE_ASSIGNED_SIZE:
3740 return GetDimensionValue( maximumSize, dimension );
3743 case ResizePolicy::FILL_TO_PARENT:
3744 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3745 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3747 return NegotiateFromParent( dimension );
3750 case ResizePolicy::FIT_TO_CHILDREN:
3752 return NegotiateFromChildren( dimension );
3755 case ResizePolicy::DIMENSION_DEPENDENCY:
3757 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
3760 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
3762 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
3765 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
3767 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
3779 return 0.0f; // Default
3782 float Actor::ClampDimension( float size, Dimension::Type dimension )
3784 const float minSize = GetMinimumSize( dimension );
3785 const float maxSize = GetMaximumSize( dimension );
3787 return std::max( minSize, std::min( size, maxSize ) );
3790 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
3792 // Check if it needs to be negotiated
3793 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
3795 // Check that we havn't gotten into an infinite loop
3796 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
3797 bool recursionFound = false;
3798 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
3800 if( *it == searchActor )
3802 recursionFound = true;
3807 if( !recursionFound )
3809 // Record the path that we have taken
3810 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
3812 // Dimension dependency check
3813 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3815 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
3817 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
3819 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
3823 // Parent dependency check
3824 Actor* parent = GetParent();
3825 if( parent && RelayoutDependentOnParent( dimension ) )
3827 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
3830 // Children dependency check
3831 if( RelayoutDependentOnChildren( dimension ) )
3833 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3835 ActorPtr child = GetChildAt( i );
3837 // Only relayout child first if it is not dependent on this actor
3838 if( !child->RelayoutDependentOnParent( dimension ) )
3840 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
3845 // For deriving classes
3846 OnCalculateRelayoutSize( dimension );
3848 // All dependencies checked, calculate the size and set negotiated flag
3849 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
3851 SetNegotiatedDimension( newSize, dimension );
3852 SetLayoutNegotiated( true, dimension );
3854 // For deriving classes
3855 OnLayoutNegotiated( newSize, dimension );
3857 // This actor has been successfully processed, pop it off the recursion stack
3858 recursionStack.pop_back();
3862 // TODO: Break infinite loop
3863 SetLayoutNegotiated( true, dimension );
3868 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
3870 // Negotiate all dimensions that require it
3871 ActorDimensionStack recursionStack;
3873 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3875 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
3878 NegotiateDimension( dimension, allocatedSize, recursionStack );
3882 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
3884 switch( mRelayoutData->sizeSetPolicy )
3886 case SizeScalePolicy::USE_SIZE_SET:
3891 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
3893 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
3894 const Vector3 naturalSize = GetNaturalSize();
3895 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
3897 const float sizeRatio = size.width / size.height;
3898 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
3900 if( naturalSizeRatio < sizeRatio )
3902 return Vector2( naturalSizeRatio * size.height, size.height );
3904 else if( naturalSizeRatio > sizeRatio )
3906 return Vector2( size.width, size.width / naturalSizeRatio );
3917 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
3919 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
3920 const Vector3 naturalSize = GetNaturalSize();
3921 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
3923 const float sizeRatio = size.width / size.height;
3924 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
3926 if( naturalSizeRatio < sizeRatio )
3928 return Vector2( size.width, size.width / naturalSizeRatio );
3930 else if( naturalSizeRatio > sizeRatio )
3932 return Vector2( naturalSizeRatio * size.height, size.height );
3950 void Actor::SetNegotiatedSize( RelayoutContainer& container )
3952 // Do the set actor size
3953 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
3955 // Adjust for size set policy
3956 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
3958 // Lock the flag to stop recursive relayouts on set size
3959 mRelayoutData->insideRelayout = true;
3960 SetSize( negotiatedSize );
3961 mRelayoutData->insideRelayout = false;
3963 // Clear flags for all dimensions
3964 SetLayoutDirty( false );
3966 // Give deriving classes a chance to respond
3967 OnRelayout( negotiatedSize, container );
3969 if( !mOnRelayoutSignal.Empty() )
3971 Dali::Actor handle( this );
3972 mOnRelayoutSignal.Emit( handle );
3976 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
3978 // Do the negotiation
3979 NegotiateDimensions( allocatedSize );
3981 // Set the actor size
3982 SetNegotiatedSize( container );
3984 // Negotiate down to children
3985 const Vector2 newBounds = GetTargetSize().GetVectorXY();
3987 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3989 ActorPtr child = GetChildAt( i );
3991 // Only relayout if required
3992 if( child->RelayoutRequired() )
3994 container.Add( Dali::Actor( child.Get() ), newBounds );
3999 void Actor::RelayoutRequest( Dimension::Type dimension )
4001 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4002 if( relayoutController )
4004 Dali::Actor self( this );
4005 relayoutController->RequestRelayout( self, dimension );
4009 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4013 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4017 void Actor::SetPreferredSize( const Vector2& size )
4019 EnsureRelayoutData();
4021 if( size.width > 0.0f )
4023 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4026 if( size.height > 0.0f )
4028 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4031 mRelayoutData->preferredSize = size;
4036 Vector2 Actor::GetPreferredSize() const
4038 if ( mRelayoutData )
4040 return Vector2( mRelayoutData->preferredSize );
4043 return GetDefaultPreferredSize();
4046 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4048 EnsureRelayoutData();
4050 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4052 if( dimension & ( 1 << i ) )
4054 mRelayoutData->minimumSize[ i ] = size;
4061 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4063 if ( mRelayoutData )
4065 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4067 if( dimension & ( 1 << i ) )
4069 return mRelayoutData->minimumSize[ i ];
4074 return 0.0f; // Default
4077 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4079 EnsureRelayoutData();
4081 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4083 if( dimension & ( 1 << i ) )
4085 mRelayoutData->maximumSize[ i ] = size;
4092 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4094 if ( mRelayoutData )
4096 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4098 if( dimension & ( 1 << i ) )
4100 return mRelayoutData->maximumSize[ i ];
4105 return FLT_MAX; // Default
4108 } // namespace Internal