2 * Copyright (c) 2016 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/events/touch-data.h>
31 #include <dali/public-api/math/vector2.h>
32 #include <dali/public-api/math/vector3.h>
33 #include <dali/public-api/math/radian.h>
34 #include <dali/public-api/object/type-registry.h>
35 #include <dali/devel-api/scripting/scripting.h>
37 #include <dali/internal/common/internal-constants.h>
38 #include <dali/internal/event/common/event-thread-services.h>
39 #include <dali/internal/event/render-tasks/render-task-impl.h>
40 #include <dali/internal/event/actors/camera-actor-impl.h>
41 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
42 #include <dali/internal/event/common/property-helper.h>
43 #include <dali/internal/event/common/stage-impl.h>
44 #include <dali/internal/event/common/type-info-impl.h>
45 #include <dali/internal/event/animation/constraint-impl.h>
46 #include <dali/internal/event/common/projection.h>
47 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
48 #include <dali/internal/update/common/animatable-property.h>
49 #include <dali/internal/update/nodes/node-messages.h>
50 #include <dali/internal/update/nodes/node-declarations.h>
51 #include <dali/internal/update/animation/scene-graph-constraint.h>
52 #include <dali/internal/event/events/actor-gesture-data.h>
53 #include <dali/internal/common/message.h>
54 #include <dali/integration-api/debug.h>
56 using Dali::Internal::SceneGraph::Node;
57 using Dali::Internal::SceneGraph::AnimatableProperty;
58 using Dali::Internal::SceneGraph::PropertyBase;
62 namespace ResizePolicy
67 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )
68 DALI_ENUM_TO_STRING( FIXED )
69 DALI_ENUM_TO_STRING( USE_NATURAL_SIZE )
70 DALI_ENUM_TO_STRING( FILL_TO_PARENT )
71 DALI_ENUM_TO_STRING( SIZE_RELATIVE_TO_PARENT )
72 DALI_ENUM_TO_STRING( SIZE_FIXED_OFFSET_FROM_PARENT )
73 DALI_ENUM_TO_STRING( FIT_TO_CHILDREN )
74 DALI_ENUM_TO_STRING( DIMENSION_DEPENDENCY )
75 DALI_ENUM_TO_STRING( USE_ASSIGNED_SIZE )
76 DALI_ENUM_TO_STRING_TABLE_END( Type )
78 } // unnamed namespace
81 namespace SizeScalePolicy
85 // Enumeration to / from string conversion tables
86 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )
87 DALI_ENUM_TO_STRING( USE_SIZE_SET )
88 DALI_ENUM_TO_STRING( FIT_WITH_ASPECT_RATIO )
89 DALI_ENUM_TO_STRING( FILL_WITH_ASPECT_RATIO )
90 DALI_ENUM_TO_STRING_TABLE_END( Type )
91 } // unnamed namespace
97 unsigned int Actor::mActorCounter = 0;
101 /// Using a function because of library initialisation order. Vector3::ONE may not have been initialised yet.
102 inline const Vector3& GetDefaultSizeModeFactor()
107 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
108 inline const Vector2& GetDefaultPreferredSize()
110 return Vector2::ZERO;
113 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
114 inline const Vector2& GetDefaultDimensionPadding()
116 return Vector2::ZERO;
119 const SizeScalePolicy::Type DEFAULT_SIZE_SCALE_POLICY = SizeScalePolicy::USE_SIZE_SET;
121 } // unnamed namespace
124 * Struct to collect relayout variables
126 struct Actor::RelayoutData
129 : sizeModeFactor( GetDefaultSizeModeFactor() ), preferredSize( GetDefaultPreferredSize() ), sizeSetPolicy( DEFAULT_SIZE_SCALE_POLICY ), relayoutEnabled( false ), insideRelayout( false )
131 // Set size negotiation defaults
132 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
134 resizePolicies[ i ] = ResizePolicy::DEFAULT;
135 negotiatedDimensions[ i ] = 0.0f;
136 dimensionNegotiated[ i ] = false;
137 dimensionDirty[ i ] = false;
138 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
139 dimensionPadding[ i ] = GetDefaultDimensionPadding();
140 minimumSize[ i ] = 0.0f;
141 maximumSize[ i ] = FLT_MAX;
145 ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies
147 Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies
149 Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
151 float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
153 float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be
154 float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be
156 bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated
157 bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
159 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
161 Vector2 preferredSize; ///< The preferred size of the actor
163 SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
165 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
166 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
169 namespace // unnamed namespace
175 * We want to discourage the use of property strings (minimize string comparisons),
176 * particularly for the default properties.
177 * Name Type writable animatable constraint-input enum for index-checking
179 DALI_PROPERTY_TABLE_BEGIN
180 DALI_PROPERTY( "parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
181 DALI_PROPERTY( "parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
182 DALI_PROPERTY( "parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
183 DALI_PROPERTY( "parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
184 DALI_PROPERTY( "anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
185 DALI_PROPERTY( "anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
186 DALI_PROPERTY( "anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
187 DALI_PROPERTY( "anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
188 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
189 DALI_PROPERTY( "sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
190 DALI_PROPERTY( "sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
191 DALI_PROPERTY( "sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
192 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
193 DALI_PROPERTY( "positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
194 DALI_PROPERTY( "positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
195 DALI_PROPERTY( "positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
196 DALI_PROPERTY( "worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
197 DALI_PROPERTY( "worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
198 DALI_PROPERTY( "worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
199 DALI_PROPERTY( "worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
200 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
201 DALI_PROPERTY( "worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
202 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
203 DALI_PROPERTY( "scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
204 DALI_PROPERTY( "scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
205 DALI_PROPERTY( "scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
206 DALI_PROPERTY( "worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
207 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
208 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
209 DALI_PROPERTY( "colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
210 DALI_PROPERTY( "colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
211 DALI_PROPERTY( "colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
212 DALI_PROPERTY( "colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
213 DALI_PROPERTY( "worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
214 DALI_PROPERTY( "worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
215 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
216 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
217 DALI_PROPERTY( "leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
218 DALI_PROPERTY( "inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
219 DALI_PROPERTY( "inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
220 DALI_PROPERTY( "colorMode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
221 DALI_PROPERTY( "positionInheritance", STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE )
222 DALI_PROPERTY( "drawMode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
223 DALI_PROPERTY( "sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
224 DALI_PROPERTY( "widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
225 DALI_PROPERTY( "heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
226 DALI_PROPERTY( "sizeScalePolicy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
227 DALI_PROPERTY( "widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
228 DALI_PROPERTY( "heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
229 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
230 DALI_PROPERTY( "minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
231 DALI_PROPERTY( "maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
232 DALI_PROPERTY( "inheritPosition", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_POSITION )
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 = "wheelEvent";
240 const char* const SIGNAL_ON_STAGE = "onStage";
241 const char* const SIGNAL_OFF_STAGE = "offStage";
242 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
246 const char* const ACTION_SHOW = "show";
247 const char* const ACTION_HIDE = "hide";
249 BaseHandle CreateActor()
251 return Dali::Actor::New();
254 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
256 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
257 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
258 SignalConnectorType signalConnector3( mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal );
259 SignalConnectorType signalConnector4( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
260 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
261 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
263 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
264 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
267 * @brief Extract a given dimension from a Vector2
269 * @param[in] values The values to extract from
270 * @param[in] dimension The dimension to extract
271 * @return Return the value for the dimension
273 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
277 case Dimension::WIDTH:
281 case Dimension::HEIGHT:
283 return values.height;
294 * @brief Extract a given dimension from a Vector3
296 * @param[in] values The values to extract from
297 * @param[in] dimension The dimension to extract
298 * @return Return the value for the dimension
300 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
302 return GetDimensionValue( values.GetVectorXY(), dimension );
306 } // unnamed namespace
308 ActorPtr Actor::New()
310 ActorPtr actor( new Actor( BASIC ) );
312 // Second-phase construction
318 const std::string& Actor::GetName() const
323 void Actor::SetName( const std::string& name )
329 // ATTENTION: string for debug purposes is not thread safe.
330 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
334 unsigned int Actor::GetId() const
339 bool Actor::OnStage() const
344 Dali::Layer Actor::GetLayer()
348 // Short-circuit for Layer derived actors
351 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
354 // Find the immediate Layer parent
355 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
357 if( parent->IsLayer() )
359 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
366 void Actor::Add( Actor& child )
368 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
369 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
373 mChildren = new ActorContainer;
376 Actor* const oldParent( child.mParent );
378 // child might already be ours
379 if( this != oldParent )
381 // if we already have parent, unparent us first
384 oldParent->Remove( child ); // This causes OnChildRemove callback
386 // Old parent may need to readjust to missing child
387 if( oldParent->RelayoutDependentOnChildren() )
389 oldParent->RelayoutRequest();
393 // Guard against Add() during previous OnChildRemove callback
396 // Do this first, since user callbacks from within SetParent() may need to remove child
397 mChildren->push_back( ActorPtr( &child ) );
399 // SetParent asserts that child can be added
400 child.SetParent( this );
402 // Notification for derived classes
405 // Only put in a relayout request if there is a suitable dependency
406 if( RelayoutDependentOnChildren() )
414 void Actor::Remove( Actor& child )
416 if( (this == &child) || (!mChildren) )
418 // no children or removing itself
424 // Find the child in mChildren, and unparent it
425 ActorIter end = mChildren->end();
426 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
428 ActorPtr actor = (*iter);
430 if( actor.Get() == &child )
432 // Keep handle for OnChildRemove notification
435 // Do this first, since user callbacks from within SetParent() may need to add the child
436 mChildren->erase( iter );
438 DALI_ASSERT_DEBUG( actor->GetParent() == this );
439 actor->SetParent( NULL );
447 // Only put in a relayout request if there is a suitable dependency
448 if( RelayoutDependentOnChildren() )
454 // Notification for derived classes
455 OnChildRemove( child );
458 void Actor::Unparent()
462 // Remove this actor from the parent. The remove will put a relayout request in for
463 // the parent if required
464 mParent->Remove( *this );
465 // mParent is now NULL!
469 unsigned int Actor::GetChildCount() const
471 return ( NULL != mChildren ) ? mChildren->size() : 0;
474 ActorPtr Actor::GetChildAt( unsigned int index ) const
476 DALI_ASSERT_ALWAYS( index < GetChildCount() );
478 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
481 ActorPtr Actor::FindChildByName( const std::string& actorName )
484 if( actorName == mName )
490 ActorIter end = mChildren->end();
491 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
493 child = (*iter)->FindChildByName( actorName );
504 ActorPtr Actor::FindChildById( const unsigned int id )
513 ActorIter end = mChildren->end();
514 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
516 child = (*iter)->FindChildById( id );
527 void Actor::SetParentOrigin( const Vector3& origin )
531 // mNode is being used in a separate thread; queue a message to set the value & base value
532 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
535 // Cache for event-thread access
538 // not allocated, check if different from default
539 if( ParentOrigin::DEFAULT != origin )
541 mParentOrigin = new Vector3( origin );
546 // check if different from current costs more than just set
547 *mParentOrigin = origin;
551 void Actor::SetParentOriginX( float x )
553 const Vector3& current = GetCurrentParentOrigin();
555 SetParentOrigin( Vector3( x, current.y, current.z ) );
558 void Actor::SetParentOriginY( float y )
560 const Vector3& current = GetCurrentParentOrigin();
562 SetParentOrigin( Vector3( current.x, y, current.z ) );
565 void Actor::SetParentOriginZ( float z )
567 const Vector3& current = GetCurrentParentOrigin();
569 SetParentOrigin( Vector3( current.x, current.y, z ) );
572 const Vector3& Actor::GetCurrentParentOrigin() const
574 // Cached for event-thread access
575 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
578 void Actor::SetAnchorPoint( const Vector3& anchor )
582 // mNode is being used in a separate thread; queue a message to set the value & base value
583 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
586 // Cache for event-thread access
589 // not allocated, check if different from default
590 if( AnchorPoint::DEFAULT != anchor )
592 mAnchorPoint = new Vector3( anchor );
597 // check if different from current costs more than just set
598 *mAnchorPoint = anchor;
602 void Actor::SetAnchorPointX( float x )
604 const Vector3& current = GetCurrentAnchorPoint();
606 SetAnchorPoint( Vector3( x, current.y, current.z ) );
609 void Actor::SetAnchorPointY( float y )
611 const Vector3& current = GetCurrentAnchorPoint();
613 SetAnchorPoint( Vector3( current.x, y, current.z ) );
616 void Actor::SetAnchorPointZ( float z )
618 const Vector3& current = GetCurrentAnchorPoint();
620 SetAnchorPoint( Vector3( current.x, current.y, z ) );
623 const Vector3& Actor::GetCurrentAnchorPoint() const
625 // Cached for event-thread access
626 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
629 void Actor::SetPosition( float x, float y )
631 SetPosition( Vector3( x, y, 0.0f ) );
634 void Actor::SetPosition( float x, float y, float z )
636 SetPosition( Vector3( x, y, z ) );
639 void Actor::SetPosition( const Vector3& position )
641 mTargetPosition = position;
645 // mNode is being used in a separate thread; queue a message to set the value & base value
646 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
650 void Actor::SetX( float x )
652 mTargetPosition.x = x;
656 // mNode is being used in a separate thread; queue a message to set the value & base value
657 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
661 void Actor::SetY( float y )
663 mTargetPosition.y = y;
667 // mNode is being used in a separate thread; queue a message to set the value & base value
668 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
672 void Actor::SetZ( float z )
674 mTargetPosition.z = z;
678 // mNode is being used in a separate thread; queue a message to set the value & base value
679 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
683 void Actor::TranslateBy( const Vector3& distance )
685 mTargetPosition += distance;
689 // mNode is being used in a separate thread; queue a message to set the value & base value
690 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
694 const Vector3& Actor::GetCurrentPosition() const
698 // mNode is being used in a separate thread; copy the value from the previous update
699 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
702 return Vector3::ZERO;
705 const Vector3& Actor::GetTargetPosition() const
707 return mTargetPosition;
710 const Vector3& Actor::GetCurrentWorldPosition() const
714 // mNode is being used in a separate thread; copy the value from the previous update
715 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
718 return Vector3::ZERO;
721 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
723 // this flag is not animatable so keep the value
724 mPositionInheritanceMode = mode;
727 // mNode is being used in a separate thread; queue a message to set the value
728 SetInheritPositionMessage( GetEventThreadServices(), *mNode, mode == INHERIT_PARENT_POSITION );
732 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
734 // Cached for event-thread access
735 return mPositionInheritanceMode;
738 void Actor::SetInheritPosition( bool inherit )
740 if( mInheritPosition != inherit && NULL != mNode )
742 // non animateable so keep local copy
743 mInheritPosition = inherit;
744 SetInheritPositionMessage( GetEventThreadServices(), *mNode, inherit );
748 bool Actor::IsPositionInherited() const
750 return mInheritPosition;
753 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
755 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
756 normalizedAxis.Normalize();
758 Quaternion orientation( angle, normalizedAxis );
760 SetOrientation( orientation );
763 void Actor::SetOrientation( const Quaternion& orientation )
767 // mNode is being used in a separate thread; queue a message to set the value & base value
768 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation );
772 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
776 // mNode is being used in a separate thread; queue a message to set the value & base value
777 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, Quaternion(angle, axis) );
781 void Actor::RotateBy( const Quaternion& relativeRotation )
785 // mNode is being used in a separate thread; queue a message to set the value & base value
786 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
790 const Quaternion& Actor::GetCurrentOrientation() const
794 // mNode is being used in a separate thread; copy the value from the previous update
795 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
798 return Quaternion::IDENTITY;
801 const Quaternion& Actor::GetCurrentWorldOrientation() const
805 // mNode is being used in a separate thread; copy the value from the previous update
806 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
809 return Quaternion::IDENTITY;
812 void Actor::SetScale( float scale )
814 SetScale( Vector3( scale, scale, scale ) );
817 void Actor::SetScale( float x, float y, float z )
819 SetScale( Vector3( x, y, z ) );
822 void Actor::SetScale( const Vector3& scale )
826 // mNode is being used in a separate thread; queue a message to set the value & base value
827 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
831 void Actor::SetScaleX( float x )
835 // mNode is being used in a separate thread; queue a message to set the value & base value
836 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
840 void Actor::SetScaleY( float y )
844 // mNode is being used in a separate thread; queue a message to set the value & base value
845 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
849 void Actor::SetScaleZ( float z )
853 // mNode is being used in a separate thread; queue a message to set the value & base value
854 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
858 void Actor::ScaleBy(const Vector3& relativeScale)
862 // mNode is being used in a separate thread; queue a message to set the value & base value
863 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
867 const Vector3& Actor::GetCurrentScale() const
871 // mNode is being used in a separate thread; copy the value from the previous update
872 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
878 const Vector3& Actor::GetCurrentWorldScale() const
882 // mNode is being used in a separate thread; copy the value from the previous update
883 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
889 void Actor::SetInheritScale( bool inherit )
892 if( mInheritScale != inherit && NULL != mNode )
894 // non animateable so keep local copy
895 mInheritScale = inherit;
896 // mNode is being used in a separate thread; queue a message to set the value
897 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
901 bool Actor::IsScaleInherited() const
903 return mInheritScale;
906 Matrix Actor::GetCurrentWorldMatrix() const
910 return mNode->GetWorldMatrix(0);
913 return Matrix::IDENTITY;
916 void Actor::SetVisible( bool visible )
920 // mNode is being used in a separate thread; queue a message to set the value & base value
921 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
925 bool Actor::IsVisible() const
929 // mNode is being used in a separate thread; copy the value from the previous update
930 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
936 void Actor::SetOpacity( float opacity )
940 // mNode is being used in a separate thread; queue a message to set the value & base value
941 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
945 float Actor::GetCurrentOpacity() const
949 // mNode is being used in a separate thread; copy the value from the previous update
950 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
956 const Vector4& Actor::GetCurrentWorldColor() const
960 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
966 void Actor::SetColor( const Vector4& color )
970 // mNode is being used in a separate thread; queue a message to set the value & base value
971 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
975 void Actor::SetColorRed( float red )
979 // mNode is being used in a separate thread; queue a message to set the value & base value
980 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
984 void Actor::SetColorGreen( float green )
988 // mNode is being used in a separate thread; queue a message to set the value & base value
989 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
993 void Actor::SetColorBlue( float blue )
997 // mNode is being used in a separate thread; queue a message to set the value & base value
998 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1002 const Vector4& Actor::GetCurrentColor() const
1006 // mNode is being used in a separate thread; copy the value from the previous update
1007 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1010 return Color::WHITE;
1013 void Actor::SetInheritOrientation( bool inherit )
1015 if( mInheritOrientation != inherit && NULL != mNode)
1017 // non animateable so keep local copy
1018 mInheritOrientation = inherit;
1019 // mNode is being used in a separate thread; queue a message to set the value
1020 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1024 bool Actor::IsOrientationInherited() const
1026 return mInheritOrientation;
1029 void Actor::SetSizeModeFactor( const Vector3& factor )
1031 EnsureRelayoutData();
1033 mRelayoutData->sizeModeFactor = factor;
1036 const Vector3& Actor::GetSizeModeFactor() const
1038 if ( mRelayoutData )
1040 return mRelayoutData->sizeModeFactor;
1043 return GetDefaultSizeModeFactor();
1046 void Actor::SetColorMode( ColorMode colorMode )
1048 // non animateable so keep local copy
1049 mColorMode = colorMode;
1052 // mNode is being used in a separate thread; queue a message to set the value
1053 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1057 ColorMode Actor::GetColorMode() const
1059 // we have cached copy
1063 void Actor::SetSize( float width, float height )
1065 SetSize( Vector2( width, height ) );
1068 void Actor::SetSize( float width, float height, float depth )
1070 SetSize( Vector3( width, height, depth ) );
1073 void Actor::SetSize( const Vector2& size )
1075 SetSize( Vector3( size.width, size.height, 0.f ) );
1078 void Actor::SetSizeInternal( const Vector2& size )
1080 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1083 void Actor::SetSize( const Vector3& size )
1085 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1087 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1088 SetPreferredSize( size.GetVectorXY() );
1092 SetSizeInternal( size );
1096 void Actor::SetSizeInternal( const Vector3& size )
1098 // dont allow recursive loop
1099 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1100 // 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
1101 if( ( NULL != mNode )&&
1102 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1103 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1104 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1108 // mNode is being used in a separate thread; queue a message to set the value & base value
1109 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
1111 // Notification for derived classes
1112 mInsideOnSizeSet = true;
1113 OnSizeSet( mTargetSize );
1114 mInsideOnSizeSet = false;
1116 // Raise a relayout request if the flag is not locked
1117 if( mRelayoutData && !mRelayoutData->insideRelayout )
1124 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1126 mTargetSize = targetSize;
1128 // Notify deriving classes
1129 OnSizeAnimation( animation, mTargetSize );
1132 void Actor::NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property )
1134 if ( Dali::Actor::Property::SIZE_WIDTH == property )
1136 mTargetSize.width = targetSize;
1138 else if ( Dali::Actor::Property::SIZE_HEIGHT == property )
1140 mTargetSize.height = targetSize;
1142 else if ( Dali::Actor::Property::SIZE_DEPTH == property )
1144 mTargetSize.depth = targetSize;
1146 // Notify deriving classes
1147 OnSizeAnimation( animation, mTargetSize );
1150 void Actor::NotifyPositionAnimation( Animation& animation, const Vector3& targetPosition )
1152 mTargetPosition = targetPosition;
1155 void Actor::NotifyPositionAnimation( Animation& animation, float targetPosition, Property::Index property )
1157 if ( Dali::Actor::Property::POSITION_X == property )
1159 mTargetPosition.x = targetPosition;
1161 else if ( Dali::Actor::Property::POSITION_Y == property )
1163 mTargetPosition.y = targetPosition;
1165 else if ( Dali::Actor::Property::POSITION_Z == property )
1167 mTargetPosition.z = targetPosition;
1171 void Actor::SetWidth( float width )
1173 mTargetSize.width = width;
1177 // mNode is being used in a separate thread; queue a message to set the value & base value
1178 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1182 void Actor::SetHeight( float height )
1184 mTargetSize.height = height;
1188 // mNode is being used in a separate thread; queue a message to set the value & base value
1189 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1193 void Actor::SetDepth( float depth )
1195 mTargetSize.depth = depth;
1199 // mNode is being used in a separate thread; queue a message to set the value & base value
1200 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1204 const Vector3& Actor::GetTargetSize() const
1209 const Vector3& Actor::GetCurrentSize() const
1213 // mNode is being used in a separate thread; copy the value from the previous update
1214 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1217 return Vector3::ZERO;
1220 Vector3 Actor::GetNaturalSize() const
1222 // It is up to deriving classes to return the appropriate natural size
1223 return Vector3( 0.0f, 0.0f, 0.0f );
1226 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1228 EnsureRelayoutData();
1230 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1232 if( dimension & ( 1 << i ) )
1234 mRelayoutData->resizePolicies[ i ] = policy;
1238 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1240 if( dimension & Dimension::WIDTH )
1242 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1245 if( dimension & Dimension::HEIGHT )
1247 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1251 // If calling SetResizePolicy, assume we want relayout enabled
1252 SetRelayoutEnabled( true );
1254 OnSetResizePolicy( policy, dimension );
1256 // Trigger relayout on this control
1260 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1262 if ( mRelayoutData )
1264 // If more than one dimension is requested, just return the first one found
1265 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1267 if( ( dimension & ( 1 << i ) ) )
1269 return mRelayoutData->resizePolicies[ i ];
1274 return ResizePolicy::DEFAULT;
1277 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1279 EnsureRelayoutData();
1281 mRelayoutData->sizeSetPolicy = policy;
1284 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1286 if ( mRelayoutData )
1288 return mRelayoutData->sizeSetPolicy;
1291 return DEFAULT_SIZE_SCALE_POLICY;
1294 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1296 EnsureRelayoutData();
1298 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1300 if( dimension & ( 1 << i ) )
1302 mRelayoutData->dimensionDependencies[ i ] = dependency;
1307 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1309 if ( mRelayoutData )
1311 // If more than one dimension is requested, just return the first one found
1312 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1314 if( ( dimension & ( 1 << i ) ) )
1316 return mRelayoutData->dimensionDependencies[ i ];
1321 return Dimension::ALL_DIMENSIONS; // Default
1324 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1326 // If relayout data has not been allocated yet and the client is requesting
1327 // to disable it, do nothing
1328 if( mRelayoutData || relayoutEnabled )
1330 EnsureRelayoutData();
1332 mRelayoutData->relayoutEnabled = relayoutEnabled;
1336 bool Actor::IsRelayoutEnabled() const
1338 // Assume that if relayout data has not been allocated yet then
1339 // relayout is disabled
1340 return mRelayoutData && mRelayoutData->relayoutEnabled;
1343 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1345 EnsureRelayoutData();
1347 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1349 if( dimension & ( 1 << i ) )
1351 mRelayoutData->dimensionDirty[ i ] = dirty;
1356 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1358 if ( mRelayoutData )
1360 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1362 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1372 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1374 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1377 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1379 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1382 unsigned int Actor::AddRenderer( Renderer& renderer )
1386 mRenderers = new RendererContainer;
1389 unsigned int index = mRenderers->size();
1390 RendererPtr rendererPtr = RendererPtr( &renderer );
1391 mRenderers->push_back( rendererPtr );
1392 AddRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1396 rendererPtr->Connect();
1402 unsigned int Actor::GetRendererCount() const
1404 unsigned int rendererCount(0);
1407 rendererCount = mRenderers->size();
1410 return rendererCount;
1413 RendererPtr Actor::GetRendererAt( unsigned int index )
1415 RendererPtr renderer;
1416 if( index < GetRendererCount() )
1418 renderer = ( *mRenderers )[ index ];
1424 void Actor::RemoveRenderer( Renderer& renderer )
1428 RendererIter end = mRenderers->end();
1429 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1431 if( (*iter).Get() == &renderer )
1433 mRenderers->erase( iter );
1434 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1441 void Actor::RemoveRenderer( unsigned int index )
1443 if( index < GetRendererCount() )
1445 RendererPtr renderer = ( *mRenderers )[ index ];
1446 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.Get()->GetRendererSceneObject() );
1447 mRenderers->erase( mRenderers->begin()+index );
1451 void Actor::SetOverlay( bool enable )
1453 // Setting STENCIL will override OVERLAY_2D
1454 if( DrawMode::STENCIL != mDrawMode )
1456 SetDrawMode( enable ? DrawMode::OVERLAY_2D : DrawMode::NORMAL );
1460 bool Actor::IsOverlay() const
1462 return ( DrawMode::OVERLAY_2D == mDrawMode );
1465 void Actor::SetDrawMode( DrawMode::Type drawMode )
1467 // this flag is not animatable so keep the value
1468 mDrawMode = drawMode;
1471 // mNode is being used in a separate thread; queue a message to set the value
1472 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1476 DrawMode::Type Actor::GetDrawMode() const
1481 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1483 // only valid when on-stage
1484 StagePtr stage = Stage::GetCurrent();
1485 if( stage && OnStage() )
1487 const RenderTaskList& taskList = stage->GetRenderTaskList();
1489 Vector2 converted( screenX, screenY );
1491 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1492 const int taskCount = taskList.GetTaskCount();
1493 for( int i = taskCount - 1; i >= 0; --i )
1495 Dali::RenderTask task = taskList.GetTask( i );
1496 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1498 // found a task where this conversion was ok so return
1506 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1508 bool retval = false;
1509 // only valid when on-stage
1512 CameraActor* camera = renderTask.GetCameraActor();
1516 renderTask.GetViewport( viewport );
1518 // need to translate coordinates to render tasks coordinate space
1519 Vector2 converted( screenX, screenY );
1520 if( renderTask.TranslateCoordinates( converted ) )
1522 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1529 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1531 // Early-out if mNode is NULL
1537 // Get the ModelView matrix
1539 Matrix::Multiply( modelView, mNode->GetWorldMatrix(0), viewMatrix );
1541 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1542 Matrix invertedMvp( false/*don't init*/);
1543 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1544 bool success = invertedMvp.Invert();
1546 // Convert to GL coordinates
1547 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1552 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1559 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1565 if( XyPlaneIntersect( nearPos, farPos, local ) )
1567 Vector3 size = GetCurrentSize();
1568 localX = local.x + size.x * 0.5f;
1569 localY = local.y + size.y * 0.5f;
1580 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1583 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1585 Mathematical Formulation
1587 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1589 ( p - c ) dot ( p - c ) = r^2
1591 Given a ray with a point of origin 'o', and a direction vector 'd':
1593 ray(t) = o + td, t >= 0
1595 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1597 (o + td - c ) dot ( o + td - c ) = r^2
1599 To solve for t we first expand the above into a more recognisable quadratic equation form
1601 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1610 B = 2( o - c ) dot d
1611 C = ( o - c ) dot ( o - c ) - r^2
1613 which can be solved using a standard quadratic formula.
1615 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1617 Practical Simplification
1619 In a renderer, we often differentiate between world space and object space. In the object space
1620 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1621 into object space, the mathematical solution presented above can be simplified significantly.
1623 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1627 and we can find the t at which the (transformed) ray intersects the sphere by
1629 ( o + td ) dot ( o + td ) = r^2
1631 According to the reasoning above, we expand the above quadratic equation into the general form
1635 which now has coefficients:
1642 // Early out if mNode is NULL
1648 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1650 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1651 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1652 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1654 // Compute the radius is not needed, square radius it's enough.
1655 const Vector3& size( mNode->GetSize( bufferIndex ) );
1657 // Scale the sphere.
1658 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1660 const float width = size.width * scale.width;
1661 const float height = size.height * scale.height;
1663 float squareSphereRadius = 0.5f * ( width * width + height * height );
1665 float a = rayDir.Dot( rayDir ); // a
1666 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1667 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1669 return ( b2 * b2 - a * c ) >= 0.f;
1672 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
1679 // Transforms the ray to the local reference system.
1680 // Calculate the inverse of Model matrix
1681 Matrix invModelMatrix( false/*don't init*/);
1683 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1684 invModelMatrix = mNode->GetWorldMatrix(0);
1685 invModelMatrix.Invert();
1687 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1688 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1690 // Test with the actor's XY plane (Normal = 0 0 1 1).
1692 float a = -rayOriginLocal.z;
1693 float b = rayDirLocal.z;
1695 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1697 // Ray travels distance * rayDirLocal to intersect with plane.
1700 const Vector3& size = mNode->GetSize( bufferIndex );
1702 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1703 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1705 // Test with the actor's geometry.
1706 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1713 void Actor::SetLeaveRequired( bool required )
1715 mLeaveRequired = required;
1718 bool Actor::GetLeaveRequired() const
1720 return mLeaveRequired;
1723 void Actor::SetKeyboardFocusable( bool focusable )
1725 mKeyboardFocusable = focusable;
1728 bool Actor::IsKeyboardFocusable() const
1730 return mKeyboardFocusable;
1733 bool Actor::GetTouchRequired() const
1735 return !mTouchedSignal.Empty() || !mTouchSignal.Empty() || mDerivedRequiresTouch;
1738 bool Actor::GetHoverRequired() const
1740 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1743 bool Actor::GetWheelEventRequired() const
1745 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1748 bool Actor::IsHittable() const
1750 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1753 ActorGestureData& Actor::GetGestureData()
1755 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1756 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1757 if( NULL == mGestureData )
1759 mGestureData = new ActorGestureData;
1761 return *mGestureData;
1764 bool Actor::IsGestureRequred( Gesture::Type type ) const
1766 return mGestureData && mGestureData->IsGestureRequred( type );
1769 bool Actor::EmitTouchEventSignal( const TouchEvent& event, const Dali::TouchData& touch )
1771 bool consumed = false;
1773 if( !mTouchSignal.Empty() )
1775 Dali::Actor handle( this );
1776 consumed = mTouchSignal.Emit( handle, touch );
1779 if( !mTouchedSignal.Empty() || !mTouchSignal.Empty() )
1781 Dali::Actor handle( this );
1782 consumed |= mTouchedSignal.Emit( handle, event );
1787 // Notification for derived classes
1788 consumed = OnTouchEvent( event ); // TODO
1794 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1796 bool consumed = false;
1798 if( !mHoveredSignal.Empty() )
1800 Dali::Actor handle( this );
1801 consumed = mHoveredSignal.Emit( handle, event );
1806 // Notification for derived classes
1807 consumed = OnHoverEvent( event );
1813 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1815 bool consumed = false;
1817 if( !mWheelEventSignal.Empty() )
1819 Dali::Actor handle( this );
1820 consumed = mWheelEventSignal.Emit( handle, event );
1825 // Notification for derived classes
1826 consumed = OnWheelEvent( event );
1832 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
1834 DALI_LOG_WARNING( "Deprecated: Use TouchSignal() instead\n" );
1835 return mTouchedSignal;
1838 Dali::Actor::TouchDataSignalType& Actor::TouchSignal()
1840 return mTouchSignal;
1843 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
1845 return mHoveredSignal;
1848 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
1850 return mWheelEventSignal;
1853 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
1855 return mOnStageSignal;
1858 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
1860 return mOffStageSignal;
1863 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
1865 return mOnRelayoutSignal;
1868 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1870 bool connected( true );
1871 Actor* actor = dynamic_cast< Actor* >( object );
1873 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1875 actor->TouchedSignal().Connect( tracker, functor );
1877 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1879 actor->HoveredSignal().Connect( tracker, functor );
1881 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1883 actor->WheelEventSignal().Connect( tracker, functor );
1885 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
1887 actor->OnStageSignal().Connect( tracker, functor );
1889 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
1891 actor->OffStageSignal().Connect( tracker, functor );
1893 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
1895 actor->OnRelayoutSignal().Connect( tracker, functor );
1899 // signalName does not match any signal
1906 Actor::Actor( DerivedType derivedType )
1911 mParentOrigin( NULL ),
1912 mAnchorPoint( NULL ),
1913 mRelayoutData( NULL ),
1914 mGestureData( NULL ),
1915 mTargetSize( 0.0f, 0.0f, 0.0f ),
1917 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
1919 mIsRoot( ROOT_LAYER == derivedType ),
1920 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
1921 mIsOnStage( false ),
1923 mLeaveRequired( false ),
1924 mKeyboardFocusable( false ),
1925 mDerivedRequiresTouch( false ),
1926 mDerivedRequiresHover( false ),
1927 mDerivedRequiresWheelEvent( false ),
1928 mOnStageSignalled( false ),
1929 mInsideOnSizeSet( false ),
1930 mInheritPosition( true ),
1931 mInheritOrientation( true ),
1932 mInheritScale( true ),
1933 mDrawMode( DrawMode::NORMAL ),
1934 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
1935 mColorMode( Node::DEFAULT_COLOR_MODE )
1939 void Actor::Initialize()
1942 SceneGraph::Node* node = CreateNode();
1944 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
1945 mNode = node; // Keep raw-pointer to Node
1949 GetEventThreadServices().RegisterObject( this );
1954 // Remove mParent pointers from children even if we're destroying core,
1955 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1958 ActorConstIter endIter = mChildren->end();
1959 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1961 (*iter)->SetParent( NULL );
1967 // Guard to allow handle destruction after Core has been destroyed
1968 if( EventThreadServices::IsCoreRunning() )
1972 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
1973 mNode = NULL; // Node is about to be destroyed
1976 GetEventThreadServices().UnregisterObject( this );
1979 // Cleanup optional gesture data
1980 delete mGestureData;
1982 // Cleanup optional parent origin and anchor
1983 delete mParentOrigin;
1984 delete mAnchorPoint;
1986 // Delete optional relayout data
1989 delete mRelayoutData;
1993 void Actor::ConnectToStage( unsigned int parentDepth )
1995 // This container is used instead of walking the Actor hierarchy.
1996 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
1997 ActorContainer connectionList;
1999 // This stage is atomic i.e. not interrupted by user callbacks.
2000 RecursiveConnectToStage( connectionList, parentDepth + 1 );
2002 // Notify applications about the newly connected actors.
2003 const ActorIter endIter = connectionList.end();
2004 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2006 (*iter)->NotifyStageConnection();
2012 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth )
2014 DALI_ASSERT_ALWAYS( !OnStage() );
2019 ConnectToSceneGraph();
2021 // Notification for internal derived classes
2022 OnStageConnectionInternal();
2024 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2025 connectionList.push_back( ActorPtr( this ) );
2027 // Recursively connect children
2030 ActorConstIter endIter = mChildren->end();
2031 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2033 (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
2039 * This method is called when the Actor is connected to the Stage.
2040 * The parent must have added its Node to the scene-graph.
2041 * The child must connect its Node to the parent's Node.
2042 * This is recursive; the child calls ConnectToStage() for its children.
2044 void Actor::ConnectToSceneGraph()
2046 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2050 // Reparent Node in next Update
2051 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode );
2054 unsigned int rendererCount( GetRendererCount() );
2055 for( unsigned int i(0); i<rendererCount; ++i )
2057 GetRendererAt(i)->Connect();
2060 // Request relayout on all actors that are added to the scenegraph
2063 // Notification for Object::Observers
2067 void Actor::NotifyStageConnection()
2069 // Actors can be removed (in a callback), before the on-stage stage is reported.
2070 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2071 if( OnStage() && !mOnStageSignalled )
2073 // Notification for external (CustomActor) derived classes
2074 OnStageConnectionExternal( mDepth );
2076 if( !mOnStageSignal.Empty() )
2078 Dali::Actor handle( this );
2079 mOnStageSignal.Emit( handle );
2082 // Guard against Remove during callbacks
2085 mOnStageSignalled = true; // signal required next time Actor is removed
2090 void Actor::DisconnectFromStage()
2092 // This container is used instead of walking the Actor hierachy.
2093 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2094 ActorContainer disconnectionList;
2096 // This stage is atomic i.e. not interrupted by user callbacks
2097 RecursiveDisconnectFromStage( disconnectionList );
2099 // Notify applications about the newly disconnected actors.
2100 const ActorIter endIter = disconnectionList.end();
2101 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2103 (*iter)->NotifyStageDisconnection();
2107 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2109 DALI_ASSERT_ALWAYS( OnStage() );
2111 // Recursively disconnect children
2114 ActorConstIter endIter = mChildren->end();
2115 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2117 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2121 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2122 disconnectionList.push_back( ActorPtr( this ) );
2124 // Notification for internal derived classes
2125 OnStageDisconnectionInternal();
2127 DisconnectFromSceneGraph();
2133 * This method is called by an actor or its parent, before a node removal message is sent.
2134 * This is recursive; the child calls DisconnectFromStage() for its children.
2136 void Actor::DisconnectFromSceneGraph()
2138 // Notification for Object::Observers
2139 OnSceneObjectRemove();
2141 unsigned int rendererCount( GetRendererCount() );
2142 for( unsigned int i(0); i<rendererCount; ++i )
2144 GetRendererAt(i)->Disconnect();
2148 void Actor::NotifyStageDisconnection()
2150 // Actors can be added (in a callback), before the off-stage state is reported.
2151 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2152 // only do this step if there is a stage, i.e. Core is not being shut down
2153 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2155 // Notification for external (CustomeActor) derived classes
2156 OnStageDisconnectionExternal();
2158 if( !mOffStageSignal.Empty() )
2160 Dali::Actor handle( this );
2161 mOffStageSignal.Emit( handle );
2164 // Guard against Add during callbacks
2167 mOnStageSignalled = false; // signal required next time Actor is added
2172 bool Actor::IsNodeConnected() const
2174 bool connected( false );
2176 if( OnStage() && ( NULL != mNode ) )
2178 if( IsRoot() || mNode->GetParent() )
2187 unsigned int Actor::GetDefaultPropertyCount() const
2189 return DEFAULT_PROPERTY_COUNT;
2192 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2194 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2196 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2198 indices.PushBack( i );
2202 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2204 if( index < DEFAULT_PROPERTY_COUNT )
2206 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2212 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2214 Property::Index index = Property::INVALID_INDEX;
2216 // Look for name in default properties
2217 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2219 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2220 if( 0 == name.compare( property->name ) )
2230 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2232 if( index < DEFAULT_PROPERTY_COUNT )
2234 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2240 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2242 if( index < DEFAULT_PROPERTY_COUNT )
2244 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2250 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2252 if( index < DEFAULT_PROPERTY_COUNT )
2254 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2260 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2262 if( index < DEFAULT_PROPERTY_COUNT )
2264 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2267 // index out of range...return Property::NONE
2268 return Property::NONE;
2271 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2275 case Dali::Actor::Property::PARENT_ORIGIN:
2277 SetParentOrigin( property.Get< Vector3 >() );
2281 case Dali::Actor::Property::PARENT_ORIGIN_X:
2283 SetParentOriginX( property.Get< float >() );
2287 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2289 SetParentOriginY( property.Get< float >() );
2293 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2295 SetParentOriginZ( property.Get< float >() );
2299 case Dali::Actor::Property::ANCHOR_POINT:
2301 SetAnchorPoint( property.Get< Vector3 >() );
2305 case Dali::Actor::Property::ANCHOR_POINT_X:
2307 SetAnchorPointX( property.Get< float >() );
2311 case Dali::Actor::Property::ANCHOR_POINT_Y:
2313 SetAnchorPointY( property.Get< float >() );
2317 case Dali::Actor::Property::ANCHOR_POINT_Z:
2319 SetAnchorPointZ( property.Get< float >() );
2323 case Dali::Actor::Property::SIZE:
2325 SetSize( property.Get< Vector3 >() );
2329 case Dali::Actor::Property::SIZE_WIDTH:
2331 SetWidth( property.Get< float >() );
2335 case Dali::Actor::Property::SIZE_HEIGHT:
2337 SetHeight( property.Get< float >() );
2341 case Dali::Actor::Property::SIZE_DEPTH:
2343 SetDepth( property.Get< float >() );
2347 case Dali::Actor::Property::POSITION:
2349 SetPosition( property.Get< Vector3 >() );
2353 case Dali::Actor::Property::POSITION_X:
2355 SetX( property.Get< float >() );
2359 case Dali::Actor::Property::POSITION_Y:
2361 SetY( property.Get< float >() );
2365 case Dali::Actor::Property::POSITION_Z:
2367 SetZ( property.Get< float >() );
2371 case Dali::Actor::Property::ORIENTATION:
2373 SetOrientation( property.Get< Quaternion >() );
2377 case Dali::Actor::Property::SCALE:
2379 SetScale( property.Get< Vector3 >() );
2383 case Dali::Actor::Property::SCALE_X:
2385 SetScaleX( property.Get< float >() );
2389 case Dali::Actor::Property::SCALE_Y:
2391 SetScaleY( property.Get< float >() );
2395 case Dali::Actor::Property::SCALE_Z:
2397 SetScaleZ( property.Get< float >() );
2401 case Dali::Actor::Property::VISIBLE:
2403 SetVisible( property.Get< bool >() );
2407 case Dali::Actor::Property::COLOR:
2409 SetColor( property.Get< Vector4 >() );
2413 case Dali::Actor::Property::COLOR_RED:
2415 SetColorRed( property.Get< float >() );
2419 case Dali::Actor::Property::COLOR_GREEN:
2421 SetColorGreen( property.Get< float >() );
2425 case Dali::Actor::Property::COLOR_BLUE:
2427 SetColorBlue( property.Get< float >() );
2431 case Dali::Actor::Property::COLOR_ALPHA:
2433 SetOpacity( property.Get< float >() );
2437 case Dali::Actor::Property::NAME:
2439 SetName( property.Get< std::string >() );
2443 case Dali::Actor::Property::SENSITIVE:
2445 SetSensitive( property.Get< bool >() );
2449 case Dali::Actor::Property::LEAVE_REQUIRED:
2451 SetLeaveRequired( property.Get< bool >() );
2455 case Dali::Actor::Property::INHERIT_POSITION:
2457 SetInheritPosition( property.Get< bool >() );
2461 case Dali::Actor::Property::INHERIT_ORIENTATION:
2463 SetInheritOrientation( property.Get< bool >() );
2467 case Dali::Actor::Property::INHERIT_SCALE:
2469 SetInheritScale( property.Get< bool >() );
2473 case Dali::Actor::Property::COLOR_MODE:
2475 SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2479 case Dali::Actor::Property::POSITION_INHERITANCE:
2481 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2485 case Dali::Actor::Property::DRAW_MODE:
2487 SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2491 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2493 SetSizeModeFactor( property.Get< Vector3 >() );
2497 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2499 ResizePolicy::Type type;
2500 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2502 SetResizePolicy( type, Dimension::WIDTH );
2507 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2509 ResizePolicy::Type type;
2510 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2512 SetResizePolicy( type, Dimension::HEIGHT );
2517 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2519 SizeScalePolicy::Type type;
2520 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount, type ) )
2522 SetSizeScalePolicy( type );
2527 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2529 if( property.Get< bool >() )
2531 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2536 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2538 if( property.Get< bool >() )
2540 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2545 case Dali::Actor::Property::PADDING:
2547 Vector4 padding = property.Get< Vector4 >();
2548 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2549 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2553 case Dali::Actor::Property::MINIMUM_SIZE:
2555 Vector2 size = property.Get< Vector2 >();
2556 SetMinimumSize( size.x, Dimension::WIDTH );
2557 SetMinimumSize( size.y, Dimension::HEIGHT );
2561 case Dali::Actor::Property::MAXIMUM_SIZE:
2563 Vector2 size = property.Get< Vector2 >();
2564 SetMaximumSize( size.x, Dimension::WIDTH );
2565 SetMaximumSize( size.y, Dimension::HEIGHT );
2571 // this can happen in the case of a non-animatable default property so just do nothing
2577 // TODO: This method needs to be removed
2578 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2580 switch( entry.GetType() )
2582 case Property::BOOLEAN:
2584 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2585 DALI_ASSERT_DEBUG( NULL != property );
2587 // property is being used in a separate thread; queue a message to set the property
2588 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2593 case Property::INTEGER:
2595 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2596 DALI_ASSERT_DEBUG( NULL != property );
2598 // property is being used in a separate thread; queue a message to set the property
2599 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2604 case Property::FLOAT:
2606 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2607 DALI_ASSERT_DEBUG( NULL != property );
2609 // property is being used in a separate thread; queue a message to set the property
2610 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2615 case Property::VECTOR2:
2617 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2618 DALI_ASSERT_DEBUG( NULL != property );
2620 // property is being used in a separate thread; queue a message to set the property
2621 if(entry.componentIndex == 0)
2623 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2625 else if(entry.componentIndex == 1)
2627 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2631 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2637 case Property::VECTOR3:
2639 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2640 DALI_ASSERT_DEBUG( NULL != property );
2642 // property is being used in a separate thread; queue a message to set the property
2643 if(entry.componentIndex == 0)
2645 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2647 else if(entry.componentIndex == 1)
2649 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2651 else if(entry.componentIndex == 2)
2653 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2657 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2663 case Property::VECTOR4:
2665 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2666 DALI_ASSERT_DEBUG( NULL != property );
2668 // property is being used in a separate thread; queue a message to set the property
2669 if(entry.componentIndex == 0)
2671 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
2673 else if(entry.componentIndex == 1)
2675 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
2677 else if(entry.componentIndex == 2)
2679 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
2681 else if(entry.componentIndex == 3)
2683 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
2687 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2693 case Property::ROTATION:
2695 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
2696 DALI_ASSERT_DEBUG( NULL != property );
2698 // property is being used in a separate thread; queue a message to set the property
2699 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
2704 case Property::MATRIX:
2706 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
2707 DALI_ASSERT_DEBUG( NULL != property );
2709 // property is being used in a separate thread; queue a message to set the property
2710 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
2715 case Property::MATRIX3:
2717 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
2718 DALI_ASSERT_DEBUG( NULL != property );
2720 // property is being used in a separate thread; queue a message to set the property
2721 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
2728 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
2734 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
2736 Property::Value value;
2740 case Dali::Actor::Property::PARENT_ORIGIN:
2742 value = GetCurrentParentOrigin();
2746 case Dali::Actor::Property::PARENT_ORIGIN_X:
2748 value = GetCurrentParentOrigin().x;
2752 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2754 value = GetCurrentParentOrigin().y;
2758 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2760 value = GetCurrentParentOrigin().z;
2764 case Dali::Actor::Property::ANCHOR_POINT:
2766 value = GetCurrentAnchorPoint();
2770 case Dali::Actor::Property::ANCHOR_POINT_X:
2772 value = GetCurrentAnchorPoint().x;
2776 case Dali::Actor::Property::ANCHOR_POINT_Y:
2778 value = GetCurrentAnchorPoint().y;
2782 case Dali::Actor::Property::ANCHOR_POINT_Z:
2784 value = GetCurrentAnchorPoint().z;
2788 case Dali::Actor::Property::SIZE:
2790 value = GetTargetSize();
2794 case Dali::Actor::Property::SIZE_WIDTH:
2796 value = GetTargetSize().width;
2800 case Dali::Actor::Property::SIZE_HEIGHT:
2802 value = GetTargetSize().height;
2806 case Dali::Actor::Property::SIZE_DEPTH:
2808 value = GetTargetSize().depth;
2812 case Dali::Actor::Property::POSITION:
2814 value = GetTargetPosition();
2818 case Dali::Actor::Property::POSITION_X:
2820 value = GetTargetPosition().x;
2824 case Dali::Actor::Property::POSITION_Y:
2826 value = GetTargetPosition().y;
2830 case Dali::Actor::Property::POSITION_Z:
2832 value = GetTargetPosition().z;
2836 case Dali::Actor::Property::WORLD_POSITION:
2838 value = GetCurrentWorldPosition();
2842 case Dali::Actor::Property::WORLD_POSITION_X:
2844 value = GetCurrentWorldPosition().x;
2848 case Dali::Actor::Property::WORLD_POSITION_Y:
2850 value = GetCurrentWorldPosition().y;
2854 case Dali::Actor::Property::WORLD_POSITION_Z:
2856 value = GetCurrentWorldPosition().z;
2860 case Dali::Actor::Property::ORIENTATION:
2862 value = GetCurrentOrientation();
2866 case Dali::Actor::Property::WORLD_ORIENTATION:
2868 value = GetCurrentWorldOrientation();
2872 case Dali::Actor::Property::SCALE:
2874 value = GetCurrentScale();
2878 case Dali::Actor::Property::SCALE_X:
2880 value = GetCurrentScale().x;
2884 case Dali::Actor::Property::SCALE_Y:
2886 value = GetCurrentScale().y;
2890 case Dali::Actor::Property::SCALE_Z:
2892 value = GetCurrentScale().z;
2896 case Dali::Actor::Property::WORLD_SCALE:
2898 value = GetCurrentWorldScale();
2902 case Dali::Actor::Property::VISIBLE:
2904 value = IsVisible();
2908 case Dali::Actor::Property::COLOR:
2910 value = GetCurrentColor();
2914 case Dali::Actor::Property::COLOR_RED:
2916 value = GetCurrentColor().r;
2920 case Dali::Actor::Property::COLOR_GREEN:
2922 value = GetCurrentColor().g;
2926 case Dali::Actor::Property::COLOR_BLUE:
2928 value = GetCurrentColor().b;
2932 case Dali::Actor::Property::COLOR_ALPHA:
2934 value = GetCurrentColor().a;
2938 case Dali::Actor::Property::WORLD_COLOR:
2940 value = GetCurrentWorldColor();
2944 case Dali::Actor::Property::WORLD_MATRIX:
2946 value = GetCurrentWorldMatrix();
2950 case Dali::Actor::Property::NAME:
2956 case Dali::Actor::Property::SENSITIVE:
2958 value = IsSensitive();
2962 case Dali::Actor::Property::LEAVE_REQUIRED:
2964 value = GetLeaveRequired();
2968 case Dali::Actor::Property::INHERIT_POSITION:
2970 value = IsPositionInherited();
2974 case Dali::Actor::Property::INHERIT_ORIENTATION:
2976 value = IsOrientationInherited();
2980 case Dali::Actor::Property::INHERIT_SCALE:
2982 value = IsScaleInherited();
2986 case Dali::Actor::Property::COLOR_MODE:
2988 value = Scripting::GetColorMode( GetColorMode() );
2992 case Dali::Actor::Property::POSITION_INHERITANCE:
2994 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
2998 case Dali::Actor::Property::DRAW_MODE:
3000 value = Scripting::GetDrawMode( GetDrawMode() );
3004 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3006 value = GetSizeModeFactor();
3010 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3012 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3016 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3018 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3022 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3024 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3028 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3030 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3034 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3036 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3040 case Dali::Actor::Property::PADDING:
3042 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3043 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3044 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3048 case Dali::Actor::Property::MINIMUM_SIZE:
3050 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3054 case Dali::Actor::Property::MAXIMUM_SIZE:
3056 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3062 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3070 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3075 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3077 // This method should only return an object connected to the scene-graph
3078 return OnStage() ? mNode : NULL;
3081 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3083 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3085 const PropertyBase* property( NULL );
3087 // This method should only return a property of an object connected to the scene-graph
3093 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3095 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3096 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3098 property = animatable->GetSceneGraphProperty();
3100 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3102 CustomPropertyMetadata* custom = FindCustomProperty( index );
3103 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3105 property = custom->GetSceneGraphProperty();
3107 else if( NULL != mNode )
3111 case Dali::Actor::Property::SIZE:
3112 property = &mNode->mSize;
3115 case Dali::Actor::Property::SIZE_WIDTH:
3116 property = &mNode->mSize;
3119 case Dali::Actor::Property::SIZE_HEIGHT:
3120 property = &mNode->mSize;
3123 case Dali::Actor::Property::SIZE_DEPTH:
3124 property = &mNode->mSize;
3127 case Dali::Actor::Property::POSITION:
3128 property = &mNode->mPosition;
3131 case Dali::Actor::Property::POSITION_X:
3132 property = &mNode->mPosition;
3135 case Dali::Actor::Property::POSITION_Y:
3136 property = &mNode->mPosition;
3139 case Dali::Actor::Property::POSITION_Z:
3140 property = &mNode->mPosition;
3143 case Dali::Actor::Property::ORIENTATION:
3144 property = &mNode->mOrientation;
3147 case Dali::Actor::Property::SCALE:
3148 property = &mNode->mScale;
3151 case Dali::Actor::Property::SCALE_X:
3152 property = &mNode->mScale;
3155 case Dali::Actor::Property::SCALE_Y:
3156 property = &mNode->mScale;
3159 case Dali::Actor::Property::SCALE_Z:
3160 property = &mNode->mScale;
3163 case Dali::Actor::Property::VISIBLE:
3164 property = &mNode->mVisible;
3167 case Dali::Actor::Property::COLOR:
3168 property = &mNode->mColor;
3171 case Dali::Actor::Property::COLOR_RED:
3172 property = &mNode->mColor;
3175 case Dali::Actor::Property::COLOR_GREEN:
3176 property = &mNode->mColor;
3179 case Dali::Actor::Property::COLOR_BLUE:
3180 property = &mNode->mColor;
3183 case Dali::Actor::Property::COLOR_ALPHA:
3184 property = &mNode->mColor;
3195 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3197 const PropertyInputImpl* property( NULL );
3199 // This method should only return a property of an object connected to the scene-graph
3205 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3207 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3208 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3210 property = animatable->GetSceneGraphProperty();
3212 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3214 CustomPropertyMetadata* custom = FindCustomProperty( index );
3215 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3216 property = custom->GetSceneGraphProperty();
3218 else if( NULL != mNode )
3222 case Dali::Actor::Property::PARENT_ORIGIN:
3223 property = &mNode->mParentOrigin;
3226 case Dali::Actor::Property::PARENT_ORIGIN_X:
3227 property = &mNode->mParentOrigin;
3230 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3231 property = &mNode->mParentOrigin;
3234 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3235 property = &mNode->mParentOrigin;
3238 case Dali::Actor::Property::ANCHOR_POINT:
3239 property = &mNode->mAnchorPoint;
3242 case Dali::Actor::Property::ANCHOR_POINT_X:
3243 property = &mNode->mAnchorPoint;
3246 case Dali::Actor::Property::ANCHOR_POINT_Y:
3247 property = &mNode->mAnchorPoint;
3250 case Dali::Actor::Property::ANCHOR_POINT_Z:
3251 property = &mNode->mAnchorPoint;
3254 case Dali::Actor::Property::SIZE:
3255 property = &mNode->mSize;
3258 case Dali::Actor::Property::SIZE_WIDTH:
3259 property = &mNode->mSize;
3262 case Dali::Actor::Property::SIZE_HEIGHT:
3263 property = &mNode->mSize;
3266 case Dali::Actor::Property::SIZE_DEPTH:
3267 property = &mNode->mSize;
3270 case Dali::Actor::Property::POSITION:
3271 property = &mNode->mPosition;
3274 case Dali::Actor::Property::POSITION_X:
3275 property = &mNode->mPosition;
3278 case Dali::Actor::Property::POSITION_Y:
3279 property = &mNode->mPosition;
3282 case Dali::Actor::Property::POSITION_Z:
3283 property = &mNode->mPosition;
3286 case Dali::Actor::Property::WORLD_POSITION:
3287 property = &mNode->mWorldPosition;
3290 case Dali::Actor::Property::WORLD_POSITION_X:
3291 property = &mNode->mWorldPosition;
3294 case Dali::Actor::Property::WORLD_POSITION_Y:
3295 property = &mNode->mWorldPosition;
3298 case Dali::Actor::Property::WORLD_POSITION_Z:
3299 property = &mNode->mWorldPosition;
3302 case Dali::Actor::Property::ORIENTATION:
3303 property = &mNode->mOrientation;
3306 case Dali::Actor::Property::WORLD_ORIENTATION:
3307 property = &mNode->mWorldOrientation;
3310 case Dali::Actor::Property::SCALE:
3311 property = &mNode->mScale;
3314 case Dali::Actor::Property::SCALE_X:
3315 property = &mNode->mScale;
3318 case Dali::Actor::Property::SCALE_Y:
3319 property = &mNode->mScale;
3322 case Dali::Actor::Property::SCALE_Z:
3323 property = &mNode->mScale;
3326 case Dali::Actor::Property::WORLD_SCALE:
3327 property = &mNode->mWorldScale;
3330 case Dali::Actor::Property::VISIBLE:
3331 property = &mNode->mVisible;
3334 case Dali::Actor::Property::COLOR:
3335 property = &mNode->mColor;
3338 case Dali::Actor::Property::COLOR_RED:
3339 property = &mNode->mColor;
3342 case Dali::Actor::Property::COLOR_GREEN:
3343 property = &mNode->mColor;
3346 case Dali::Actor::Property::COLOR_BLUE:
3347 property = &mNode->mColor;
3350 case Dali::Actor::Property::COLOR_ALPHA:
3351 property = &mNode->mColor;
3354 case Dali::Actor::Property::WORLD_COLOR:
3355 property = &mNode->mWorldColor;
3358 case Dali::Actor::Property::WORLD_MATRIX:
3359 property = &mNode->mWorldMatrix;
3370 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3372 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3374 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3376 // check whether the animatable property is registered already, if not then register one.
3377 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3378 if( animatableProperty )
3380 componentIndex = animatableProperty->componentIndex;
3387 case Dali::Actor::Property::PARENT_ORIGIN_X:
3388 case Dali::Actor::Property::ANCHOR_POINT_X:
3389 case Dali::Actor::Property::SIZE_WIDTH:
3390 case Dali::Actor::Property::POSITION_X:
3391 case Dali::Actor::Property::WORLD_POSITION_X:
3392 case Dali::Actor::Property::SCALE_X:
3393 case Dali::Actor::Property::COLOR_RED:
3399 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3400 case Dali::Actor::Property::ANCHOR_POINT_Y:
3401 case Dali::Actor::Property::SIZE_HEIGHT:
3402 case Dali::Actor::Property::POSITION_Y:
3403 case Dali::Actor::Property::WORLD_POSITION_Y:
3404 case Dali::Actor::Property::SCALE_Y:
3405 case Dali::Actor::Property::COLOR_GREEN:
3411 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3412 case Dali::Actor::Property::ANCHOR_POINT_Z:
3413 case Dali::Actor::Property::SIZE_DEPTH:
3414 case Dali::Actor::Property::POSITION_Z:
3415 case Dali::Actor::Property::WORLD_POSITION_Z:
3416 case Dali::Actor::Property::SCALE_Z:
3417 case Dali::Actor::Property::COLOR_BLUE:
3423 case Dali::Actor::Property::COLOR_ALPHA:
3437 return componentIndex;
3440 void Actor::SetParent( Actor* parent )
3444 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3448 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3451 // Instruct each actor to create a corresponding node in the scene graph
3452 ConnectToStage( parent->GetHierarchyDepth() );
3455 // Resolve the name and index for the child properties if any
3456 ResolveChildProperties();
3458 else // parent being set to NULL
3460 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3464 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3467 DALI_ASSERT_ALWAYS( mNode != NULL );
3471 // Disconnect the Node & its children from the scene-graph.
3472 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3475 // Instruct each actor to discard pointers to the scene-graph
3476 DisconnectFromStage();
3481 SceneGraph::Node* Actor::CreateNode() const
3486 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3489 Actor* actor = dynamic_cast< Actor* >( object );
3493 if( 0 == actionName.compare( ACTION_SHOW ) )
3495 actor->SetVisible( true );
3498 else if( 0 == actionName.compare( ACTION_HIDE ) )
3500 actor->SetVisible( false );
3508 void Actor::EnsureRelayoutData()
3510 // Assign relayout data.
3511 if( !mRelayoutData )
3513 mRelayoutData = new RelayoutData();
3517 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3519 // Check if actor is dependent on parent
3520 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3522 if( ( dimension & ( 1 << i ) ) )
3524 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3525 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3535 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3537 // Check if actor is dependent on children
3538 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3540 if( ( dimension & ( 1 << i ) ) )
3542 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3543 switch( resizePolicy )
3545 case ResizePolicy::FIT_TO_CHILDREN:
3546 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3562 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3564 return Actor::RelayoutDependentOnChildren( dimension );
3567 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3569 // Check each possible dimension and see if it is dependent on the input one
3570 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3572 if( dimension & ( 1 << i ) )
3574 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3581 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3583 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3585 if( dimension & ( 1 << i ) )
3587 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3592 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3594 // If more than one dimension is requested, just return the first one found
3595 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3597 if( ( dimension & ( 1 << i ) ) )
3599 return mRelayoutData->negotiatedDimensions[ i ];
3603 return 0.0f; // Default
3606 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3608 EnsureRelayoutData();
3610 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3612 if( dimension & ( 1 << i ) )
3614 mRelayoutData->dimensionPadding[ i ] = padding;
3619 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3621 if ( mRelayoutData )
3623 // If more than one dimension is requested, just return the first one found
3624 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3626 if( ( dimension & ( 1 << i ) ) )
3628 return mRelayoutData->dimensionPadding[ i ];
3633 return GetDefaultDimensionPadding();
3636 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
3638 EnsureRelayoutData();
3640 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3642 if( dimension & ( 1 << i ) )
3644 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3649 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
3651 if ( mRelayoutData )
3653 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3655 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
3665 float Actor::GetHeightForWidthBase( float width )
3667 float height = 0.0f;
3669 const Vector3 naturalSize = GetNaturalSize();
3670 if( naturalSize.width > 0.0f )
3672 height = naturalSize.height * width / naturalSize.width;
3674 else // we treat 0 as 1:1 aspect ratio
3682 float Actor::GetWidthForHeightBase( float height )
3686 const Vector3 naturalSize = GetNaturalSize();
3687 if( naturalSize.height > 0.0f )
3689 width = naturalSize.width * height / naturalSize.height;
3691 else // we treat 0 as 1:1 aspect ratio
3699 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
3701 // Fill to parent, taking size mode factor into account
3702 switch( child.GetResizePolicy( dimension ) )
3704 case ResizePolicy::FILL_TO_PARENT:
3706 return GetLatestSize( dimension );
3709 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3711 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
3714 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3716 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
3721 return GetLatestSize( dimension );
3726 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
3728 // Can be overridden in derived class
3729 return CalculateChildSizeBase( child, dimension );
3732 float Actor::GetHeightForWidth( float width )
3734 // Can be overridden in derived class
3735 return GetHeightForWidthBase( width );
3738 float Actor::GetWidthForHeight( float height )
3740 // Can be overridden in derived class
3741 return GetWidthForHeightBase( height );
3744 float Actor::GetLatestSize( Dimension::Type dimension ) const
3746 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
3749 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
3751 Vector2 padding = GetPadding( dimension );
3753 return GetLatestSize( dimension ) + padding.x + padding.y;
3756 float Actor::NegotiateFromParent( Dimension::Type dimension )
3758 Actor* parent = GetParent();
3761 Vector2 padding( GetPadding( dimension ) );
3762 Vector2 parentPadding( parent->GetPadding( dimension ) );
3763 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
3769 float Actor::NegotiateFromChildren( Dimension::Type dimension )
3771 float maxDimensionPoint = 0.0f;
3773 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3775 ActorPtr child = GetChildAt( i );
3777 if( !child->RelayoutDependentOnParent( dimension ) )
3779 // Calculate the min and max points that the children range across
3780 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
3781 float dimensionSize = child->GetRelayoutSize( dimension );
3782 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
3786 return maxDimensionPoint;
3789 float Actor::GetSize( Dimension::Type dimension ) const
3791 return GetDimensionValue( GetTargetSize(), dimension );
3794 float Actor::GetNaturalSize( Dimension::Type dimension ) const
3796 return GetDimensionValue( GetNaturalSize(), dimension );
3799 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
3801 switch( GetResizePolicy( dimension ) )
3803 case ResizePolicy::USE_NATURAL_SIZE:
3805 return GetNaturalSize( dimension );
3808 case ResizePolicy::FIXED:
3810 return GetDimensionValue( GetPreferredSize(), dimension );
3813 case ResizePolicy::USE_ASSIGNED_SIZE:
3815 return GetDimensionValue( maximumSize, dimension );
3818 case ResizePolicy::FILL_TO_PARENT:
3819 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3820 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3822 return NegotiateFromParent( dimension );
3825 case ResizePolicy::FIT_TO_CHILDREN:
3827 return NegotiateFromChildren( dimension );
3830 case ResizePolicy::DIMENSION_DEPENDENCY:
3832 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
3835 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
3837 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
3840 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
3842 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
3854 return 0.0f; // Default
3857 float Actor::ClampDimension( float size, Dimension::Type dimension )
3859 const float minSize = GetMinimumSize( dimension );
3860 const float maxSize = GetMaximumSize( dimension );
3862 return std::max( minSize, std::min( size, maxSize ) );
3865 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
3867 // Check if it needs to be negotiated
3868 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
3870 // Check that we havn't gotten into an infinite loop
3871 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
3872 bool recursionFound = false;
3873 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
3875 if( *it == searchActor )
3877 recursionFound = true;
3882 if( !recursionFound )
3884 // Record the path that we have taken
3885 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
3887 // Dimension dependency check
3888 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3890 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
3892 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
3894 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
3898 // Parent dependency check
3899 Actor* parent = GetParent();
3900 if( parent && RelayoutDependentOnParent( dimension ) )
3902 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
3905 // Children dependency check
3906 if( RelayoutDependentOnChildren( dimension ) )
3908 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3910 ActorPtr child = GetChildAt( i );
3912 // Only relayout child first if it is not dependent on this actor
3913 if( !child->RelayoutDependentOnParent( dimension ) )
3915 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
3920 // For deriving classes
3921 OnCalculateRelayoutSize( dimension );
3923 // All dependencies checked, calculate the size and set negotiated flag
3924 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
3926 SetNegotiatedDimension( newSize, dimension );
3927 SetLayoutNegotiated( true, dimension );
3929 // For deriving classes
3930 OnLayoutNegotiated( newSize, dimension );
3932 // This actor has been successfully processed, pop it off the recursion stack
3933 recursionStack.pop_back();
3937 // TODO: Break infinite loop
3938 SetLayoutNegotiated( true, dimension );
3943 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
3945 // Negotiate all dimensions that require it
3946 ActorDimensionStack recursionStack;
3948 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3950 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
3953 NegotiateDimension( dimension, allocatedSize, recursionStack );
3957 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
3959 switch( mRelayoutData->sizeSetPolicy )
3961 case SizeScalePolicy::USE_SIZE_SET:
3966 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
3968 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
3969 const Vector3 naturalSize = GetNaturalSize();
3970 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
3972 const float sizeRatio = size.width / size.height;
3973 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
3975 if( naturalSizeRatio < sizeRatio )
3977 return Vector2( naturalSizeRatio * size.height, size.height );
3979 else if( naturalSizeRatio > sizeRatio )
3981 return Vector2( size.width, size.width / naturalSizeRatio );
3992 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
3994 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
3995 const Vector3 naturalSize = GetNaturalSize();
3996 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
3998 const float sizeRatio = size.width / size.height;
3999 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4001 if( naturalSizeRatio < sizeRatio )
4003 return Vector2( size.width, size.width / naturalSizeRatio );
4005 else if( naturalSizeRatio > sizeRatio )
4007 return Vector2( naturalSizeRatio * size.height, size.height );
4026 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4028 // Do the set actor size
4029 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4031 // Adjust for size set policy
4032 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4034 // Lock the flag to stop recursive relayouts on set size
4035 mRelayoutData->insideRelayout = true;
4036 SetSize( negotiatedSize );
4037 mRelayoutData->insideRelayout = false;
4039 // Clear flags for all dimensions
4040 SetLayoutDirty( false );
4042 // Give deriving classes a chance to respond
4043 OnRelayout( negotiatedSize, container );
4045 if( !mOnRelayoutSignal.Empty() )
4047 Dali::Actor handle( this );
4048 mOnRelayoutSignal.Emit( handle );
4052 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4054 // Force a size negotiation for actors that has assigned size during relayout
4055 // This is required as otherwise the flags that force a relayout will not
4056 // necessarilly be set. This will occur if the actor has already been laid out.
4057 // The dirty flags are then cleared. Then if the actor is added back into the
4058 // relayout container afterwards, the dirty flags would still be clear...
4059 // causing a relayout to be skipped. Here we force any actors added to the
4060 // container to be relayed out.
4061 if(GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE)
4063 SetLayoutNegotiated(false, Dimension::WIDTH);
4065 if(GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE)
4067 SetLayoutNegotiated(false, Dimension::HEIGHT);
4070 // Do the negotiation
4071 NegotiateDimensions( allocatedSize );
4073 // Set the actor size
4074 SetNegotiatedSize( container );
4076 // Negotiate down to children
4077 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4079 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4081 ActorPtr child = GetChildAt( i );
4083 // Forces children that have already been laid out to be relayed out
4084 // if they have assigned size during relayout.
4085 if(child->GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE)
4087 child->SetLayoutNegotiated(false, Dimension::WIDTH);
4088 child->SetLayoutDirty(true, Dimension::WIDTH);
4090 if(child->GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE)
4092 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
4093 child->SetLayoutDirty(true, Dimension::HEIGHT);
4096 // Only relayout if required
4097 if( child->RelayoutRequired() )
4099 container.Add( Dali::Actor( child.Get() ), newBounds );
4104 void Actor::RelayoutRequest( Dimension::Type dimension )
4106 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4107 if( relayoutController )
4109 Dali::Actor self( this );
4110 relayoutController->RequestRelayout( self, dimension );
4114 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4118 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4122 void Actor::SetPreferredSize( const Vector2& size )
4124 EnsureRelayoutData();
4126 if( size.width > 0.0f )
4128 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4131 if( size.height > 0.0f )
4133 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4136 mRelayoutData->preferredSize = size;
4141 Vector2 Actor::GetPreferredSize() const
4143 if ( mRelayoutData )
4145 return Vector2( mRelayoutData->preferredSize );
4148 return GetDefaultPreferredSize();
4151 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4153 EnsureRelayoutData();
4155 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4157 if( dimension & ( 1 << i ) )
4159 mRelayoutData->minimumSize[ i ] = size;
4166 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4168 if ( mRelayoutData )
4170 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4172 if( dimension & ( 1 << i ) )
4174 return mRelayoutData->minimumSize[ i ];
4179 return 0.0f; // Default
4182 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4184 EnsureRelayoutData();
4186 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4188 if( dimension & ( 1 << i ) )
4190 mRelayoutData->maximumSize[ i ] = size;
4197 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4199 if ( mRelayoutData )
4201 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4203 if( dimension & ( 1 << i ) )
4205 return mRelayoutData->maximumSize[ i ];
4210 return FLT_MAX; // Default
4213 Object* Actor::GetParentObject() const
4218 } // namespace Internal