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 )
1938 // This container is used instead of walking the Actor hierarchy.
1939 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
1940 ActorContainer connectionList;
1942 // This stage is atomic i.e. not interrupted by user callbacks.
1943 RecursiveConnectToStage( connectionList, parentDepth + 1 );
1945 // Notify applications about the newly connected actors.
1946 const ActorIter endIter = connectionList.end();
1947 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
1949 (*iter)->NotifyStageConnection();
1955 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth )
1957 DALI_ASSERT_ALWAYS( !OnStage() );
1962 ConnectToSceneGraph();
1964 // Notification for internal derived classes
1965 OnStageConnectionInternal();
1967 // This stage is atomic; avoid emitting callbacks until all Actors are connected
1968 connectionList.push_back( ActorPtr( this ) );
1970 // Recursively connect children
1973 ActorConstIter endIter = mChildren->end();
1974 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1976 (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
1982 * This method is called when the Actor is connected to the Stage.
1983 * The parent must have added its Node to the scene-graph.
1984 * The child must connect its Node to the parent's Node.
1985 * This is recursive; the child calls ConnectToStage() for its children.
1987 void Actor::ConnectToSceneGraph()
1989 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
1993 // Reparent Node in next Update
1994 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode );
1997 // Notify attachment
2000 mAttachment->Connect();
2003 // Request relayout on all actors that are added to the scenegraph
2006 // Notification for Object::Observers
2010 void Actor::NotifyStageConnection()
2012 // Actors can be removed (in a callback), before the on-stage stage is reported.
2013 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2014 if( OnStage() && !mOnStageSignalled )
2016 // Notification for external (CustomActor) derived classes
2017 OnStageConnectionExternal( mDepth );
2019 if( !mOnStageSignal.Empty() )
2021 Dali::Actor handle( this );
2022 mOnStageSignal.Emit( handle );
2025 // Guard against Remove during callbacks
2028 mOnStageSignalled = true; // signal required next time Actor is removed
2033 void Actor::DisconnectFromStage()
2035 // This container is used instead of walking the Actor hierachy.
2036 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2037 ActorContainer disconnectionList;
2039 // This stage is atomic i.e. not interrupted by user callbacks
2040 RecursiveDisconnectFromStage( disconnectionList );
2042 // Notify applications about the newly disconnected actors.
2043 const ActorIter endIter = disconnectionList.end();
2044 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2046 (*iter)->NotifyStageDisconnection();
2050 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2052 DALI_ASSERT_ALWAYS( OnStage() );
2054 // Recursively disconnect children
2057 ActorConstIter endIter = mChildren->end();
2058 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2060 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2064 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2065 disconnectionList.push_back( ActorPtr( this ) );
2067 // Notification for internal derived classes
2068 OnStageDisconnectionInternal();
2070 DisconnectFromSceneGraph();
2076 * This method is called by an actor or its parent, before a node removal message is sent.
2077 * This is recursive; the child calls DisconnectFromStage() for its children.
2079 void Actor::DisconnectFromSceneGraph()
2081 // Notification for Object::Observers
2082 OnSceneObjectRemove();
2084 // Notify attachment
2087 mAttachment->Disconnect();
2091 void Actor::NotifyStageDisconnection()
2093 // Actors can be added (in a callback), before the off-stage state is reported.
2094 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2095 // only do this step if there is a stage, i.e. Core is not being shut down
2096 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2098 // Notification for external (CustomeActor) derived classes
2099 OnStageDisconnectionExternal();
2101 if( !mOffStageSignal.Empty() )
2103 Dali::Actor handle( this );
2104 mOffStageSignal.Emit( handle );
2107 // Guard against Add during callbacks
2110 mOnStageSignalled = false; // signal required next time Actor is added
2115 bool Actor::IsNodeConnected() const
2117 bool connected( false );
2122 if( mNode->IsRoot() || mNode->GetParent() )
2131 unsigned int Actor::GetDefaultPropertyCount() const
2133 return DEFAULT_PROPERTY_COUNT;
2136 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2138 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2140 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2142 indices.PushBack( i );
2146 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2148 if( index < DEFAULT_PROPERTY_COUNT )
2150 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2156 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2158 Property::Index index = Property::INVALID_INDEX;
2160 // Look for name in default properties
2161 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2163 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2164 if( 0 == name.compare( property->name ) )
2174 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2176 if( index < DEFAULT_PROPERTY_COUNT )
2178 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2184 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2186 if( index < DEFAULT_PROPERTY_COUNT )
2188 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2194 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2196 if( index < DEFAULT_PROPERTY_COUNT )
2198 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2204 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2206 if( index < DEFAULT_PROPERTY_COUNT )
2208 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2211 // index out of range...return Property::NONE
2212 return Property::NONE;
2215 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2219 case Dali::Actor::Property::PARENT_ORIGIN:
2221 SetParentOrigin( property.Get< Vector3 >() );
2225 case Dali::Actor::Property::PARENT_ORIGIN_X:
2227 SetParentOriginX( property.Get< float >() );
2231 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2233 SetParentOriginY( property.Get< float >() );
2237 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2239 SetParentOriginZ( property.Get< float >() );
2243 case Dali::Actor::Property::ANCHOR_POINT:
2245 SetAnchorPoint( property.Get< Vector3 >() );
2249 case Dali::Actor::Property::ANCHOR_POINT_X:
2251 SetAnchorPointX( property.Get< float >() );
2255 case Dali::Actor::Property::ANCHOR_POINT_Y:
2257 SetAnchorPointY( property.Get< float >() );
2261 case Dali::Actor::Property::ANCHOR_POINT_Z:
2263 SetAnchorPointZ( property.Get< float >() );
2267 case Dali::Actor::Property::SIZE:
2269 SetSize( property.Get< Vector3 >() );
2273 case Dali::Actor::Property::SIZE_WIDTH:
2275 SetWidth( property.Get< float >() );
2279 case Dali::Actor::Property::SIZE_HEIGHT:
2281 SetHeight( property.Get< float >() );
2285 case Dali::Actor::Property::SIZE_DEPTH:
2287 SetDepth( property.Get< float >() );
2291 case Dali::Actor::Property::POSITION:
2293 SetPosition( property.Get< Vector3 >() );
2297 case Dali::Actor::Property::POSITION_X:
2299 SetX( property.Get< float >() );
2303 case Dali::Actor::Property::POSITION_Y:
2305 SetY( property.Get< float >() );
2309 case Dali::Actor::Property::POSITION_Z:
2311 SetZ( property.Get< float >() );
2315 case Dali::Actor::Property::ORIENTATION:
2317 SetOrientation( property.Get< Quaternion >() );
2321 case Dali::Actor::Property::SCALE:
2323 SetScale( property.Get< Vector3 >() );
2327 case Dali::Actor::Property::SCALE_X:
2329 SetScaleX( property.Get< float >() );
2333 case Dali::Actor::Property::SCALE_Y:
2335 SetScaleY( property.Get< float >() );
2339 case Dali::Actor::Property::SCALE_Z:
2341 SetScaleZ( property.Get< float >() );
2345 case Dali::Actor::Property::VISIBLE:
2347 SetVisible( property.Get< bool >() );
2351 case Dali::Actor::Property::COLOR:
2353 SetColor( property.Get< Vector4 >() );
2357 case Dali::Actor::Property::COLOR_RED:
2359 SetColorRed( property.Get< float >() );
2363 case Dali::Actor::Property::COLOR_GREEN:
2365 SetColorGreen( property.Get< float >() );
2369 case Dali::Actor::Property::COLOR_BLUE:
2371 SetColorBlue( property.Get< float >() );
2375 case Dali::Actor::Property::COLOR_ALPHA:
2377 SetOpacity( property.Get< float >() );
2381 case Dali::Actor::Property::NAME:
2383 SetName( property.Get< std::string >() );
2387 case Dali::Actor::Property::SENSITIVE:
2389 SetSensitive( property.Get< bool >() );
2393 case Dali::Actor::Property::LEAVE_REQUIRED:
2395 SetLeaveRequired( property.Get< bool >() );
2399 case Dali::Actor::Property::INHERIT_ORIENTATION:
2401 SetInheritOrientation( property.Get< bool >() );
2405 case Dali::Actor::Property::INHERIT_SCALE:
2407 SetInheritScale( property.Get< bool >() );
2411 case Dali::Actor::Property::COLOR_MODE:
2413 SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2417 case Dali::Actor::Property::POSITION_INHERITANCE:
2419 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2423 case Dali::Actor::Property::DRAW_MODE:
2425 SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2429 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2431 SetSizeModeFactor( property.Get< Vector3 >() );
2435 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2437 ResizePolicy::Type type;
2438 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2440 SetResizePolicy( type, Dimension::WIDTH );
2445 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2447 ResizePolicy::Type type;
2448 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2450 SetResizePolicy( type, Dimension::HEIGHT );
2455 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2457 SizeScalePolicy::Type type;
2458 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount, type ) )
2460 SetSizeScalePolicy( type );
2465 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2467 if( property.Get< bool >() )
2469 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2474 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2476 if( property.Get< bool >() )
2478 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2483 case Dali::Actor::Property::PADDING:
2485 Vector4 padding = property.Get< Vector4 >();
2486 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2487 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2491 case Dali::Actor::Property::MINIMUM_SIZE:
2493 Vector2 size = property.Get< Vector2 >();
2494 SetMinimumSize( size.x, Dimension::WIDTH );
2495 SetMinimumSize( size.y, Dimension::HEIGHT );
2499 case Dali::Actor::Property::MAXIMUM_SIZE:
2501 Vector2 size = property.Get< Vector2 >();
2502 SetMaximumSize( size.x, Dimension::WIDTH );
2503 SetMaximumSize( size.y, Dimension::HEIGHT );
2509 // this can happen in the case of a non-animatable default property so just do nothing
2515 // TODO: This method needs to be removed
2516 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2518 switch( entry.type )
2520 case Property::BOOLEAN:
2522 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2523 DALI_ASSERT_DEBUG( NULL != property );
2525 // property is being used in a separate thread; queue a message to set the property
2526 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2531 case Property::INTEGER:
2533 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2534 DALI_ASSERT_DEBUG( NULL != property );
2536 // property is being used in a separate thread; queue a message to set the property
2537 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2542 case Property::FLOAT:
2544 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2545 DALI_ASSERT_DEBUG( NULL != property );
2547 // property is being used in a separate thread; queue a message to set the property
2548 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2553 case Property::VECTOR2:
2555 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2556 DALI_ASSERT_DEBUG( NULL != property );
2558 // property is being used in a separate thread; queue a message to set the property
2559 if(entry.componentIndex == 0)
2561 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2563 else if(entry.componentIndex == 1)
2565 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2569 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2575 case Property::VECTOR3:
2577 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2578 DALI_ASSERT_DEBUG( NULL != property );
2580 // property is being used in a separate thread; queue a message to set the property
2581 if(entry.componentIndex == 0)
2583 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2585 else if(entry.componentIndex == 1)
2587 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2589 else if(entry.componentIndex == 2)
2591 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2595 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2601 case Property::VECTOR4:
2603 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2604 DALI_ASSERT_DEBUG( NULL != property );
2606 // property is being used in a separate thread; queue a message to set the property
2607 if(entry.componentIndex == 0)
2609 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
2611 else if(entry.componentIndex == 1)
2613 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
2615 else if(entry.componentIndex == 2)
2617 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
2619 else if(entry.componentIndex == 3)
2621 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
2625 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2631 case Property::ROTATION:
2633 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
2634 DALI_ASSERT_DEBUG( NULL != property );
2636 // property is being used in a separate thread; queue a message to set the property
2637 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
2642 case Property::MATRIX:
2644 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
2645 DALI_ASSERT_DEBUG( NULL != property );
2647 // property is being used in a separate thread; queue a message to set the property
2648 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
2653 case Property::MATRIX3:
2655 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
2656 DALI_ASSERT_DEBUG( NULL != property );
2658 // property is being used in a separate thread; queue a message to set the property
2659 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
2666 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
2672 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
2674 Property::Value value;
2678 case Dali::Actor::Property::PARENT_ORIGIN:
2680 value = GetCurrentParentOrigin();
2684 case Dali::Actor::Property::PARENT_ORIGIN_X:
2686 value = GetCurrentParentOrigin().x;
2690 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2692 value = GetCurrentParentOrigin().y;
2696 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2698 value = GetCurrentParentOrigin().z;
2702 case Dali::Actor::Property::ANCHOR_POINT:
2704 value = GetCurrentAnchorPoint();
2708 case Dali::Actor::Property::ANCHOR_POINT_X:
2710 value = GetCurrentAnchorPoint().x;
2714 case Dali::Actor::Property::ANCHOR_POINT_Y:
2716 value = GetCurrentAnchorPoint().y;
2720 case Dali::Actor::Property::ANCHOR_POINT_Z:
2722 value = GetCurrentAnchorPoint().z;
2726 case Dali::Actor::Property::SIZE:
2728 value = GetCurrentSize();
2732 case Dali::Actor::Property::SIZE_WIDTH:
2734 value = GetCurrentSize().width;
2738 case Dali::Actor::Property::SIZE_HEIGHT:
2740 value = GetCurrentSize().height;
2744 case Dali::Actor::Property::SIZE_DEPTH:
2746 value = GetCurrentSize().depth;
2750 case Dali::Actor::Property::POSITION:
2752 value = GetCurrentPosition();
2756 case Dali::Actor::Property::POSITION_X:
2758 value = GetCurrentPosition().x;
2762 case Dali::Actor::Property::POSITION_Y:
2764 value = GetCurrentPosition().y;
2768 case Dali::Actor::Property::POSITION_Z:
2770 value = GetCurrentPosition().z;
2774 case Dali::Actor::Property::WORLD_POSITION:
2776 value = GetCurrentWorldPosition();
2780 case Dali::Actor::Property::WORLD_POSITION_X:
2782 value = GetCurrentWorldPosition().x;
2786 case Dali::Actor::Property::WORLD_POSITION_Y:
2788 value = GetCurrentWorldPosition().y;
2792 case Dali::Actor::Property::WORLD_POSITION_Z:
2794 value = GetCurrentWorldPosition().z;
2798 case Dali::Actor::Property::ORIENTATION:
2800 value = GetCurrentOrientation();
2804 case Dali::Actor::Property::WORLD_ORIENTATION:
2806 value = GetCurrentWorldOrientation();
2810 case Dali::Actor::Property::SCALE:
2812 value = GetCurrentScale();
2816 case Dali::Actor::Property::SCALE_X:
2818 value = GetCurrentScale().x;
2822 case Dali::Actor::Property::SCALE_Y:
2824 value = GetCurrentScale().y;
2828 case Dali::Actor::Property::SCALE_Z:
2830 value = GetCurrentScale().z;
2834 case Dali::Actor::Property::WORLD_SCALE:
2836 value = GetCurrentWorldScale();
2840 case Dali::Actor::Property::VISIBLE:
2842 value = IsVisible();
2846 case Dali::Actor::Property::COLOR:
2848 value = GetCurrentColor();
2852 case Dali::Actor::Property::COLOR_RED:
2854 value = GetCurrentColor().r;
2858 case Dali::Actor::Property::COLOR_GREEN:
2860 value = GetCurrentColor().g;
2864 case Dali::Actor::Property::COLOR_BLUE:
2866 value = GetCurrentColor().b;
2870 case Dali::Actor::Property::COLOR_ALPHA:
2872 value = GetCurrentColor().a;
2876 case Dali::Actor::Property::WORLD_COLOR:
2878 value = GetCurrentWorldColor();
2882 case Dali::Actor::Property::WORLD_MATRIX:
2884 value = GetCurrentWorldMatrix();
2888 case Dali::Actor::Property::NAME:
2894 case Dali::Actor::Property::SENSITIVE:
2896 value = IsSensitive();
2900 case Dali::Actor::Property::LEAVE_REQUIRED:
2902 value = GetLeaveRequired();
2906 case Dali::Actor::Property::INHERIT_ORIENTATION:
2908 value = IsOrientationInherited();
2912 case Dali::Actor::Property::INHERIT_SCALE:
2914 value = IsScaleInherited();
2918 case Dali::Actor::Property::COLOR_MODE:
2920 value = Scripting::GetColorMode( GetColorMode() );
2924 case Dali::Actor::Property::POSITION_INHERITANCE:
2926 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
2930 case Dali::Actor::Property::DRAW_MODE:
2932 value = Scripting::GetDrawMode( GetDrawMode() );
2936 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2938 value = GetSizeModeFactor();
2942 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2944 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
2948 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2950 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
2954 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2956 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
2960 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2962 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
2966 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2968 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
2972 case Dali::Actor::Property::PADDING:
2974 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
2975 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
2976 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
2980 case Dali::Actor::Property::MINIMUM_SIZE:
2982 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
2986 case Dali::Actor::Property::MAXIMUM_SIZE:
2988 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
2994 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3002 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3007 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3009 // This method should only return an object connected to the scene-graph
3010 return OnStage() ? mNode : NULL;
3013 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3015 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3017 const PropertyBase* property( NULL );
3019 // This method should only return a property of an object connected to the scene-graph
3025 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3027 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3028 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3030 property = animatable->GetSceneGraphProperty();
3032 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3034 CustomPropertyMetadata* custom = FindCustomProperty( index );
3035 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3037 property = custom->GetSceneGraphProperty();
3039 else if( NULL != mNode )
3043 case Dali::Actor::Property::SIZE:
3044 property = &mNode->mSize;
3047 case Dali::Actor::Property::SIZE_WIDTH:
3048 property = &mNode->mSize;
3051 case Dali::Actor::Property::SIZE_HEIGHT:
3052 property = &mNode->mSize;
3055 case Dali::Actor::Property::SIZE_DEPTH:
3056 property = &mNode->mSize;
3059 case Dali::Actor::Property::POSITION:
3060 property = &mNode->mPosition;
3063 case Dali::Actor::Property::POSITION_X:
3064 property = &mNode->mPosition;
3067 case Dali::Actor::Property::POSITION_Y:
3068 property = &mNode->mPosition;
3071 case Dali::Actor::Property::POSITION_Z:
3072 property = &mNode->mPosition;
3075 case Dali::Actor::Property::ORIENTATION:
3076 property = &mNode->mOrientation;
3079 case Dali::Actor::Property::SCALE:
3080 property = &mNode->mScale;
3083 case Dali::Actor::Property::SCALE_X:
3084 property = &mNode->mScale;
3087 case Dali::Actor::Property::SCALE_Y:
3088 property = &mNode->mScale;
3091 case Dali::Actor::Property::SCALE_Z:
3092 property = &mNode->mScale;
3095 case Dali::Actor::Property::VISIBLE:
3096 property = &mNode->mVisible;
3099 case Dali::Actor::Property::COLOR:
3100 property = &mNode->mColor;
3103 case Dali::Actor::Property::COLOR_RED:
3104 property = &mNode->mColor;
3107 case Dali::Actor::Property::COLOR_GREEN:
3108 property = &mNode->mColor;
3111 case Dali::Actor::Property::COLOR_BLUE:
3112 property = &mNode->mColor;
3115 case Dali::Actor::Property::COLOR_ALPHA:
3116 property = &mNode->mColor;
3127 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3129 const PropertyInputImpl* property( NULL );
3131 // This method should only return a property of an object connected to the scene-graph
3137 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3139 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3140 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3142 property = animatable->GetSceneGraphProperty();
3144 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3146 CustomPropertyMetadata* custom = FindCustomProperty( index );
3147 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3148 property = custom->GetSceneGraphProperty();
3150 else if( NULL != mNode )
3154 case Dali::Actor::Property::PARENT_ORIGIN:
3155 property = &mNode->mParentOrigin;
3158 case Dali::Actor::Property::PARENT_ORIGIN_X:
3159 property = &mNode->mParentOrigin;
3162 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3163 property = &mNode->mParentOrigin;
3166 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3167 property = &mNode->mParentOrigin;
3170 case Dali::Actor::Property::ANCHOR_POINT:
3171 property = &mNode->mAnchorPoint;
3174 case Dali::Actor::Property::ANCHOR_POINT_X:
3175 property = &mNode->mAnchorPoint;
3178 case Dali::Actor::Property::ANCHOR_POINT_Y:
3179 property = &mNode->mAnchorPoint;
3182 case Dali::Actor::Property::ANCHOR_POINT_Z:
3183 property = &mNode->mAnchorPoint;
3186 case Dali::Actor::Property::SIZE:
3187 property = &mNode->mSize;
3190 case Dali::Actor::Property::SIZE_WIDTH:
3191 property = &mNode->mSize;
3194 case Dali::Actor::Property::SIZE_HEIGHT:
3195 property = &mNode->mSize;
3198 case Dali::Actor::Property::SIZE_DEPTH:
3199 property = &mNode->mSize;
3202 case Dali::Actor::Property::POSITION:
3203 property = &mNode->mPosition;
3206 case Dali::Actor::Property::POSITION_X:
3207 property = &mNode->mPosition;
3210 case Dali::Actor::Property::POSITION_Y:
3211 property = &mNode->mPosition;
3214 case Dali::Actor::Property::POSITION_Z:
3215 property = &mNode->mPosition;
3218 case Dali::Actor::Property::WORLD_POSITION:
3219 property = &mNode->mWorldPosition;
3222 case Dali::Actor::Property::WORLD_POSITION_X:
3223 property = &mNode->mWorldPosition;
3226 case Dali::Actor::Property::WORLD_POSITION_Y:
3227 property = &mNode->mWorldPosition;
3230 case Dali::Actor::Property::WORLD_POSITION_Z:
3231 property = &mNode->mWorldPosition;
3234 case Dali::Actor::Property::ORIENTATION:
3235 property = &mNode->mOrientation;
3238 case Dali::Actor::Property::WORLD_ORIENTATION:
3239 property = &mNode->mWorldOrientation;
3242 case Dali::Actor::Property::SCALE:
3243 property = &mNode->mScale;
3246 case Dali::Actor::Property::SCALE_X:
3247 property = &mNode->mScale;
3250 case Dali::Actor::Property::SCALE_Y:
3251 property = &mNode->mScale;
3254 case Dali::Actor::Property::SCALE_Z:
3255 property = &mNode->mScale;
3258 case Dali::Actor::Property::WORLD_SCALE:
3259 property = &mNode->mWorldScale;
3262 case Dali::Actor::Property::VISIBLE:
3263 property = &mNode->mVisible;
3266 case Dali::Actor::Property::COLOR:
3267 property = &mNode->mColor;
3270 case Dali::Actor::Property::COLOR_RED:
3271 property = &mNode->mColor;
3274 case Dali::Actor::Property::COLOR_GREEN:
3275 property = &mNode->mColor;
3278 case Dali::Actor::Property::COLOR_BLUE:
3279 property = &mNode->mColor;
3282 case Dali::Actor::Property::COLOR_ALPHA:
3283 property = &mNode->mColor;
3286 case Dali::Actor::Property::WORLD_COLOR:
3287 property = &mNode->mWorldColor;
3290 case Dali::Actor::Property::WORLD_MATRIX:
3291 property = &mNode->mWorldMatrix;
3302 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3304 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3306 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3308 // check whether the animatable property is registered already, if not then register one.
3309 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3310 if( animatableProperty )
3312 componentIndex = animatableProperty->componentIndex;
3319 case Dali::Actor::Property::PARENT_ORIGIN_X:
3320 case Dali::Actor::Property::ANCHOR_POINT_X:
3321 case Dali::Actor::Property::SIZE_WIDTH:
3322 case Dali::Actor::Property::POSITION_X:
3323 case Dali::Actor::Property::WORLD_POSITION_X:
3324 case Dali::Actor::Property::SCALE_X:
3325 case Dali::Actor::Property::COLOR_RED:
3331 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3332 case Dali::Actor::Property::ANCHOR_POINT_Y:
3333 case Dali::Actor::Property::SIZE_HEIGHT:
3334 case Dali::Actor::Property::POSITION_Y:
3335 case Dali::Actor::Property::WORLD_POSITION_Y:
3336 case Dali::Actor::Property::SCALE_Y:
3337 case Dali::Actor::Property::COLOR_GREEN:
3343 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3344 case Dali::Actor::Property::ANCHOR_POINT_Z:
3345 case Dali::Actor::Property::SIZE_DEPTH:
3346 case Dali::Actor::Property::POSITION_Z:
3347 case Dali::Actor::Property::WORLD_POSITION_Z:
3348 case Dali::Actor::Property::SCALE_Z:
3349 case Dali::Actor::Property::COLOR_BLUE:
3355 case Dali::Actor::Property::COLOR_ALPHA:
3369 return componentIndex;
3372 void Actor::SetParent( Actor* parent )
3376 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3380 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3383 // Instruct each actor to create a corresponding node in the scene graph
3384 ConnectToStage( parent->GetHierarchyDepth() );
3387 else // parent being set to NULL
3389 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3393 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3396 DALI_ASSERT_ALWAYS( mNode != NULL );
3400 // Disconnect the Node & its children from the scene-graph.
3401 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3404 // Instruct each actor to discard pointers to the scene-graph
3405 DisconnectFromStage();
3410 SceneGraph::Node* Actor::CreateNode() const
3415 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3418 Actor* actor = dynamic_cast< Actor* >( object );
3422 if( 0 == actionName.compare( ACTION_SHOW ) )
3424 actor->SetVisible( true );
3427 else if( 0 == actionName.compare( ACTION_HIDE ) )
3429 actor->SetVisible( false );
3437 void Actor::EnsureRelayoutData()
3439 // Assign relayout data.
3440 if( !mRelayoutData )
3442 mRelayoutData = new RelayoutData();
3446 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3448 // Check if actor is dependent on parent
3449 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3451 if( ( dimension & ( 1 << i ) ) )
3453 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3454 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3464 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3466 // Check if actor is dependent on children
3467 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3469 if( ( dimension & ( 1 << i ) ) )
3471 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3472 switch( resizePolicy )
3474 case ResizePolicy::FIT_TO_CHILDREN:
3475 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3491 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3493 return Actor::RelayoutDependentOnChildren( dimension );
3496 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3498 // Check each possible dimension and see if it is dependent on the input one
3499 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3501 if( dimension & ( 1 << i ) )
3503 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3510 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3512 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3514 if( dimension & ( 1 << i ) )
3516 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3521 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3523 // If more than one dimension is requested, just return the first one found
3524 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3526 if( ( dimension & ( 1 << i ) ) )
3528 return mRelayoutData->negotiatedDimensions[ i ];
3532 return 0.0f; // Default
3535 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3537 EnsureRelayoutData();
3539 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3541 if( dimension & ( 1 << i ) )
3543 mRelayoutData->dimensionPadding[ i ] = padding;
3548 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3550 if ( mRelayoutData )
3552 // If more than one dimension is requested, just return the first one found
3553 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3555 if( ( dimension & ( 1 << i ) ) )
3557 return mRelayoutData->dimensionPadding[ i ];
3562 return GetDefaultDimensionPadding();
3565 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
3567 EnsureRelayoutData();
3569 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3571 if( dimension & ( 1 << i ) )
3573 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3578 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
3580 if ( mRelayoutData )
3582 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3584 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
3594 float Actor::GetHeightForWidthBase( float width )
3596 float height = 0.0f;
3598 const Vector3 naturalSize = GetNaturalSize();
3599 if( naturalSize.width > 0.0f )
3601 height = naturalSize.height * width / naturalSize.width;
3603 else // we treat 0 as 1:1 aspect ratio
3611 float Actor::GetWidthForHeightBase( float height )
3615 const Vector3 naturalSize = GetNaturalSize();
3616 if( naturalSize.height > 0.0f )
3618 width = naturalSize.width * height / naturalSize.height;
3620 else // we treat 0 as 1:1 aspect ratio
3628 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
3630 // Fill to parent, taking size mode factor into account
3631 switch( child.GetResizePolicy( dimension ) )
3633 case ResizePolicy::FILL_TO_PARENT:
3635 return GetLatestSize( dimension );
3638 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3640 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
3643 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3645 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
3650 return GetLatestSize( dimension );
3655 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
3657 // Can be overridden in derived class
3658 return CalculateChildSizeBase( child, dimension );
3661 float Actor::GetHeightForWidth( float width )
3663 // Can be overridden in derived class
3664 return GetHeightForWidthBase( width );
3667 float Actor::GetWidthForHeight( float height )
3669 // Can be overridden in derived class
3670 return GetWidthForHeightBase( height );
3673 float Actor::GetLatestSize( Dimension::Type dimension ) const
3675 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
3678 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
3680 Vector2 padding = GetPadding( dimension );
3682 return GetLatestSize( dimension ) + padding.x + padding.y;
3685 float Actor::NegotiateFromParent( Dimension::Type dimension )
3687 Actor* parent = GetParent();
3690 Vector2 padding( GetPadding( dimension ) );
3691 Vector2 parentPadding( parent->GetPadding( dimension ) );
3692 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
3698 float Actor::NegotiateFromChildren( Dimension::Type dimension )
3700 float maxDimensionPoint = 0.0f;
3702 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3704 ActorPtr child = GetChildAt( i );
3706 if( !child->RelayoutDependentOnParent( dimension ) )
3708 // Calculate the min and max points that the children range across
3709 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
3710 float dimensionSize = child->GetRelayoutSize( dimension );
3711 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
3715 return maxDimensionPoint;
3718 float Actor::GetSize( Dimension::Type dimension ) const
3720 return GetDimensionValue( GetTargetSize(), dimension );
3723 float Actor::GetNaturalSize( Dimension::Type dimension ) const
3725 return GetDimensionValue( GetNaturalSize(), dimension );
3728 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
3730 switch( GetResizePolicy( dimension ) )
3732 case ResizePolicy::USE_NATURAL_SIZE:
3734 return GetNaturalSize( dimension );
3737 case ResizePolicy::FIXED:
3739 return GetDimensionValue( GetPreferredSize(), dimension );
3742 case ResizePolicy::USE_ASSIGNED_SIZE:
3744 return GetDimensionValue( maximumSize, dimension );
3747 case ResizePolicy::FILL_TO_PARENT:
3748 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3749 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3751 return NegotiateFromParent( dimension );
3754 case ResizePolicy::FIT_TO_CHILDREN:
3756 return NegotiateFromChildren( dimension );
3759 case ResizePolicy::DIMENSION_DEPENDENCY:
3761 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
3764 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
3766 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
3769 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
3771 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
3783 return 0.0f; // Default
3786 float Actor::ClampDimension( float size, Dimension::Type dimension )
3788 const float minSize = GetMinimumSize( dimension );
3789 const float maxSize = GetMaximumSize( dimension );
3791 return std::max( minSize, std::min( size, maxSize ) );
3794 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
3796 // Check if it needs to be negotiated
3797 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
3799 // Check that we havn't gotten into an infinite loop
3800 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
3801 bool recursionFound = false;
3802 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
3804 if( *it == searchActor )
3806 recursionFound = true;
3811 if( !recursionFound )
3813 // Record the path that we have taken
3814 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
3816 // Dimension dependency check
3817 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3819 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
3821 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
3823 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
3827 // Parent dependency check
3828 Actor* parent = GetParent();
3829 if( parent && RelayoutDependentOnParent( dimension ) )
3831 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
3834 // Children dependency check
3835 if( RelayoutDependentOnChildren( dimension ) )
3837 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3839 ActorPtr child = GetChildAt( i );
3841 // Only relayout child first if it is not dependent on this actor
3842 if( !child->RelayoutDependentOnParent( dimension ) )
3844 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
3849 // For deriving classes
3850 OnCalculateRelayoutSize( dimension );
3852 // All dependencies checked, calculate the size and set negotiated flag
3853 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
3855 SetNegotiatedDimension( newSize, dimension );
3856 SetLayoutNegotiated( true, dimension );
3858 // For deriving classes
3859 OnLayoutNegotiated( newSize, dimension );
3861 // This actor has been successfully processed, pop it off the recursion stack
3862 recursionStack.pop_back();
3866 // TODO: Break infinite loop
3867 SetLayoutNegotiated( true, dimension );
3872 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
3874 // Negotiate all dimensions that require it
3875 ActorDimensionStack recursionStack;
3877 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3879 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
3882 NegotiateDimension( dimension, allocatedSize, recursionStack );
3886 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
3888 switch( mRelayoutData->sizeSetPolicy )
3890 case SizeScalePolicy::USE_SIZE_SET:
3895 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
3897 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
3898 const Vector3 naturalSize = GetNaturalSize();
3899 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
3901 const float sizeRatio = size.width / size.height;
3902 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
3904 if( naturalSizeRatio < sizeRatio )
3906 return Vector2( naturalSizeRatio * size.height, size.height );
3908 else if( naturalSizeRatio > sizeRatio )
3910 return Vector2( size.width, size.width / naturalSizeRatio );
3921 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
3923 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
3924 const Vector3 naturalSize = GetNaturalSize();
3925 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
3927 const float sizeRatio = size.width / size.height;
3928 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
3930 if( naturalSizeRatio < sizeRatio )
3932 return Vector2( size.width, size.width / naturalSizeRatio );
3934 else if( naturalSizeRatio > sizeRatio )
3936 return Vector2( naturalSizeRatio * size.height, size.height );
3954 void Actor::SetNegotiatedSize( RelayoutContainer& container )
3956 // Do the set actor size
3957 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
3959 // Adjust for size set policy
3960 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
3962 // Lock the flag to stop recursive relayouts on set size
3963 mRelayoutData->insideRelayout = true;
3964 SetSize( negotiatedSize );
3965 mRelayoutData->insideRelayout = false;
3967 // Clear flags for all dimensions
3968 SetLayoutDirty( false );
3970 // Give deriving classes a chance to respond
3971 OnRelayout( negotiatedSize, container );
3973 if( !mOnRelayoutSignal.Empty() )
3975 Dali::Actor handle( this );
3976 mOnRelayoutSignal.Emit( handle );
3980 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
3982 // Do the negotiation
3983 NegotiateDimensions( allocatedSize );
3985 // Set the actor size
3986 SetNegotiatedSize( container );
3988 // Negotiate down to children
3989 const Vector2 newBounds = GetTargetSize().GetVectorXY();
3991 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3993 ActorPtr child = GetChildAt( i );
3995 // Only relayout if required
3996 if( child->RelayoutRequired() )
3998 container.Add( Dali::Actor( child.Get() ), newBounds );
4003 void Actor::RelayoutRequest( Dimension::Type dimension )
4005 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4006 if( relayoutController )
4008 Dali::Actor self( this );
4009 relayoutController->RequestRelayout( self, dimension );
4013 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4017 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4021 void Actor::SetPreferredSize( const Vector2& size )
4023 EnsureRelayoutData();
4025 if( size.width > 0.0f )
4027 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4030 if( size.height > 0.0f )
4032 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4035 mRelayoutData->preferredSize = size;
4040 Vector2 Actor::GetPreferredSize() const
4042 if ( mRelayoutData )
4044 return mRelayoutData->preferredSize;
4047 return GetDefaultPreferredSize();
4050 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4052 EnsureRelayoutData();
4054 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4056 if( dimension & ( 1 << i ) )
4058 mRelayoutData->minimumSize[ i ] = size;
4065 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4067 if ( mRelayoutData )
4069 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4071 if( dimension & ( 1 << i ) )
4073 return mRelayoutData->minimumSize[ i ];
4078 return 0.0f; // Default
4081 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4083 EnsureRelayoutData();
4085 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4087 if( dimension & ( 1 << i ) )
4089 mRelayoutData->maximumSize[ i ] = size;
4096 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4098 if ( mRelayoutData )
4100 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4102 if( dimension & ( 1 << i ) )
4104 return mRelayoutData->maximumSize[ i ];
4109 return FLT_MAX; // Default
4112 } // namespace Internal