2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/event/actors/actor-impl.h>
28 #include <dali/public-api/common/dali-common.h>
29 #include <dali/public-api/common/constants.h>
30 #include <dali/public-api/math/vector2.h>
31 #include <dali/public-api/math/vector3.h>
32 #include <dali/public-api/math/radian.h>
33 #include <dali/public-api/object/type-registry.h>
34 #include <dali/devel-api/scripting/scripting.h>
36 #include <dali/internal/common/internal-constants.h>
37 #include <dali/internal/event/common/event-thread-services.h>
38 #include <dali/internal/event/render-tasks/render-task-impl.h>
39 #include <dali/internal/event/actors/camera-actor-impl.h>
40 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
41 #include <dali/internal/event/common/property-helper.h>
42 #include <dali/internal/event/common/stage-impl.h>
43 #include <dali/internal/event/common/type-info-impl.h>
44 #include <dali/internal/event/animation/constraint-impl.h>
45 #include <dali/internal/event/common/projection.h>
46 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
47 #include <dali/internal/update/common/animatable-property.h>
48 #include <dali/internal/update/nodes/node-messages.h>
49 #include <dali/internal/update/nodes/node-declarations.h>
50 #include <dali/internal/update/animation/scene-graph-constraint.h>
51 #include <dali/internal/event/events/actor-gesture-data.h>
52 #include <dali/internal/common/message.h>
53 #include <dali/integration-api/debug.h>
55 using Dali::Internal::SceneGraph::Node;
56 using Dali::Internal::SceneGraph::AnimatableProperty;
57 using Dali::Internal::SceneGraph::PropertyBase;
61 namespace ResizePolicy
66 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )
67 DALI_ENUM_TO_STRING( FIXED )
68 DALI_ENUM_TO_STRING( USE_NATURAL_SIZE )
69 DALI_ENUM_TO_STRING( FILL_TO_PARENT )
70 DALI_ENUM_TO_STRING( SIZE_RELATIVE_TO_PARENT )
71 DALI_ENUM_TO_STRING( SIZE_FIXED_OFFSET_FROM_PARENT )
72 DALI_ENUM_TO_STRING( FIT_TO_CHILDREN )
73 DALI_ENUM_TO_STRING( DIMENSION_DEPENDENCY )
74 DALI_ENUM_TO_STRING( USE_ASSIGNED_SIZE )
75 DALI_ENUM_TO_STRING_TABLE_END( Type )
77 } // unnamed namespace
80 namespace SizeScalePolicy
84 // Enumeration to / from string conversion tables
85 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )
86 DALI_ENUM_TO_STRING( USE_SIZE_SET )
87 DALI_ENUM_TO_STRING( FIT_WITH_ASPECT_RATIO )
88 DALI_ENUM_TO_STRING( FILL_WITH_ASPECT_RATIO )
89 DALI_ENUM_TO_STRING_TABLE_END( Type )
90 } // unnamed namespace
96 unsigned int Actor::mActorCounter = 0;
100 /// Using a function because of library initialisation order. Vector3::ONE may not have been initialised yet.
101 inline const Vector3& GetDefaultSizeModeFactor()
106 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
107 inline const Vector2& GetDefaultPreferredSize()
109 return Vector2::ZERO;
112 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
113 inline const Vector2& GetDefaultDimensionPadding()
115 return Vector2::ZERO;
118 const SizeScalePolicy::Type DEFAULT_SIZE_SCALE_POLICY = SizeScalePolicy::USE_SIZE_SET;
120 } // unnamed namespace
123 * Struct to collect relayout variables
125 struct Actor::RelayoutData
128 : sizeModeFactor( GetDefaultSizeModeFactor() ), preferredSize( GetDefaultPreferredSize() ), sizeSetPolicy( DEFAULT_SIZE_SCALE_POLICY ), relayoutEnabled( false ), insideRelayout( false )
130 // Set size negotiation defaults
131 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
133 resizePolicies[ i ] = ResizePolicy::DEFAULT;
134 negotiatedDimensions[ i ] = 0.0f;
135 dimensionNegotiated[ i ] = false;
136 dimensionDirty[ i ] = false;
137 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
138 dimensionPadding[ i ] = GetDefaultDimensionPadding();
139 minimumSize[ i ] = 0.0f;
140 maximumSize[ i ] = FLT_MAX;
144 ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies
146 Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies
148 Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
150 float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
152 float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be
153 float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be
155 bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated
156 bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
158 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
160 Vector2 preferredSize; ///< The preferred size of the actor
162 SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
164 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
165 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
168 namespace // unnamed namespace
174 * We want to discourage the use of property strings (minimize string comparisons),
175 * particularly for the default properties.
176 * Name Type writable animatable constraint-input enum for index-checking
178 DALI_PROPERTY_TABLE_BEGIN
179 DALI_PROPERTY( "parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
180 DALI_PROPERTY( "parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
181 DALI_PROPERTY( "parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
182 DALI_PROPERTY( "parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
183 DALI_PROPERTY( "anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
184 DALI_PROPERTY( "anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
185 DALI_PROPERTY( "anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
186 DALI_PROPERTY( "anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
187 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
188 DALI_PROPERTY( "sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
189 DALI_PROPERTY( "sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
190 DALI_PROPERTY( "sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
191 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
192 DALI_PROPERTY( "positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
193 DALI_PROPERTY( "positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
194 DALI_PROPERTY( "positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
195 DALI_PROPERTY( "worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
196 DALI_PROPERTY( "worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
197 DALI_PROPERTY( "worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
198 DALI_PROPERTY( "worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
199 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
200 DALI_PROPERTY( "worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
201 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
202 DALI_PROPERTY( "scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
203 DALI_PROPERTY( "scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
204 DALI_PROPERTY( "scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
205 DALI_PROPERTY( "worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
206 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
207 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
208 DALI_PROPERTY( "colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
209 DALI_PROPERTY( "colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
210 DALI_PROPERTY( "colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
211 DALI_PROPERTY( "colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
212 DALI_PROPERTY( "worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
213 DALI_PROPERTY( "worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
214 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
215 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
216 DALI_PROPERTY( "leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
217 DALI_PROPERTY( "inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
218 DALI_PROPERTY( "inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
219 DALI_PROPERTY( "colorMode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
220 DALI_PROPERTY( "positionInheritance", STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE )
221 DALI_PROPERTY( "drawMode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
222 DALI_PROPERTY( "sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
223 DALI_PROPERTY( "widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
224 DALI_PROPERTY( "heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
225 DALI_PROPERTY( "sizeScalePolicy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
226 DALI_PROPERTY( "widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
227 DALI_PROPERTY( "heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
228 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
229 DALI_PROPERTY( "minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
230 DALI_PROPERTY( "maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
231 DALI_PROPERTY( "inheritPosition", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_POSITION )
232 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
236 const char* const SIGNAL_TOUCHED = "touched";
237 const char* const SIGNAL_HOVERED = "hovered";
238 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
239 const char* const SIGNAL_ON_STAGE = "onStage";
240 const char* const SIGNAL_OFF_STAGE = "offStage";
241 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
245 const char* const ACTION_SHOW = "show";
246 const char* const ACTION_HIDE = "hide";
248 BaseHandle CreateActor()
250 return Dali::Actor::New();
253 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
255 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
256 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
257 SignalConnectorType signalConnector3( mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal );
258 SignalConnectorType signalConnector4( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
259 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
260 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
262 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
263 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
266 * @brief Extract a given dimension from a Vector2
268 * @param[in] values The values to extract from
269 * @param[in] dimension The dimension to extract
270 * @return Return the value for the dimension
272 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
276 case Dimension::WIDTH:
280 case Dimension::HEIGHT:
282 return values.height;
293 * @brief Extract a given dimension from a Vector3
295 * @param[in] values The values to extract from
296 * @param[in] dimension The dimension to extract
297 * @return Return the value for the dimension
299 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
301 return GetDimensionValue( values.GetVectorXY(), dimension );
305 } // unnamed namespace
307 ActorPtr Actor::New()
309 ActorPtr actor( new Actor( BASIC ) );
311 // Second-phase construction
317 const std::string& Actor::GetName() const
322 void Actor::SetName( const std::string& name )
328 // ATTENTION: string for debug purposes is not thread safe.
329 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
333 unsigned int Actor::GetId() const
338 bool Actor::OnStage() const
343 Dali::Layer Actor::GetLayer()
347 // Short-circuit for Layer derived actors
350 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
353 // Find the immediate Layer parent
354 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
356 if( parent->IsLayer() )
358 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
365 void Actor::Add( Actor& child )
367 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
368 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
372 mChildren = new ActorContainer;
375 Actor* const oldParent( child.mParent );
377 // child might already be ours
378 if( this != oldParent )
380 // if we already have parent, unparent us first
383 oldParent->Remove( child ); // This causes OnChildRemove callback
385 // Old parent may need to readjust to missing child
386 if( oldParent->RelayoutDependentOnChildren() )
388 oldParent->RelayoutRequest();
392 // Guard against Add() during previous OnChildRemove callback
395 // Do this first, since user callbacks from within SetParent() may need to remove child
396 mChildren->push_back( ActorPtr( &child ) );
398 // SetParent asserts that child can be added
399 child.SetParent( this );
401 // Notification for derived classes
404 // Only put in a relayout request if there is a suitable dependency
405 if( RelayoutDependentOnChildren() )
413 void Actor::Remove( Actor& child )
415 if( (this == &child) || (!mChildren) )
417 // no children or removing itself
423 // Find the child in mChildren, and unparent it
424 ActorIter end = mChildren->end();
425 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
427 ActorPtr actor = (*iter);
429 if( actor.Get() == &child )
431 // Keep handle for OnChildRemove notification
434 // Do this first, since user callbacks from within SetParent() may need to add the child
435 mChildren->erase( iter );
437 DALI_ASSERT_DEBUG( actor->GetParent() == this );
438 actor->SetParent( NULL );
446 // Only put in a relayout request if there is a suitable dependency
447 if( RelayoutDependentOnChildren() )
453 // Notification for derived classes
454 OnChildRemove( child );
457 void Actor::Unparent()
461 // Remove this actor from the parent. The remove will put a relayout request in for
462 // the parent if required
463 mParent->Remove( *this );
464 // mParent is now NULL!
468 unsigned int Actor::GetChildCount() const
470 return ( NULL != mChildren ) ? mChildren->size() : 0;
473 ActorPtr Actor::GetChildAt( unsigned int index ) const
475 DALI_ASSERT_ALWAYS( index < GetChildCount() );
477 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
480 ActorPtr Actor::FindChildByName( const std::string& actorName )
483 if( actorName == mName )
489 ActorIter end = mChildren->end();
490 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
492 child = (*iter)->FindChildByName( actorName );
503 ActorPtr Actor::FindChildById( const unsigned int id )
512 ActorIter end = mChildren->end();
513 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
515 child = (*iter)->FindChildById( id );
526 void Actor::SetParentOrigin( const Vector3& origin )
530 // mNode is being used in a separate thread; queue a message to set the value & base value
531 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
534 // Cache for event-thread access
537 // not allocated, check if different from default
538 if( ParentOrigin::DEFAULT != origin )
540 mParentOrigin = new Vector3( origin );
545 // check if different from current costs more than just set
546 *mParentOrigin = origin;
550 void Actor::SetParentOriginX( float x )
552 const Vector3& current = GetCurrentParentOrigin();
554 SetParentOrigin( Vector3( x, current.y, current.z ) );
557 void Actor::SetParentOriginY( float y )
559 const Vector3& current = GetCurrentParentOrigin();
561 SetParentOrigin( Vector3( current.x, y, current.z ) );
564 void Actor::SetParentOriginZ( float z )
566 const Vector3& current = GetCurrentParentOrigin();
568 SetParentOrigin( Vector3( current.x, current.y, z ) );
571 const Vector3& Actor::GetCurrentParentOrigin() const
573 // Cached for event-thread access
574 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
577 void Actor::SetAnchorPoint( const Vector3& anchor )
581 // mNode is being used in a separate thread; queue a message to set the value & base value
582 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
585 // Cache for event-thread access
588 // not allocated, check if different from default
589 if( AnchorPoint::DEFAULT != anchor )
591 mAnchorPoint = new Vector3( anchor );
596 // check if different from current costs more than just set
597 *mAnchorPoint = anchor;
601 void Actor::SetAnchorPointX( float x )
603 const Vector3& current = GetCurrentAnchorPoint();
605 SetAnchorPoint( Vector3( x, current.y, current.z ) );
608 void Actor::SetAnchorPointY( float y )
610 const Vector3& current = GetCurrentAnchorPoint();
612 SetAnchorPoint( Vector3( current.x, y, current.z ) );
615 void Actor::SetAnchorPointZ( float z )
617 const Vector3& current = GetCurrentAnchorPoint();
619 SetAnchorPoint( Vector3( current.x, current.y, z ) );
622 const Vector3& Actor::GetCurrentAnchorPoint() const
624 // Cached for event-thread access
625 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
628 void Actor::SetPosition( float x, float y )
630 SetPosition( Vector3( x, y, 0.0f ) );
633 void Actor::SetPosition( float x, float y, float z )
635 SetPosition( Vector3( x, y, z ) );
638 void Actor::SetPosition( const Vector3& position )
640 mTargetPosition = position;
644 // mNode is being used in a separate thread; queue a message to set the value & base value
645 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
649 void Actor::SetX( float x )
651 mTargetPosition.x = x;
655 // mNode is being used in a separate thread; queue a message to set the value & base value
656 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
660 void Actor::SetY( float y )
662 mTargetPosition.y = y;
666 // mNode is being used in a separate thread; queue a message to set the value & base value
667 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
671 void Actor::SetZ( float z )
673 mTargetPosition.z = z;
677 // mNode is being used in a separate thread; queue a message to set the value & base value
678 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
682 void Actor::TranslateBy( const Vector3& distance )
684 mTargetPosition += distance;
688 // mNode is being used in a separate thread; queue a message to set the value & base value
689 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
693 const Vector3& Actor::GetCurrentPosition() const
697 // mNode is being used in a separate thread; copy the value from the previous update
698 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
701 return Vector3::ZERO;
704 const Vector3& Actor::GetTargetPosition() const
706 return mTargetPosition;
709 const Vector3& Actor::GetCurrentWorldPosition() const
713 // mNode is being used in a separate thread; copy the value from the previous update
714 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
717 return Vector3::ZERO;
720 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
722 // this flag is not animatable so keep the value
723 mPositionInheritanceMode = mode;
726 // mNode is being used in a separate thread; queue a message to set the value
727 SetInheritPositionMessage( GetEventThreadServices(), *mNode, mode == INHERIT_PARENT_POSITION );
731 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
733 // Cached for event-thread access
734 return mPositionInheritanceMode;
737 void Actor::SetInheritPosition( bool inherit )
739 if( mInheritPosition != inherit && NULL != mNode )
741 // non animateable so keep local copy
742 mInheritPosition = inherit;
743 SetInheritPositionMessage( GetEventThreadServices(), *mNode, inherit );
747 bool Actor::IsPositionInherited() const
749 return mInheritPosition;
752 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
754 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
755 normalizedAxis.Normalize();
757 Quaternion orientation( angle, normalizedAxis );
759 SetOrientation( orientation );
762 void Actor::SetOrientation( const Quaternion& orientation )
766 // mNode is being used in a separate thread; queue a message to set the value & base value
767 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation );
771 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
775 // mNode is being used in a separate thread; queue a message to set the value & base value
776 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, Quaternion(angle, axis) );
780 void Actor::RotateBy( const Quaternion& relativeRotation )
784 // mNode is being used in a separate thread; queue a message to set the value & base value
785 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
789 const Quaternion& Actor::GetCurrentOrientation() const
793 // mNode is being used in a separate thread; copy the value from the previous update
794 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
797 return Quaternion::IDENTITY;
800 const Quaternion& Actor::GetCurrentWorldOrientation() const
804 // mNode is being used in a separate thread; copy the value from the previous update
805 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
808 return Quaternion::IDENTITY;
811 void Actor::SetScale( float scale )
813 SetScale( Vector3( scale, scale, scale ) );
816 void Actor::SetScale( float x, float y, float z )
818 SetScale( Vector3( x, y, z ) );
821 void Actor::SetScale( const Vector3& scale )
825 // mNode is being used in a separate thread; queue a message to set the value & base value
826 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
830 void Actor::SetScaleX( float x )
834 // mNode is being used in a separate thread; queue a message to set the value & base value
835 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
839 void Actor::SetScaleY( float y )
843 // mNode is being used in a separate thread; queue a message to set the value & base value
844 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
848 void Actor::SetScaleZ( float z )
852 // mNode is being used in a separate thread; queue a message to set the value & base value
853 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
857 void Actor::ScaleBy(const Vector3& relativeScale)
861 // mNode is being used in a separate thread; queue a message to set the value & base value
862 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
866 const Vector3& Actor::GetCurrentScale() const
870 // mNode is being used in a separate thread; copy the value from the previous update
871 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
877 const Vector3& Actor::GetCurrentWorldScale() const
881 // mNode is being used in a separate thread; copy the value from the previous update
882 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
888 void Actor::SetInheritScale( bool inherit )
891 if( mInheritScale != inherit && NULL != mNode )
893 // non animateable so keep local copy
894 mInheritScale = inherit;
895 // mNode is being used in a separate thread; queue a message to set the value
896 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
900 bool Actor::IsScaleInherited() const
902 return mInheritScale;
905 Matrix Actor::GetCurrentWorldMatrix() const
909 return mNode->GetWorldMatrix(0);
912 return Matrix::IDENTITY;
915 void Actor::SetVisible( bool visible )
919 // mNode is being used in a separate thread; queue a message to set the value & base value
920 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
924 bool Actor::IsVisible() const
928 // mNode is being used in a separate thread; copy the value from the previous update
929 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
935 void Actor::SetOpacity( float opacity )
939 // mNode is being used in a separate thread; queue a message to set the value & base value
940 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
944 float Actor::GetCurrentOpacity() const
948 // mNode is being used in a separate thread; copy the value from the previous update
949 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
955 const Vector4& Actor::GetCurrentWorldColor() const
959 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
965 void Actor::SetColor( const Vector4& color )
969 // mNode is being used in a separate thread; queue a message to set the value & base value
970 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
974 void Actor::SetColorRed( float red )
978 // mNode is being used in a separate thread; queue a message to set the value & base value
979 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
983 void Actor::SetColorGreen( float green )
987 // mNode is being used in a separate thread; queue a message to set the value & base value
988 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
992 void Actor::SetColorBlue( float blue )
996 // mNode is being used in a separate thread; queue a message to set the value & base value
997 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1001 const Vector4& Actor::GetCurrentColor() const
1005 // mNode is being used in a separate thread; copy the value from the previous update
1006 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1009 return Color::WHITE;
1012 void Actor::SetInheritOrientation( bool inherit )
1014 if( mInheritOrientation != inherit && NULL != mNode)
1016 // non animateable so keep local copy
1017 mInheritOrientation = inherit;
1018 // mNode is being used in a separate thread; queue a message to set the value
1019 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1023 bool Actor::IsOrientationInherited() const
1025 return mInheritOrientation;
1028 void Actor::SetSizeModeFactor( const Vector3& factor )
1030 EnsureRelayoutData();
1032 mRelayoutData->sizeModeFactor = factor;
1035 const Vector3& Actor::GetSizeModeFactor() const
1037 if ( mRelayoutData )
1039 return mRelayoutData->sizeModeFactor;
1042 return GetDefaultSizeModeFactor();
1045 void Actor::SetColorMode( ColorMode colorMode )
1047 // non animateable so keep local copy
1048 mColorMode = colorMode;
1051 // mNode is being used in a separate thread; queue a message to set the value
1052 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1056 ColorMode Actor::GetColorMode() const
1058 // we have cached copy
1062 void Actor::SetSize( float width, float height )
1064 SetSize( Vector2( width, height ) );
1067 void Actor::SetSize( float width, float height, float depth )
1069 SetSize( Vector3( width, height, depth ) );
1072 void Actor::SetSize( const Vector2& size )
1074 SetSize( Vector3( size.width, size.height, 0.f ) );
1077 void Actor::SetSizeInternal( const Vector2& size )
1079 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1082 void Actor::SetSize( const Vector3& size )
1084 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1086 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1087 SetPreferredSize( size.GetVectorXY() );
1091 SetSizeInternal( size );
1095 void Actor::SetSizeInternal( const Vector3& size )
1097 // dont allow recursive loop
1098 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1099 // 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
1100 if( ( NULL != mNode )&&
1101 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1102 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1103 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1107 // mNode is being used in a separate thread; queue a message to set the value & base value
1108 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
1110 // Notification for derived classes
1111 mInsideOnSizeSet = true;
1112 OnSizeSet( mTargetSize );
1113 mInsideOnSizeSet = false;
1115 // Raise a relayout request if the flag is not locked
1116 if( mRelayoutData && !mRelayoutData->insideRelayout )
1123 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1125 mTargetSize = targetSize;
1127 // Notify deriving classes
1128 OnSizeAnimation( animation, mTargetSize );
1131 void Actor::NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property )
1133 if ( Dali::Actor::Property::SIZE_WIDTH == property )
1135 mTargetSize.width = targetSize;
1137 else if ( Dali::Actor::Property::SIZE_HEIGHT == property )
1139 mTargetSize.height = targetSize;
1141 else if ( Dali::Actor::Property::SIZE_DEPTH == property )
1143 mTargetSize.depth = targetSize;
1145 // Notify deriving classes
1146 OnSizeAnimation( animation, mTargetSize );
1149 void Actor::NotifyPositionAnimation( Animation& animation, const Vector3& targetPosition )
1151 mTargetPosition = targetPosition;
1154 void Actor::NotifyPositionAnimation( Animation& animation, float targetPosition, Property::Index property )
1156 if ( Dali::Actor::Property::POSITION_X == property )
1158 mTargetPosition.x = targetPosition;
1160 else if ( Dali::Actor::Property::POSITION_Y == property )
1162 mTargetPosition.y = targetPosition;
1164 else if ( Dali::Actor::Property::POSITION_Z == property )
1166 mTargetPosition.z = targetPosition;
1170 void Actor::SetWidth( float width )
1172 mTargetSize.width = width;
1176 // mNode is being used in a separate thread; queue a message to set the value & base value
1177 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1181 void Actor::SetHeight( float height )
1183 mTargetSize.height = height;
1187 // mNode is being used in a separate thread; queue a message to set the value & base value
1188 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1192 void Actor::SetDepth( float depth )
1194 mTargetSize.depth = depth;
1198 // mNode is being used in a separate thread; queue a message to set the value & base value
1199 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1203 const Vector3& Actor::GetTargetSize() const
1208 const Vector3& Actor::GetCurrentSize() const
1212 // mNode is being used in a separate thread; copy the value from the previous update
1213 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1216 return Vector3::ZERO;
1219 Vector3 Actor::GetNaturalSize() const
1221 // It is up to deriving classes to return the appropriate natural size
1222 return Vector3( 0.0f, 0.0f, 0.0f );
1225 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1227 EnsureRelayoutData();
1229 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1231 if( dimension & ( 1 << i ) )
1233 mRelayoutData->resizePolicies[ i ] = policy;
1237 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1239 if( dimension & Dimension::WIDTH )
1241 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1244 if( dimension & Dimension::HEIGHT )
1246 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1250 // If calling SetResizePolicy, assume we want relayout enabled
1251 SetRelayoutEnabled( true );
1253 OnSetResizePolicy( policy, dimension );
1255 // Trigger relayout on this control
1259 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1261 if ( mRelayoutData )
1263 // If more than one dimension is requested, just return the first one found
1264 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1266 if( ( dimension & ( 1 << i ) ) )
1268 return mRelayoutData->resizePolicies[ i ];
1273 return ResizePolicy::DEFAULT;
1276 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1278 EnsureRelayoutData();
1280 mRelayoutData->sizeSetPolicy = policy;
1283 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1285 if ( mRelayoutData )
1287 return mRelayoutData->sizeSetPolicy;
1290 return DEFAULT_SIZE_SCALE_POLICY;
1293 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1295 EnsureRelayoutData();
1297 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1299 if( dimension & ( 1 << i ) )
1301 mRelayoutData->dimensionDependencies[ i ] = dependency;
1306 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1308 if ( mRelayoutData )
1310 // If more than one dimension is requested, just return the first one found
1311 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1313 if( ( dimension & ( 1 << i ) ) )
1315 return mRelayoutData->dimensionDependencies[ i ];
1320 return Dimension::ALL_DIMENSIONS; // Default
1323 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1325 // If relayout data has not been allocated yet and the client is requesting
1326 // to disable it, do nothing
1327 if( mRelayoutData || relayoutEnabled )
1329 EnsureRelayoutData();
1331 mRelayoutData->relayoutEnabled = relayoutEnabled;
1335 bool Actor::IsRelayoutEnabled() const
1337 // Assume that if relayout data has not been allocated yet then
1338 // relayout is disabled
1339 return mRelayoutData && mRelayoutData->relayoutEnabled;
1342 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1344 EnsureRelayoutData();
1346 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1348 if( dimension & ( 1 << i ) )
1350 mRelayoutData->dimensionDirty[ i ] = dirty;
1355 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1357 if ( mRelayoutData )
1359 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1361 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1371 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1373 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1376 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1378 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1381 unsigned int Actor::AddRenderer( Renderer& renderer )
1385 mRenderers = new RendererContainer;
1388 unsigned int index = mRenderers->size();
1389 RendererPtr rendererPtr = RendererPtr( &renderer );
1390 mRenderers->push_back( rendererPtr );
1391 AddRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1395 rendererPtr->Connect();
1401 unsigned int Actor::GetRendererCount() const
1403 unsigned int rendererCount(0);
1406 rendererCount = mRenderers->size();
1409 return rendererCount;
1412 RendererPtr Actor::GetRendererAt( unsigned int index )
1414 RendererPtr renderer;
1415 if( index < GetRendererCount() )
1417 renderer = ( *mRenderers )[ index ];
1423 void Actor::RemoveRenderer( Renderer& renderer )
1427 RendererIter end = mRenderers->end();
1428 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1430 if( (*iter).Get() == &renderer )
1432 mRenderers->erase( iter );
1433 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1440 void Actor::RemoveRenderer( unsigned int index )
1442 if( index < GetRendererCount() )
1444 RendererPtr renderer = ( *mRenderers )[ index ];
1445 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.Get()->GetRendererSceneObject() );
1446 mRenderers->erase( mRenderers->begin()+index );
1450 void Actor::SetOverlay( bool enable )
1452 // Setting STENCIL will override OVERLAY_2D
1453 if( DrawMode::STENCIL != mDrawMode )
1455 SetDrawMode( enable ? DrawMode::OVERLAY_2D : DrawMode::NORMAL );
1459 bool Actor::IsOverlay() const
1461 return ( DrawMode::OVERLAY_2D == mDrawMode );
1464 void Actor::SetDrawMode( DrawMode::Type drawMode )
1466 // this flag is not animatable so keep the value
1467 mDrawMode = drawMode;
1470 // mNode is being used in a separate thread; queue a message to set the value
1471 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1475 DrawMode::Type Actor::GetDrawMode() const
1480 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1482 // only valid when on-stage
1483 StagePtr stage = Stage::GetCurrent();
1484 if( stage && OnStage() )
1486 const RenderTaskList& taskList = stage->GetRenderTaskList();
1488 Vector2 converted( screenX, screenY );
1490 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1491 const int taskCount = taskList.GetTaskCount();
1492 for( int i = taskCount - 1; i >= 0; --i )
1494 Dali::RenderTask task = taskList.GetTask( i );
1495 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1497 // found a task where this conversion was ok so return
1505 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1507 bool retval = false;
1508 // only valid when on-stage
1511 CameraActor* camera = renderTask.GetCameraActor();
1515 renderTask.GetViewport( viewport );
1517 // need to translate coordinates to render tasks coordinate space
1518 Vector2 converted( screenX, screenY );
1519 if( renderTask.TranslateCoordinates( converted ) )
1521 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1528 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1530 // Early-out if mNode is NULL
1536 // Get the ModelView matrix
1538 Matrix::Multiply( modelView, mNode->GetWorldMatrix(0), viewMatrix );
1540 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1541 Matrix invertedMvp( false/*don't init*/);
1542 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1543 bool success = invertedMvp.Invert();
1545 // Convert to GL coordinates
1546 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1551 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1558 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1564 if( XyPlaneIntersect( nearPos, farPos, local ) )
1566 Vector3 size = GetCurrentSize();
1567 localX = local.x + size.x * 0.5f;
1568 localY = local.y + size.y * 0.5f;
1579 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1582 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1584 Mathematical Formulation
1586 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1588 ( p - c ) dot ( p - c ) = r^2
1590 Given a ray with a point of origin 'o', and a direction vector 'd':
1592 ray(t) = o + td, t >= 0
1594 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1596 (o + td - c ) dot ( o + td - c ) = r^2
1598 To solve for t we first expand the above into a more recognisable quadratic equation form
1600 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1609 B = 2( o - c ) dot d
1610 C = ( o - c ) dot ( o - c ) - r^2
1612 which can be solved using a standard quadratic formula.
1614 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1616 Practical Simplification
1618 In a renderer, we often differentiate between world space and object space. In the object space
1619 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1620 into object space, the mathematical solution presented above can be simplified significantly.
1622 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1626 and we can find the t at which the (transformed) ray intersects the sphere by
1628 ( o + td ) dot ( o + td ) = r^2
1630 According to the reasoning above, we expand the above quadratic equation into the general form
1634 which now has coefficients:
1641 // Early out if mNode is NULL
1647 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1649 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1650 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1651 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1653 // Compute the radius is not needed, square radius it's enough.
1654 const Vector3& size( mNode->GetSize( bufferIndex ) );
1656 // Scale the sphere.
1657 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1659 const float width = size.width * scale.width;
1660 const float height = size.height * scale.height;
1662 float squareSphereRadius = 0.5f * ( width * width + height * height );
1664 float a = rayDir.Dot( rayDir ); // a
1665 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1666 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1668 return ( b2 * b2 - a * c ) >= 0.f;
1671 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
1678 // Transforms the ray to the local reference system.
1679 // Calculate the inverse of Model matrix
1680 Matrix invModelMatrix( false/*don't init*/);
1682 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1683 invModelMatrix = mNode->GetWorldMatrix(0);
1684 invModelMatrix.Invert();
1686 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1687 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1689 // Test with the actor's XY plane (Normal = 0 0 1 1).
1691 float a = -rayOriginLocal.z;
1692 float b = rayDirLocal.z;
1694 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1696 // Ray travels distance * rayDirLocal to intersect with plane.
1699 const Vector3& size = mNode->GetSize( bufferIndex );
1701 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1702 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1704 // Test with the actor's geometry.
1705 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1712 void Actor::SetLeaveRequired( bool required )
1714 mLeaveRequired = required;
1717 bool Actor::GetLeaveRequired() const
1719 return mLeaveRequired;
1722 void Actor::SetKeyboardFocusable( bool focusable )
1724 mKeyboardFocusable = focusable;
1727 bool Actor::IsKeyboardFocusable() const
1729 return mKeyboardFocusable;
1732 bool Actor::GetTouchRequired() const
1734 return !mTouchedSignal.Empty() || mDerivedRequiresTouch;
1737 bool Actor::GetHoverRequired() const
1739 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1742 bool Actor::GetWheelEventRequired() const
1744 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1747 bool Actor::IsHittable() const
1749 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1752 ActorGestureData& Actor::GetGestureData()
1754 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1755 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1756 if( NULL == mGestureData )
1758 mGestureData = new ActorGestureData;
1760 return *mGestureData;
1763 bool Actor::IsGestureRequred( Gesture::Type type ) const
1765 return mGestureData && mGestureData->IsGestureRequred( type );
1768 bool Actor::EmitTouchEventSignal( const TouchEvent& event )
1770 bool consumed = false;
1772 if( !mTouchedSignal.Empty() )
1774 Dali::Actor handle( this );
1775 consumed = mTouchedSignal.Emit( handle, event );
1780 // Notification for derived classes
1781 consumed = OnTouchEvent( event );
1787 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1789 bool consumed = false;
1791 if( !mHoveredSignal.Empty() )
1793 Dali::Actor handle( this );
1794 consumed = mHoveredSignal.Emit( handle, event );
1799 // Notification for derived classes
1800 consumed = OnHoverEvent( event );
1806 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1808 bool consumed = false;
1810 if( !mWheelEventSignal.Empty() )
1812 Dali::Actor handle( this );
1813 consumed = mWheelEventSignal.Emit( handle, event );
1818 // Notification for derived classes
1819 consumed = OnWheelEvent( event );
1825 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
1827 return mTouchedSignal;
1830 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
1832 return mHoveredSignal;
1835 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
1837 return mWheelEventSignal;
1840 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
1842 return mOnStageSignal;
1845 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
1847 return mOffStageSignal;
1850 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
1852 return mOnRelayoutSignal;
1855 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1857 bool connected( true );
1858 Actor* actor = dynamic_cast< Actor* >( object );
1860 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1862 actor->TouchedSignal().Connect( tracker, functor );
1864 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1866 actor->HoveredSignal().Connect( tracker, functor );
1868 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1870 actor->WheelEventSignal().Connect( tracker, functor );
1872 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
1874 actor->OnStageSignal().Connect( tracker, functor );
1876 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
1878 actor->OffStageSignal().Connect( tracker, functor );
1880 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
1882 actor->OnRelayoutSignal().Connect( tracker, functor );
1886 // signalName does not match any signal
1893 Actor::Actor( DerivedType derivedType )
1898 mParentOrigin( NULL ),
1899 mAnchorPoint( NULL ),
1900 mRelayoutData( NULL ),
1901 mGestureData( NULL ),
1902 mTargetSize( 0.0f, 0.0f, 0.0f ),
1904 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
1906 mIsRoot( ROOT_LAYER == derivedType ),
1907 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
1908 mIsOnStage( false ),
1910 mLeaveRequired( false ),
1911 mKeyboardFocusable( false ),
1912 mDerivedRequiresTouch( false ),
1913 mDerivedRequiresHover( false ),
1914 mDerivedRequiresWheelEvent( false ),
1915 mOnStageSignalled( false ),
1916 mInsideOnSizeSet( false ),
1917 mInheritPosition( true ),
1918 mInheritOrientation( true ),
1919 mInheritScale( true ),
1920 mDrawMode( DrawMode::NORMAL ),
1921 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
1922 mColorMode( Node::DEFAULT_COLOR_MODE )
1926 void Actor::Initialize()
1929 SceneGraph::Node* node = CreateNode();
1931 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
1932 mNode = node; // Keep raw-pointer to Node
1936 GetEventThreadServices().RegisterObject( this );
1941 // Remove mParent pointers from children even if we're destroying core,
1942 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1945 ActorConstIter endIter = mChildren->end();
1946 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1948 (*iter)->SetParent( NULL );
1954 // Guard to allow handle destruction after Core has been destroyed
1955 if( EventThreadServices::IsCoreRunning() )
1959 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
1960 mNode = NULL; // Node is about to be destroyed
1963 GetEventThreadServices().UnregisterObject( this );
1966 // Cleanup optional gesture data
1967 delete mGestureData;
1969 // Cleanup optional parent origin and anchor
1970 delete mParentOrigin;
1971 delete mAnchorPoint;
1973 // Delete optional relayout data
1976 delete mRelayoutData;
1980 void Actor::ConnectToStage( unsigned int parentDepth )
1982 // This container is used instead of walking the Actor hierarchy.
1983 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
1984 ActorContainer connectionList;
1986 // This stage is atomic i.e. not interrupted by user callbacks.
1987 RecursiveConnectToStage( connectionList, parentDepth + 1 );
1989 // Notify applications about the newly connected actors.
1990 const ActorIter endIter = connectionList.end();
1991 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
1993 (*iter)->NotifyStageConnection();
1999 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth )
2001 DALI_ASSERT_ALWAYS( !OnStage() );
2006 ConnectToSceneGraph();
2008 // Notification for internal derived classes
2009 OnStageConnectionInternal();
2011 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2012 connectionList.push_back( ActorPtr( this ) );
2014 // Recursively connect children
2017 ActorConstIter endIter = mChildren->end();
2018 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2020 (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
2026 * This method is called when the Actor is connected to the Stage.
2027 * The parent must have added its Node to the scene-graph.
2028 * The child must connect its Node to the parent's Node.
2029 * This is recursive; the child calls ConnectToStage() for its children.
2031 void Actor::ConnectToSceneGraph()
2033 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2037 // Reparent Node in next Update
2038 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode );
2041 unsigned int rendererCount( GetRendererCount() );
2042 for( unsigned int i(0); i<rendererCount; ++i )
2044 GetRendererAt(i)->Connect();
2047 // Request relayout on all actors that are added to the scenegraph
2050 // Notification for Object::Observers
2054 void Actor::NotifyStageConnection()
2056 // Actors can be removed (in a callback), before the on-stage stage is reported.
2057 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2058 if( OnStage() && !mOnStageSignalled )
2060 // Notification for external (CustomActor) derived classes
2061 OnStageConnectionExternal( mDepth );
2063 if( !mOnStageSignal.Empty() )
2065 Dali::Actor handle( this );
2066 mOnStageSignal.Emit( handle );
2069 // Guard against Remove during callbacks
2072 mOnStageSignalled = true; // signal required next time Actor is removed
2077 void Actor::DisconnectFromStage()
2079 // This container is used instead of walking the Actor hierachy.
2080 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2081 ActorContainer disconnectionList;
2083 // This stage is atomic i.e. not interrupted by user callbacks
2084 RecursiveDisconnectFromStage( disconnectionList );
2086 // Notify applications about the newly disconnected actors.
2087 const ActorIter endIter = disconnectionList.end();
2088 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2090 (*iter)->NotifyStageDisconnection();
2094 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2096 DALI_ASSERT_ALWAYS( OnStage() );
2098 // Recursively disconnect children
2101 ActorConstIter endIter = mChildren->end();
2102 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2104 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2108 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2109 disconnectionList.push_back( ActorPtr( this ) );
2111 // Notification for internal derived classes
2112 OnStageDisconnectionInternal();
2114 DisconnectFromSceneGraph();
2120 * This method is called by an actor or its parent, before a node removal message is sent.
2121 * This is recursive; the child calls DisconnectFromStage() for its children.
2123 void Actor::DisconnectFromSceneGraph()
2125 // Notification for Object::Observers
2126 OnSceneObjectRemove();
2128 unsigned int rendererCount( GetRendererCount() );
2129 for( unsigned int i(0); i<rendererCount; ++i )
2131 GetRendererAt(i)->Disconnect();
2135 void Actor::NotifyStageDisconnection()
2137 // Actors can be added (in a callback), before the off-stage state is reported.
2138 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2139 // only do this step if there is a stage, i.e. Core is not being shut down
2140 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2142 // Notification for external (CustomeActor) derived classes
2143 OnStageDisconnectionExternal();
2145 if( !mOffStageSignal.Empty() )
2147 Dali::Actor handle( this );
2148 mOffStageSignal.Emit( handle );
2151 // Guard against Add during callbacks
2154 mOnStageSignalled = false; // signal required next time Actor is added
2159 bool Actor::IsNodeConnected() const
2161 bool connected( false );
2163 if( OnStage() && ( NULL != mNode ) )
2165 if( IsRoot() || mNode->GetParent() )
2174 unsigned int Actor::GetDefaultPropertyCount() const
2176 return DEFAULT_PROPERTY_COUNT;
2179 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2181 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2183 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2185 indices.PushBack( i );
2189 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2191 if( index < DEFAULT_PROPERTY_COUNT )
2193 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2199 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2201 Property::Index index = Property::INVALID_INDEX;
2203 // Look for name in default properties
2204 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2206 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2207 if( 0 == name.compare( property->name ) )
2217 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2219 if( index < DEFAULT_PROPERTY_COUNT )
2221 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2227 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2229 if( index < DEFAULT_PROPERTY_COUNT )
2231 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2237 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2239 if( index < DEFAULT_PROPERTY_COUNT )
2241 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2247 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2249 if( index < DEFAULT_PROPERTY_COUNT )
2251 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2254 // index out of range...return Property::NONE
2255 return Property::NONE;
2258 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2262 case Dali::Actor::Property::PARENT_ORIGIN:
2264 SetParentOrigin( property.Get< Vector3 >() );
2268 case Dali::Actor::Property::PARENT_ORIGIN_X:
2270 SetParentOriginX( property.Get< float >() );
2274 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2276 SetParentOriginY( property.Get< float >() );
2280 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2282 SetParentOriginZ( property.Get< float >() );
2286 case Dali::Actor::Property::ANCHOR_POINT:
2288 SetAnchorPoint( property.Get< Vector3 >() );
2292 case Dali::Actor::Property::ANCHOR_POINT_X:
2294 SetAnchorPointX( property.Get< float >() );
2298 case Dali::Actor::Property::ANCHOR_POINT_Y:
2300 SetAnchorPointY( property.Get< float >() );
2304 case Dali::Actor::Property::ANCHOR_POINT_Z:
2306 SetAnchorPointZ( property.Get< float >() );
2310 case Dali::Actor::Property::SIZE:
2312 SetSize( property.Get< Vector3 >() );
2316 case Dali::Actor::Property::SIZE_WIDTH:
2318 SetWidth( property.Get< float >() );
2322 case Dali::Actor::Property::SIZE_HEIGHT:
2324 SetHeight( property.Get< float >() );
2328 case Dali::Actor::Property::SIZE_DEPTH:
2330 SetDepth( property.Get< float >() );
2334 case Dali::Actor::Property::POSITION:
2336 SetPosition( property.Get< Vector3 >() );
2340 case Dali::Actor::Property::POSITION_X:
2342 SetX( property.Get< float >() );
2346 case Dali::Actor::Property::POSITION_Y:
2348 SetY( property.Get< float >() );
2352 case Dali::Actor::Property::POSITION_Z:
2354 SetZ( property.Get< float >() );
2358 case Dali::Actor::Property::ORIENTATION:
2360 SetOrientation( property.Get< Quaternion >() );
2364 case Dali::Actor::Property::SCALE:
2366 SetScale( property.Get< Vector3 >() );
2370 case Dali::Actor::Property::SCALE_X:
2372 SetScaleX( property.Get< float >() );
2376 case Dali::Actor::Property::SCALE_Y:
2378 SetScaleY( property.Get< float >() );
2382 case Dali::Actor::Property::SCALE_Z:
2384 SetScaleZ( property.Get< float >() );
2388 case Dali::Actor::Property::VISIBLE:
2390 SetVisible( property.Get< bool >() );
2394 case Dali::Actor::Property::COLOR:
2396 SetColor( property.Get< Vector4 >() );
2400 case Dali::Actor::Property::COLOR_RED:
2402 SetColorRed( property.Get< float >() );
2406 case Dali::Actor::Property::COLOR_GREEN:
2408 SetColorGreen( property.Get< float >() );
2412 case Dali::Actor::Property::COLOR_BLUE:
2414 SetColorBlue( property.Get< float >() );
2418 case Dali::Actor::Property::COLOR_ALPHA:
2420 SetOpacity( property.Get< float >() );
2424 case Dali::Actor::Property::NAME:
2426 SetName( property.Get< std::string >() );
2430 case Dali::Actor::Property::SENSITIVE:
2432 SetSensitive( property.Get< bool >() );
2436 case Dali::Actor::Property::LEAVE_REQUIRED:
2438 SetLeaveRequired( property.Get< bool >() );
2442 case Dali::Actor::Property::INHERIT_POSITION:
2444 SetInheritPosition( property.Get< bool >() );
2448 case Dali::Actor::Property::INHERIT_ORIENTATION:
2450 SetInheritOrientation( property.Get< bool >() );
2454 case Dali::Actor::Property::INHERIT_SCALE:
2456 SetInheritScale( property.Get< bool >() );
2460 case Dali::Actor::Property::COLOR_MODE:
2462 SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2466 case Dali::Actor::Property::POSITION_INHERITANCE:
2468 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2472 case Dali::Actor::Property::DRAW_MODE:
2474 SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2478 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2480 SetSizeModeFactor( property.Get< Vector3 >() );
2484 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2486 ResizePolicy::Type type;
2487 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2489 SetResizePolicy( type, Dimension::WIDTH );
2494 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2496 ResizePolicy::Type type;
2497 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2499 SetResizePolicy( type, Dimension::HEIGHT );
2504 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2506 SizeScalePolicy::Type type;
2507 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount, type ) )
2509 SetSizeScalePolicy( type );
2514 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2516 if( property.Get< bool >() )
2518 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2523 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2525 if( property.Get< bool >() )
2527 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2532 case Dali::Actor::Property::PADDING:
2534 Vector4 padding = property.Get< Vector4 >();
2535 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2536 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2540 case Dali::Actor::Property::MINIMUM_SIZE:
2542 Vector2 size = property.Get< Vector2 >();
2543 SetMinimumSize( size.x, Dimension::WIDTH );
2544 SetMinimumSize( size.y, Dimension::HEIGHT );
2548 case Dali::Actor::Property::MAXIMUM_SIZE:
2550 Vector2 size = property.Get< Vector2 >();
2551 SetMaximumSize( size.x, Dimension::WIDTH );
2552 SetMaximumSize( size.y, Dimension::HEIGHT );
2558 // this can happen in the case of a non-animatable default property so just do nothing
2564 // TODO: This method needs to be removed
2565 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2567 switch( entry.GetType() )
2569 case Property::BOOLEAN:
2571 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2572 DALI_ASSERT_DEBUG( NULL != property );
2574 // property is being used in a separate thread; queue a message to set the property
2575 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2580 case Property::INTEGER:
2582 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2583 DALI_ASSERT_DEBUG( NULL != property );
2585 // property is being used in a separate thread; queue a message to set the property
2586 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2591 case Property::FLOAT:
2593 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2594 DALI_ASSERT_DEBUG( NULL != property );
2596 // property is being used in a separate thread; queue a message to set the property
2597 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2602 case Property::VECTOR2:
2604 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2605 DALI_ASSERT_DEBUG( NULL != property );
2607 // property is being used in a separate thread; queue a message to set the property
2608 if(entry.componentIndex == 0)
2610 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2612 else if(entry.componentIndex == 1)
2614 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2618 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2624 case Property::VECTOR3:
2626 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2627 DALI_ASSERT_DEBUG( NULL != property );
2629 // property is being used in a separate thread; queue a message to set the property
2630 if(entry.componentIndex == 0)
2632 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2634 else if(entry.componentIndex == 1)
2636 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2638 else if(entry.componentIndex == 2)
2640 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2644 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2650 case Property::VECTOR4:
2652 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2653 DALI_ASSERT_DEBUG( NULL != property );
2655 // property is being used in a separate thread; queue a message to set the property
2656 if(entry.componentIndex == 0)
2658 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
2660 else if(entry.componentIndex == 1)
2662 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
2664 else if(entry.componentIndex == 2)
2666 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
2668 else if(entry.componentIndex == 3)
2670 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
2674 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2680 case Property::ROTATION:
2682 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
2683 DALI_ASSERT_DEBUG( NULL != property );
2685 // property is being used in a separate thread; queue a message to set the property
2686 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
2691 case Property::MATRIX:
2693 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
2694 DALI_ASSERT_DEBUG( NULL != property );
2696 // property is being used in a separate thread; queue a message to set the property
2697 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
2702 case Property::MATRIX3:
2704 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
2705 DALI_ASSERT_DEBUG( NULL != property );
2707 // property is being used in a separate thread; queue a message to set the property
2708 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
2715 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
2721 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
2723 Property::Value value;
2727 case Dali::Actor::Property::PARENT_ORIGIN:
2729 value = GetCurrentParentOrigin();
2733 case Dali::Actor::Property::PARENT_ORIGIN_X:
2735 value = GetCurrentParentOrigin().x;
2739 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2741 value = GetCurrentParentOrigin().y;
2745 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2747 value = GetCurrentParentOrigin().z;
2751 case Dali::Actor::Property::ANCHOR_POINT:
2753 value = GetCurrentAnchorPoint();
2757 case Dali::Actor::Property::ANCHOR_POINT_X:
2759 value = GetCurrentAnchorPoint().x;
2763 case Dali::Actor::Property::ANCHOR_POINT_Y:
2765 value = GetCurrentAnchorPoint().y;
2769 case Dali::Actor::Property::ANCHOR_POINT_Z:
2771 value = GetCurrentAnchorPoint().z;
2775 case Dali::Actor::Property::SIZE:
2777 value = GetTargetSize();
2781 case Dali::Actor::Property::SIZE_WIDTH:
2783 value = GetTargetSize().width;
2787 case Dali::Actor::Property::SIZE_HEIGHT:
2789 value = GetTargetSize().height;
2793 case Dali::Actor::Property::SIZE_DEPTH:
2795 value = GetTargetSize().depth;
2799 case Dali::Actor::Property::POSITION:
2801 value = GetTargetPosition();
2805 case Dali::Actor::Property::POSITION_X:
2807 value = GetTargetPosition().x;
2811 case Dali::Actor::Property::POSITION_Y:
2813 value = GetTargetPosition().y;
2817 case Dali::Actor::Property::POSITION_Z:
2819 value = GetTargetPosition().z;
2823 case Dali::Actor::Property::WORLD_POSITION:
2825 value = GetCurrentWorldPosition();
2829 case Dali::Actor::Property::WORLD_POSITION_X:
2831 value = GetCurrentWorldPosition().x;
2835 case Dali::Actor::Property::WORLD_POSITION_Y:
2837 value = GetCurrentWorldPosition().y;
2841 case Dali::Actor::Property::WORLD_POSITION_Z:
2843 value = GetCurrentWorldPosition().z;
2847 case Dali::Actor::Property::ORIENTATION:
2849 value = GetCurrentOrientation();
2853 case Dali::Actor::Property::WORLD_ORIENTATION:
2855 value = GetCurrentWorldOrientation();
2859 case Dali::Actor::Property::SCALE:
2861 value = GetCurrentScale();
2865 case Dali::Actor::Property::SCALE_X:
2867 value = GetCurrentScale().x;
2871 case Dali::Actor::Property::SCALE_Y:
2873 value = GetCurrentScale().y;
2877 case Dali::Actor::Property::SCALE_Z:
2879 value = GetCurrentScale().z;
2883 case Dali::Actor::Property::WORLD_SCALE:
2885 value = GetCurrentWorldScale();
2889 case Dali::Actor::Property::VISIBLE:
2891 value = IsVisible();
2895 case Dali::Actor::Property::COLOR:
2897 value = GetCurrentColor();
2901 case Dali::Actor::Property::COLOR_RED:
2903 value = GetCurrentColor().r;
2907 case Dali::Actor::Property::COLOR_GREEN:
2909 value = GetCurrentColor().g;
2913 case Dali::Actor::Property::COLOR_BLUE:
2915 value = GetCurrentColor().b;
2919 case Dali::Actor::Property::COLOR_ALPHA:
2921 value = GetCurrentColor().a;
2925 case Dali::Actor::Property::WORLD_COLOR:
2927 value = GetCurrentWorldColor();
2931 case Dali::Actor::Property::WORLD_MATRIX:
2933 value = GetCurrentWorldMatrix();
2937 case Dali::Actor::Property::NAME:
2943 case Dali::Actor::Property::SENSITIVE:
2945 value = IsSensitive();
2949 case Dali::Actor::Property::LEAVE_REQUIRED:
2951 value = GetLeaveRequired();
2955 case Dali::Actor::Property::INHERIT_POSITION:
2957 value = IsPositionInherited();
2961 case Dali::Actor::Property::INHERIT_ORIENTATION:
2963 value = IsOrientationInherited();
2967 case Dali::Actor::Property::INHERIT_SCALE:
2969 value = IsScaleInherited();
2973 case Dali::Actor::Property::COLOR_MODE:
2975 value = Scripting::GetColorMode( GetColorMode() );
2979 case Dali::Actor::Property::POSITION_INHERITANCE:
2981 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
2985 case Dali::Actor::Property::DRAW_MODE:
2987 value = Scripting::GetDrawMode( GetDrawMode() );
2991 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2993 value = GetSizeModeFactor();
2997 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2999 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3003 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3005 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3009 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3011 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3015 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3017 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3021 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3023 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3027 case Dali::Actor::Property::PADDING:
3029 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3030 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3031 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3035 case Dali::Actor::Property::MINIMUM_SIZE:
3037 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3041 case Dali::Actor::Property::MAXIMUM_SIZE:
3043 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3049 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3057 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3062 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3064 // This method should only return an object connected to the scene-graph
3065 return OnStage() ? mNode : NULL;
3068 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3070 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3072 const PropertyBase* property( NULL );
3074 // This method should only return a property of an object connected to the scene-graph
3080 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3082 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3083 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3085 property = animatable->GetSceneGraphProperty();
3087 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3089 CustomPropertyMetadata* custom = FindCustomProperty( index );
3090 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3092 property = custom->GetSceneGraphProperty();
3094 else if( NULL != mNode )
3098 case Dali::Actor::Property::SIZE:
3099 property = &mNode->mSize;
3102 case Dali::Actor::Property::SIZE_WIDTH:
3103 property = &mNode->mSize;
3106 case Dali::Actor::Property::SIZE_HEIGHT:
3107 property = &mNode->mSize;
3110 case Dali::Actor::Property::SIZE_DEPTH:
3111 property = &mNode->mSize;
3114 case Dali::Actor::Property::POSITION:
3115 property = &mNode->mPosition;
3118 case Dali::Actor::Property::POSITION_X:
3119 property = &mNode->mPosition;
3122 case Dali::Actor::Property::POSITION_Y:
3123 property = &mNode->mPosition;
3126 case Dali::Actor::Property::POSITION_Z:
3127 property = &mNode->mPosition;
3130 case Dali::Actor::Property::ORIENTATION:
3131 property = &mNode->mOrientation;
3134 case Dali::Actor::Property::SCALE:
3135 property = &mNode->mScale;
3138 case Dali::Actor::Property::SCALE_X:
3139 property = &mNode->mScale;
3142 case Dali::Actor::Property::SCALE_Y:
3143 property = &mNode->mScale;
3146 case Dali::Actor::Property::SCALE_Z:
3147 property = &mNode->mScale;
3150 case Dali::Actor::Property::VISIBLE:
3151 property = &mNode->mVisible;
3154 case Dali::Actor::Property::COLOR:
3155 property = &mNode->mColor;
3158 case Dali::Actor::Property::COLOR_RED:
3159 property = &mNode->mColor;
3162 case Dali::Actor::Property::COLOR_GREEN:
3163 property = &mNode->mColor;
3166 case Dali::Actor::Property::COLOR_BLUE:
3167 property = &mNode->mColor;
3170 case Dali::Actor::Property::COLOR_ALPHA:
3171 property = &mNode->mColor;
3182 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3184 const PropertyInputImpl* property( NULL );
3186 // This method should only return a property of an object connected to the scene-graph
3192 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3194 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3195 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3197 property = animatable->GetSceneGraphProperty();
3199 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3201 CustomPropertyMetadata* custom = FindCustomProperty( index );
3202 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3203 property = custom->GetSceneGraphProperty();
3205 else if( NULL != mNode )
3209 case Dali::Actor::Property::PARENT_ORIGIN:
3210 property = &mNode->mParentOrigin;
3213 case Dali::Actor::Property::PARENT_ORIGIN_X:
3214 property = &mNode->mParentOrigin;
3217 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3218 property = &mNode->mParentOrigin;
3221 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3222 property = &mNode->mParentOrigin;
3225 case Dali::Actor::Property::ANCHOR_POINT:
3226 property = &mNode->mAnchorPoint;
3229 case Dali::Actor::Property::ANCHOR_POINT_X:
3230 property = &mNode->mAnchorPoint;
3233 case Dali::Actor::Property::ANCHOR_POINT_Y:
3234 property = &mNode->mAnchorPoint;
3237 case Dali::Actor::Property::ANCHOR_POINT_Z:
3238 property = &mNode->mAnchorPoint;
3241 case Dali::Actor::Property::SIZE:
3242 property = &mNode->mSize;
3245 case Dali::Actor::Property::SIZE_WIDTH:
3246 property = &mNode->mSize;
3249 case Dali::Actor::Property::SIZE_HEIGHT:
3250 property = &mNode->mSize;
3253 case Dali::Actor::Property::SIZE_DEPTH:
3254 property = &mNode->mSize;
3257 case Dali::Actor::Property::POSITION:
3258 property = &mNode->mPosition;
3261 case Dali::Actor::Property::POSITION_X:
3262 property = &mNode->mPosition;
3265 case Dali::Actor::Property::POSITION_Y:
3266 property = &mNode->mPosition;
3269 case Dali::Actor::Property::POSITION_Z:
3270 property = &mNode->mPosition;
3273 case Dali::Actor::Property::WORLD_POSITION:
3274 property = &mNode->mWorldPosition;
3277 case Dali::Actor::Property::WORLD_POSITION_X:
3278 property = &mNode->mWorldPosition;
3281 case Dali::Actor::Property::WORLD_POSITION_Y:
3282 property = &mNode->mWorldPosition;
3285 case Dali::Actor::Property::WORLD_POSITION_Z:
3286 property = &mNode->mWorldPosition;
3289 case Dali::Actor::Property::ORIENTATION:
3290 property = &mNode->mOrientation;
3293 case Dali::Actor::Property::WORLD_ORIENTATION:
3294 property = &mNode->mWorldOrientation;
3297 case Dali::Actor::Property::SCALE:
3298 property = &mNode->mScale;
3301 case Dali::Actor::Property::SCALE_X:
3302 property = &mNode->mScale;
3305 case Dali::Actor::Property::SCALE_Y:
3306 property = &mNode->mScale;
3309 case Dali::Actor::Property::SCALE_Z:
3310 property = &mNode->mScale;
3313 case Dali::Actor::Property::WORLD_SCALE:
3314 property = &mNode->mWorldScale;
3317 case Dali::Actor::Property::VISIBLE:
3318 property = &mNode->mVisible;
3321 case Dali::Actor::Property::COLOR:
3322 property = &mNode->mColor;
3325 case Dali::Actor::Property::COLOR_RED:
3326 property = &mNode->mColor;
3329 case Dali::Actor::Property::COLOR_GREEN:
3330 property = &mNode->mColor;
3333 case Dali::Actor::Property::COLOR_BLUE:
3334 property = &mNode->mColor;
3337 case Dali::Actor::Property::COLOR_ALPHA:
3338 property = &mNode->mColor;
3341 case Dali::Actor::Property::WORLD_COLOR:
3342 property = &mNode->mWorldColor;
3345 case Dali::Actor::Property::WORLD_MATRIX:
3346 property = &mNode->mWorldMatrix;
3357 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3359 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3361 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3363 // check whether the animatable property is registered already, if not then register one.
3364 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3365 if( animatableProperty )
3367 componentIndex = animatableProperty->componentIndex;
3374 case Dali::Actor::Property::PARENT_ORIGIN_X:
3375 case Dali::Actor::Property::ANCHOR_POINT_X:
3376 case Dali::Actor::Property::SIZE_WIDTH:
3377 case Dali::Actor::Property::POSITION_X:
3378 case Dali::Actor::Property::WORLD_POSITION_X:
3379 case Dali::Actor::Property::SCALE_X:
3380 case Dali::Actor::Property::COLOR_RED:
3386 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3387 case Dali::Actor::Property::ANCHOR_POINT_Y:
3388 case Dali::Actor::Property::SIZE_HEIGHT:
3389 case Dali::Actor::Property::POSITION_Y:
3390 case Dali::Actor::Property::WORLD_POSITION_Y:
3391 case Dali::Actor::Property::SCALE_Y:
3392 case Dali::Actor::Property::COLOR_GREEN:
3398 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3399 case Dali::Actor::Property::ANCHOR_POINT_Z:
3400 case Dali::Actor::Property::SIZE_DEPTH:
3401 case Dali::Actor::Property::POSITION_Z:
3402 case Dali::Actor::Property::WORLD_POSITION_Z:
3403 case Dali::Actor::Property::SCALE_Z:
3404 case Dali::Actor::Property::COLOR_BLUE:
3410 case Dali::Actor::Property::COLOR_ALPHA:
3424 return componentIndex;
3427 void Actor::SetParent( Actor* parent )
3431 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3435 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3438 // Instruct each actor to create a corresponding node in the scene graph
3439 ConnectToStage( parent->GetHierarchyDepth() );
3442 else // parent being set to NULL
3444 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3448 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3451 DALI_ASSERT_ALWAYS( mNode != NULL );
3455 // Disconnect the Node & its children from the scene-graph.
3456 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3459 // Instruct each actor to discard pointers to the scene-graph
3460 DisconnectFromStage();
3465 SceneGraph::Node* Actor::CreateNode() const
3470 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3473 Actor* actor = dynamic_cast< Actor* >( object );
3477 if( 0 == actionName.compare( ACTION_SHOW ) )
3479 actor->SetVisible( true );
3482 else if( 0 == actionName.compare( ACTION_HIDE ) )
3484 actor->SetVisible( false );
3492 void Actor::EnsureRelayoutData()
3494 // Assign relayout data.
3495 if( !mRelayoutData )
3497 mRelayoutData = new RelayoutData();
3501 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3503 // Check if actor is dependent on parent
3504 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3506 if( ( dimension & ( 1 << i ) ) )
3508 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3509 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3519 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3521 // Check if actor is dependent on children
3522 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3524 if( ( dimension & ( 1 << i ) ) )
3526 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3527 switch( resizePolicy )
3529 case ResizePolicy::FIT_TO_CHILDREN:
3530 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3546 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3548 return Actor::RelayoutDependentOnChildren( dimension );
3551 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3553 // Check each possible dimension and see if it is dependent on the input one
3554 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3556 if( dimension & ( 1 << i ) )
3558 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3565 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3567 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3569 if( dimension & ( 1 << i ) )
3571 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3576 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3578 // If more than one dimension is requested, just return the first one found
3579 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3581 if( ( dimension & ( 1 << i ) ) )
3583 return mRelayoutData->negotiatedDimensions[ i ];
3587 return 0.0f; // Default
3590 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3592 EnsureRelayoutData();
3594 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3596 if( dimension & ( 1 << i ) )
3598 mRelayoutData->dimensionPadding[ i ] = padding;
3603 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3605 if ( mRelayoutData )
3607 // If more than one dimension is requested, just return the first one found
3608 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3610 if( ( dimension & ( 1 << i ) ) )
3612 return mRelayoutData->dimensionPadding[ i ];
3617 return GetDefaultDimensionPadding();
3620 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
3622 EnsureRelayoutData();
3624 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3626 if( dimension & ( 1 << i ) )
3628 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3633 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
3635 if ( mRelayoutData )
3637 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3639 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
3649 float Actor::GetHeightForWidthBase( float width )
3651 float height = 0.0f;
3653 const Vector3 naturalSize = GetNaturalSize();
3654 if( naturalSize.width > 0.0f )
3656 height = naturalSize.height * width / naturalSize.width;
3658 else // we treat 0 as 1:1 aspect ratio
3666 float Actor::GetWidthForHeightBase( float height )
3670 const Vector3 naturalSize = GetNaturalSize();
3671 if( naturalSize.height > 0.0f )
3673 width = naturalSize.width * height / naturalSize.height;
3675 else // we treat 0 as 1:1 aspect ratio
3683 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
3685 // Fill to parent, taking size mode factor into account
3686 switch( child.GetResizePolicy( dimension ) )
3688 case ResizePolicy::FILL_TO_PARENT:
3690 return GetLatestSize( dimension );
3693 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3695 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
3698 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3700 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
3705 return GetLatestSize( dimension );
3710 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
3712 // Can be overridden in derived class
3713 return CalculateChildSizeBase( child, dimension );
3716 float Actor::GetHeightForWidth( float width )
3718 // Can be overridden in derived class
3719 return GetHeightForWidthBase( width );
3722 float Actor::GetWidthForHeight( float height )
3724 // Can be overridden in derived class
3725 return GetWidthForHeightBase( height );
3728 float Actor::GetLatestSize( Dimension::Type dimension ) const
3730 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
3733 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
3735 Vector2 padding = GetPadding( dimension );
3737 return GetLatestSize( dimension ) + padding.x + padding.y;
3740 float Actor::NegotiateFromParent( Dimension::Type dimension )
3742 Actor* parent = GetParent();
3745 Vector2 padding( GetPadding( dimension ) );
3746 Vector2 parentPadding( parent->GetPadding( dimension ) );
3747 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
3753 float Actor::NegotiateFromChildren( Dimension::Type dimension )
3755 float maxDimensionPoint = 0.0f;
3757 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3759 ActorPtr child = GetChildAt( i );
3761 if( !child->RelayoutDependentOnParent( dimension ) )
3763 // Calculate the min and max points that the children range across
3764 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
3765 float dimensionSize = child->GetRelayoutSize( dimension );
3766 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
3770 return maxDimensionPoint;
3773 float Actor::GetSize( Dimension::Type dimension ) const
3775 return GetDimensionValue( GetTargetSize(), dimension );
3778 float Actor::GetNaturalSize( Dimension::Type dimension ) const
3780 return GetDimensionValue( GetNaturalSize(), dimension );
3783 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
3785 switch( GetResizePolicy( dimension ) )
3787 case ResizePolicy::USE_NATURAL_SIZE:
3789 return GetNaturalSize( dimension );
3792 case ResizePolicy::FIXED:
3794 return GetDimensionValue( GetPreferredSize(), dimension );
3797 case ResizePolicy::USE_ASSIGNED_SIZE:
3799 return GetDimensionValue( maximumSize, dimension );
3802 case ResizePolicy::FILL_TO_PARENT:
3803 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3804 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3806 return NegotiateFromParent( dimension );
3809 case ResizePolicy::FIT_TO_CHILDREN:
3811 return NegotiateFromChildren( dimension );
3814 case ResizePolicy::DIMENSION_DEPENDENCY:
3816 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
3819 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
3821 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
3824 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
3826 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
3838 return 0.0f; // Default
3841 float Actor::ClampDimension( float size, Dimension::Type dimension )
3843 const float minSize = GetMinimumSize( dimension );
3844 const float maxSize = GetMaximumSize( dimension );
3846 return std::max( minSize, std::min( size, maxSize ) );
3849 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
3851 // Check if it needs to be negotiated
3852 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
3854 // Check that we havn't gotten into an infinite loop
3855 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
3856 bool recursionFound = false;
3857 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
3859 if( *it == searchActor )
3861 recursionFound = true;
3866 if( !recursionFound )
3868 // Record the path that we have taken
3869 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
3871 // Dimension dependency check
3872 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3874 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
3876 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
3878 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
3882 // Parent dependency check
3883 Actor* parent = GetParent();
3884 if( parent && RelayoutDependentOnParent( dimension ) )
3886 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
3889 // Children dependency check
3890 if( RelayoutDependentOnChildren( dimension ) )
3892 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3894 ActorPtr child = GetChildAt( i );
3896 // Only relayout child first if it is not dependent on this actor
3897 if( !child->RelayoutDependentOnParent( dimension ) )
3899 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
3904 // For deriving classes
3905 OnCalculateRelayoutSize( dimension );
3907 // All dependencies checked, calculate the size and set negotiated flag
3908 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
3910 SetNegotiatedDimension( newSize, dimension );
3911 SetLayoutNegotiated( true, dimension );
3913 // For deriving classes
3914 OnLayoutNegotiated( newSize, dimension );
3916 // This actor has been successfully processed, pop it off the recursion stack
3917 recursionStack.pop_back();
3921 // TODO: Break infinite loop
3922 SetLayoutNegotiated( true, dimension );
3927 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
3929 // Negotiate all dimensions that require it
3930 ActorDimensionStack recursionStack;
3932 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3934 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
3937 NegotiateDimension( dimension, allocatedSize, recursionStack );
3941 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
3943 switch( mRelayoutData->sizeSetPolicy )
3945 case SizeScalePolicy::USE_SIZE_SET:
3950 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
3952 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
3953 const Vector3 naturalSize = GetNaturalSize();
3954 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
3956 const float sizeRatio = size.width / size.height;
3957 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
3959 if( naturalSizeRatio < sizeRatio )
3961 return Vector2( naturalSizeRatio * size.height, size.height );
3963 else if( naturalSizeRatio > sizeRatio )
3965 return Vector2( size.width, size.width / naturalSizeRatio );
3976 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
3978 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
3979 const Vector3 naturalSize = GetNaturalSize();
3980 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
3982 const float sizeRatio = size.width / size.height;
3983 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
3985 if( naturalSizeRatio < sizeRatio )
3987 return Vector2( size.width, size.width / naturalSizeRatio );
3989 else if( naturalSizeRatio > sizeRatio )
3991 return Vector2( naturalSizeRatio * size.height, size.height );
4010 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4012 // Do the set actor size
4013 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4015 // Adjust for size set policy
4016 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4018 // Lock the flag to stop recursive relayouts on set size
4019 mRelayoutData->insideRelayout = true;
4020 SetSize( negotiatedSize );
4021 mRelayoutData->insideRelayout = false;
4023 // Clear flags for all dimensions
4024 SetLayoutDirty( false );
4026 // Give deriving classes a chance to respond
4027 OnRelayout( negotiatedSize, container );
4029 if( !mOnRelayoutSignal.Empty() )
4031 Dali::Actor handle( this );
4032 mOnRelayoutSignal.Emit( handle );
4036 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4038 // Force a size negotiation for actors that has assigned size during relayout
4039 // This is required as otherwise the flags that force a relayout will not
4040 // necessarilly be set. This will occur if the actor has already been laid out.
4041 // The dirty flags are then cleared. Then if the actor is added back into the
4042 // relayout container afterwards, the dirty flags would still be clear...
4043 // causing a relayout to be skipped. Here we force any actors added to the
4044 // container to be relayed out.
4045 if(GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE)
4047 SetLayoutNegotiated(false, Dimension::WIDTH);
4049 if(GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE)
4051 SetLayoutNegotiated(false, Dimension::HEIGHT);
4054 // Do the negotiation
4055 NegotiateDimensions( allocatedSize );
4057 // Set the actor size
4058 SetNegotiatedSize( container );
4060 // Negotiate down to children
4061 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4063 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4065 ActorPtr child = GetChildAt( i );
4067 // Forces children that have already been laid out to be relayed out
4068 // if they have assigned size during relayout.
4069 if(child->GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE)
4071 child->SetLayoutNegotiated(false, Dimension::WIDTH);
4072 child->SetLayoutDirty(true, Dimension::WIDTH);
4074 if(child->GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE)
4076 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
4077 child->SetLayoutDirty(true, Dimension::HEIGHT);
4080 // Only relayout if required
4081 if( child->RelayoutRequired() )
4083 container.Add( Dali::Actor( child.Get() ), newBounds );
4088 void Actor::RelayoutRequest( Dimension::Type dimension )
4090 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4091 if( relayoutController )
4093 Dali::Actor self( this );
4094 relayoutController->RequestRelayout( self, dimension );
4098 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4102 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4106 void Actor::SetPreferredSize( const Vector2& size )
4108 EnsureRelayoutData();
4110 if( size.width > 0.0f )
4112 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4115 if( size.height > 0.0f )
4117 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4120 mRelayoutData->preferredSize = size;
4125 Vector2 Actor::GetPreferredSize() const
4127 if ( mRelayoutData )
4129 return Vector2( mRelayoutData->preferredSize );
4132 return GetDefaultPreferredSize();
4135 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4137 EnsureRelayoutData();
4139 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4141 if( dimension & ( 1 << i ) )
4143 mRelayoutData->minimumSize[ i ] = size;
4150 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4152 if ( mRelayoutData )
4154 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4156 if( dimension & ( 1 << i ) )
4158 return mRelayoutData->minimumSize[ i ];
4163 return 0.0f; // Default
4166 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4168 EnsureRelayoutData();
4170 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4172 if( dimension & ( 1 << i ) )
4174 mRelayoutData->maximumSize[ i ] = size;
4181 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4183 if ( mRelayoutData )
4185 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4187 if( dimension & ( 1 << i ) )
4189 return mRelayoutData->maximumSize[ i ];
4194 return FLT_MAX; // Default
4197 } // namespace Internal