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 // Transforms the ray to the local reference system.
1635 // Calculate the inverse of Model matrix
1636 Matrix invModelMatrix( false/*don't init*/);
1638 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1639 // need to use the components as world matrix is only updated for actors that need it
1640 invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1642 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1643 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1645 // Test with the actor's XY plane (Normal = 0 0 1 1).
1647 float a = -rayOriginLocal.z;
1648 float b = rayDirLocal.z;
1650 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1652 // Ray travels distance * rayDirLocal to intersect with plane.
1655 const Vector3& size = mNode->GetSize( bufferIndex );
1657 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1658 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1660 // Test with the actor's geometry.
1661 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1668 void Actor::SetLeaveRequired( bool required )
1670 mLeaveRequired = required;
1673 bool Actor::GetLeaveRequired() const
1675 return mLeaveRequired;
1678 void Actor::SetKeyboardFocusable( bool focusable )
1680 mKeyboardFocusable = focusable;
1683 bool Actor::IsKeyboardFocusable() const
1685 return mKeyboardFocusable;
1688 bool Actor::GetTouchRequired() const
1690 return !mTouchedSignal.Empty() || mDerivedRequiresTouch;
1693 bool Actor::GetHoverRequired() const
1695 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1698 bool Actor::GetWheelEventRequired() const
1700 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1703 bool Actor::IsHittable() const
1705 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1708 ActorGestureData& Actor::GetGestureData()
1710 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1711 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1712 if( NULL == mGestureData )
1714 mGestureData = new ActorGestureData;
1716 return *mGestureData;
1719 bool Actor::IsGestureRequred( Gesture::Type type ) const
1721 return mGestureData && mGestureData->IsGestureRequred( type );
1724 bool Actor::EmitTouchEventSignal( const TouchEvent& event )
1726 bool consumed = false;
1728 if( !mTouchedSignal.Empty() )
1730 Dali::Actor handle( this );
1731 consumed = mTouchedSignal.Emit( handle, event );
1736 // Notification for derived classes
1737 consumed = OnTouchEvent( event );
1743 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1745 bool consumed = false;
1747 if( !mHoveredSignal.Empty() )
1749 Dali::Actor handle( this );
1750 consumed = mHoveredSignal.Emit( handle, event );
1755 // Notification for derived classes
1756 consumed = OnHoverEvent( event );
1762 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1764 bool consumed = false;
1766 if( !mWheelEventSignal.Empty() )
1768 Dali::Actor handle( this );
1769 consumed = mWheelEventSignal.Emit( handle, event );
1774 // Notification for derived classes
1775 consumed = OnWheelEvent( event );
1781 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
1783 return mTouchedSignal;
1786 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
1788 return mHoveredSignal;
1791 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
1793 return mWheelEventSignal;
1796 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
1798 return mOnStageSignal;
1801 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
1803 return mOffStageSignal;
1806 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
1808 return mOnRelayoutSignal;
1811 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1813 bool connected( true );
1814 Actor* actor = dynamic_cast< Actor* >( object );
1816 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1818 actor->TouchedSignal().Connect( tracker, functor );
1820 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1822 actor->HoveredSignal().Connect( tracker, functor );
1824 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1826 actor->WheelEventSignal().Connect( tracker, functor );
1828 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
1830 actor->OnStageSignal().Connect( tracker, functor );
1832 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
1834 actor->OffStageSignal().Connect( tracker, functor );
1838 // signalName does not match any signal
1845 Actor::Actor( DerivedType derivedType )
1849 mParentOrigin( NULL ),
1850 mAnchorPoint( NULL ),
1851 mRelayoutData( NULL ),
1852 mGestureData( NULL ),
1854 mTargetSize( 0.0f, 0.0f, 0.0f ),
1856 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
1858 mIsRoot( ROOT_LAYER == derivedType ),
1859 mIsRenderable( RENDERABLE == derivedType ),
1860 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
1861 mIsOnStage( false ),
1863 mLeaveRequired( false ),
1864 mKeyboardFocusable( false ),
1865 mDerivedRequiresTouch( false ),
1866 mDerivedRequiresHover( false ),
1867 mDerivedRequiresWheelEvent( false ),
1868 mOnStageSignalled( false ),
1869 mInsideOnSizeSet( false ),
1870 mInheritOrientation( true ),
1871 mInheritScale( true ),
1872 mDrawMode( DrawMode::NORMAL ),
1873 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
1874 mColorMode( Node::DEFAULT_COLOR_MODE )
1878 void Actor::Initialize()
1881 SceneGraph::Node* node = CreateNode();
1883 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
1884 mNode = node; // Keep raw-pointer to Node
1888 GetEventThreadServices().RegisterObject( this );
1893 // Remove mParent pointers from children even if we're destroying core,
1894 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1897 ActorConstIter endIter = mChildren->end();
1898 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1900 (*iter)->SetParent( NULL );
1905 // Guard to allow handle destruction after Core has been destroyed
1906 if( EventThreadServices::IsCoreRunning() )
1910 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
1911 mNode = NULL; // Node is about to be destroyed
1914 GetEventThreadServices().UnregisterObject( this );
1917 // Cleanup optional gesture data
1918 delete mGestureData;
1920 // Cleanup optional parent origin and anchor
1921 delete mParentOrigin;
1922 delete mAnchorPoint;
1924 // Delete optional relayout data
1927 delete mRelayoutData;
1931 void Actor::ConnectToStage( unsigned int parentDepth )
1933 // This container is used instead of walking the Actor hierarchy.
1934 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
1935 ActorContainer connectionList;
1937 // This stage is atomic i.e. not interrupted by user callbacks.
1938 RecursiveConnectToStage( connectionList, parentDepth + 1 );
1940 // Notify applications about the newly connected actors.
1941 const ActorIter endIter = connectionList.end();
1942 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
1944 (*iter)->NotifyStageConnection();
1950 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth )
1952 DALI_ASSERT_ALWAYS( !OnStage() );
1957 ConnectToSceneGraph();
1959 // Notification for internal derived classes
1960 OnStageConnectionInternal();
1962 // This stage is atomic; avoid emitting callbacks until all Actors are connected
1963 connectionList.push_back( ActorPtr( this ) );
1965 // Recursively connect children
1968 ActorConstIter endIter = mChildren->end();
1969 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1971 (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
1977 * This method is called when the Actor is connected to the Stage.
1978 * The parent must have added its Node to the scene-graph.
1979 * The child must connect its Node to the parent's Node.
1980 * This is recursive; the child calls ConnectToStage() for its children.
1982 void Actor::ConnectToSceneGraph()
1984 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
1988 // Reparent Node in next Update
1989 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode );
1992 // Notify attachment
1995 mAttachment->Connect();
1998 // Request relayout on all actors that are added to the scenegraph
2001 // Notification for Object::Observers
2005 void Actor::NotifyStageConnection()
2007 // Actors can be removed (in a callback), before the on-stage stage is reported.
2008 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2009 if( OnStage() && !mOnStageSignalled )
2011 // Notification for external (CustomActor) derived classes
2012 OnStageConnectionExternal( mDepth );
2014 if( !mOnStageSignal.Empty() )
2016 Dali::Actor handle( this );
2017 mOnStageSignal.Emit( handle );
2020 // Guard against Remove during callbacks
2023 mOnStageSignalled = true; // signal required next time Actor is removed
2028 void Actor::DisconnectFromStage()
2030 // This container is used instead of walking the Actor hierachy.
2031 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2032 ActorContainer disconnectionList;
2034 // This stage is atomic i.e. not interrupted by user callbacks
2035 RecursiveDisconnectFromStage( disconnectionList );
2037 // Notify applications about the newly disconnected actors.
2038 const ActorIter endIter = disconnectionList.end();
2039 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2041 (*iter)->NotifyStageDisconnection();
2045 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2047 DALI_ASSERT_ALWAYS( OnStage() );
2049 // Recursively disconnect children
2052 ActorConstIter endIter = mChildren->end();
2053 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2055 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2059 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2060 disconnectionList.push_back( ActorPtr( this ) );
2062 // Notification for internal derived classes
2063 OnStageDisconnectionInternal();
2065 DisconnectFromSceneGraph();
2071 * This method is called by an actor or its parent, before a node removal message is sent.
2072 * This is recursive; the child calls DisconnectFromStage() for its children.
2074 void Actor::DisconnectFromSceneGraph()
2076 // Notification for Object::Observers
2077 OnSceneObjectRemove();
2079 // Notify attachment
2082 mAttachment->Disconnect();
2086 void Actor::NotifyStageDisconnection()
2088 // Actors can be added (in a callback), before the off-stage state is reported.
2089 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2090 // only do this step if there is a stage, i.e. Core is not being shut down
2091 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2093 // Notification for external (CustomeActor) derived classes
2094 OnStageDisconnectionExternal();
2096 if( !mOffStageSignal.Empty() )
2098 Dali::Actor handle( this );
2099 mOffStageSignal.Emit( handle );
2102 // Guard against Add during callbacks
2105 mOnStageSignalled = false; // signal required next time Actor is added
2110 bool Actor::IsNodeConnected() const
2112 bool connected( false );
2114 if( OnStage() && ( NULL != mNode ) )
2116 if( IsRoot() || mNode->GetParent() )
2125 unsigned int Actor::GetDefaultPropertyCount() const
2127 return DEFAULT_PROPERTY_COUNT;
2130 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2132 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2134 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2136 indices.PushBack( i );
2140 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2142 if( index < DEFAULT_PROPERTY_COUNT )
2144 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2150 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2152 Property::Index index = Property::INVALID_INDEX;
2154 // Look for name in default properties
2155 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2157 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2158 if( 0 == name.compare( property->name ) )
2168 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2170 if( index < DEFAULT_PROPERTY_COUNT )
2172 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2178 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2180 if( index < DEFAULT_PROPERTY_COUNT )
2182 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2188 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2190 if( index < DEFAULT_PROPERTY_COUNT )
2192 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2198 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2200 if( index < DEFAULT_PROPERTY_COUNT )
2202 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2205 // index out of range...return Property::NONE
2206 return Property::NONE;
2209 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2213 case Dali::Actor::Property::PARENT_ORIGIN:
2215 SetParentOrigin( property.Get< Vector3 >() );
2219 case Dali::Actor::Property::PARENT_ORIGIN_X:
2221 SetParentOriginX( property.Get< float >() );
2225 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2227 SetParentOriginY( property.Get< float >() );
2231 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2233 SetParentOriginZ( property.Get< float >() );
2237 case Dali::Actor::Property::ANCHOR_POINT:
2239 SetAnchorPoint( property.Get< Vector3 >() );
2243 case Dali::Actor::Property::ANCHOR_POINT_X:
2245 SetAnchorPointX( property.Get< float >() );
2249 case Dali::Actor::Property::ANCHOR_POINT_Y:
2251 SetAnchorPointY( property.Get< float >() );
2255 case Dali::Actor::Property::ANCHOR_POINT_Z:
2257 SetAnchorPointZ( property.Get< float >() );
2261 case Dali::Actor::Property::SIZE:
2263 SetSize( property.Get< Vector3 >() );
2267 case Dali::Actor::Property::SIZE_WIDTH:
2269 SetWidth( property.Get< float >() );
2273 case Dali::Actor::Property::SIZE_HEIGHT:
2275 SetHeight( property.Get< float >() );
2279 case Dali::Actor::Property::SIZE_DEPTH:
2281 SetDepth( property.Get< float >() );
2285 case Dali::Actor::Property::POSITION:
2287 SetPosition( property.Get< Vector3 >() );
2291 case Dali::Actor::Property::POSITION_X:
2293 SetX( property.Get< float >() );
2297 case Dali::Actor::Property::POSITION_Y:
2299 SetY( property.Get< float >() );
2303 case Dali::Actor::Property::POSITION_Z:
2305 SetZ( property.Get< float >() );
2309 case Dali::Actor::Property::ORIENTATION:
2311 SetOrientation( property.Get< Quaternion >() );
2315 case Dali::Actor::Property::SCALE:
2317 SetScale( property.Get< Vector3 >() );
2321 case Dali::Actor::Property::SCALE_X:
2323 SetScaleX( property.Get< float >() );
2327 case Dali::Actor::Property::SCALE_Y:
2329 SetScaleY( property.Get< float >() );
2333 case Dali::Actor::Property::SCALE_Z:
2335 SetScaleZ( property.Get< float >() );
2339 case Dali::Actor::Property::VISIBLE:
2341 SetVisible( property.Get< bool >() );
2345 case Dali::Actor::Property::COLOR:
2347 SetColor( property.Get< Vector4 >() );
2351 case Dali::Actor::Property::COLOR_RED:
2353 SetColorRed( property.Get< float >() );
2357 case Dali::Actor::Property::COLOR_GREEN:
2359 SetColorGreen( property.Get< float >() );
2363 case Dali::Actor::Property::COLOR_BLUE:
2365 SetColorBlue( property.Get< float >() );
2369 case Dali::Actor::Property::COLOR_ALPHA:
2371 SetOpacity( property.Get< float >() );
2375 case Dali::Actor::Property::NAME:
2377 SetName( property.Get< std::string >() );
2381 case Dali::Actor::Property::SENSITIVE:
2383 SetSensitive( property.Get< bool >() );
2387 case Dali::Actor::Property::LEAVE_REQUIRED:
2389 SetLeaveRequired( property.Get< bool >() );
2393 case Dali::Actor::Property::INHERIT_ORIENTATION:
2395 SetInheritOrientation( property.Get< bool >() );
2399 case Dali::Actor::Property::INHERIT_SCALE:
2401 SetInheritScale( property.Get< bool >() );
2405 case Dali::Actor::Property::COLOR_MODE:
2407 SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2411 case Dali::Actor::Property::POSITION_INHERITANCE:
2413 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2417 case Dali::Actor::Property::DRAW_MODE:
2419 SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2423 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2425 SetSizeModeFactor( property.Get< Vector3 >() );
2429 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2431 ResizePolicy::Type type;
2432 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2434 SetResizePolicy( type, Dimension::WIDTH );
2439 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2441 ResizePolicy::Type type;
2442 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2444 SetResizePolicy( type, Dimension::HEIGHT );
2449 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2451 SizeScalePolicy::Type type;
2452 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount, type ) )
2454 SetSizeScalePolicy( type );
2459 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2461 if( property.Get< bool >() )
2463 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2468 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2470 if( property.Get< bool >() )
2472 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2477 case Dali::Actor::Property::PADDING:
2479 Vector4 padding = property.Get< Vector4 >();
2480 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2481 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2485 case Dali::Actor::Property::MINIMUM_SIZE:
2487 Vector2 size = property.Get< Vector2 >();
2488 SetMinimumSize( size.x, Dimension::WIDTH );
2489 SetMinimumSize( size.y, Dimension::HEIGHT );
2493 case Dali::Actor::Property::MAXIMUM_SIZE:
2495 Vector2 size = property.Get< Vector2 >();
2496 SetMaximumSize( size.x, Dimension::WIDTH );
2497 SetMaximumSize( size.y, Dimension::HEIGHT );
2503 // this can happen in the case of a non-animatable default property so just do nothing
2509 // TODO: This method needs to be removed
2510 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2512 switch( entry.type )
2514 case Property::BOOLEAN:
2516 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2517 DALI_ASSERT_DEBUG( NULL != property );
2519 // property is being used in a separate thread; queue a message to set the property
2520 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2525 case Property::INTEGER:
2527 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2528 DALI_ASSERT_DEBUG( NULL != property );
2530 // property is being used in a separate thread; queue a message to set the property
2531 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2536 case Property::FLOAT:
2538 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2539 DALI_ASSERT_DEBUG( NULL != property );
2541 // property is being used in a separate thread; queue a message to set the property
2542 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2547 case Property::VECTOR2:
2549 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2550 DALI_ASSERT_DEBUG( NULL != property );
2552 // property is being used in a separate thread; queue a message to set the property
2553 if(entry.componentIndex == 0)
2555 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2557 else if(entry.componentIndex == 1)
2559 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2563 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2569 case Property::VECTOR3:
2571 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2572 DALI_ASSERT_DEBUG( NULL != property );
2574 // property is being used in a separate thread; queue a message to set the property
2575 if(entry.componentIndex == 0)
2577 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2579 else if(entry.componentIndex == 1)
2581 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2583 else if(entry.componentIndex == 2)
2585 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2589 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2595 case Property::VECTOR4:
2597 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2598 DALI_ASSERT_DEBUG( NULL != property );
2600 // property is being used in a separate thread; queue a message to set the property
2601 if(entry.componentIndex == 0)
2603 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
2605 else if(entry.componentIndex == 1)
2607 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
2609 else if(entry.componentIndex == 2)
2611 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
2613 else if(entry.componentIndex == 3)
2615 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
2619 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2625 case Property::ROTATION:
2627 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
2628 DALI_ASSERT_DEBUG( NULL != property );
2630 // property is being used in a separate thread; queue a message to set the property
2631 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
2636 case Property::MATRIX:
2638 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
2639 DALI_ASSERT_DEBUG( NULL != property );
2641 // property is being used in a separate thread; queue a message to set the property
2642 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
2647 case Property::MATRIX3:
2649 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
2650 DALI_ASSERT_DEBUG( NULL != property );
2652 // property is being used in a separate thread; queue a message to set the property
2653 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
2660 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
2666 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
2668 Property::Value value;
2672 case Dali::Actor::Property::PARENT_ORIGIN:
2674 value = GetCurrentParentOrigin();
2678 case Dali::Actor::Property::PARENT_ORIGIN_X:
2680 value = GetCurrentParentOrigin().x;
2684 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2686 value = GetCurrentParentOrigin().y;
2690 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2692 value = GetCurrentParentOrigin().z;
2696 case Dali::Actor::Property::ANCHOR_POINT:
2698 value = GetCurrentAnchorPoint();
2702 case Dali::Actor::Property::ANCHOR_POINT_X:
2704 value = GetCurrentAnchorPoint().x;
2708 case Dali::Actor::Property::ANCHOR_POINT_Y:
2710 value = GetCurrentAnchorPoint().y;
2714 case Dali::Actor::Property::ANCHOR_POINT_Z:
2716 value = GetCurrentAnchorPoint().z;
2720 case Dali::Actor::Property::SIZE:
2722 value = GetCurrentSize();
2726 case Dali::Actor::Property::SIZE_WIDTH:
2728 value = GetCurrentSize().width;
2732 case Dali::Actor::Property::SIZE_HEIGHT:
2734 value = GetCurrentSize().height;
2738 case Dali::Actor::Property::SIZE_DEPTH:
2740 value = GetCurrentSize().depth;
2744 case Dali::Actor::Property::POSITION:
2746 value = GetCurrentPosition();
2750 case Dali::Actor::Property::POSITION_X:
2752 value = GetCurrentPosition().x;
2756 case Dali::Actor::Property::POSITION_Y:
2758 value = GetCurrentPosition().y;
2762 case Dali::Actor::Property::POSITION_Z:
2764 value = GetCurrentPosition().z;
2768 case Dali::Actor::Property::WORLD_POSITION:
2770 value = GetCurrentWorldPosition();
2774 case Dali::Actor::Property::WORLD_POSITION_X:
2776 value = GetCurrentWorldPosition().x;
2780 case Dali::Actor::Property::WORLD_POSITION_Y:
2782 value = GetCurrentWorldPosition().y;
2786 case Dali::Actor::Property::WORLD_POSITION_Z:
2788 value = GetCurrentWorldPosition().z;
2792 case Dali::Actor::Property::ORIENTATION:
2794 value = GetCurrentOrientation();
2798 case Dali::Actor::Property::WORLD_ORIENTATION:
2800 value = GetCurrentWorldOrientation();
2804 case Dali::Actor::Property::SCALE:
2806 value = GetCurrentScale();
2810 case Dali::Actor::Property::SCALE_X:
2812 value = GetCurrentScale().x;
2816 case Dali::Actor::Property::SCALE_Y:
2818 value = GetCurrentScale().y;
2822 case Dali::Actor::Property::SCALE_Z:
2824 value = GetCurrentScale().z;
2828 case Dali::Actor::Property::WORLD_SCALE:
2830 value = GetCurrentWorldScale();
2834 case Dali::Actor::Property::VISIBLE:
2836 value = IsVisible();
2840 case Dali::Actor::Property::COLOR:
2842 value = GetCurrentColor();
2846 case Dali::Actor::Property::COLOR_RED:
2848 value = GetCurrentColor().r;
2852 case Dali::Actor::Property::COLOR_GREEN:
2854 value = GetCurrentColor().g;
2858 case Dali::Actor::Property::COLOR_BLUE:
2860 value = GetCurrentColor().b;
2864 case Dali::Actor::Property::COLOR_ALPHA:
2866 value = GetCurrentColor().a;
2870 case Dali::Actor::Property::WORLD_COLOR:
2872 value = GetCurrentWorldColor();
2876 case Dali::Actor::Property::WORLD_MATRIX:
2878 value = GetCurrentWorldMatrix();
2882 case Dali::Actor::Property::NAME:
2888 case Dali::Actor::Property::SENSITIVE:
2890 value = IsSensitive();
2894 case Dali::Actor::Property::LEAVE_REQUIRED:
2896 value = GetLeaveRequired();
2900 case Dali::Actor::Property::INHERIT_ORIENTATION:
2902 value = IsOrientationInherited();
2906 case Dali::Actor::Property::INHERIT_SCALE:
2908 value = IsScaleInherited();
2912 case Dali::Actor::Property::COLOR_MODE:
2914 value = Scripting::GetColorMode( GetColorMode() );
2918 case Dali::Actor::Property::POSITION_INHERITANCE:
2920 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
2924 case Dali::Actor::Property::DRAW_MODE:
2926 value = Scripting::GetDrawMode( GetDrawMode() );
2930 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2932 value = GetSizeModeFactor();
2936 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2938 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
2942 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2944 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
2948 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2950 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
2954 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2956 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
2960 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2962 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
2966 case Dali::Actor::Property::PADDING:
2968 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
2969 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
2970 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
2974 case Dali::Actor::Property::MINIMUM_SIZE:
2976 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
2980 case Dali::Actor::Property::MAXIMUM_SIZE:
2982 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
2988 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
2996 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3001 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3003 // This method should only return an object connected to the scene-graph
3004 return OnStage() ? mNode : NULL;
3007 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3009 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3011 const PropertyBase* property( NULL );
3013 // This method should only return a property of an object connected to the scene-graph
3019 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3021 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3022 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3024 property = animatable->GetSceneGraphProperty();
3026 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3028 CustomPropertyMetadata* custom = FindCustomProperty( index );
3029 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3031 property = custom->GetSceneGraphProperty();
3033 else if( NULL != mNode )
3037 case Dali::Actor::Property::SIZE:
3038 property = &mNode->mSize;
3041 case Dali::Actor::Property::SIZE_WIDTH:
3042 property = &mNode->mSize;
3045 case Dali::Actor::Property::SIZE_HEIGHT:
3046 property = &mNode->mSize;
3049 case Dali::Actor::Property::SIZE_DEPTH:
3050 property = &mNode->mSize;
3053 case Dali::Actor::Property::POSITION:
3054 property = &mNode->mPosition;
3057 case Dali::Actor::Property::POSITION_X:
3058 property = &mNode->mPosition;
3061 case Dali::Actor::Property::POSITION_Y:
3062 property = &mNode->mPosition;
3065 case Dali::Actor::Property::POSITION_Z:
3066 property = &mNode->mPosition;
3069 case Dali::Actor::Property::ORIENTATION:
3070 property = &mNode->mOrientation;
3073 case Dali::Actor::Property::SCALE:
3074 property = &mNode->mScale;
3077 case Dali::Actor::Property::SCALE_X:
3078 property = &mNode->mScale;
3081 case Dali::Actor::Property::SCALE_Y:
3082 property = &mNode->mScale;
3085 case Dali::Actor::Property::SCALE_Z:
3086 property = &mNode->mScale;
3089 case Dali::Actor::Property::VISIBLE:
3090 property = &mNode->mVisible;
3093 case Dali::Actor::Property::COLOR:
3094 property = &mNode->mColor;
3097 case Dali::Actor::Property::COLOR_RED:
3098 property = &mNode->mColor;
3101 case Dali::Actor::Property::COLOR_GREEN:
3102 property = &mNode->mColor;
3105 case Dali::Actor::Property::COLOR_BLUE:
3106 property = &mNode->mColor;
3109 case Dali::Actor::Property::COLOR_ALPHA:
3110 property = &mNode->mColor;
3121 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3123 const PropertyInputImpl* property( NULL );
3125 // This method should only return a property of an object connected to the scene-graph
3131 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3133 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3134 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3136 property = animatable->GetSceneGraphProperty();
3138 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3140 CustomPropertyMetadata* custom = FindCustomProperty( index );
3141 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3142 property = custom->GetSceneGraphProperty();
3144 else if( NULL != mNode )
3148 case Dali::Actor::Property::PARENT_ORIGIN:
3149 property = &mNode->mParentOrigin;
3152 case Dali::Actor::Property::PARENT_ORIGIN_X:
3153 property = &mNode->mParentOrigin;
3156 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3157 property = &mNode->mParentOrigin;
3160 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3161 property = &mNode->mParentOrigin;
3164 case Dali::Actor::Property::ANCHOR_POINT:
3165 property = &mNode->mAnchorPoint;
3168 case Dali::Actor::Property::ANCHOR_POINT_X:
3169 property = &mNode->mAnchorPoint;
3172 case Dali::Actor::Property::ANCHOR_POINT_Y:
3173 property = &mNode->mAnchorPoint;
3176 case Dali::Actor::Property::ANCHOR_POINT_Z:
3177 property = &mNode->mAnchorPoint;
3180 case Dali::Actor::Property::SIZE:
3181 property = &mNode->mSize;
3184 case Dali::Actor::Property::SIZE_WIDTH:
3185 property = &mNode->mSize;
3188 case Dali::Actor::Property::SIZE_HEIGHT:
3189 property = &mNode->mSize;
3192 case Dali::Actor::Property::SIZE_DEPTH:
3193 property = &mNode->mSize;
3196 case Dali::Actor::Property::POSITION:
3197 property = &mNode->mPosition;
3200 case Dali::Actor::Property::POSITION_X:
3201 property = &mNode->mPosition;
3204 case Dali::Actor::Property::POSITION_Y:
3205 property = &mNode->mPosition;
3208 case Dali::Actor::Property::POSITION_Z:
3209 property = &mNode->mPosition;
3212 case Dali::Actor::Property::WORLD_POSITION:
3213 property = &mNode->mWorldPosition;
3216 case Dali::Actor::Property::WORLD_POSITION_X:
3217 property = &mNode->mWorldPosition;
3220 case Dali::Actor::Property::WORLD_POSITION_Y:
3221 property = &mNode->mWorldPosition;
3224 case Dali::Actor::Property::WORLD_POSITION_Z:
3225 property = &mNode->mWorldPosition;
3228 case Dali::Actor::Property::ORIENTATION:
3229 property = &mNode->mOrientation;
3232 case Dali::Actor::Property::WORLD_ORIENTATION:
3233 property = &mNode->mWorldOrientation;
3236 case Dali::Actor::Property::SCALE:
3237 property = &mNode->mScale;
3240 case Dali::Actor::Property::SCALE_X:
3241 property = &mNode->mScale;
3244 case Dali::Actor::Property::SCALE_Y:
3245 property = &mNode->mScale;
3248 case Dali::Actor::Property::SCALE_Z:
3249 property = &mNode->mScale;
3252 case Dali::Actor::Property::WORLD_SCALE:
3253 property = &mNode->mWorldScale;
3256 case Dali::Actor::Property::VISIBLE:
3257 property = &mNode->mVisible;
3260 case Dali::Actor::Property::COLOR:
3261 property = &mNode->mColor;
3264 case Dali::Actor::Property::COLOR_RED:
3265 property = &mNode->mColor;
3268 case Dali::Actor::Property::COLOR_GREEN:
3269 property = &mNode->mColor;
3272 case Dali::Actor::Property::COLOR_BLUE:
3273 property = &mNode->mColor;
3276 case Dali::Actor::Property::COLOR_ALPHA:
3277 property = &mNode->mColor;
3280 case Dali::Actor::Property::WORLD_COLOR:
3281 property = &mNode->mWorldColor;
3284 case Dali::Actor::Property::WORLD_MATRIX:
3285 property = &mNode->mWorldMatrix;
3296 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3298 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3300 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3302 // check whether the animatable property is registered already, if not then register one.
3303 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3304 if( animatableProperty )
3306 componentIndex = animatableProperty->componentIndex;
3313 case Dali::Actor::Property::PARENT_ORIGIN_X:
3314 case Dali::Actor::Property::ANCHOR_POINT_X:
3315 case Dali::Actor::Property::SIZE_WIDTH:
3316 case Dali::Actor::Property::POSITION_X:
3317 case Dali::Actor::Property::WORLD_POSITION_X:
3318 case Dali::Actor::Property::SCALE_X:
3319 case Dali::Actor::Property::COLOR_RED:
3325 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3326 case Dali::Actor::Property::ANCHOR_POINT_Y:
3327 case Dali::Actor::Property::SIZE_HEIGHT:
3328 case Dali::Actor::Property::POSITION_Y:
3329 case Dali::Actor::Property::WORLD_POSITION_Y:
3330 case Dali::Actor::Property::SCALE_Y:
3331 case Dali::Actor::Property::COLOR_GREEN:
3337 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3338 case Dali::Actor::Property::ANCHOR_POINT_Z:
3339 case Dali::Actor::Property::SIZE_DEPTH:
3340 case Dali::Actor::Property::POSITION_Z:
3341 case Dali::Actor::Property::WORLD_POSITION_Z:
3342 case Dali::Actor::Property::SCALE_Z:
3343 case Dali::Actor::Property::COLOR_BLUE:
3349 case Dali::Actor::Property::COLOR_ALPHA:
3363 return componentIndex;
3366 void Actor::SetParent( Actor* parent )
3370 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3374 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3377 // Instruct each actor to create a corresponding node in the scene graph
3378 ConnectToStage( parent->GetHierarchyDepth() );
3381 else // parent being set to NULL
3383 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3387 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3390 DALI_ASSERT_ALWAYS( mNode != NULL );
3394 // Disconnect the Node & its children from the scene-graph.
3395 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3398 // Instruct each actor to discard pointers to the scene-graph
3399 DisconnectFromStage();
3404 SceneGraph::Node* Actor::CreateNode() const
3409 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3412 Actor* actor = dynamic_cast< Actor* >( object );
3416 if( 0 == actionName.compare( ACTION_SHOW ) )
3418 actor->SetVisible( true );
3421 else if( 0 == actionName.compare( ACTION_HIDE ) )
3423 actor->SetVisible( false );
3431 void Actor::EnsureRelayoutData()
3433 // Assign relayout data.
3434 if( !mRelayoutData )
3436 mRelayoutData = new RelayoutData();
3440 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3442 // Check if actor is dependent on parent
3443 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3445 if( ( dimension & ( 1 << i ) ) )
3447 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3448 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3458 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3460 // Check if actor is dependent on children
3461 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3463 if( ( dimension & ( 1 << i ) ) )
3465 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3466 switch( resizePolicy )
3468 case ResizePolicy::FIT_TO_CHILDREN:
3469 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3485 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3487 return Actor::RelayoutDependentOnChildren( dimension );
3490 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3492 // Check each possible dimension and see if it is dependent on the input one
3493 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3495 if( dimension & ( 1 << i ) )
3497 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3504 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3506 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3508 if( dimension & ( 1 << i ) )
3510 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3515 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3517 // If more than one dimension is requested, just return the first one found
3518 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3520 if( ( dimension & ( 1 << i ) ) )
3522 return mRelayoutData->negotiatedDimensions[ i ];
3526 return 0.0f; // Default
3529 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3531 EnsureRelayoutData();
3533 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3535 if( dimension & ( 1 << i ) )
3537 mRelayoutData->dimensionPadding[ i ] = padding;
3542 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3544 if ( mRelayoutData )
3546 // If more than one dimension is requested, just return the first one found
3547 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3549 if( ( dimension & ( 1 << i ) ) )
3551 return mRelayoutData->dimensionPadding[ i ];
3556 return GetDefaultDimensionPadding();
3559 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
3561 EnsureRelayoutData();
3563 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3565 if( dimension & ( 1 << i ) )
3567 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3572 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
3574 if ( mRelayoutData )
3576 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3578 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
3588 float Actor::GetHeightForWidthBase( float width )
3590 float height = 0.0f;
3592 const Vector3 naturalSize = GetNaturalSize();
3593 if( naturalSize.width > 0.0f )
3595 height = naturalSize.height * width / naturalSize.width;
3597 else // we treat 0 as 1:1 aspect ratio
3605 float Actor::GetWidthForHeightBase( float height )
3609 const Vector3 naturalSize = GetNaturalSize();
3610 if( naturalSize.height > 0.0f )
3612 width = naturalSize.width * height / naturalSize.height;
3614 else // we treat 0 as 1:1 aspect ratio
3622 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
3624 // Fill to parent, taking size mode factor into account
3625 switch( child.GetResizePolicy( dimension ) )
3627 case ResizePolicy::FILL_TO_PARENT:
3629 return GetLatestSize( dimension );
3632 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3634 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
3637 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3639 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
3644 return GetLatestSize( dimension );
3649 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
3651 // Can be overridden in derived class
3652 return CalculateChildSizeBase( child, dimension );
3655 float Actor::GetHeightForWidth( float width )
3657 // Can be overridden in derived class
3658 return GetHeightForWidthBase( width );
3661 float Actor::GetWidthForHeight( float height )
3663 // Can be overridden in derived class
3664 return GetWidthForHeightBase( height );
3667 float Actor::GetLatestSize( Dimension::Type dimension ) const
3669 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
3672 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
3674 Vector2 padding = GetPadding( dimension );
3676 return GetLatestSize( dimension ) + padding.x + padding.y;
3679 float Actor::NegotiateFromParent( Dimension::Type dimension )
3681 Actor* parent = GetParent();
3684 Vector2 padding( GetPadding( dimension ) );
3685 Vector2 parentPadding( parent->GetPadding( dimension ) );
3686 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
3692 float Actor::NegotiateFromChildren( Dimension::Type dimension )
3694 float maxDimensionPoint = 0.0f;
3696 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3698 ActorPtr child = GetChildAt( i );
3700 if( !child->RelayoutDependentOnParent( dimension ) )
3702 // Calculate the min and max points that the children range across
3703 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
3704 float dimensionSize = child->GetRelayoutSize( dimension );
3705 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
3709 return maxDimensionPoint;
3712 float Actor::GetSize( Dimension::Type dimension ) const
3714 return GetDimensionValue( GetTargetSize(), dimension );
3717 float Actor::GetNaturalSize( Dimension::Type dimension ) const
3719 return GetDimensionValue( GetNaturalSize(), dimension );
3722 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
3724 switch( GetResizePolicy( dimension ) )
3726 case ResizePolicy::USE_NATURAL_SIZE:
3728 return GetNaturalSize( dimension );
3731 case ResizePolicy::FIXED:
3733 return GetDimensionValue( GetPreferredSize(), dimension );
3736 case ResizePolicy::USE_ASSIGNED_SIZE:
3738 return GetDimensionValue( maximumSize, dimension );
3741 case ResizePolicy::FILL_TO_PARENT:
3742 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3743 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3745 return NegotiateFromParent( dimension );
3748 case ResizePolicy::FIT_TO_CHILDREN:
3750 return NegotiateFromChildren( dimension );
3753 case ResizePolicy::DIMENSION_DEPENDENCY:
3755 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
3758 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
3760 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
3763 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
3765 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
3777 return 0.0f; // Default
3780 float Actor::ClampDimension( float size, Dimension::Type dimension )
3782 const float minSize = GetMinimumSize( dimension );
3783 const float maxSize = GetMaximumSize( dimension );
3785 return std::max( minSize, std::min( size, maxSize ) );
3788 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
3790 // Check if it needs to be negotiated
3791 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
3793 // Check that we havn't gotten into an infinite loop
3794 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
3795 bool recursionFound = false;
3796 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
3798 if( *it == searchActor )
3800 recursionFound = true;
3805 if( !recursionFound )
3807 // Record the path that we have taken
3808 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
3810 // Dimension dependency check
3811 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3813 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
3815 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
3817 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
3821 // Parent dependency check
3822 Actor* parent = GetParent();
3823 if( parent && RelayoutDependentOnParent( dimension ) )
3825 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
3828 // Children dependency check
3829 if( RelayoutDependentOnChildren( dimension ) )
3831 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3833 ActorPtr child = GetChildAt( i );
3835 // Only relayout child first if it is not dependent on this actor
3836 if( !child->RelayoutDependentOnParent( dimension ) )
3838 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
3843 // For deriving classes
3844 OnCalculateRelayoutSize( dimension );
3846 // All dependencies checked, calculate the size and set negotiated flag
3847 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
3849 SetNegotiatedDimension( newSize, dimension );
3850 SetLayoutNegotiated( true, dimension );
3852 // For deriving classes
3853 OnLayoutNegotiated( newSize, dimension );
3855 // This actor has been successfully processed, pop it off the recursion stack
3856 recursionStack.pop_back();
3860 // TODO: Break infinite loop
3861 SetLayoutNegotiated( true, dimension );
3866 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
3868 // Negotiate all dimensions that require it
3869 ActorDimensionStack recursionStack;
3871 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3873 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
3876 NegotiateDimension( dimension, allocatedSize, recursionStack );
3880 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
3882 switch( mRelayoutData->sizeSetPolicy )
3884 case SizeScalePolicy::USE_SIZE_SET:
3889 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
3891 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
3892 const Vector3 naturalSize = GetNaturalSize();
3893 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
3895 const float sizeRatio = size.width / size.height;
3896 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
3898 if( naturalSizeRatio < sizeRatio )
3900 return Vector2( naturalSizeRatio * size.height, size.height );
3902 else if( naturalSizeRatio > sizeRatio )
3904 return Vector2( size.width, size.width / naturalSizeRatio );
3915 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
3917 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
3918 const Vector3 naturalSize = GetNaturalSize();
3919 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
3921 const float sizeRatio = size.width / size.height;
3922 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
3924 if( naturalSizeRatio < sizeRatio )
3926 return Vector2( size.width, size.width / naturalSizeRatio );
3928 else if( naturalSizeRatio > sizeRatio )
3930 return Vector2( naturalSizeRatio * size.height, size.height );
3948 void Actor::SetNegotiatedSize( RelayoutContainer& container )
3950 // Do the set actor size
3951 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
3953 // Adjust for size set policy
3954 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
3956 // Lock the flag to stop recursive relayouts on set size
3957 mRelayoutData->insideRelayout = true;
3958 SetSize( negotiatedSize );
3959 mRelayoutData->insideRelayout = false;
3961 // Clear flags for all dimensions
3962 SetLayoutDirty( false );
3964 // Give deriving classes a chance to respond
3965 OnRelayout( negotiatedSize, container );
3967 if( !mOnRelayoutSignal.Empty() )
3969 Dali::Actor handle( this );
3970 mOnRelayoutSignal.Emit( handle );
3974 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
3976 // Do the negotiation
3977 NegotiateDimensions( allocatedSize );
3979 // Set the actor size
3980 SetNegotiatedSize( container );
3982 // Negotiate down to children
3983 const Vector2 newBounds = GetTargetSize().GetVectorXY();
3985 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3987 ActorPtr child = GetChildAt( i );
3989 // Only relayout if required
3990 if( child->RelayoutRequired() )
3992 container.Add( Dali::Actor( child.Get() ), newBounds );
3997 void Actor::RelayoutRequest( Dimension::Type dimension )
3999 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4000 if( relayoutController )
4002 Dali::Actor self( this );
4003 relayoutController->RequestRelayout( self, dimension );
4007 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4011 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4015 void Actor::SetPreferredSize( const Vector2& size )
4017 EnsureRelayoutData();
4019 if( size.width > 0.0f )
4021 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4024 if( size.height > 0.0f )
4026 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4029 mRelayoutData->preferredSize = size;
4034 Vector2 Actor::GetPreferredSize() const
4036 if ( mRelayoutData )
4038 return Vector2( mRelayoutData->preferredSize );
4041 return GetDefaultPreferredSize();
4044 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4046 EnsureRelayoutData();
4048 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4050 if( dimension & ( 1 << i ) )
4052 mRelayoutData->minimumSize[ i ] = size;
4059 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4061 if ( mRelayoutData )
4063 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4065 if( dimension & ( 1 << i ) )
4067 return mRelayoutData->minimumSize[ i ];
4072 return 0.0f; // Default
4075 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4077 EnsureRelayoutData();
4079 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4081 if( dimension & ( 1 << i ) )
4083 mRelayoutData->maximumSize[ i ] = size;
4090 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4092 if ( mRelayoutData )
4094 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4096 if( dimension & ( 1 << i ) )
4098 return mRelayoutData->maximumSize[ i ];
4103 return FLT_MAX; // Default
4106 } // namespace Internal