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 );
1371 unsigned int Actor::GetRendererCount() const
1373 //TODO: MESH_REWORK : Add support for multiple renderers
1374 RendererAttachment* attachment = dynamic_cast<RendererAttachment*>(mAttachment.Get());
1375 return attachment ? 1u : 0u;
1378 Renderer& Actor::GetRendererAt( unsigned int index )
1380 //TODO: MESH_REWORK : Add support for multiple renderers
1381 DALI_ASSERT_DEBUG( index == 0 && "Only one renderer is supported." );
1383 //TODO: MESH_REWORK : Temporary code
1384 RendererAttachment* attachment = dynamic_cast<RendererAttachment*>(mAttachment.Get());
1385 DALI_ASSERT_ALWAYS( attachment && "Actor doesn't have a renderer" );
1387 return attachment->GetRenderer();
1390 void Actor::RemoveRenderer( Renderer& renderer )
1392 //TODO: MESH_REWORK : Add support for multiple renderers
1396 void Actor::RemoveRenderer( unsigned int index )
1398 //TODO: MESH_REWORK : Add support for multiple renderers
1402 void Actor::SetOverlay( bool enable )
1404 // Setting STENCIL will override OVERLAY_2D
1405 if( DrawMode::STENCIL != mDrawMode )
1407 SetDrawMode( enable ? DrawMode::OVERLAY_2D : DrawMode::NORMAL );
1411 bool Actor::IsOverlay() const
1413 return ( DrawMode::OVERLAY_2D == mDrawMode );
1416 void Actor::SetDrawMode( DrawMode::Type drawMode )
1418 // this flag is not animatable so keep the value
1419 mDrawMode = drawMode;
1422 // mNode is being used in a separate thread; queue a message to set the value
1423 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1427 DrawMode::Type Actor::GetDrawMode() const
1432 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1434 // only valid when on-stage
1435 StagePtr stage = Stage::GetCurrent();
1436 if( stage && OnStage() )
1438 const RenderTaskList& taskList = stage->GetRenderTaskList();
1440 Vector2 converted( screenX, screenY );
1442 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1443 const int taskCount = taskList.GetTaskCount();
1444 for( int i = taskCount - 1; i >= 0; --i )
1446 Dali::RenderTask task = taskList.GetTask( i );
1447 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1449 // found a task where this conversion was ok so return
1457 bool Actor::ScreenToLocal( RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1459 bool retval = false;
1460 // only valid when on-stage
1463 CameraActor* camera = renderTask.GetCameraActor();
1467 renderTask.GetViewport( viewport );
1469 // need to translate coordinates to render tasks coordinate space
1470 Vector2 converted( screenX, screenY );
1471 if( renderTask.TranslateCoordinates( converted ) )
1473 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1480 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1482 // Early-out if mNode is NULL
1488 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1490 // Calculate the ModelView matrix
1491 Matrix modelView( false/*don't init*/);
1492 // need to use the components as world matrix is only updated for actors that need it
1493 modelView.SetTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1494 Matrix::Multiply( modelView, modelView, viewMatrix );
1496 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1497 Matrix invertedMvp( false/*don't init*/);
1498 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1499 bool success = invertedMvp.Invert();
1501 // Convert to GL coordinates
1502 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1507 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1514 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1520 if( XyPlaneIntersect( nearPos, farPos, local ) )
1522 Vector3 size = GetCurrentSize();
1523 localX = local.x + size.x * 0.5f;
1524 localY = local.y + size.y * 0.5f;
1535 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1538 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1540 Mathematical Formulation
1542 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1544 ( p - c ) dot ( p - c ) = r^2
1546 Given a ray with a point of origin 'o', and a direction vector 'd':
1548 ray(t) = o + td, t >= 0
1550 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1552 (o + td - c ) dot ( o + td - c ) = r^2
1554 To solve for t we first expand the above into a more recognisable quadratic equation form
1556 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1565 B = 2( o - c ) dot d
1566 C = ( o - c ) dot ( o - c ) - r^2
1568 which can be solved using a standard quadratic formula.
1570 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1572 Practical Simplification
1574 In a renderer, we often differentiate between world space and object space. In the object space
1575 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1576 into object space, the mathematical solution presented above can be simplified significantly.
1578 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1582 and we can find the t at which the (transformed) ray intersects the sphere by
1584 ( o + td ) dot ( o + td ) = r^2
1586 According to the reasoning above, we expand the above quadratic equation into the general form
1590 which now has coefficients:
1597 // Early out if mNode is NULL
1603 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1605 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1606 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1607 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1609 // Compute the radius is not needed, square radius it's enough.
1610 const Vector3& size( mNode->GetSize( bufferIndex ) );
1612 // Scale the sphere.
1613 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1615 const float width = size.width * scale.width;
1616 const float height = size.height * scale.height;
1618 float squareSphereRadius = 0.5f * ( width * width + height * height );
1620 float a = rayDir.Dot( rayDir ); // a
1621 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1622 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1624 return ( b2 * b2 - a * c ) >= 0.f;
1627 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
1634 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1636 // Transforms the ray to the local reference system.
1638 // Calculate the inverse of Model matrix
1639 Matrix invModelMatrix( false/*don't init*/);
1640 // need to use the components as world matrix is only updated for actors that need it
1641 invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
1643 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1644 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1646 // Test with the actor's XY plane (Normal = 0 0 1 1).
1648 float a = -rayOriginLocal.z;
1649 float b = rayDirLocal.z;
1651 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1653 // Ray travels distance * rayDirLocal to intersect with plane.
1656 const Vector3& size = mNode->GetSize( bufferIndex );
1658 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1659 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1661 // Test with the actor's geometry.
1662 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1669 void Actor::SetLeaveRequired( bool required )
1671 mLeaveRequired = required;
1674 bool Actor::GetLeaveRequired() const
1676 return mLeaveRequired;
1679 void Actor::SetKeyboardFocusable( bool focusable )
1681 mKeyboardFocusable = focusable;
1684 bool Actor::IsKeyboardFocusable() const
1686 return mKeyboardFocusable;
1689 bool Actor::GetTouchRequired() const
1691 return !mTouchedSignal.Empty() || mDerivedRequiresTouch;
1694 bool Actor::GetHoverRequired() const
1696 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1699 bool Actor::GetWheelEventRequired() const
1701 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1704 bool Actor::IsHittable() const
1706 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1709 ActorGestureData& Actor::GetGestureData()
1711 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1712 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1713 if( NULL == mGestureData )
1715 mGestureData = new ActorGestureData;
1717 return *mGestureData;
1720 bool Actor::IsGestureRequred( Gesture::Type type ) const
1722 return mGestureData && mGestureData->IsGestureRequred( type );
1725 bool Actor::EmitTouchEventSignal( const TouchEvent& event )
1727 bool consumed = false;
1729 if( !mTouchedSignal.Empty() )
1731 Dali::Actor handle( this );
1732 consumed = mTouchedSignal.Emit( handle, event );
1737 // Notification for derived classes
1738 consumed = OnTouchEvent( event );
1744 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1746 bool consumed = false;
1748 if( !mHoveredSignal.Empty() )
1750 Dali::Actor handle( this );
1751 consumed = mHoveredSignal.Emit( handle, event );
1756 // Notification for derived classes
1757 consumed = OnHoverEvent( event );
1763 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1765 bool consumed = false;
1767 if( !mWheelEventSignal.Empty() )
1769 Dali::Actor handle( this );
1770 consumed = mWheelEventSignal.Emit( handle, event );
1775 // Notification for derived classes
1776 consumed = OnWheelEvent( event );
1782 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
1784 return mTouchedSignal;
1787 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
1789 return mHoveredSignal;
1792 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
1794 return mWheelEventSignal;
1797 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
1799 return mOnStageSignal;
1802 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
1804 return mOffStageSignal;
1807 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
1809 return mOnRelayoutSignal;
1812 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1814 bool connected( true );
1815 Actor* actor = dynamic_cast< Actor* >( object );
1817 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1819 actor->TouchedSignal().Connect( tracker, functor );
1821 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1823 actor->HoveredSignal().Connect( tracker, functor );
1825 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1827 actor->WheelEventSignal().Connect( tracker, functor );
1829 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
1831 actor->OnStageSignal().Connect( tracker, functor );
1833 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
1835 actor->OffStageSignal().Connect( tracker, functor );
1839 // signalName does not match any signal
1846 Actor::Actor( DerivedType derivedType )
1850 mParentOrigin( NULL ),
1851 mAnchorPoint( NULL ),
1852 mRelayoutData( NULL ),
1853 mGestureData( NULL ),
1855 mTargetSize( 0.0f, 0.0f, 0.0f ),
1857 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
1859 mIsRoot( ROOT_LAYER == derivedType ),
1860 mIsRenderable( RENDERABLE == derivedType ),
1861 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
1862 mIsOnStage( false ),
1864 mLeaveRequired( false ),
1865 mKeyboardFocusable( false ),
1866 mDerivedRequiresTouch( false ),
1867 mDerivedRequiresHover( false ),
1868 mDerivedRequiresWheelEvent( false ),
1869 mOnStageSignalled( false ),
1870 mInsideOnSizeSet( false ),
1871 mInheritOrientation( true ),
1872 mInheritScale( true ),
1873 mDrawMode( DrawMode::NORMAL ),
1874 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
1875 mColorMode( Node::DEFAULT_COLOR_MODE )
1879 void Actor::Initialize()
1882 SceneGraph::Node* node = CreateNode();
1884 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
1885 mNode = node; // Keep raw-pointer to Node
1889 GetEventThreadServices().RegisterObject( this );
1894 // Remove mParent pointers from children even if we're destroying core,
1895 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1898 ActorConstIter endIter = mChildren->end();
1899 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1901 (*iter)->SetParent( NULL );
1906 // Guard to allow handle destruction after Core has been destroyed
1907 if( EventThreadServices::IsCoreRunning() )
1911 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
1912 mNode = NULL; // Node is about to be destroyed
1915 GetEventThreadServices().UnregisterObject( this );
1918 // Cleanup optional gesture data
1919 delete mGestureData;
1921 // Cleanup optional parent origin and anchor
1922 delete mParentOrigin;
1923 delete mAnchorPoint;
1925 // Delete optional relayout data
1928 delete mRelayoutData;
1932 void Actor::ConnectToStage( unsigned int parentDepth, int index )
1934 // This container is used instead of walking the Actor hierachy.
1935 // It protects us when the Actor hierachy is modified during OnStageConnectionExternal callbacks.
1936 ActorContainer connectionList;
1939 // This stage is atomic i.e. not interrupted by user callbacks
1940 RecursiveConnectToStage( connectionList, parentDepth+1, index );
1942 // Notify applications about the newly connected actors.
1943 const ActorIter endIter = connectionList.end();
1944 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
1946 (*iter)->NotifyStageConnection();
1952 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth, int index )
1954 DALI_ASSERT_ALWAYS( !OnStage() );
1959 ConnectToSceneGraph( index );
1961 // Notification for internal derived classes
1962 OnStageConnectionInternal();
1964 // This stage is atomic; avoid emitting callbacks until all Actors are connected
1965 connectionList.push_back( ActorPtr( this ) );
1967 // Recursively connect children
1970 ActorConstIter endIter = mChildren->end();
1971 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1973 (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
1979 * This method is called when the Actor is connected to the Stage.
1980 * The parent must have added its Node to the scene-graph.
1981 * The child must connect its Node to the parent's Node.
1982 * This is resursive; the child calls ConnectToStage() for its children.
1984 void Actor::ConnectToSceneGraph( int index )
1986 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
1990 // Reparent Node in next Update
1991 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode, index );
1994 // Notify attachment
1997 mAttachment->Connect();
2000 // Request relayout on all actors that are added to the scenegraph
2003 // Notification for Object::Observers
2007 void Actor::NotifyStageConnection()
2009 // Actors can be removed (in a callback), before the on-stage stage is reported.
2010 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2011 if( OnStage() && !mOnStageSignalled )
2013 // Notification for external (CustomActor) derived classes
2014 OnStageConnectionExternal( mDepth );
2016 if( !mOnStageSignal.Empty() )
2018 Dali::Actor handle( this );
2019 mOnStageSignal.Emit( handle );
2022 // Guard against Remove during callbacks
2025 mOnStageSignalled = true; // signal required next time Actor is removed
2030 void Actor::DisconnectFromStage()
2032 // This container is used instead of walking the Actor hierachy.
2033 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2034 ActorContainer disconnectionList;
2036 // This stage is atomic i.e. not interrupted by user callbacks
2037 RecursiveDisconnectFromStage( disconnectionList );
2039 // Notify applications about the newly disconnected actors.
2040 const ActorIter endIter = disconnectionList.end();
2041 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2043 (*iter)->NotifyStageDisconnection();
2047 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2049 DALI_ASSERT_ALWAYS( OnStage() );
2051 // Recursively disconnect children
2054 ActorConstIter endIter = mChildren->end();
2055 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2057 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2061 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2062 disconnectionList.push_back( ActorPtr( this ) );
2064 // Notification for internal derived classes
2065 OnStageDisconnectionInternal();
2067 DisconnectFromSceneGraph();
2073 * This method is called by an actor or its parent, before a node removal message is sent.
2074 * This is recursive; the child calls DisconnectFromStage() for its children.
2076 void Actor::DisconnectFromSceneGraph()
2078 // Notification for Object::Observers
2079 OnSceneObjectRemove();
2081 // Notify attachment
2084 mAttachment->Disconnect();
2088 void Actor::NotifyStageDisconnection()
2090 // Actors can be added (in a callback), before the off-stage state is reported.
2091 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2092 // only do this step if there is a stage, i.e. Core is not being shut down
2093 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2095 // Notification for external (CustomeActor) derived classes
2096 OnStageDisconnectionExternal();
2098 if( !mOffStageSignal.Empty() )
2100 Dali::Actor handle( this );
2101 mOffStageSignal.Emit( handle );
2104 // Guard against Add during callbacks
2107 mOnStageSignalled = false; // signal required next time Actor is added
2112 bool Actor::IsNodeConnected() const
2114 bool connected( false );
2119 if( mNode->IsRoot() || mNode->GetParent() )
2128 unsigned int Actor::GetDefaultPropertyCount() const
2130 return DEFAULT_PROPERTY_COUNT;
2133 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2135 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2137 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2139 indices.PushBack( i );
2143 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2145 if( index < DEFAULT_PROPERTY_COUNT )
2147 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2153 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2155 Property::Index index = Property::INVALID_INDEX;
2157 // Look for name in default properties
2158 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2160 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2161 if( 0 == name.compare( property->name ) )
2171 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2173 if( index < DEFAULT_PROPERTY_COUNT )
2175 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2181 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2183 if( index < DEFAULT_PROPERTY_COUNT )
2185 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2191 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2193 if( index < DEFAULT_PROPERTY_COUNT )
2195 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2201 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2203 if( index < DEFAULT_PROPERTY_COUNT )
2205 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2208 // index out of range...return Property::NONE
2209 return Property::NONE;
2212 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2216 case Dali::Actor::Property::PARENT_ORIGIN:
2218 SetParentOrigin( property.Get< Vector3 >() );
2222 case Dali::Actor::Property::PARENT_ORIGIN_X:
2224 SetParentOriginX( property.Get< float >() );
2228 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2230 SetParentOriginY( property.Get< float >() );
2234 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2236 SetParentOriginZ( property.Get< float >() );
2240 case Dali::Actor::Property::ANCHOR_POINT:
2242 SetAnchorPoint( property.Get< Vector3 >() );
2246 case Dali::Actor::Property::ANCHOR_POINT_X:
2248 SetAnchorPointX( property.Get< float >() );
2252 case Dali::Actor::Property::ANCHOR_POINT_Y:
2254 SetAnchorPointY( property.Get< float >() );
2258 case Dali::Actor::Property::ANCHOR_POINT_Z:
2260 SetAnchorPointZ( property.Get< float >() );
2264 case Dali::Actor::Property::SIZE:
2266 SetSize( property.Get< Vector3 >() );
2270 case Dali::Actor::Property::SIZE_WIDTH:
2272 SetWidth( property.Get< float >() );
2276 case Dali::Actor::Property::SIZE_HEIGHT:
2278 SetHeight( property.Get< float >() );
2282 case Dali::Actor::Property::SIZE_DEPTH:
2284 SetDepth( property.Get< float >() );
2288 case Dali::Actor::Property::POSITION:
2290 SetPosition( property.Get< Vector3 >() );
2294 case Dali::Actor::Property::POSITION_X:
2296 SetX( property.Get< float >() );
2300 case Dali::Actor::Property::POSITION_Y:
2302 SetY( property.Get< float >() );
2306 case Dali::Actor::Property::POSITION_Z:
2308 SetZ( property.Get< float >() );
2312 case Dali::Actor::Property::ORIENTATION:
2314 SetOrientation( property.Get< Quaternion >() );
2318 case Dali::Actor::Property::SCALE:
2320 SetScale( property.Get< Vector3 >() );
2324 case Dali::Actor::Property::SCALE_X:
2326 SetScaleX( property.Get< float >() );
2330 case Dali::Actor::Property::SCALE_Y:
2332 SetScaleY( property.Get< float >() );
2336 case Dali::Actor::Property::SCALE_Z:
2338 SetScaleZ( property.Get< float >() );
2342 case Dali::Actor::Property::VISIBLE:
2344 SetVisible( property.Get< bool >() );
2348 case Dali::Actor::Property::COLOR:
2350 SetColor( property.Get< Vector4 >() );
2354 case Dali::Actor::Property::COLOR_RED:
2356 SetColorRed( property.Get< float >() );
2360 case Dali::Actor::Property::COLOR_GREEN:
2362 SetColorGreen( property.Get< float >() );
2366 case Dali::Actor::Property::COLOR_BLUE:
2368 SetColorBlue( property.Get< float >() );
2372 case Dali::Actor::Property::COLOR_ALPHA:
2374 SetOpacity( property.Get< float >() );
2378 case Dali::Actor::Property::NAME:
2380 SetName( property.Get< std::string >() );
2384 case Dali::Actor::Property::SENSITIVE:
2386 SetSensitive( property.Get< bool >() );
2390 case Dali::Actor::Property::LEAVE_REQUIRED:
2392 SetLeaveRequired( property.Get< bool >() );
2396 case Dali::Actor::Property::INHERIT_ORIENTATION:
2398 SetInheritOrientation( property.Get< bool >() );
2402 case Dali::Actor::Property::INHERIT_SCALE:
2404 SetInheritScale( property.Get< bool >() );
2408 case Dali::Actor::Property::COLOR_MODE:
2410 SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2414 case Dali::Actor::Property::POSITION_INHERITANCE:
2416 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2420 case Dali::Actor::Property::DRAW_MODE:
2422 SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2426 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2428 SetSizeModeFactor( property.Get< Vector3 >() );
2432 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2434 ResizePolicy::Type type;
2435 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2437 SetResizePolicy( type, Dimension::WIDTH );
2442 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2444 ResizePolicy::Type type;
2445 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2447 SetResizePolicy( type, Dimension::HEIGHT );
2452 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2454 SizeScalePolicy::Type type;
2455 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount, type ) )
2457 SetSizeScalePolicy( type );
2462 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2464 if( property.Get< bool >() )
2466 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2471 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2473 if( property.Get< bool >() )
2475 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2480 case Dali::Actor::Property::PADDING:
2482 Vector4 padding = property.Get< Vector4 >();
2483 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2484 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2488 case Dali::Actor::Property::MINIMUM_SIZE:
2490 Vector2 size = property.Get< Vector2 >();
2491 SetMinimumSize( size.x, Dimension::WIDTH );
2492 SetMinimumSize( size.y, Dimension::HEIGHT );
2496 case Dali::Actor::Property::MAXIMUM_SIZE:
2498 Vector2 size = property.Get< Vector2 >();
2499 SetMaximumSize( size.x, Dimension::WIDTH );
2500 SetMaximumSize( size.y, Dimension::HEIGHT );
2506 // this can happen in the case of a non-animatable default property so just do nothing
2512 // TODO: This method needs to be removed
2513 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2515 switch( entry.type )
2517 case Property::BOOLEAN:
2519 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2520 DALI_ASSERT_DEBUG( NULL != property );
2522 // property is being used in a separate thread; queue a message to set the property
2523 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2528 case Property::INTEGER:
2530 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2531 DALI_ASSERT_DEBUG( NULL != property );
2533 // property is being used in a separate thread; queue a message to set the property
2534 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2539 case Property::FLOAT:
2541 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2542 DALI_ASSERT_DEBUG( NULL != property );
2544 // property is being used in a separate thread; queue a message to set the property
2545 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2550 case Property::VECTOR2:
2552 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2553 DALI_ASSERT_DEBUG( NULL != property );
2555 // property is being used in a separate thread; queue a message to set the property
2556 if(entry.componentIndex == 0)
2558 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2560 else if(entry.componentIndex == 1)
2562 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2566 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2572 case Property::VECTOR3:
2574 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2575 DALI_ASSERT_DEBUG( NULL != property );
2577 // property is being used in a separate thread; queue a message to set the property
2578 if(entry.componentIndex == 0)
2580 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2582 else if(entry.componentIndex == 1)
2584 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2586 else if(entry.componentIndex == 2)
2588 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2592 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2598 case Property::VECTOR4:
2600 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2601 DALI_ASSERT_DEBUG( NULL != property );
2603 // property is being used in a separate thread; queue a message to set the property
2604 if(entry.componentIndex == 0)
2606 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
2608 else if(entry.componentIndex == 1)
2610 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
2612 else if(entry.componentIndex == 2)
2614 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
2616 else if(entry.componentIndex == 3)
2618 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
2622 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2628 case Property::ROTATION:
2630 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
2631 DALI_ASSERT_DEBUG( NULL != property );
2633 // property is being used in a separate thread; queue a message to set the property
2634 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
2639 case Property::MATRIX:
2641 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
2642 DALI_ASSERT_DEBUG( NULL != property );
2644 // property is being used in a separate thread; queue a message to set the property
2645 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
2650 case Property::MATRIX3:
2652 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
2653 DALI_ASSERT_DEBUG( NULL != property );
2655 // property is being used in a separate thread; queue a message to set the property
2656 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
2663 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
2669 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
2671 Property::Value value;
2675 case Dali::Actor::Property::PARENT_ORIGIN:
2677 value = GetCurrentParentOrigin();
2681 case Dali::Actor::Property::PARENT_ORIGIN_X:
2683 value = GetCurrentParentOrigin().x;
2687 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2689 value = GetCurrentParentOrigin().y;
2693 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2695 value = GetCurrentParentOrigin().z;
2699 case Dali::Actor::Property::ANCHOR_POINT:
2701 value = GetCurrentAnchorPoint();
2705 case Dali::Actor::Property::ANCHOR_POINT_X:
2707 value = GetCurrentAnchorPoint().x;
2711 case Dali::Actor::Property::ANCHOR_POINT_Y:
2713 value = GetCurrentAnchorPoint().y;
2717 case Dali::Actor::Property::ANCHOR_POINT_Z:
2719 value = GetCurrentAnchorPoint().z;
2723 case Dali::Actor::Property::SIZE:
2725 value = GetCurrentSize();
2729 case Dali::Actor::Property::SIZE_WIDTH:
2731 value = GetCurrentSize().width;
2735 case Dali::Actor::Property::SIZE_HEIGHT:
2737 value = GetCurrentSize().height;
2741 case Dali::Actor::Property::SIZE_DEPTH:
2743 value = GetCurrentSize().depth;
2747 case Dali::Actor::Property::POSITION:
2749 value = GetCurrentPosition();
2753 case Dali::Actor::Property::POSITION_X:
2755 value = GetCurrentPosition().x;
2759 case Dali::Actor::Property::POSITION_Y:
2761 value = GetCurrentPosition().y;
2765 case Dali::Actor::Property::POSITION_Z:
2767 value = GetCurrentPosition().z;
2771 case Dali::Actor::Property::WORLD_POSITION:
2773 value = GetCurrentWorldPosition();
2777 case Dali::Actor::Property::WORLD_POSITION_X:
2779 value = GetCurrentWorldPosition().x;
2783 case Dali::Actor::Property::WORLD_POSITION_Y:
2785 value = GetCurrentWorldPosition().y;
2789 case Dali::Actor::Property::WORLD_POSITION_Z:
2791 value = GetCurrentWorldPosition().z;
2795 case Dali::Actor::Property::ORIENTATION:
2797 value = GetCurrentOrientation();
2801 case Dali::Actor::Property::WORLD_ORIENTATION:
2803 value = GetCurrentWorldOrientation();
2807 case Dali::Actor::Property::SCALE:
2809 value = GetCurrentScale();
2813 case Dali::Actor::Property::SCALE_X:
2815 value = GetCurrentScale().x;
2819 case Dali::Actor::Property::SCALE_Y:
2821 value = GetCurrentScale().y;
2825 case Dali::Actor::Property::SCALE_Z:
2827 value = GetCurrentScale().z;
2831 case Dali::Actor::Property::WORLD_SCALE:
2833 value = GetCurrentWorldScale();
2837 case Dali::Actor::Property::VISIBLE:
2839 value = IsVisible();
2843 case Dali::Actor::Property::COLOR:
2845 value = GetCurrentColor();
2849 case Dali::Actor::Property::COLOR_RED:
2851 value = GetCurrentColor().r;
2855 case Dali::Actor::Property::COLOR_GREEN:
2857 value = GetCurrentColor().g;
2861 case Dali::Actor::Property::COLOR_BLUE:
2863 value = GetCurrentColor().b;
2867 case Dali::Actor::Property::COLOR_ALPHA:
2869 value = GetCurrentColor().a;
2873 case Dali::Actor::Property::WORLD_COLOR:
2875 value = GetCurrentWorldColor();
2879 case Dali::Actor::Property::WORLD_MATRIX:
2881 value = GetCurrentWorldMatrix();
2885 case Dali::Actor::Property::NAME:
2891 case Dali::Actor::Property::SENSITIVE:
2893 value = IsSensitive();
2897 case Dali::Actor::Property::LEAVE_REQUIRED:
2899 value = GetLeaveRequired();
2903 case Dali::Actor::Property::INHERIT_ORIENTATION:
2905 value = IsOrientationInherited();
2909 case Dali::Actor::Property::INHERIT_SCALE:
2911 value = IsScaleInherited();
2915 case Dali::Actor::Property::COLOR_MODE:
2917 value = Scripting::GetColorMode( GetColorMode() );
2921 case Dali::Actor::Property::POSITION_INHERITANCE:
2923 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
2927 case Dali::Actor::Property::DRAW_MODE:
2929 value = Scripting::GetDrawMode( GetDrawMode() );
2933 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2935 value = GetSizeModeFactor();
2939 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2941 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
2945 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2947 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
2951 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2953 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
2957 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2959 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
2963 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2965 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
2969 case Dali::Actor::Property::PADDING:
2971 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
2972 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
2973 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
2977 case Dali::Actor::Property::MINIMUM_SIZE:
2979 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
2983 case Dali::Actor::Property::MAXIMUM_SIZE:
2985 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
2991 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
2999 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3004 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3006 // This method should only return an object connected to the scene-graph
3007 return OnStage() ? mNode : NULL;
3010 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3012 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3014 const PropertyBase* property( NULL );
3016 // This method should only return a property of an object connected to the scene-graph
3022 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3024 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3025 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3027 property = animatable->GetSceneGraphProperty();
3029 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3031 CustomPropertyMetadata* custom = FindCustomProperty( index );
3032 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3034 property = custom->GetSceneGraphProperty();
3036 else if( NULL != mNode )
3040 case Dali::Actor::Property::SIZE:
3041 property = &mNode->mSize;
3044 case Dali::Actor::Property::SIZE_WIDTH:
3045 property = &mNode->mSize;
3048 case Dali::Actor::Property::SIZE_HEIGHT:
3049 property = &mNode->mSize;
3052 case Dali::Actor::Property::SIZE_DEPTH:
3053 property = &mNode->mSize;
3056 case Dali::Actor::Property::POSITION:
3057 property = &mNode->mPosition;
3060 case Dali::Actor::Property::POSITION_X:
3061 property = &mNode->mPosition;
3064 case Dali::Actor::Property::POSITION_Y:
3065 property = &mNode->mPosition;
3068 case Dali::Actor::Property::POSITION_Z:
3069 property = &mNode->mPosition;
3072 case Dali::Actor::Property::ORIENTATION:
3073 property = &mNode->mOrientation;
3076 case Dali::Actor::Property::SCALE:
3077 property = &mNode->mScale;
3080 case Dali::Actor::Property::SCALE_X:
3081 property = &mNode->mScale;
3084 case Dali::Actor::Property::SCALE_Y:
3085 property = &mNode->mScale;
3088 case Dali::Actor::Property::SCALE_Z:
3089 property = &mNode->mScale;
3092 case Dali::Actor::Property::VISIBLE:
3093 property = &mNode->mVisible;
3096 case Dali::Actor::Property::COLOR:
3097 property = &mNode->mColor;
3100 case Dali::Actor::Property::COLOR_RED:
3101 property = &mNode->mColor;
3104 case Dali::Actor::Property::COLOR_GREEN:
3105 property = &mNode->mColor;
3108 case Dali::Actor::Property::COLOR_BLUE:
3109 property = &mNode->mColor;
3112 case Dali::Actor::Property::COLOR_ALPHA:
3113 property = &mNode->mColor;
3124 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3126 const PropertyInputImpl* property( NULL );
3128 // This method should only return a property of an object connected to the scene-graph
3134 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3136 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3137 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3139 property = animatable->GetSceneGraphProperty();
3141 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3143 CustomPropertyMetadata* custom = FindCustomProperty( index );
3144 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3145 property = custom->GetSceneGraphProperty();
3147 else if( NULL != mNode )
3151 case Dali::Actor::Property::PARENT_ORIGIN:
3152 property = &mNode->mParentOrigin;
3155 case Dali::Actor::Property::PARENT_ORIGIN_X:
3156 property = &mNode->mParentOrigin;
3159 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3160 property = &mNode->mParentOrigin;
3163 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3164 property = &mNode->mParentOrigin;
3167 case Dali::Actor::Property::ANCHOR_POINT:
3168 property = &mNode->mAnchorPoint;
3171 case Dali::Actor::Property::ANCHOR_POINT_X:
3172 property = &mNode->mAnchorPoint;
3175 case Dali::Actor::Property::ANCHOR_POINT_Y:
3176 property = &mNode->mAnchorPoint;
3179 case Dali::Actor::Property::ANCHOR_POINT_Z:
3180 property = &mNode->mAnchorPoint;
3183 case Dali::Actor::Property::SIZE:
3184 property = &mNode->mSize;
3187 case Dali::Actor::Property::SIZE_WIDTH:
3188 property = &mNode->mSize;
3191 case Dali::Actor::Property::SIZE_HEIGHT:
3192 property = &mNode->mSize;
3195 case Dali::Actor::Property::SIZE_DEPTH:
3196 property = &mNode->mSize;
3199 case Dali::Actor::Property::POSITION:
3200 property = &mNode->mPosition;
3203 case Dali::Actor::Property::POSITION_X:
3204 property = &mNode->mPosition;
3207 case Dali::Actor::Property::POSITION_Y:
3208 property = &mNode->mPosition;
3211 case Dali::Actor::Property::POSITION_Z:
3212 property = &mNode->mPosition;
3215 case Dali::Actor::Property::WORLD_POSITION:
3216 property = &mNode->mWorldPosition;
3219 case Dali::Actor::Property::WORLD_POSITION_X:
3220 property = &mNode->mWorldPosition;
3223 case Dali::Actor::Property::WORLD_POSITION_Y:
3224 property = &mNode->mWorldPosition;
3227 case Dali::Actor::Property::WORLD_POSITION_Z:
3228 property = &mNode->mWorldPosition;
3231 case Dali::Actor::Property::ORIENTATION:
3232 property = &mNode->mOrientation;
3235 case Dali::Actor::Property::WORLD_ORIENTATION:
3236 property = &mNode->mWorldOrientation;
3239 case Dali::Actor::Property::SCALE:
3240 property = &mNode->mScale;
3243 case Dali::Actor::Property::SCALE_X:
3244 property = &mNode->mScale;
3247 case Dali::Actor::Property::SCALE_Y:
3248 property = &mNode->mScale;
3251 case Dali::Actor::Property::SCALE_Z:
3252 property = &mNode->mScale;
3255 case Dali::Actor::Property::WORLD_SCALE:
3256 property = &mNode->mWorldScale;
3259 case Dali::Actor::Property::VISIBLE:
3260 property = &mNode->mVisible;
3263 case Dali::Actor::Property::COLOR:
3264 property = &mNode->mColor;
3267 case Dali::Actor::Property::COLOR_RED:
3268 property = &mNode->mColor;
3271 case Dali::Actor::Property::COLOR_GREEN:
3272 property = &mNode->mColor;
3275 case Dali::Actor::Property::COLOR_BLUE:
3276 property = &mNode->mColor;
3279 case Dali::Actor::Property::COLOR_ALPHA:
3280 property = &mNode->mColor;
3283 case Dali::Actor::Property::WORLD_COLOR:
3284 property = &mNode->mWorldColor;
3287 case Dali::Actor::Property::WORLD_MATRIX:
3288 property = &mNode->mWorldMatrix;
3299 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3301 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3303 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3305 // check whether the animatable property is registered already, if not then register one.
3306 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3307 if( animatableProperty )
3309 componentIndex = animatableProperty->componentIndex;
3316 case Dali::Actor::Property::PARENT_ORIGIN_X:
3317 case Dali::Actor::Property::ANCHOR_POINT_X:
3318 case Dali::Actor::Property::SIZE_WIDTH:
3319 case Dali::Actor::Property::POSITION_X:
3320 case Dali::Actor::Property::WORLD_POSITION_X:
3321 case Dali::Actor::Property::SCALE_X:
3322 case Dali::Actor::Property::COLOR_RED:
3328 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3329 case Dali::Actor::Property::ANCHOR_POINT_Y:
3330 case Dali::Actor::Property::SIZE_HEIGHT:
3331 case Dali::Actor::Property::POSITION_Y:
3332 case Dali::Actor::Property::WORLD_POSITION_Y:
3333 case Dali::Actor::Property::SCALE_Y:
3334 case Dali::Actor::Property::COLOR_GREEN:
3340 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3341 case Dali::Actor::Property::ANCHOR_POINT_Z:
3342 case Dali::Actor::Property::SIZE_DEPTH:
3343 case Dali::Actor::Property::POSITION_Z:
3344 case Dali::Actor::Property::WORLD_POSITION_Z:
3345 case Dali::Actor::Property::SCALE_Z:
3346 case Dali::Actor::Property::COLOR_BLUE:
3352 case Dali::Actor::Property::COLOR_ALPHA:
3366 return componentIndex;
3369 void Actor::SetParent( Actor* parent, int index )
3373 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3377 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3380 // Instruct each actor to create a corresponding node in the scene graph
3381 ConnectToStage( parent->GetHierarchyDepth(), index );
3384 else // parent being set to NULL
3386 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3390 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3393 DALI_ASSERT_ALWAYS( mNode != NULL );
3397 // Disconnect the Node & its children from the scene-graph.
3398 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3401 // Instruct each actor to discard pointers to the scene-graph
3402 DisconnectFromStage();
3407 SceneGraph::Node* Actor::CreateNode() const
3412 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3415 Actor* actor = dynamic_cast< Actor* >( object );
3419 if( 0 == actionName.compare( ACTION_SHOW ) )
3421 actor->SetVisible( true );
3424 else if( 0 == actionName.compare( ACTION_HIDE ) )
3426 actor->SetVisible( false );
3434 void Actor::EnsureRelayoutData()
3436 // Assign relayout data.
3437 if( !mRelayoutData )
3439 mRelayoutData = new RelayoutData();
3443 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3445 // Check if actor is dependent on parent
3446 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3448 if( ( dimension & ( 1 << i ) ) )
3450 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3451 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3461 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3463 // Check if actor is dependent on children
3464 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3466 if( ( dimension & ( 1 << i ) ) )
3468 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3469 switch( resizePolicy )
3471 case ResizePolicy::FIT_TO_CHILDREN:
3472 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3488 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3490 return Actor::RelayoutDependentOnChildren( dimension );
3493 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3495 // Check each possible dimension and see if it is dependent on the input one
3496 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3498 if( dimension & ( 1 << i ) )
3500 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3507 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3509 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3511 if( dimension & ( 1 << i ) )
3513 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3518 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3520 // If more than one dimension is requested, just return the first one found
3521 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3523 if( ( dimension & ( 1 << i ) ) )
3525 return mRelayoutData->negotiatedDimensions[ i ];
3529 return 0.0f; // Default
3532 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3534 EnsureRelayoutData();
3536 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3538 if( dimension & ( 1 << i ) )
3540 mRelayoutData->dimensionPadding[ i ] = padding;
3545 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3547 if ( mRelayoutData )
3549 // If more than one dimension is requested, just return the first one found
3550 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3552 if( ( dimension & ( 1 << i ) ) )
3554 return mRelayoutData->dimensionPadding[ i ];
3559 return GetDefaultDimensionPadding();
3562 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
3564 EnsureRelayoutData();
3566 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3568 if( dimension & ( 1 << i ) )
3570 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3575 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
3577 if ( mRelayoutData )
3579 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3581 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
3591 float Actor::GetHeightForWidthBase( float width )
3593 float height = 0.0f;
3595 const Vector3 naturalSize = GetNaturalSize();
3596 if( naturalSize.width > 0.0f )
3598 height = naturalSize.height * width / naturalSize.width;
3600 else // we treat 0 as 1:1 aspect ratio
3608 float Actor::GetWidthForHeightBase( float height )
3612 const Vector3 naturalSize = GetNaturalSize();
3613 if( naturalSize.height > 0.0f )
3615 width = naturalSize.width * height / naturalSize.height;
3617 else // we treat 0 as 1:1 aspect ratio
3625 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
3627 // Fill to parent, taking size mode factor into account
3628 switch( child.GetResizePolicy( dimension ) )
3630 case ResizePolicy::FILL_TO_PARENT:
3632 return GetLatestSize( dimension );
3635 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3637 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
3640 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3642 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
3647 return GetLatestSize( dimension );
3652 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
3654 // Can be overridden in derived class
3655 return CalculateChildSizeBase( child, dimension );
3658 float Actor::GetHeightForWidth( float width )
3660 // Can be overridden in derived class
3661 return GetHeightForWidthBase( width );
3664 float Actor::GetWidthForHeight( float height )
3666 // Can be overridden in derived class
3667 return GetWidthForHeightBase( height );
3670 float Actor::GetLatestSize( Dimension::Type dimension ) const
3672 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
3675 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
3677 Vector2 padding = GetPadding( dimension );
3679 return GetLatestSize( dimension ) + padding.x + padding.y;
3682 float Actor::NegotiateFromParent( Dimension::Type dimension )
3684 Actor* parent = GetParent();
3687 Vector2 padding( GetPadding( dimension ) );
3688 Vector2 parentPadding( parent->GetPadding( dimension ) );
3689 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
3695 float Actor::NegotiateFromChildren( Dimension::Type dimension )
3697 float maxDimensionPoint = 0.0f;
3699 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3701 ActorPtr child = GetChildAt( i );
3703 if( !child->RelayoutDependentOnParent( dimension ) )
3705 // Calculate the min and max points that the children range across
3706 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
3707 float dimensionSize = child->GetRelayoutSize( dimension );
3708 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
3712 return maxDimensionPoint;
3715 float Actor::GetSize( Dimension::Type dimension ) const
3717 return GetDimensionValue( GetTargetSize(), dimension );
3720 float Actor::GetNaturalSize( Dimension::Type dimension ) const
3722 return GetDimensionValue( GetNaturalSize(), dimension );
3725 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
3727 switch( GetResizePolicy( dimension ) )
3729 case ResizePolicy::USE_NATURAL_SIZE:
3731 return GetNaturalSize( dimension );
3734 case ResizePolicy::FIXED:
3736 return GetDimensionValue( GetPreferredSize(), dimension );
3739 case ResizePolicy::USE_ASSIGNED_SIZE:
3741 return GetDimensionValue( maximumSize, dimension );
3744 case ResizePolicy::FILL_TO_PARENT:
3745 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3746 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3748 return NegotiateFromParent( dimension );
3751 case ResizePolicy::FIT_TO_CHILDREN:
3753 return NegotiateFromChildren( dimension );
3756 case ResizePolicy::DIMENSION_DEPENDENCY:
3758 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
3761 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
3763 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
3766 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
3768 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
3780 return 0.0f; // Default
3783 float Actor::ClampDimension( float size, Dimension::Type dimension )
3785 const float minSize = GetMinimumSize( dimension );
3786 const float maxSize = GetMaximumSize( dimension );
3788 return std::max( minSize, std::min( size, maxSize ) );
3791 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
3793 // Check if it needs to be negotiated
3794 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
3796 // Check that we havn't gotten into an infinite loop
3797 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
3798 bool recursionFound = false;
3799 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
3801 if( *it == searchActor )
3803 recursionFound = true;
3808 if( !recursionFound )
3810 // Record the path that we have taken
3811 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
3813 // Dimension dependency check
3814 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3816 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
3818 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
3820 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
3824 // Parent dependency check
3825 Actor* parent = GetParent();
3826 if( parent && RelayoutDependentOnParent( dimension ) )
3828 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
3831 // Children dependency check
3832 if( RelayoutDependentOnChildren( dimension ) )
3834 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3836 ActorPtr child = GetChildAt( i );
3838 // Only relayout child first if it is not dependent on this actor
3839 if( !child->RelayoutDependentOnParent( dimension ) )
3841 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
3846 // For deriving classes
3847 OnCalculateRelayoutSize( dimension );
3849 // All dependencies checked, calculate the size and set negotiated flag
3850 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
3852 SetNegotiatedDimension( newSize, dimension );
3853 SetLayoutNegotiated( true, dimension );
3855 // For deriving classes
3856 OnLayoutNegotiated( newSize, dimension );
3858 // This actor has been successfully processed, pop it off the recursion stack
3859 recursionStack.pop_back();
3863 // TODO: Break infinite loop
3864 SetLayoutNegotiated( true, dimension );
3869 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
3871 // Negotiate all dimensions that require it
3872 ActorDimensionStack recursionStack;
3874 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3876 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
3879 NegotiateDimension( dimension, allocatedSize, recursionStack );
3883 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
3885 switch( mRelayoutData->sizeSetPolicy )
3887 case SizeScalePolicy::USE_SIZE_SET:
3892 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
3894 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
3895 const Vector3 naturalSize = GetNaturalSize();
3896 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
3898 const float sizeRatio = size.width / size.height;
3899 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
3901 if( naturalSizeRatio < sizeRatio )
3903 return Vector2( naturalSizeRatio * size.height, size.height );
3905 else if( naturalSizeRatio > sizeRatio )
3907 return Vector2( size.width, size.width / naturalSizeRatio );
3918 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
3920 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
3921 const Vector3 naturalSize = GetNaturalSize();
3922 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
3924 const float sizeRatio = size.width / size.height;
3925 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
3927 if( naturalSizeRatio < sizeRatio )
3929 return Vector2( size.width, size.width / naturalSizeRatio );
3931 else if( naturalSizeRatio > sizeRatio )
3933 return Vector2( naturalSizeRatio * size.height, size.height );
3951 void Actor::SetNegotiatedSize( RelayoutContainer& container )
3953 // Do the set actor size
3954 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
3956 // Adjust for size set policy
3957 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
3959 // Lock the flag to stop recursive relayouts on set size
3960 mRelayoutData->insideRelayout = true;
3961 SetSize( negotiatedSize );
3962 mRelayoutData->insideRelayout = false;
3964 // Clear flags for all dimensions
3965 SetLayoutDirty( false );
3967 // Give deriving classes a chance to respond
3968 OnRelayout( negotiatedSize, container );
3970 if( !mOnRelayoutSignal.Empty() )
3972 Dali::Actor handle( this );
3973 mOnRelayoutSignal.Emit( handle );
3977 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
3979 // Do the negotiation
3980 NegotiateDimensions( allocatedSize );
3982 // Set the actor size
3983 SetNegotiatedSize( container );
3985 // Negotiate down to children
3986 const Vector2 newBounds = GetTargetSize().GetVectorXY();
3988 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3990 ActorPtr child = GetChildAt( i );
3992 // Only relayout if required
3993 if( child->RelayoutRequired() )
3995 container.Add( Dali::Actor( child.Get() ), newBounds );
4000 void Actor::RelayoutRequest( Dimension::Type dimension )
4002 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4003 if( relayoutController )
4005 Dali::Actor self( this );
4006 relayoutController->RequestRelayout( self, dimension );
4010 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4014 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4018 void Actor::SetPreferredSize( const Vector2& size )
4020 EnsureRelayoutData();
4022 if( size.width > 0.0f )
4024 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4027 if( size.height > 0.0f )
4029 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4032 mRelayoutData->preferredSize = size;
4037 Vector2 Actor::GetPreferredSize() const
4039 if ( mRelayoutData )
4041 return mRelayoutData->preferredSize;
4044 return GetDefaultPreferredSize();
4047 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4049 EnsureRelayoutData();
4051 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4053 if( dimension & ( 1 << i ) )
4055 mRelayoutData->minimumSize[ i ] = size;
4062 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4064 if ( mRelayoutData )
4066 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4068 if( dimension & ( 1 << i ) )
4070 return mRelayoutData->minimumSize[ i ];
4075 return 0.0f; // Default
4078 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4080 EnsureRelayoutData();
4082 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4084 if( dimension & ( 1 << i ) )
4086 mRelayoutData->maximumSize[ i ] = size;
4093 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4095 if ( mRelayoutData )
4097 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4099 if( dimension & ( 1 << i ) )
4101 return mRelayoutData->maximumSize[ i ];
4106 return FLT_MAX; // Default
4109 } // namespace Internal