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, CalculateSizeZ( size ) ) );
1083 void Actor::SetSizeInternal( const Vector2& size )
1085 SetSizeInternal( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
1088 float Actor::CalculateSizeZ( const Vector2& size ) const
1090 return std::min( size.width, size.height );
1093 void Actor::SetSize( const Vector3& size )
1095 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1097 SetPreferredSize( size.GetVectorXY() );
1101 SetSizeInternal( size );
1105 void Actor::SetSizeInternal( const Vector3& size )
1107 // dont allow recursive loop
1108 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1109 // 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
1110 if( ( NULL != mNode )&&
1111 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1112 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1113 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1117 // mNode is being used in a separate thread; queue a message to set the value & base value
1118 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::Bake, mTargetSize );
1120 // Notification for derived classes
1121 mInsideOnSizeSet = true;
1122 OnSizeSet( mTargetSize );
1123 mInsideOnSizeSet = false;
1125 // Raise a relayout request if the flag is not locked
1126 if( mRelayoutData && !mRelayoutData->insideRelayout )
1133 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1135 mTargetSize = targetSize;
1137 // Notify deriving classes
1138 OnSizeAnimation( animation, mTargetSize );
1141 void Actor::NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property )
1143 if ( Dali::Actor::Property::SIZE_WIDTH == property )
1145 mTargetSize.width = targetSize;
1147 else if ( Dali::Actor::Property::SIZE_HEIGHT == property )
1149 mTargetSize.height = targetSize;
1151 // Notify deriving classes
1152 OnSizeAnimation( animation, mTargetSize );
1155 void Actor::SetWidth( float width )
1159 // mNode is being used in a separate thread; queue a message to set the value & base value
1160 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeX, width );
1164 void Actor::SetHeight( float height )
1168 // mNode is being used in a separate thread; queue a message to set the value & base value
1169 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeY, height );
1173 void Actor::SetDepth( float depth )
1177 // mNode is being used in a separate thread; queue a message to set the value & base value
1178 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeZ, depth );
1182 const Vector3& Actor::GetTargetSize() const
1187 const Vector3& Actor::GetCurrentSize() const
1191 // mNode is being used in a separate thread; copy the value from the previous update
1192 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1195 return Vector3::ZERO;
1198 Vector3 Actor::GetNaturalSize() const
1200 // It is up to deriving classes to return the appropriate natural size
1201 return Vector3( 0.0f, 0.0f, 0.0f );
1204 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1206 EnsureRelayoutData();
1208 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1210 if( dimension & ( 1 << i ) )
1212 mRelayoutData->resizePolicies[ i ] = policy;
1216 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1218 if( dimension & Dimension::WIDTH )
1220 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1223 if( dimension & Dimension::HEIGHT )
1225 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1229 // If calling SetResizePolicy, assume we want relayout enabled
1230 SetRelayoutEnabled( true );
1232 OnSetResizePolicy( policy, dimension );
1234 // Trigger relayout on this control
1238 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1240 if ( mRelayoutData )
1242 // If more than one dimension is requested, just return the first one found
1243 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1245 if( ( dimension & ( 1 << i ) ) )
1247 return mRelayoutData->resizePolicies[ i ];
1252 return ResizePolicy::DEFAULT;
1255 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1257 EnsureRelayoutData();
1259 mRelayoutData->sizeSetPolicy = policy;
1262 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1264 if ( mRelayoutData )
1266 return mRelayoutData->sizeSetPolicy;
1269 return DEFAULT_SIZE_SCALE_POLICY;
1272 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1274 EnsureRelayoutData();
1276 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1278 if( dimension & ( 1 << i ) )
1280 mRelayoutData->dimensionDependencies[ i ] = dependency;
1285 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1287 if ( mRelayoutData )
1289 // If more than one dimension is requested, just return the first one found
1290 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1292 if( ( dimension & ( 1 << i ) ) )
1294 return mRelayoutData->dimensionDependencies[ i ];
1299 return Dimension::ALL_DIMENSIONS; // Default
1302 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1304 // If relayout data has not been allocated yet and the client is requesting
1305 // to disable it, do nothing
1306 if( mRelayoutData || relayoutEnabled )
1308 EnsureRelayoutData();
1310 mRelayoutData->relayoutEnabled = relayoutEnabled;
1314 bool Actor::IsRelayoutEnabled() const
1316 // Assume that if relayout data has not been allocated yet then
1317 // relayout is disabled
1318 return mRelayoutData && mRelayoutData->relayoutEnabled;
1321 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1323 EnsureRelayoutData();
1325 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1327 if( dimension & ( 1 << i ) )
1329 mRelayoutData->dimensionDirty[ i ] = dirty;
1334 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1336 if ( mRelayoutData )
1338 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1340 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1350 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1352 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1355 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1357 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1360 unsigned int Actor::AddRenderer( Renderer& renderer )
1362 //TODO: MESH_REWORK : Add support for multiple renderers
1363 if ( ! mAttachment )
1365 mAttachment = RendererAttachment::New( GetEventThreadServices(), *mNode, renderer );
1368 mAttachment->Connect();
1375 unsigned int Actor::GetRendererCount() const
1377 //TODO: MESH_REWORK : Add support for multiple renderers
1378 RendererAttachment* attachment = dynamic_cast<RendererAttachment*>(mAttachment.Get());
1379 return attachment ? 1u : 0u;
1382 Renderer& Actor::GetRendererAt( unsigned int index )
1384 //TODO: MESH_REWORK : Add support for multiple renderers
1385 DALI_ASSERT_DEBUG( index == 0 && "Only one renderer is supported." );
1387 //TODO: MESH_REWORK : Temporary code
1388 RendererAttachment* attachment = dynamic_cast<RendererAttachment*>(mAttachment.Get());
1389 DALI_ASSERT_ALWAYS( attachment && "Actor doesn't have a renderer" );
1391 return attachment->GetRenderer();
1394 void Actor::RemoveRenderer( Renderer& renderer )
1396 //TODO: MESH_REWORK : Add support for multiple renderers
1400 void Actor::RemoveRenderer( unsigned int index )
1402 //TODO: MESH_REWORK : Add support for multiple renderers
1406 void Actor::SetOverlay( bool enable )
1408 // Setting STENCIL will override OVERLAY_2D
1409 if( DrawMode::STENCIL != mDrawMode )
1411 SetDrawMode( enable ? DrawMode::OVERLAY_2D : DrawMode::NORMAL );
1415 bool Actor::IsOverlay() const
1417 return ( DrawMode::OVERLAY_2D == mDrawMode );
1420 void Actor::SetDrawMode( DrawMode::Type drawMode )
1422 // this flag is not animatable so keep the value
1423 mDrawMode = drawMode;
1426 // mNode is being used in a separate thread; queue a message to set the value
1427 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1431 DrawMode::Type Actor::GetDrawMode() const
1436 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1438 // only valid when on-stage
1439 StagePtr stage = Stage::GetCurrent();
1440 if( stage && OnStage() )
1442 const RenderTaskList& taskList = stage->GetRenderTaskList();
1444 Vector2 converted( screenX, screenY );
1446 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1447 const int taskCount = taskList.GetTaskCount();
1448 for( int i = taskCount - 1; i >= 0; --i )
1450 Dali::RenderTask task = taskList.GetTask( i );
1451 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1453 // found a task where this conversion was ok so return
1461 bool Actor::ScreenToLocal( RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1463 bool retval = false;
1464 // only valid when on-stage
1467 CameraActor* camera = renderTask.GetCameraActor();
1471 renderTask.GetViewport( viewport );
1473 // need to translate coordinates to render tasks coordinate space
1474 Vector2 converted( screenX, screenY );
1475 if( renderTask.TranslateCoordinates( converted ) )
1477 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1484 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1486 // Early-out if mNode is NULL
1492 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1494 // Calculate the ModelView matrix
1495 Matrix modelView( false/*don't init*/);
1496 // need to use the components as world matrix is only updated for actors that need it
1497 modelView.SetTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1498 Matrix::Multiply( modelView, modelView, viewMatrix );
1500 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1501 Matrix invertedMvp( false/*don't init*/);
1502 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1503 bool success = invertedMvp.Invert();
1505 // Convert to GL coordinates
1506 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1511 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1518 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1524 if( XyPlaneIntersect( nearPos, farPos, local ) )
1526 Vector3 size = GetCurrentSize();
1527 localX = local.x + size.x * 0.5f;
1528 localY = local.y + size.y * 0.5f;
1539 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1542 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1544 Mathematical Formulation
1546 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1548 ( p - c ) dot ( p - c ) = r^2
1550 Given a ray with a point of origin 'o', and a direction vector 'd':
1552 ray(t) = o + td, t >= 0
1554 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1556 (o + td - c ) dot ( o + td - c ) = r^2
1558 To solve for t we first expand the above into a more recognisable quadratic equation form
1560 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1569 B = 2( o - c ) dot d
1570 C = ( o - c ) dot ( o - c ) - r^2
1572 which can be solved using a standard quadratic formula.
1574 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1576 Practical Simplification
1578 In a renderer, we often differentiate between world space and object space. In the object space
1579 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1580 into object space, the mathematical solution presented above can be simplified significantly.
1582 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1586 and we can find the t at which the (transformed) ray intersects the sphere by
1588 ( o + td ) dot ( o + td ) = r^2
1590 According to the reasoning above, we expand the above quadratic equation into the general form
1594 which now has coefficients:
1601 // Early out if mNode is NULL
1607 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1609 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1610 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1611 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1613 // Compute the radius is not needed, square radius it's enough.
1614 const Vector3& size( mNode->GetSize( bufferIndex ) );
1616 // Scale the sphere.
1617 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1619 const float width = size.width * scale.width;
1620 const float height = size.height * scale.height;
1622 float squareSphereRadius = 0.5f * ( width * width + height * height );
1624 float a = rayDir.Dot( rayDir ); // a
1625 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1626 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1628 return ( b2 * b2 - a * c ) >= 0.f;
1631 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
1638 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1640 // Transforms the ray to the local reference system.
1642 // Calculate the inverse of Model matrix
1643 Matrix invModelMatrix( false/*don't init*/);
1644 // need to use the components as world matrix is only updated for actors that need it
1645 invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1647 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1648 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1650 // Test with the actor's XY plane (Normal = 0 0 1 1).
1652 float a = -rayOriginLocal.z;
1653 float b = rayDirLocal.z;
1655 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1657 // Ray travels distance * rayDirLocal to intersect with plane.
1660 const Vector3& size = mNode->GetSize( bufferIndex );
1662 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1663 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1665 // Test with the actor's geometry.
1666 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1673 void Actor::SetLeaveRequired( bool required )
1675 mLeaveRequired = required;
1678 bool Actor::GetLeaveRequired() const
1680 return mLeaveRequired;
1683 void Actor::SetKeyboardFocusable( bool focusable )
1685 mKeyboardFocusable = focusable;
1688 bool Actor::IsKeyboardFocusable() const
1690 return mKeyboardFocusable;
1693 bool Actor::GetTouchRequired() const
1695 return !mTouchedSignal.Empty() || mDerivedRequiresTouch;
1698 bool Actor::GetHoverRequired() const
1700 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1703 bool Actor::GetWheelEventRequired() const
1705 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1708 bool Actor::IsHittable() const
1710 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1713 ActorGestureData& Actor::GetGestureData()
1715 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1716 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1717 if( NULL == mGestureData )
1719 mGestureData = new ActorGestureData;
1721 return *mGestureData;
1724 bool Actor::IsGestureRequred( Gesture::Type type ) const
1726 return mGestureData && mGestureData->IsGestureRequred( type );
1729 bool Actor::EmitTouchEventSignal( const TouchEvent& event )
1731 bool consumed = false;
1733 if( !mTouchedSignal.Empty() )
1735 Dali::Actor handle( this );
1736 consumed = mTouchedSignal.Emit( handle, event );
1741 // Notification for derived classes
1742 consumed = OnTouchEvent( event );
1748 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1750 bool consumed = false;
1752 if( !mHoveredSignal.Empty() )
1754 Dali::Actor handle( this );
1755 consumed = mHoveredSignal.Emit( handle, event );
1760 // Notification for derived classes
1761 consumed = OnHoverEvent( event );
1767 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1769 bool consumed = false;
1771 if( !mWheelEventSignal.Empty() )
1773 Dali::Actor handle( this );
1774 consumed = mWheelEventSignal.Emit( handle, event );
1779 // Notification for derived classes
1780 consumed = OnWheelEvent( event );
1786 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
1788 return mTouchedSignal;
1791 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
1793 return mHoveredSignal;
1796 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
1798 return mWheelEventSignal;
1801 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
1803 return mOnStageSignal;
1806 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
1808 return mOffStageSignal;
1811 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
1813 return mOnRelayoutSignal;
1816 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1818 bool connected( true );
1819 Actor* actor = dynamic_cast< Actor* >( object );
1821 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1823 actor->TouchedSignal().Connect( tracker, functor );
1825 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1827 actor->HoveredSignal().Connect( tracker, functor );
1829 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1831 actor->WheelEventSignal().Connect( tracker, functor );
1833 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
1835 actor->OnStageSignal().Connect( tracker, functor );
1837 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
1839 actor->OffStageSignal().Connect( tracker, functor );
1843 // signalName does not match any signal
1850 Actor::Actor( DerivedType derivedType )
1854 mParentOrigin( NULL ),
1855 mAnchorPoint( NULL ),
1856 mRelayoutData( NULL ),
1857 mGestureData( NULL ),
1859 mTargetSize( 0.0f, 0.0f, 0.0f ),
1861 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
1863 mIsRoot( ROOT_LAYER == derivedType ),
1864 mIsRenderable( RENDERABLE == derivedType ),
1865 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
1866 mIsOnStage( false ),
1868 mLeaveRequired( false ),
1869 mKeyboardFocusable( false ),
1870 mDerivedRequiresTouch( false ),
1871 mDerivedRequiresHover( false ),
1872 mDerivedRequiresWheelEvent( false ),
1873 mOnStageSignalled( false ),
1874 mInsideOnSizeSet( false ),
1875 mInheritOrientation( true ),
1876 mInheritScale( true ),
1877 mDrawMode( DrawMode::NORMAL ),
1878 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
1879 mColorMode( Node::DEFAULT_COLOR_MODE )
1883 void Actor::Initialize()
1886 SceneGraph::Node* node = CreateNode();
1888 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
1889 mNode = node; // Keep raw-pointer to Node
1893 GetEventThreadServices().RegisterObject( this );
1898 // Remove mParent pointers from children even if we're destroying core,
1899 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1902 ActorConstIter endIter = mChildren->end();
1903 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1905 (*iter)->SetParent( NULL );
1910 // Guard to allow handle destruction after Core has been destroyed
1911 if( EventThreadServices::IsCoreRunning() )
1915 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
1916 mNode = NULL; // Node is about to be destroyed
1919 GetEventThreadServices().UnregisterObject( this );
1922 // Cleanup optional gesture data
1923 delete mGestureData;
1925 // Cleanup optional parent origin and anchor
1926 delete mParentOrigin;
1927 delete mAnchorPoint;
1929 // Delete optional relayout data
1932 delete mRelayoutData;
1936 void Actor::ConnectToStage( unsigned int parentDepth, int index )
1938 // This container is used instead of walking the Actor hierachy.
1939 // It protects us when the Actor hierachy is modified during OnStageConnectionExternal callbacks.
1940 ActorContainer connectionList;
1943 // This stage is atomic i.e. not interrupted by user callbacks
1944 RecursiveConnectToStage( connectionList, parentDepth+1, index );
1946 // Notify applications about the newly connected actors.
1947 const ActorIter endIter = connectionList.end();
1948 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
1950 (*iter)->NotifyStageConnection();
1956 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth, int index )
1958 DALI_ASSERT_ALWAYS( !OnStage() );
1963 ConnectToSceneGraph( index );
1965 // Notification for internal derived classes
1966 OnStageConnectionInternal();
1968 // This stage is atomic; avoid emitting callbacks until all Actors are connected
1969 connectionList.push_back( ActorPtr( this ) );
1971 // Recursively connect children
1974 ActorConstIter endIter = mChildren->end();
1975 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1977 (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
1983 * This method is called when the Actor is connected to the Stage.
1984 * The parent must have added its Node to the scene-graph.
1985 * The child must connect its Node to the parent's Node.
1986 * This is resursive; the child calls ConnectToStage() for its children.
1988 void Actor::ConnectToSceneGraph( int index )
1990 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
1994 // Reparent Node in next Update
1995 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode, index );
1998 // Notify attachment
2001 mAttachment->Connect();
2004 // Request relayout on all actors that are added to the scenegraph
2007 // Notification for Object::Observers
2011 void Actor::NotifyStageConnection()
2013 // Actors can be removed (in a callback), before the on-stage stage is reported.
2014 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2015 if( OnStage() && !mOnStageSignalled )
2017 // Notification for external (CustomActor) derived classes
2018 OnStageConnectionExternal( mDepth );
2020 if( !mOnStageSignal.Empty() )
2022 Dali::Actor handle( this );
2023 mOnStageSignal.Emit( handle );
2026 // Guard against Remove during callbacks
2029 mOnStageSignalled = true; // signal required next time Actor is removed
2034 void Actor::DisconnectFromStage()
2036 // This container is used instead of walking the Actor hierachy.
2037 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2038 ActorContainer disconnectionList;
2040 // This stage is atomic i.e. not interrupted by user callbacks
2041 RecursiveDisconnectFromStage( disconnectionList );
2043 // Notify applications about the newly disconnected actors.
2044 const ActorIter endIter = disconnectionList.end();
2045 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2047 (*iter)->NotifyStageDisconnection();
2051 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2053 DALI_ASSERT_ALWAYS( OnStage() );
2055 // Recursively disconnect children
2058 ActorConstIter endIter = mChildren->end();
2059 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2061 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2065 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2066 disconnectionList.push_back( ActorPtr( this ) );
2068 // Notification for internal derived classes
2069 OnStageDisconnectionInternal();
2071 DisconnectFromSceneGraph();
2077 * This method is called by an actor or its parent, before a node removal message is sent.
2078 * This is recursive; the child calls DisconnectFromStage() for its children.
2080 void Actor::DisconnectFromSceneGraph()
2082 // Notification for Object::Observers
2083 OnSceneObjectRemove();
2085 // Notify attachment
2088 mAttachment->Disconnect();
2092 void Actor::NotifyStageDisconnection()
2094 // Actors can be added (in a callback), before the off-stage state is reported.
2095 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2096 // only do this step if there is a stage, i.e. Core is not being shut down
2097 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2099 // Notification for external (CustomeActor) derived classes
2100 OnStageDisconnectionExternal();
2102 if( !mOffStageSignal.Empty() )
2104 Dali::Actor handle( this );
2105 mOffStageSignal.Emit( handle );
2108 // Guard against Add during callbacks
2111 mOnStageSignalled = false; // signal required next time Actor is added
2116 bool Actor::IsNodeConnected() const
2118 bool connected( false );
2123 if( mNode->IsRoot() || mNode->GetParent() )
2132 unsigned int Actor::GetDefaultPropertyCount() const
2134 return DEFAULT_PROPERTY_COUNT;
2137 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2139 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2141 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2143 indices.PushBack( i );
2147 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2149 if( index < DEFAULT_PROPERTY_COUNT )
2151 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2157 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2159 Property::Index index = Property::INVALID_INDEX;
2161 // Look for name in default properties
2162 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2164 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2165 if( 0 == name.compare( property->name ) )
2175 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2177 if( index < DEFAULT_PROPERTY_COUNT )
2179 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2185 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2187 if( index < DEFAULT_PROPERTY_COUNT )
2189 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2195 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2197 if( index < DEFAULT_PROPERTY_COUNT )
2199 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2205 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2207 if( index < DEFAULT_PROPERTY_COUNT )
2209 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2212 // index out of range...return Property::NONE
2213 return Property::NONE;
2216 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2220 case Dali::Actor::Property::PARENT_ORIGIN:
2222 SetParentOrigin( property.Get< Vector3 >() );
2226 case Dali::Actor::Property::PARENT_ORIGIN_X:
2228 SetParentOriginX( property.Get< float >() );
2232 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2234 SetParentOriginY( property.Get< float >() );
2238 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2240 SetParentOriginZ( property.Get< float >() );
2244 case Dali::Actor::Property::ANCHOR_POINT:
2246 SetAnchorPoint( property.Get< Vector3 >() );
2250 case Dali::Actor::Property::ANCHOR_POINT_X:
2252 SetAnchorPointX( property.Get< float >() );
2256 case Dali::Actor::Property::ANCHOR_POINT_Y:
2258 SetAnchorPointY( property.Get< float >() );
2262 case Dali::Actor::Property::ANCHOR_POINT_Z:
2264 SetAnchorPointZ( property.Get< float >() );
2268 case Dali::Actor::Property::SIZE:
2270 SetSize( property.Get< Vector3 >() );
2274 case Dali::Actor::Property::SIZE_WIDTH:
2276 SetWidth( property.Get< float >() );
2280 case Dali::Actor::Property::SIZE_HEIGHT:
2282 SetHeight( property.Get< float >() );
2286 case Dali::Actor::Property::SIZE_DEPTH:
2288 SetDepth( property.Get< float >() );
2292 case Dali::Actor::Property::POSITION:
2294 SetPosition( property.Get< Vector3 >() );
2298 case Dali::Actor::Property::POSITION_X:
2300 SetX( property.Get< float >() );
2304 case Dali::Actor::Property::POSITION_Y:
2306 SetY( property.Get< float >() );
2310 case Dali::Actor::Property::POSITION_Z:
2312 SetZ( property.Get< float >() );
2316 case Dali::Actor::Property::ORIENTATION:
2318 SetOrientation( property.Get< Quaternion >() );
2322 case Dali::Actor::Property::SCALE:
2324 SetScale( property.Get< Vector3 >() );
2328 case Dali::Actor::Property::SCALE_X:
2330 SetScaleX( property.Get< float >() );
2334 case Dali::Actor::Property::SCALE_Y:
2336 SetScaleY( property.Get< float >() );
2340 case Dali::Actor::Property::SCALE_Z:
2342 SetScaleZ( property.Get< float >() );
2346 case Dali::Actor::Property::VISIBLE:
2348 SetVisible( property.Get< bool >() );
2352 case Dali::Actor::Property::COLOR:
2354 SetColor( property.Get< Vector4 >() );
2358 case Dali::Actor::Property::COLOR_RED:
2360 SetColorRed( property.Get< float >() );
2364 case Dali::Actor::Property::COLOR_GREEN:
2366 SetColorGreen( property.Get< float >() );
2370 case Dali::Actor::Property::COLOR_BLUE:
2372 SetColorBlue( property.Get< float >() );
2376 case Dali::Actor::Property::COLOR_ALPHA:
2378 SetOpacity( property.Get< float >() );
2382 case Dali::Actor::Property::NAME:
2384 SetName( property.Get< std::string >() );
2388 case Dali::Actor::Property::SENSITIVE:
2390 SetSensitive( property.Get< bool >() );
2394 case Dali::Actor::Property::LEAVE_REQUIRED:
2396 SetLeaveRequired( property.Get< bool >() );
2400 case Dali::Actor::Property::INHERIT_ORIENTATION:
2402 SetInheritOrientation( property.Get< bool >() );
2406 case Dali::Actor::Property::INHERIT_SCALE:
2408 SetInheritScale( property.Get< bool >() );
2412 case Dali::Actor::Property::COLOR_MODE:
2414 SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2418 case Dali::Actor::Property::POSITION_INHERITANCE:
2420 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2424 case Dali::Actor::Property::DRAW_MODE:
2426 SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2430 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2432 SetSizeModeFactor( property.Get< Vector3 >() );
2436 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2438 ResizePolicy::Type type;
2439 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2441 SetResizePolicy( type, Dimension::WIDTH );
2446 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2448 ResizePolicy::Type type;
2449 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2451 SetResizePolicy( type, Dimension::HEIGHT );
2456 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2458 SizeScalePolicy::Type type;
2459 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount, type ) )
2461 SetSizeScalePolicy( type );
2466 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2468 if( property.Get< bool >() )
2470 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2475 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2477 if( property.Get< bool >() )
2479 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2484 case Dali::Actor::Property::PADDING:
2486 Vector4 padding = property.Get< Vector4 >();
2487 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2488 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2492 case Dali::Actor::Property::MINIMUM_SIZE:
2494 Vector2 size = property.Get< Vector2 >();
2495 SetMinimumSize( size.x, Dimension::WIDTH );
2496 SetMinimumSize( size.y, Dimension::HEIGHT );
2500 case Dali::Actor::Property::MAXIMUM_SIZE:
2502 Vector2 size = property.Get< Vector2 >();
2503 SetMaximumSize( size.x, Dimension::WIDTH );
2504 SetMaximumSize( size.y, Dimension::HEIGHT );
2510 // this can happen in the case of a non-animatable default property so just do nothing
2516 // TODO: This method needs to be removed
2517 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2519 switch( entry.type )
2521 case Property::BOOLEAN:
2523 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2524 DALI_ASSERT_DEBUG( NULL != property );
2526 // property is being used in a separate thread; queue a message to set the property
2527 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2532 case Property::INTEGER:
2534 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2535 DALI_ASSERT_DEBUG( NULL != property );
2537 // property is being used in a separate thread; queue a message to set the property
2538 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2543 case Property::FLOAT:
2545 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2546 DALI_ASSERT_DEBUG( NULL != property );
2548 // property is being used in a separate thread; queue a message to set the property
2549 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2554 case Property::VECTOR2:
2556 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2557 DALI_ASSERT_DEBUG( NULL != property );
2559 // property is being used in a separate thread; queue a message to set the property
2560 if(entry.componentIndex == 0)
2562 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2564 else if(entry.componentIndex == 1)
2566 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2570 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2576 case Property::VECTOR3:
2578 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2579 DALI_ASSERT_DEBUG( NULL != property );
2581 // property is being used in a separate thread; queue a message to set the property
2582 if(entry.componentIndex == 0)
2584 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2586 else if(entry.componentIndex == 1)
2588 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2590 else if(entry.componentIndex == 2)
2592 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2596 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2602 case Property::VECTOR4:
2604 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2605 DALI_ASSERT_DEBUG( NULL != property );
2607 // property is being used in a separate thread; queue a message to set the property
2608 if(entry.componentIndex == 0)
2610 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
2612 else if(entry.componentIndex == 1)
2614 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
2616 else if(entry.componentIndex == 2)
2618 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
2620 else if(entry.componentIndex == 3)
2622 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
2626 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2632 case Property::ROTATION:
2634 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
2635 DALI_ASSERT_DEBUG( NULL != property );
2637 // property is being used in a separate thread; queue a message to set the property
2638 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
2643 case Property::MATRIX:
2645 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
2646 DALI_ASSERT_DEBUG( NULL != property );
2648 // property is being used in a separate thread; queue a message to set the property
2649 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
2654 case Property::MATRIX3:
2656 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
2657 DALI_ASSERT_DEBUG( NULL != property );
2659 // property is being used in a separate thread; queue a message to set the property
2660 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
2667 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
2673 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
2675 Property::Value value;
2679 case Dali::Actor::Property::PARENT_ORIGIN:
2681 value = GetCurrentParentOrigin();
2685 case Dali::Actor::Property::PARENT_ORIGIN_X:
2687 value = GetCurrentParentOrigin().x;
2691 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2693 value = GetCurrentParentOrigin().y;
2697 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2699 value = GetCurrentParentOrigin().z;
2703 case Dali::Actor::Property::ANCHOR_POINT:
2705 value = GetCurrentAnchorPoint();
2709 case Dali::Actor::Property::ANCHOR_POINT_X:
2711 value = GetCurrentAnchorPoint().x;
2715 case Dali::Actor::Property::ANCHOR_POINT_Y:
2717 value = GetCurrentAnchorPoint().y;
2721 case Dali::Actor::Property::ANCHOR_POINT_Z:
2723 value = GetCurrentAnchorPoint().z;
2727 case Dali::Actor::Property::SIZE:
2729 value = GetCurrentSize();
2733 case Dali::Actor::Property::SIZE_WIDTH:
2735 value = GetCurrentSize().width;
2739 case Dali::Actor::Property::SIZE_HEIGHT:
2741 value = GetCurrentSize().height;
2745 case Dali::Actor::Property::SIZE_DEPTH:
2747 value = GetCurrentSize().depth;
2751 case Dali::Actor::Property::POSITION:
2753 value = GetCurrentPosition();
2757 case Dali::Actor::Property::POSITION_X:
2759 value = GetCurrentPosition().x;
2763 case Dali::Actor::Property::POSITION_Y:
2765 value = GetCurrentPosition().y;
2769 case Dali::Actor::Property::POSITION_Z:
2771 value = GetCurrentPosition().z;
2775 case Dali::Actor::Property::WORLD_POSITION:
2777 value = GetCurrentWorldPosition();
2781 case Dali::Actor::Property::WORLD_POSITION_X:
2783 value = GetCurrentWorldPosition().x;
2787 case Dali::Actor::Property::WORLD_POSITION_Y:
2789 value = GetCurrentWorldPosition().y;
2793 case Dali::Actor::Property::WORLD_POSITION_Z:
2795 value = GetCurrentWorldPosition().z;
2799 case Dali::Actor::Property::ORIENTATION:
2801 value = GetCurrentOrientation();
2805 case Dali::Actor::Property::WORLD_ORIENTATION:
2807 value = GetCurrentWorldOrientation();
2811 case Dali::Actor::Property::SCALE:
2813 value = GetCurrentScale();
2817 case Dali::Actor::Property::SCALE_X:
2819 value = GetCurrentScale().x;
2823 case Dali::Actor::Property::SCALE_Y:
2825 value = GetCurrentScale().y;
2829 case Dali::Actor::Property::SCALE_Z:
2831 value = GetCurrentScale().z;
2835 case Dali::Actor::Property::WORLD_SCALE:
2837 value = GetCurrentWorldScale();
2841 case Dali::Actor::Property::VISIBLE:
2843 value = IsVisible();
2847 case Dali::Actor::Property::COLOR:
2849 value = GetCurrentColor();
2853 case Dali::Actor::Property::COLOR_RED:
2855 value = GetCurrentColor().r;
2859 case Dali::Actor::Property::COLOR_GREEN:
2861 value = GetCurrentColor().g;
2865 case Dali::Actor::Property::COLOR_BLUE:
2867 value = GetCurrentColor().b;
2871 case Dali::Actor::Property::COLOR_ALPHA:
2873 value = GetCurrentColor().a;
2877 case Dali::Actor::Property::WORLD_COLOR:
2879 value = GetCurrentWorldColor();
2883 case Dali::Actor::Property::WORLD_MATRIX:
2885 value = GetCurrentWorldMatrix();
2889 case Dali::Actor::Property::NAME:
2895 case Dali::Actor::Property::SENSITIVE:
2897 value = IsSensitive();
2901 case Dali::Actor::Property::LEAVE_REQUIRED:
2903 value = GetLeaveRequired();
2907 case Dali::Actor::Property::INHERIT_ORIENTATION:
2909 value = IsOrientationInherited();
2913 case Dali::Actor::Property::INHERIT_SCALE:
2915 value = IsScaleInherited();
2919 case Dali::Actor::Property::COLOR_MODE:
2921 value = Scripting::GetColorMode( GetColorMode() );
2925 case Dali::Actor::Property::POSITION_INHERITANCE:
2927 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
2931 case Dali::Actor::Property::DRAW_MODE:
2933 value = Scripting::GetDrawMode( GetDrawMode() );
2937 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2939 value = GetSizeModeFactor();
2943 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2945 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
2949 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2951 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
2955 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2957 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
2961 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2963 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
2967 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2969 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
2973 case Dali::Actor::Property::PADDING:
2975 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
2976 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
2977 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
2981 case Dali::Actor::Property::MINIMUM_SIZE:
2983 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
2987 case Dali::Actor::Property::MAXIMUM_SIZE:
2989 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
2995 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3003 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3008 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3010 // This method should only return an object connected to the scene-graph
3011 return OnStage() ? mNode : NULL;
3014 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3016 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3018 const PropertyBase* property( NULL );
3020 // This method should only return a property of an object connected to the scene-graph
3026 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3028 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3029 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3031 property = animatable->GetSceneGraphProperty();
3033 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3035 CustomPropertyMetadata* custom = FindCustomProperty( index );
3036 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3038 property = custom->GetSceneGraphProperty();
3040 else if( NULL != mNode )
3044 case Dali::Actor::Property::SIZE:
3045 property = &mNode->mSize;
3048 case Dali::Actor::Property::SIZE_WIDTH:
3049 property = &mNode->mSize;
3052 case Dali::Actor::Property::SIZE_HEIGHT:
3053 property = &mNode->mSize;
3056 case Dali::Actor::Property::SIZE_DEPTH:
3057 property = &mNode->mSize;
3060 case Dali::Actor::Property::POSITION:
3061 property = &mNode->mPosition;
3064 case Dali::Actor::Property::POSITION_X:
3065 property = &mNode->mPosition;
3068 case Dali::Actor::Property::POSITION_Y:
3069 property = &mNode->mPosition;
3072 case Dali::Actor::Property::POSITION_Z:
3073 property = &mNode->mPosition;
3076 case Dali::Actor::Property::ORIENTATION:
3077 property = &mNode->mOrientation;
3080 case Dali::Actor::Property::SCALE:
3081 property = &mNode->mScale;
3084 case Dali::Actor::Property::SCALE_X:
3085 property = &mNode->mScale;
3088 case Dali::Actor::Property::SCALE_Y:
3089 property = &mNode->mScale;
3092 case Dali::Actor::Property::SCALE_Z:
3093 property = &mNode->mScale;
3096 case Dali::Actor::Property::VISIBLE:
3097 property = &mNode->mVisible;
3100 case Dali::Actor::Property::COLOR:
3101 property = &mNode->mColor;
3104 case Dali::Actor::Property::COLOR_RED:
3105 property = &mNode->mColor;
3108 case Dali::Actor::Property::COLOR_GREEN:
3109 property = &mNode->mColor;
3112 case Dali::Actor::Property::COLOR_BLUE:
3113 property = &mNode->mColor;
3116 case Dali::Actor::Property::COLOR_ALPHA:
3117 property = &mNode->mColor;
3128 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3130 const PropertyInputImpl* property( NULL );
3132 // This method should only return a property of an object connected to the scene-graph
3138 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3140 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3141 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3143 property = animatable->GetSceneGraphProperty();
3145 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3147 CustomPropertyMetadata* custom = FindCustomProperty( index );
3148 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3149 property = custom->GetSceneGraphProperty();
3151 else if( NULL != mNode )
3155 case Dali::Actor::Property::PARENT_ORIGIN:
3156 property = &mNode->mParentOrigin;
3159 case Dali::Actor::Property::PARENT_ORIGIN_X:
3160 property = &mNode->mParentOrigin;
3163 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3164 property = &mNode->mParentOrigin;
3167 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3168 property = &mNode->mParentOrigin;
3171 case Dali::Actor::Property::ANCHOR_POINT:
3172 property = &mNode->mAnchorPoint;
3175 case Dali::Actor::Property::ANCHOR_POINT_X:
3176 property = &mNode->mAnchorPoint;
3179 case Dali::Actor::Property::ANCHOR_POINT_Y:
3180 property = &mNode->mAnchorPoint;
3183 case Dali::Actor::Property::ANCHOR_POINT_Z:
3184 property = &mNode->mAnchorPoint;
3187 case Dali::Actor::Property::SIZE:
3188 property = &mNode->mSize;
3191 case Dali::Actor::Property::SIZE_WIDTH:
3192 property = &mNode->mSize;
3195 case Dali::Actor::Property::SIZE_HEIGHT:
3196 property = &mNode->mSize;
3199 case Dali::Actor::Property::SIZE_DEPTH:
3200 property = &mNode->mSize;
3203 case Dali::Actor::Property::POSITION:
3204 property = &mNode->mPosition;
3207 case Dali::Actor::Property::POSITION_X:
3208 property = &mNode->mPosition;
3211 case Dali::Actor::Property::POSITION_Y:
3212 property = &mNode->mPosition;
3215 case Dali::Actor::Property::POSITION_Z:
3216 property = &mNode->mPosition;
3219 case Dali::Actor::Property::WORLD_POSITION:
3220 property = &mNode->mWorldPosition;
3223 case Dali::Actor::Property::WORLD_POSITION_X:
3224 property = &mNode->mWorldPosition;
3227 case Dali::Actor::Property::WORLD_POSITION_Y:
3228 property = &mNode->mWorldPosition;
3231 case Dali::Actor::Property::WORLD_POSITION_Z:
3232 property = &mNode->mWorldPosition;
3235 case Dali::Actor::Property::ORIENTATION:
3236 property = &mNode->mOrientation;
3239 case Dali::Actor::Property::WORLD_ORIENTATION:
3240 property = &mNode->mWorldOrientation;
3243 case Dali::Actor::Property::SCALE:
3244 property = &mNode->mScale;
3247 case Dali::Actor::Property::SCALE_X:
3248 property = &mNode->mScale;
3251 case Dali::Actor::Property::SCALE_Y:
3252 property = &mNode->mScale;
3255 case Dali::Actor::Property::SCALE_Z:
3256 property = &mNode->mScale;
3259 case Dali::Actor::Property::WORLD_SCALE:
3260 property = &mNode->mWorldScale;
3263 case Dali::Actor::Property::VISIBLE:
3264 property = &mNode->mVisible;
3267 case Dali::Actor::Property::COLOR:
3268 property = &mNode->mColor;
3271 case Dali::Actor::Property::COLOR_RED:
3272 property = &mNode->mColor;
3275 case Dali::Actor::Property::COLOR_GREEN:
3276 property = &mNode->mColor;
3279 case Dali::Actor::Property::COLOR_BLUE:
3280 property = &mNode->mColor;
3283 case Dali::Actor::Property::COLOR_ALPHA:
3284 property = &mNode->mColor;
3287 case Dali::Actor::Property::WORLD_COLOR:
3288 property = &mNode->mWorldColor;
3291 case Dali::Actor::Property::WORLD_MATRIX:
3292 property = &mNode->mWorldMatrix;
3303 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3305 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3307 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3309 // check whether the animatable property is registered already, if not then register one.
3310 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3311 if( animatableProperty )
3313 componentIndex = animatableProperty->componentIndex;
3320 case Dali::Actor::Property::PARENT_ORIGIN_X:
3321 case Dali::Actor::Property::ANCHOR_POINT_X:
3322 case Dali::Actor::Property::SIZE_WIDTH:
3323 case Dali::Actor::Property::POSITION_X:
3324 case Dali::Actor::Property::WORLD_POSITION_X:
3325 case Dali::Actor::Property::SCALE_X:
3326 case Dali::Actor::Property::COLOR_RED:
3332 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3333 case Dali::Actor::Property::ANCHOR_POINT_Y:
3334 case Dali::Actor::Property::SIZE_HEIGHT:
3335 case Dali::Actor::Property::POSITION_Y:
3336 case Dali::Actor::Property::WORLD_POSITION_Y:
3337 case Dali::Actor::Property::SCALE_Y:
3338 case Dali::Actor::Property::COLOR_GREEN:
3344 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3345 case Dali::Actor::Property::ANCHOR_POINT_Z:
3346 case Dali::Actor::Property::SIZE_DEPTH:
3347 case Dali::Actor::Property::POSITION_Z:
3348 case Dali::Actor::Property::WORLD_POSITION_Z:
3349 case Dali::Actor::Property::SCALE_Z:
3350 case Dali::Actor::Property::COLOR_BLUE:
3356 case Dali::Actor::Property::COLOR_ALPHA:
3370 return componentIndex;
3373 void Actor::SetParent( Actor* parent, int index )
3377 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3381 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3384 // Instruct each actor to create a corresponding node in the scene graph
3385 ConnectToStage( parent->GetHierarchyDepth(), index );
3388 else // parent being set to NULL
3390 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3394 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3397 DALI_ASSERT_ALWAYS( mNode != NULL );
3401 // Disconnect the Node & its children from the scene-graph.
3402 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3405 // Instruct each actor to discard pointers to the scene-graph
3406 DisconnectFromStage();
3411 SceneGraph::Node* Actor::CreateNode() const
3416 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3419 Actor* actor = dynamic_cast< Actor* >( object );
3423 if( 0 == actionName.compare( ACTION_SHOW ) )
3425 actor->SetVisible( true );
3428 else if( 0 == actionName.compare( ACTION_HIDE ) )
3430 actor->SetVisible( false );
3438 void Actor::EnsureRelayoutData()
3440 // Assign relayout data.
3441 if( !mRelayoutData )
3443 mRelayoutData = new RelayoutData();
3447 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3449 // Check if actor is dependent on parent
3450 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3452 if( ( dimension & ( 1 << i ) ) )
3454 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3455 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3465 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3467 // Check if actor is dependent on children
3468 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3470 if( ( dimension & ( 1 << i ) ) )
3472 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3473 switch( resizePolicy )
3475 case ResizePolicy::FIT_TO_CHILDREN:
3476 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3492 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3494 return Actor::RelayoutDependentOnChildren( dimension );
3497 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3499 // Check each possible dimension and see if it is dependent on the input one
3500 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3502 if( dimension & ( 1 << i ) )
3504 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3511 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3513 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3515 if( dimension & ( 1 << i ) )
3517 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3522 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3524 // If more than one dimension is requested, just return the first one found
3525 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3527 if( ( dimension & ( 1 << i ) ) )
3529 return mRelayoutData->negotiatedDimensions[ i ];
3533 return 0.0f; // Default
3536 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3538 EnsureRelayoutData();
3540 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3542 if( dimension & ( 1 << i ) )
3544 mRelayoutData->dimensionPadding[ i ] = padding;
3549 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3551 if ( mRelayoutData )
3553 // If more than one dimension is requested, just return the first one found
3554 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3556 if( ( dimension & ( 1 << i ) ) )
3558 return mRelayoutData->dimensionPadding[ i ];
3563 return GetDefaultDimensionPadding();
3566 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
3568 EnsureRelayoutData();
3570 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3572 if( dimension & ( 1 << i ) )
3574 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3579 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
3581 if ( mRelayoutData )
3583 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3585 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
3595 float Actor::GetHeightForWidthBase( float width )
3597 float height = 0.0f;
3599 const Vector3 naturalSize = GetNaturalSize();
3600 if( naturalSize.width > 0.0f )
3602 height = naturalSize.height * width / naturalSize.width;
3604 else // we treat 0 as 1:1 aspect ratio
3612 float Actor::GetWidthForHeightBase( float height )
3616 const Vector3 naturalSize = GetNaturalSize();
3617 if( naturalSize.height > 0.0f )
3619 width = naturalSize.width * height / naturalSize.height;
3621 else // we treat 0 as 1:1 aspect ratio
3629 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
3631 // Fill to parent, taking size mode factor into account
3632 switch( child.GetResizePolicy( dimension ) )
3634 case ResizePolicy::FILL_TO_PARENT:
3636 return GetLatestSize( dimension );
3639 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3641 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
3644 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3646 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
3651 return GetLatestSize( dimension );
3656 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
3658 // Can be overridden in derived class
3659 return CalculateChildSizeBase( child, dimension );
3662 float Actor::GetHeightForWidth( float width )
3664 // Can be overridden in derived class
3665 return GetHeightForWidthBase( width );
3668 float Actor::GetWidthForHeight( float height )
3670 // Can be overridden in derived class
3671 return GetWidthForHeightBase( height );
3674 float Actor::GetLatestSize( Dimension::Type dimension ) const
3676 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
3679 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
3681 Vector2 padding = GetPadding( dimension );
3683 return GetLatestSize( dimension ) + padding.x + padding.y;
3686 float Actor::NegotiateFromParent( Dimension::Type dimension )
3688 Actor* parent = GetParent();
3691 Vector2 padding( GetPadding( dimension ) );
3692 Vector2 parentPadding( parent->GetPadding( dimension ) );
3693 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
3699 float Actor::NegotiateFromChildren( Dimension::Type dimension )
3701 float maxDimensionPoint = 0.0f;
3703 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3705 ActorPtr child = GetChildAt( i );
3707 if( !child->RelayoutDependentOnParent( dimension ) )
3709 // Calculate the min and max points that the children range across
3710 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
3711 float dimensionSize = child->GetRelayoutSize( dimension );
3712 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
3716 return maxDimensionPoint;
3719 float Actor::GetSize( Dimension::Type dimension ) const
3721 return GetDimensionValue( GetTargetSize(), dimension );
3724 float Actor::GetNaturalSize( Dimension::Type dimension ) const
3726 return GetDimensionValue( GetNaturalSize(), dimension );
3729 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
3731 switch( GetResizePolicy( dimension ) )
3733 case ResizePolicy::USE_NATURAL_SIZE:
3735 return GetNaturalSize( dimension );
3738 case ResizePolicy::FIXED:
3740 return GetDimensionValue( GetPreferredSize(), dimension );
3743 case ResizePolicy::USE_ASSIGNED_SIZE:
3745 return GetDimensionValue( maximumSize, dimension );
3748 case ResizePolicy::FILL_TO_PARENT:
3749 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3750 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3752 return NegotiateFromParent( dimension );
3755 case ResizePolicy::FIT_TO_CHILDREN:
3757 return NegotiateFromChildren( dimension );
3760 case ResizePolicy::DIMENSION_DEPENDENCY:
3762 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
3765 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
3767 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
3770 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
3772 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
3784 return 0.0f; // Default
3787 float Actor::ClampDimension( float size, Dimension::Type dimension )
3789 const float minSize = GetMinimumSize( dimension );
3790 const float maxSize = GetMaximumSize( dimension );
3792 return std::max( minSize, std::min( size, maxSize ) );
3795 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
3797 // Check if it needs to be negotiated
3798 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
3800 // Check that we havn't gotten into an infinite loop
3801 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
3802 bool recursionFound = false;
3803 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
3805 if( *it == searchActor )
3807 recursionFound = true;
3812 if( !recursionFound )
3814 // Record the path that we have taken
3815 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
3817 // Dimension dependency check
3818 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3820 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
3822 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
3824 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
3828 // Parent dependency check
3829 Actor* parent = GetParent();
3830 if( parent && RelayoutDependentOnParent( dimension ) )
3832 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
3835 // Children dependency check
3836 if( RelayoutDependentOnChildren( dimension ) )
3838 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3840 ActorPtr child = GetChildAt( i );
3842 // Only relayout child first if it is not dependent on this actor
3843 if( !child->RelayoutDependentOnParent( dimension ) )
3845 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
3850 // For deriving classes
3851 OnCalculateRelayoutSize( dimension );
3853 // All dependencies checked, calculate the size and set negotiated flag
3854 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
3856 SetNegotiatedDimension( newSize, dimension );
3857 SetLayoutNegotiated( true, dimension );
3859 // For deriving classes
3860 OnLayoutNegotiated( newSize, dimension );
3862 // This actor has been successfully processed, pop it off the recursion stack
3863 recursionStack.pop_back();
3867 // TODO: Break infinite loop
3868 SetLayoutNegotiated( true, dimension );
3873 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
3875 // Negotiate all dimensions that require it
3876 ActorDimensionStack recursionStack;
3878 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3880 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
3883 NegotiateDimension( dimension, allocatedSize, recursionStack );
3887 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
3889 switch( mRelayoutData->sizeSetPolicy )
3891 case SizeScalePolicy::USE_SIZE_SET:
3896 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
3898 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
3899 const Vector3 naturalSize = GetNaturalSize();
3900 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
3902 const float sizeRatio = size.width / size.height;
3903 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
3905 if( naturalSizeRatio < sizeRatio )
3907 return Vector2( naturalSizeRatio * size.height, size.height );
3909 else if( naturalSizeRatio > sizeRatio )
3911 return Vector2( size.width, size.width / naturalSizeRatio );
3922 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
3924 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
3925 const Vector3 naturalSize = GetNaturalSize();
3926 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
3928 const float sizeRatio = size.width / size.height;
3929 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
3931 if( naturalSizeRatio < sizeRatio )
3933 return Vector2( size.width, size.width / naturalSizeRatio );
3935 else if( naturalSizeRatio > sizeRatio )
3937 return Vector2( naturalSizeRatio * size.height, size.height );
3955 void Actor::SetNegotiatedSize( RelayoutContainer& container )
3957 // Do the set actor size
3958 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
3960 // Adjust for size set policy
3961 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
3963 // Lock the flag to stop recursive relayouts on set size
3964 mRelayoutData->insideRelayout = true;
3965 SetSize( negotiatedSize );
3966 mRelayoutData->insideRelayout = false;
3968 // Clear flags for all dimensions
3969 SetLayoutDirty( false );
3971 // Give deriving classes a chance to respond
3972 OnRelayout( negotiatedSize, container );
3974 if( !mOnRelayoutSignal.Empty() )
3976 Dali::Actor handle( this );
3977 mOnRelayoutSignal.Emit( handle );
3981 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
3983 // Do the negotiation
3984 NegotiateDimensions( allocatedSize );
3986 // Set the actor size
3987 SetNegotiatedSize( container );
3989 // Negotiate down to children
3990 const Vector2 newBounds = GetTargetSize().GetVectorXY();
3992 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3994 ActorPtr child = GetChildAt( i );
3996 // Only relayout if required
3997 if( child->RelayoutRequired() )
3999 container.Add( Dali::Actor( child.Get() ), newBounds );
4004 void Actor::RelayoutRequest( Dimension::Type dimension )
4006 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4007 if( relayoutController )
4009 Dali::Actor self( this );
4010 relayoutController->RequestRelayout( self, dimension );
4014 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4018 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4022 void Actor::SetPreferredSize( const Vector2& size )
4024 EnsureRelayoutData();
4026 if( size.width > 0.0f )
4028 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4031 if( size.height > 0.0f )
4033 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4036 mRelayoutData->preferredSize = size;
4041 Vector2 Actor::GetPreferredSize() const
4043 if ( mRelayoutData )
4045 return mRelayoutData->preferredSize;
4048 return GetDefaultPreferredSize();
4051 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4053 EnsureRelayoutData();
4055 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4057 if( dimension & ( 1 << i ) )
4059 mRelayoutData->minimumSize[ i ] = size;
4066 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4068 if ( mRelayoutData )
4070 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4072 if( dimension & ( 1 << i ) )
4074 return mRelayoutData->minimumSize[ i ];
4079 return 0.0f; // Default
4082 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4084 EnsureRelayoutData();
4086 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4088 if( dimension & ( 1 << i ) )
4090 mRelayoutData->maximumSize[ i ] = size;
4097 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4099 if ( mRelayoutData )
4101 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4103 if( dimension & ( 1 << i ) )
4105 return mRelayoutData->maximumSize[ i ];
4110 return FLT_MAX; // Default
4113 } // namespace Internal