2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/event/actors/actor-impl.h>
28 #include <dali/public-api/common/dali-common.h>
29 #include <dali/public-api/common/constants.h>
30 #include <dali/public-api/math/vector2.h>
31 #include <dali/public-api/math/vector3.h>
32 #include <dali/public-api/math/radian.h>
33 #include <dali/public-api/object/type-registry.h>
34 #include <dali/devel-api/scripting/scripting.h>
36 #include <dali/internal/common/internal-constants.h>
37 #include <dali/internal/event/common/event-thread-services.h>
38 #include <dali/internal/event/render-tasks/render-task-impl.h>
39 #include <dali/internal/event/actors/camera-actor-impl.h>
40 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
41 #include <dali/internal/event/common/property-helper.h>
42 #include <dali/internal/event/common/stage-impl.h>
43 #include <dali/internal/event/common/type-info-impl.h>
44 #include <dali/internal/event/actor-attachments/actor-attachment-impl.h>
45 #include <dali/internal/event/animation/constraint-impl.h>
46 #include <dali/internal/event/common/projection.h>
47 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
48 #include <dali/internal/update/common/animatable-property.h>
49 #include <dali/internal/update/nodes/node-messages.h>
50 #include <dali/internal/update/nodes/node-declarations.h>
51 #include <dali/internal/update/animation/scene-graph-constraint.h>
52 #include <dali/internal/event/events/actor-gesture-data.h>
53 #include <dali/internal/common/message.h>
54 #include <dali/integration-api/debug.h>
56 using Dali::Internal::SceneGraph::Node;
57 using Dali::Internal::SceneGraph::AnimatableProperty;
58 using Dali::Internal::SceneGraph::PropertyBase;
62 namespace ResizePolicy
67 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )
68 DALI_ENUM_TO_STRING( FIXED )
69 DALI_ENUM_TO_STRING( USE_NATURAL_SIZE )
70 DALI_ENUM_TO_STRING( FILL_TO_PARENT )
71 DALI_ENUM_TO_STRING( SIZE_RELATIVE_TO_PARENT )
72 DALI_ENUM_TO_STRING( SIZE_FIXED_OFFSET_FROM_PARENT )
73 DALI_ENUM_TO_STRING( FIT_TO_CHILDREN )
74 DALI_ENUM_TO_STRING( DIMENSION_DEPENDENCY )
75 DALI_ENUM_TO_STRING( USE_ASSIGNED_SIZE )
76 DALI_ENUM_TO_STRING_TABLE_END( Type )
78 } // unnamed namespace
81 namespace SizeScalePolicy
85 // Enumeration to / from string conversion tables
86 DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )
87 DALI_ENUM_TO_STRING( USE_SIZE_SET )
88 DALI_ENUM_TO_STRING( FIT_WITH_ASPECT_RATIO )
89 DALI_ENUM_TO_STRING( FILL_WITH_ASPECT_RATIO )
90 DALI_ENUM_TO_STRING_TABLE_END( Type )
91 } // unnamed namespace
97 unsigned int Actor::mActorCounter = 0;
101 /// Using a function because of library initialisation order. Vector3::ONE may not have been initialised yet.
102 inline const Vector3& GetDefaultSizeModeFactor()
107 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
108 inline const Vector2& GetDefaultPreferredSize()
110 return Vector2::ZERO;
113 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
114 inline const Vector2& GetDefaultDimensionPadding()
116 return Vector2::ZERO;
119 const SizeScalePolicy::Type DEFAULT_SIZE_SCALE_POLICY = SizeScalePolicy::USE_SIZE_SET;
121 } // unnamed namespace
124 * Struct to collect relayout variables
126 struct Actor::RelayoutData
129 : sizeModeFactor( GetDefaultSizeModeFactor() ), preferredSize( GetDefaultPreferredSize() ), sizeSetPolicy( DEFAULT_SIZE_SCALE_POLICY ), relayoutEnabled( false ), insideRelayout( false )
131 // Set size negotiation defaults
132 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
134 resizePolicies[ i ] = ResizePolicy::DEFAULT;
135 negotiatedDimensions[ i ] = 0.0f;
136 dimensionNegotiated[ i ] = false;
137 dimensionDirty[ i ] = false;
138 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
139 dimensionPadding[ i ] = GetDefaultDimensionPadding();
140 minimumSize[ i ] = 0.0f;
141 maximumSize[ i ] = FLT_MAX;
145 ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies
147 Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies
149 Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
151 float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
153 float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be
154 float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be
156 bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated
157 bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
159 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
161 Vector2 preferredSize; ///< The preferred size of the actor
163 SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
165 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
166 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
169 namespace // unnamed namespace
175 * We want to discourage the use of property strings (minimize string comparisons),
176 * particularly for the default properties.
177 * Name Type writable animatable constraint-input enum for index-checking
179 DALI_PROPERTY_TABLE_BEGIN
180 DALI_PROPERTY( "parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
181 DALI_PROPERTY( "parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
182 DALI_PROPERTY( "parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
183 DALI_PROPERTY( "parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
184 DALI_PROPERTY( "anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
185 DALI_PROPERTY( "anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
186 DALI_PROPERTY( "anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
187 DALI_PROPERTY( "anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
188 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
189 DALI_PROPERTY( "sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
190 DALI_PROPERTY( "sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
191 DALI_PROPERTY( "sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
192 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
193 DALI_PROPERTY( "positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
194 DALI_PROPERTY( "positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
195 DALI_PROPERTY( "positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
196 DALI_PROPERTY( "worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
197 DALI_PROPERTY( "worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
198 DALI_PROPERTY( "worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
199 DALI_PROPERTY( "worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
200 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
201 DALI_PROPERTY( "worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
202 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
203 DALI_PROPERTY( "scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
204 DALI_PROPERTY( "scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
205 DALI_PROPERTY( "scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
206 DALI_PROPERTY( "worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
207 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
208 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
209 DALI_PROPERTY( "colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
210 DALI_PROPERTY( "colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
211 DALI_PROPERTY( "colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
212 DALI_PROPERTY( "colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
213 DALI_PROPERTY( "worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
214 DALI_PROPERTY( "worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
215 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
216 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
217 DALI_PROPERTY( "leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
218 DALI_PROPERTY( "inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
219 DALI_PROPERTY( "inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
220 DALI_PROPERTY( "colorMode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
221 DALI_PROPERTY( "positionInheritance", STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE )
222 DALI_PROPERTY( "drawMode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
223 DALI_PROPERTY( "sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
224 DALI_PROPERTY( "widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
225 DALI_PROPERTY( "heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
226 DALI_PROPERTY( "sizeScalePolicy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
227 DALI_PROPERTY( "widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
228 DALI_PROPERTY( "heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
229 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
230 DALI_PROPERTY( "minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
231 DALI_PROPERTY( "maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
232 DALI_PROPERTY( "inheritPosition", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_POSITION )
233 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
237 const char* const SIGNAL_TOUCHED = "touched";
238 const char* const SIGNAL_HOVERED = "hovered";
239 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
240 const char* const SIGNAL_ON_STAGE = "onStage";
241 const char* const SIGNAL_OFF_STAGE = "offStage";
242 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
246 const char* const ACTION_SHOW = "show";
247 const char* const ACTION_HIDE = "hide";
249 BaseHandle CreateActor()
251 return Dali::Actor::New();
254 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
256 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
257 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
258 SignalConnectorType signalConnector3( mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal );
259 SignalConnectorType signalConnector4( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
260 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
261 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
263 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
264 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
267 * @brief Extract a given dimension from a Vector2
269 * @param[in] values The values to extract from
270 * @param[in] dimension The dimension to extract
271 * @return Return the value for the dimension
273 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
277 case Dimension::WIDTH:
281 case Dimension::HEIGHT:
283 return values.height;
294 * @brief Extract a given dimension from a Vector3
296 * @param[in] values The values to extract from
297 * @param[in] dimension The dimension to extract
298 * @return Return the value for the dimension
300 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
302 return GetDimensionValue( values.GetVectorXY(), dimension );
306 } // unnamed namespace
308 ActorPtr Actor::New()
310 ActorPtr actor( new Actor( BASIC ) );
312 // Second-phase construction
318 const std::string& Actor::GetName() const
323 void Actor::SetName( const std::string& name )
329 // ATTENTION: string for debug purposes is not thread safe.
330 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
334 unsigned int Actor::GetId() const
339 void Actor::Attach( ActorAttachment& attachment )
341 DALI_ASSERT_DEBUG( !mAttachment && "An Actor can only have one attachment" );
345 attachment.Connect();
348 mAttachment = ActorAttachmentPtr( &attachment );
351 ActorAttachmentPtr Actor::GetAttachment()
356 bool Actor::OnStage() const
361 Dali::Layer Actor::GetLayer()
365 // Short-circuit for Layer derived actors
368 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
371 // Find the immediate Layer parent
372 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
374 if( parent->IsLayer() )
376 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
383 void Actor::Add( Actor& child )
385 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
386 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
390 mChildren = new ActorContainer;
393 Actor* const oldParent( child.mParent );
395 // child might already be ours
396 if( this != oldParent )
398 // if we already have parent, unparent us first
401 oldParent->Remove( child ); // This causes OnChildRemove callback
403 // Old parent may need to readjust to missing child
404 if( oldParent->RelayoutDependentOnChildren() )
406 oldParent->RelayoutRequest();
410 // Guard against Add() during previous OnChildRemove callback
413 // Do this first, since user callbacks from within SetParent() may need to remove child
414 mChildren->push_back( ActorPtr( &child ) );
416 // SetParent asserts that child can be added
417 child.SetParent( this );
419 // Notification for derived classes
422 // Only put in a relayout request if there is a suitable dependency
423 if( RelayoutDependentOnChildren() )
431 void Actor::Remove( Actor& child )
433 if( (this == &child) || (!mChildren) )
435 // no children or removing itself
441 // Find the child in mChildren, and unparent it
442 ActorIter end = mChildren->end();
443 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
445 ActorPtr actor = (*iter);
447 if( actor.Get() == &child )
449 // Keep handle for OnChildRemove notification
452 // Do this first, since user callbacks from within SetParent() may need to add the child
453 mChildren->erase( iter );
455 DALI_ASSERT_DEBUG( actor->GetParent() == this );
456 actor->SetParent( NULL );
464 // Notification for derived classes
465 OnChildRemove( *(removed.Get()) );
467 // Only put in a relayout request if there is a suitable dependency
468 if( RelayoutDependentOnChildren() )
475 void Actor::Unparent()
479 // Remove this actor from the parent. The remove will put a relayout request in for
480 // the parent if required
481 mParent->Remove( *this );
482 // mParent is now NULL!
486 unsigned int Actor::GetChildCount() const
488 return ( NULL != mChildren ) ? mChildren->size() : 0;
491 ActorPtr Actor::GetChildAt( unsigned int index ) const
493 DALI_ASSERT_ALWAYS( index < GetChildCount() );
495 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
498 ActorPtr Actor::FindChildByName( const std::string& actorName )
501 if( actorName == mName )
507 ActorIter end = mChildren->end();
508 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
510 child = (*iter)->FindChildByName( actorName );
521 ActorPtr Actor::FindChildById( const unsigned int id )
530 ActorIter end = mChildren->end();
531 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
533 child = (*iter)->FindChildById( id );
544 void Actor::SetParentOrigin( const Vector3& origin )
548 // mNode is being used in a separate thread; queue a message to set the value & base value
549 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
552 // Cache for event-thread access
555 // not allocated, check if different from default
556 if( ParentOrigin::DEFAULT != origin )
558 mParentOrigin = new Vector3( origin );
563 // check if different from current costs more than just set
564 *mParentOrigin = origin;
568 void Actor::SetParentOriginX( float x )
570 const Vector3& current = GetCurrentParentOrigin();
572 SetParentOrigin( Vector3( x, current.y, current.z ) );
575 void Actor::SetParentOriginY( float y )
577 const Vector3& current = GetCurrentParentOrigin();
579 SetParentOrigin( Vector3( current.x, y, current.z ) );
582 void Actor::SetParentOriginZ( float z )
584 const Vector3& current = GetCurrentParentOrigin();
586 SetParentOrigin( Vector3( current.x, current.y, z ) );
589 const Vector3& Actor::GetCurrentParentOrigin() const
591 // Cached for event-thread access
592 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
595 void Actor::SetAnchorPoint( const Vector3& anchor )
599 // mNode is being used in a separate thread; queue a message to set the value & base value
600 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
603 // Cache for event-thread access
606 // not allocated, check if different from default
607 if( AnchorPoint::DEFAULT != anchor )
609 mAnchorPoint = new Vector3( anchor );
614 // check if different from current costs more than just set
615 *mAnchorPoint = anchor;
619 void Actor::SetAnchorPointX( float x )
621 const Vector3& current = GetCurrentAnchorPoint();
623 SetAnchorPoint( Vector3( x, current.y, current.z ) );
626 void Actor::SetAnchorPointY( float y )
628 const Vector3& current = GetCurrentAnchorPoint();
630 SetAnchorPoint( Vector3( current.x, y, current.z ) );
633 void Actor::SetAnchorPointZ( float z )
635 const Vector3& current = GetCurrentAnchorPoint();
637 SetAnchorPoint( Vector3( current.x, current.y, z ) );
640 const Vector3& Actor::GetCurrentAnchorPoint() const
642 // Cached for event-thread access
643 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
646 void Actor::SetPosition( float x, float y )
648 SetPosition( Vector3( x, y, 0.0f ) );
651 void Actor::SetPosition( float x, float y, float z )
653 SetPosition( Vector3( x, y, z ) );
656 void Actor::SetPosition( const Vector3& position )
658 mTargetPosition = position;
662 // mNode is being used in a separate thread; queue a message to set the value & base value
663 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
667 void Actor::SetX( float x )
669 mTargetPosition.x = x;
673 // mNode is being used in a separate thread; queue a message to set the value & base value
674 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
678 void Actor::SetY( float y )
680 mTargetPosition.y = y;
684 // mNode is being used in a separate thread; queue a message to set the value & base value
685 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
689 void Actor::SetZ( float z )
691 mTargetPosition.z = z;
695 // mNode is being used in a separate thread; queue a message to set the value & base value
696 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
700 void Actor::TranslateBy( const Vector3& distance )
702 mTargetPosition += distance;
706 // mNode is being used in a separate thread; queue a message to set the value & base value
707 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
711 const Vector3& Actor::GetCurrentPosition() const
715 // mNode is being used in a separate thread; copy the value from the previous update
716 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
719 return Vector3::ZERO;
722 const Vector3& Actor::GetTargetPosition() const
724 return mTargetPosition;
727 const Vector3& Actor::GetCurrentWorldPosition() const
731 // mNode is being used in a separate thread; copy the value from the previous update
732 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
735 return Vector3::ZERO;
738 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
740 // this flag is not animatable so keep the value
741 mPositionInheritanceMode = mode;
744 // mNode is being used in a separate thread; queue a message to set the value
745 SetPositionInheritanceModeMessage( GetEventThreadServices(), *mNode, mode );
749 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
751 // Cached for event-thread access
752 return mPositionInheritanceMode;
755 void Actor::SetInheritPosition( bool inherit )
757 if( mInheritPosition != inherit && NULL != mNode )
759 // non animateable so keep local copy
760 mInheritPosition = inherit;
761 SetInheritPositionMessage( GetEventThreadServices(), *mNode, inherit );
765 bool Actor::IsPositionInherited() const
767 return mInheritPosition;
770 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
772 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
773 normalizedAxis.Normalize();
775 Quaternion orientation( angle, normalizedAxis );
777 SetOrientation( orientation );
780 void Actor::SetOrientation( const Quaternion& orientation )
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>::Bake, orientation );
789 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
793 // mNode is being used in a separate thread; queue a message to set the value & base value
794 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, Quaternion(angle, axis) );
798 void Actor::RotateBy( const Quaternion& relativeRotation )
802 // mNode is being used in a separate thread; queue a message to set the value & base value
803 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
807 const Quaternion& Actor::GetCurrentOrientation() const
811 // mNode is being used in a separate thread; copy the value from the previous update
812 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
815 return Quaternion::IDENTITY;
818 const Quaternion& Actor::GetCurrentWorldOrientation() const
822 // mNode is being used in a separate thread; copy the value from the previous update
823 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
826 return Quaternion::IDENTITY;
829 void Actor::SetScale( float scale )
831 SetScale( Vector3( scale, scale, scale ) );
834 void Actor::SetScale( float x, float y, float z )
836 SetScale( Vector3( x, y, z ) );
839 void Actor::SetScale( const Vector3& scale )
843 // mNode is being used in a separate thread; queue a message to set the value & base value
844 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
848 void Actor::SetScaleX( float x )
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>::BakeX, x );
857 void Actor::SetScaleY( float y )
861 // mNode is being used in a separate thread; queue a message to set the value & base value
862 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
866 void Actor::SetScaleZ( float z )
870 // mNode is being used in a separate thread; queue a message to set the value & base value
871 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
875 void Actor::ScaleBy(const Vector3& relativeScale)
879 // mNode is being used in a separate thread; queue a message to set the value & base value
880 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
884 const Vector3& Actor::GetCurrentScale() const
888 // mNode is being used in a separate thread; copy the value from the previous update
889 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
895 const Vector3& Actor::GetCurrentWorldScale() const
899 // mNode is being used in a separate thread; copy the value from the previous update
900 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
906 void Actor::SetInheritScale( bool inherit )
909 if( mInheritScale != inherit && NULL != mNode )
911 // non animateable so keep local copy
912 mInheritScale = inherit;
913 // mNode is being used in a separate thread; queue a message to set the value
914 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
918 bool Actor::IsScaleInherited() const
920 return mInheritScale;
923 Matrix Actor::GetCurrentWorldMatrix() const
927 return mNode->GetWorldMatrix(0);
930 return Matrix::IDENTITY;
933 void Actor::SetVisible( bool visible )
937 // mNode is being used in a separate thread; queue a message to set the value & base value
938 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
942 bool Actor::IsVisible() const
946 // mNode is being used in a separate thread; copy the value from the previous update
947 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
953 void Actor::SetOpacity( float opacity )
957 // mNode is being used in a separate thread; queue a message to set the value & base value
958 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
962 float Actor::GetCurrentOpacity() const
966 // mNode is being used in a separate thread; copy the value from the previous update
967 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
973 const Vector4& Actor::GetCurrentWorldColor() const
977 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
983 void Actor::SetColor( const Vector4& color )
987 // mNode is being used in a separate thread; queue a message to set the value & base value
988 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
992 void Actor::SetColorRed( float red )
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>::BakeX, red );
1001 void Actor::SetColorGreen( float green )
1005 // mNode is being used in a separate thread; queue a message to set the value & base value
1006 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1010 void Actor::SetColorBlue( float blue )
1014 // mNode is being used in a separate thread; queue a message to set the value & base value
1015 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1019 const Vector4& Actor::GetCurrentColor() const
1023 // mNode is being used in a separate thread; copy the value from the previous update
1024 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1027 return Color::WHITE;
1030 void Actor::SetInheritOrientation( bool inherit )
1032 if( mInheritOrientation != inherit && NULL != mNode)
1034 // non animateable so keep local copy
1035 mInheritOrientation = inherit;
1036 // mNode is being used in a separate thread; queue a message to set the value
1037 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1041 bool Actor::IsOrientationInherited() const
1043 return mInheritOrientation;
1046 void Actor::SetSizeModeFactor( const Vector3& factor )
1048 EnsureRelayoutData();
1050 mRelayoutData->sizeModeFactor = factor;
1053 const Vector3& Actor::GetSizeModeFactor() const
1055 if ( mRelayoutData )
1057 return mRelayoutData->sizeModeFactor;
1060 return GetDefaultSizeModeFactor();
1063 void Actor::SetColorMode( ColorMode colorMode )
1065 // non animateable so keep local copy
1066 mColorMode = colorMode;
1069 // mNode is being used in a separate thread; queue a message to set the value
1070 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1074 ColorMode Actor::GetColorMode() const
1076 // we have cached copy
1080 void Actor::SetSize( float width, float height )
1082 SetSize( Vector2( width, height ) );
1085 void Actor::SetSize( float width, float height, float depth )
1087 SetSize( Vector3( width, height, depth ) );
1090 void Actor::SetSize( const Vector2& size )
1092 SetSize( Vector3( size.width, size.height, 0.f ) );
1095 void Actor::SetSizeInternal( const Vector2& size )
1097 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1100 void Actor::SetSize( const Vector3& size )
1102 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1104 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1105 SetPreferredSize( size.GetVectorXY() );
1109 SetSizeInternal( size );
1113 void Actor::SetSizeInternal( const Vector3& size )
1115 // dont allow recursive loop
1116 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1117 // 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
1118 if( ( NULL != mNode )&&
1119 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1120 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1121 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1125 // mNode is being used in a separate thread; queue a message to set the value & base value
1126 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
1128 // Notification for derived classes
1129 mInsideOnSizeSet = true;
1130 OnSizeSet( mTargetSize );
1131 mInsideOnSizeSet = false;
1133 // Raise a relayout request if the flag is not locked
1134 if( mRelayoutData && !mRelayoutData->insideRelayout )
1141 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1143 mTargetSize = targetSize;
1145 // Notify deriving classes
1146 OnSizeAnimation( animation, mTargetSize );
1149 void Actor::NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property )
1151 if ( Dali::Actor::Property::SIZE_WIDTH == property )
1153 mTargetSize.width = targetSize;
1155 else if ( Dali::Actor::Property::SIZE_HEIGHT == property )
1157 mTargetSize.height = targetSize;
1159 else if ( Dali::Actor::Property::SIZE_DEPTH == property )
1161 mTargetSize.depth = targetSize;
1163 // Notify deriving classes
1164 OnSizeAnimation( animation, mTargetSize );
1167 void Actor::NotifyPositionAnimation( Animation& animation, const Vector3& targetPosition )
1169 mTargetPosition = targetPosition;
1172 void Actor::NotifyPositionAnimation( Animation& animation, float targetPosition, Property::Index property )
1174 if ( Dali::Actor::Property::POSITION_X == property )
1176 mTargetPosition.x = targetPosition;
1178 else if ( Dali::Actor::Property::POSITION_Y == property )
1180 mTargetPosition.y = targetPosition;
1182 else if ( Dali::Actor::Property::POSITION_Z == property )
1184 mTargetPosition.z = targetPosition;
1188 void Actor::SetWidth( float width )
1190 mTargetSize.width = width;
1194 // mNode is being used in a separate thread; queue a message to set the value & base value
1195 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1199 void Actor::SetHeight( float height )
1201 mTargetSize.height = height;
1205 // mNode is being used in a separate thread; queue a message to set the value & base value
1206 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1210 void Actor::SetDepth( float depth )
1212 mTargetSize.depth = depth;
1216 // mNode is being used in a separate thread; queue a message to set the value & base value
1217 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1221 const Vector3& Actor::GetTargetSize() const
1226 const Vector3& Actor::GetCurrentSize() const
1230 // mNode is being used in a separate thread; copy the value from the previous update
1231 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1234 return Vector3::ZERO;
1237 Vector3 Actor::GetNaturalSize() const
1239 // It is up to deriving classes to return the appropriate natural size
1240 return Vector3( 0.0f, 0.0f, 0.0f );
1243 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1245 EnsureRelayoutData();
1247 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1249 if( dimension & ( 1 << i ) )
1251 mRelayoutData->resizePolicies[ i ] = policy;
1255 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1257 if( dimension & Dimension::WIDTH )
1259 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1262 if( dimension & Dimension::HEIGHT )
1264 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1268 // If calling SetResizePolicy, assume we want relayout enabled
1269 SetRelayoutEnabled( true );
1271 OnSetResizePolicy( policy, dimension );
1273 // Trigger relayout on this control
1277 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1279 if ( mRelayoutData )
1281 // If more than one dimension is requested, just return the first one found
1282 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1284 if( ( dimension & ( 1 << i ) ) )
1286 return mRelayoutData->resizePolicies[ i ];
1291 return ResizePolicy::DEFAULT;
1294 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1296 EnsureRelayoutData();
1298 mRelayoutData->sizeSetPolicy = policy;
1301 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1303 if ( mRelayoutData )
1305 return mRelayoutData->sizeSetPolicy;
1308 return DEFAULT_SIZE_SCALE_POLICY;
1311 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1313 EnsureRelayoutData();
1315 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1317 if( dimension & ( 1 << i ) )
1319 mRelayoutData->dimensionDependencies[ i ] = dependency;
1324 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1326 if ( mRelayoutData )
1328 // If more than one dimension is requested, just return the first one found
1329 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1331 if( ( dimension & ( 1 << i ) ) )
1333 return mRelayoutData->dimensionDependencies[ i ];
1338 return Dimension::ALL_DIMENSIONS; // Default
1341 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1343 // If relayout data has not been allocated yet and the client is requesting
1344 // to disable it, do nothing
1345 if( mRelayoutData || relayoutEnabled )
1347 EnsureRelayoutData();
1349 mRelayoutData->relayoutEnabled = relayoutEnabled;
1353 bool Actor::IsRelayoutEnabled() const
1355 // Assume that if relayout data has not been allocated yet then
1356 // relayout is disabled
1357 return mRelayoutData && mRelayoutData->relayoutEnabled;
1360 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1362 EnsureRelayoutData();
1364 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1366 if( dimension & ( 1 << i ) )
1368 mRelayoutData->dimensionDirty[ i ] = dirty;
1373 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1375 if ( mRelayoutData )
1377 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1379 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1389 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1391 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1394 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1396 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1399 unsigned int Actor::AddRenderer( Renderer& renderer )
1403 mRenderers = new RendererContainer;
1406 unsigned int index = mRenderers->size();
1407 RendererPtr rendererPtr = RendererPtr( &renderer );
1408 mRenderers->push_back( rendererPtr );
1409 AddRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1413 rendererPtr->Connect();
1419 unsigned int Actor::GetRendererCount() const
1421 unsigned int rendererCount(0);
1424 rendererCount = mRenderers->size();
1427 return rendererCount;
1430 RendererPtr Actor::GetRendererAt( unsigned int index )
1432 RendererPtr renderer;
1433 if( index < GetRendererCount() )
1435 renderer = ( *mRenderers )[ index ];
1441 void Actor::RemoveRenderer( Renderer& renderer )
1445 RendererIter end = mRenderers->end();
1446 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1448 if( (*iter).Get() == &renderer )
1450 mRenderers->erase( iter );
1451 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1458 void Actor::RemoveRenderer( unsigned int index )
1460 if( index < GetRendererCount() )
1462 RendererPtr renderer = ( *mRenderers )[ index ];
1463 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.Get()->GetRendererSceneObject() );
1464 mRenderers->erase( mRenderers->begin()+index );
1468 void Actor::SetOverlay( bool enable )
1470 // Setting STENCIL will override OVERLAY_2D
1471 if( DrawMode::STENCIL != mDrawMode )
1473 SetDrawMode( enable ? DrawMode::OVERLAY_2D : DrawMode::NORMAL );
1477 bool Actor::IsOverlay() const
1479 return ( DrawMode::OVERLAY_2D == mDrawMode );
1482 void Actor::SetDrawMode( DrawMode::Type drawMode )
1484 // this flag is not animatable so keep the value
1485 mDrawMode = drawMode;
1488 // mNode is being used in a separate thread; queue a message to set the value
1489 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1493 DrawMode::Type Actor::GetDrawMode() const
1498 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1500 // only valid when on-stage
1501 StagePtr stage = Stage::GetCurrent();
1502 if( stage && OnStage() )
1504 const RenderTaskList& taskList = stage->GetRenderTaskList();
1506 Vector2 converted( screenX, screenY );
1508 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1509 const int taskCount = taskList.GetTaskCount();
1510 for( int i = taskCount - 1; i >= 0; --i )
1512 Dali::RenderTask task = taskList.GetTask( i );
1513 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1515 // found a task where this conversion was ok so return
1523 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1525 bool retval = false;
1526 // only valid when on-stage
1529 CameraActor* camera = renderTask.GetCameraActor();
1533 renderTask.GetViewport( viewport );
1535 // need to translate coordinates to render tasks coordinate space
1536 Vector2 converted( screenX, screenY );
1537 if( renderTask.TranslateCoordinates( converted ) )
1539 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1546 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1548 // Early-out if mNode is NULL
1554 // Get the ModelView matrix
1556 Matrix::Multiply( modelView, mNode->GetWorldMatrix(0), viewMatrix );
1558 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1559 Matrix invertedMvp( false/*don't init*/);
1560 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1561 bool success = invertedMvp.Invert();
1563 // Convert to GL coordinates
1564 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1569 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1576 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1582 if( XyPlaneIntersect( nearPos, farPos, local ) )
1584 Vector3 size = GetCurrentSize();
1585 localX = local.x + size.x * 0.5f;
1586 localY = local.y + size.y * 0.5f;
1597 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1600 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1602 Mathematical Formulation
1604 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1606 ( p - c ) dot ( p - c ) = r^2
1608 Given a ray with a point of origin 'o', and a direction vector 'd':
1610 ray(t) = o + td, t >= 0
1612 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1614 (o + td - c ) dot ( o + td - c ) = r^2
1616 To solve for t we first expand the above into a more recognisable quadratic equation form
1618 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1627 B = 2( o - c ) dot d
1628 C = ( o - c ) dot ( o - c ) - r^2
1630 which can be solved using a standard quadratic formula.
1632 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1634 Practical Simplification
1636 In a renderer, we often differentiate between world space and object space. In the object space
1637 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1638 into object space, the mathematical solution presented above can be simplified significantly.
1640 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1644 and we can find the t at which the (transformed) ray intersects the sphere by
1646 ( o + td ) dot ( o + td ) = r^2
1648 According to the reasoning above, we expand the above quadratic equation into the general form
1652 which now has coefficients:
1659 // Early out if mNode is NULL
1665 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1667 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1668 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1669 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1671 // Compute the radius is not needed, square radius it's enough.
1672 const Vector3& size( mNode->GetSize( bufferIndex ) );
1674 // Scale the sphere.
1675 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1677 const float width = size.width * scale.width;
1678 const float height = size.height * scale.height;
1680 float squareSphereRadius = 0.5f * ( width * width + height * height );
1682 float a = rayDir.Dot( rayDir ); // a
1683 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1684 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1686 return ( b2 * b2 - a * c ) >= 0.f;
1689 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
1696 // Transforms the ray to the local reference system.
1697 // Calculate the inverse of Model matrix
1698 Matrix invModelMatrix( false/*don't init*/);
1700 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1701 invModelMatrix = mNode->GetWorldMatrix(0);
1702 invModelMatrix.Invert();
1704 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1705 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1707 // Test with the actor's XY plane (Normal = 0 0 1 1).
1709 float a = -rayOriginLocal.z;
1710 float b = rayDirLocal.z;
1712 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1714 // Ray travels distance * rayDirLocal to intersect with plane.
1717 const Vector3& size = mNode->GetSize( bufferIndex );
1719 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1720 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1722 // Test with the actor's geometry.
1723 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1730 void Actor::SetLeaveRequired( bool required )
1732 mLeaveRequired = required;
1735 bool Actor::GetLeaveRequired() const
1737 return mLeaveRequired;
1740 void Actor::SetKeyboardFocusable( bool focusable )
1742 mKeyboardFocusable = focusable;
1745 bool Actor::IsKeyboardFocusable() const
1747 return mKeyboardFocusable;
1750 bool Actor::GetTouchRequired() const
1752 return !mTouchedSignal.Empty() || mDerivedRequiresTouch;
1755 bool Actor::GetHoverRequired() const
1757 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1760 bool Actor::GetWheelEventRequired() const
1762 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1765 bool Actor::IsHittable() const
1767 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1770 ActorGestureData& Actor::GetGestureData()
1772 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1773 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1774 if( NULL == mGestureData )
1776 mGestureData = new ActorGestureData;
1778 return *mGestureData;
1781 bool Actor::IsGestureRequred( Gesture::Type type ) const
1783 return mGestureData && mGestureData->IsGestureRequred( type );
1786 bool Actor::EmitTouchEventSignal( const TouchEvent& event )
1788 bool consumed = false;
1790 if( !mTouchedSignal.Empty() )
1792 Dali::Actor handle( this );
1793 consumed = mTouchedSignal.Emit( handle, event );
1798 // Notification for derived classes
1799 consumed = OnTouchEvent( event );
1805 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1807 bool consumed = false;
1809 if( !mHoveredSignal.Empty() )
1811 Dali::Actor handle( this );
1812 consumed = mHoveredSignal.Emit( handle, event );
1817 // Notification for derived classes
1818 consumed = OnHoverEvent( event );
1824 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1826 bool consumed = false;
1828 if( !mWheelEventSignal.Empty() )
1830 Dali::Actor handle( this );
1831 consumed = mWheelEventSignal.Emit( handle, event );
1836 // Notification for derived classes
1837 consumed = OnWheelEvent( event );
1843 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
1845 return mTouchedSignal;
1848 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
1850 return mHoveredSignal;
1853 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
1855 return mWheelEventSignal;
1858 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
1860 return mOnStageSignal;
1863 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
1865 return mOffStageSignal;
1868 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
1870 return mOnRelayoutSignal;
1873 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1875 bool connected( true );
1876 Actor* actor = dynamic_cast< Actor* >( object );
1878 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1880 actor->TouchedSignal().Connect( tracker, functor );
1882 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1884 actor->HoveredSignal().Connect( tracker, functor );
1886 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1888 actor->WheelEventSignal().Connect( tracker, functor );
1890 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
1892 actor->OnStageSignal().Connect( tracker, functor );
1894 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
1896 actor->OffStageSignal().Connect( tracker, functor );
1898 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
1900 actor->OnRelayoutSignal().Connect( tracker, functor );
1904 // signalName does not match any signal
1911 Actor::Actor( DerivedType derivedType )
1916 mParentOrigin( NULL ),
1917 mAnchorPoint( NULL ),
1918 mRelayoutData( NULL ),
1919 mGestureData( NULL ),
1921 mTargetSize( 0.0f, 0.0f, 0.0f ),
1923 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
1925 mIsRoot( ROOT_LAYER == derivedType ),
1926 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
1927 mIsOnStage( false ),
1929 mLeaveRequired( false ),
1930 mKeyboardFocusable( false ),
1931 mDerivedRequiresTouch( false ),
1932 mDerivedRequiresHover( false ),
1933 mDerivedRequiresWheelEvent( false ),
1934 mOnStageSignalled( false ),
1935 mInsideOnSizeSet( false ),
1936 mInheritPosition( true ),
1937 mInheritOrientation( true ),
1938 mInheritScale( true ),
1939 mDrawMode( DrawMode::NORMAL ),
1940 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
1941 mColorMode( Node::DEFAULT_COLOR_MODE )
1945 void Actor::Initialize()
1948 SceneGraph::Node* node = CreateNode();
1950 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
1951 mNode = node; // Keep raw-pointer to Node
1955 GetEventThreadServices().RegisterObject( this );
1960 // Remove mParent pointers from children even if we're destroying core,
1961 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1964 ActorConstIter endIter = mChildren->end();
1965 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1967 (*iter)->SetParent( NULL );
1973 // Guard to allow handle destruction after Core has been destroyed
1974 if( EventThreadServices::IsCoreRunning() )
1978 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
1979 mNode = NULL; // Node is about to be destroyed
1982 GetEventThreadServices().UnregisterObject( this );
1985 // Cleanup optional gesture data
1986 delete mGestureData;
1988 // Cleanup optional parent origin and anchor
1989 delete mParentOrigin;
1990 delete mAnchorPoint;
1992 // Delete optional relayout data
1995 delete mRelayoutData;
1999 void Actor::ConnectToStage( unsigned int parentDepth )
2001 // This container is used instead of walking the Actor hierarchy.
2002 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
2003 ActorContainer connectionList;
2005 // This stage is atomic i.e. not interrupted by user callbacks.
2006 RecursiveConnectToStage( connectionList, parentDepth + 1 );
2008 // Notify applications about the newly connected actors.
2009 const ActorIter endIter = connectionList.end();
2010 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2012 (*iter)->NotifyStageConnection();
2018 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth )
2020 DALI_ASSERT_ALWAYS( !OnStage() );
2025 ConnectToSceneGraph();
2027 // Notification for internal derived classes
2028 OnStageConnectionInternal();
2030 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2031 connectionList.push_back( ActorPtr( this ) );
2033 // Recursively connect children
2036 ActorConstIter endIter = mChildren->end();
2037 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2039 (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
2045 * This method is called when the Actor is connected to the Stage.
2046 * The parent must have added its Node to the scene-graph.
2047 * The child must connect its Node to the parent's Node.
2048 * This is recursive; the child calls ConnectToStage() for its children.
2050 void Actor::ConnectToSceneGraph()
2052 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2056 // Reparent Node in next Update
2057 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode );
2060 // Notify attachment
2063 mAttachment->Connect();
2066 unsigned int rendererCount( GetRendererCount() );
2067 for( unsigned int i(0); i<rendererCount; ++i )
2069 GetRendererAt(i)->Connect();
2072 // Request relayout on all actors that are added to the scenegraph
2075 // Notification for Object::Observers
2079 void Actor::NotifyStageConnection()
2081 // Actors can be removed (in a callback), before the on-stage stage is reported.
2082 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2083 if( OnStage() && !mOnStageSignalled )
2085 // Notification for external (CustomActor) derived classes
2086 OnStageConnectionExternal( mDepth );
2088 if( !mOnStageSignal.Empty() )
2090 Dali::Actor handle( this );
2091 mOnStageSignal.Emit( handle );
2094 // Guard against Remove during callbacks
2097 mOnStageSignalled = true; // signal required next time Actor is removed
2102 void Actor::DisconnectFromStage()
2104 // This container is used instead of walking the Actor hierachy.
2105 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2106 ActorContainer disconnectionList;
2108 // This stage is atomic i.e. not interrupted by user callbacks
2109 RecursiveDisconnectFromStage( disconnectionList );
2111 // Notify applications about the newly disconnected actors.
2112 const ActorIter endIter = disconnectionList.end();
2113 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2115 (*iter)->NotifyStageDisconnection();
2119 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2121 DALI_ASSERT_ALWAYS( OnStage() );
2123 // Recursively disconnect children
2126 ActorConstIter endIter = mChildren->end();
2127 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2129 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2133 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2134 disconnectionList.push_back( ActorPtr( this ) );
2136 // Notification for internal derived classes
2137 OnStageDisconnectionInternal();
2139 DisconnectFromSceneGraph();
2145 * This method is called by an actor or its parent, before a node removal message is sent.
2146 * This is recursive; the child calls DisconnectFromStage() for its children.
2148 void Actor::DisconnectFromSceneGraph()
2150 // Notification for Object::Observers
2151 OnSceneObjectRemove();
2153 // Notify attachment
2156 mAttachment->Disconnect();
2159 unsigned int rendererCount( GetRendererCount() );
2160 for( unsigned int i(0); i<rendererCount; ++i )
2162 GetRendererAt(i)->Disconnect();
2166 void Actor::NotifyStageDisconnection()
2168 // Actors can be added (in a callback), before the off-stage state is reported.
2169 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2170 // only do this step if there is a stage, i.e. Core is not being shut down
2171 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2173 // Notification for external (CustomeActor) derived classes
2174 OnStageDisconnectionExternal();
2176 if( !mOffStageSignal.Empty() )
2178 Dali::Actor handle( this );
2179 mOffStageSignal.Emit( handle );
2182 // Guard against Add during callbacks
2185 mOnStageSignalled = false; // signal required next time Actor is added
2190 bool Actor::IsNodeConnected() const
2192 bool connected( false );
2194 if( OnStage() && ( NULL != mNode ) )
2196 if( IsRoot() || mNode->GetParent() )
2205 unsigned int Actor::GetDefaultPropertyCount() const
2207 return DEFAULT_PROPERTY_COUNT;
2210 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2212 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2214 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2216 indices.PushBack( i );
2220 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2222 if( index < DEFAULT_PROPERTY_COUNT )
2224 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2230 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2232 Property::Index index = Property::INVALID_INDEX;
2234 // Look for name in default properties
2235 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2237 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2238 if( 0 == name.compare( property->name ) )
2248 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2250 if( index < DEFAULT_PROPERTY_COUNT )
2252 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2258 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2260 if( index < DEFAULT_PROPERTY_COUNT )
2262 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2268 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2270 if( index < DEFAULT_PROPERTY_COUNT )
2272 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2278 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2280 if( index < DEFAULT_PROPERTY_COUNT )
2282 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2285 // index out of range...return Property::NONE
2286 return Property::NONE;
2289 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2293 case Dali::Actor::Property::PARENT_ORIGIN:
2295 SetParentOrigin( property.Get< Vector3 >() );
2299 case Dali::Actor::Property::PARENT_ORIGIN_X:
2301 SetParentOriginX( property.Get< float >() );
2305 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2307 SetParentOriginY( property.Get< float >() );
2311 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2313 SetParentOriginZ( property.Get< float >() );
2317 case Dali::Actor::Property::ANCHOR_POINT:
2319 SetAnchorPoint( property.Get< Vector3 >() );
2323 case Dali::Actor::Property::ANCHOR_POINT_X:
2325 SetAnchorPointX( property.Get< float >() );
2329 case Dali::Actor::Property::ANCHOR_POINT_Y:
2331 SetAnchorPointY( property.Get< float >() );
2335 case Dali::Actor::Property::ANCHOR_POINT_Z:
2337 SetAnchorPointZ( property.Get< float >() );
2341 case Dali::Actor::Property::SIZE:
2343 SetSize( property.Get< Vector3 >() );
2347 case Dali::Actor::Property::SIZE_WIDTH:
2349 SetWidth( property.Get< float >() );
2353 case Dali::Actor::Property::SIZE_HEIGHT:
2355 SetHeight( property.Get< float >() );
2359 case Dali::Actor::Property::SIZE_DEPTH:
2361 SetDepth( property.Get< float >() );
2365 case Dali::Actor::Property::POSITION:
2367 SetPosition( property.Get< Vector3 >() );
2371 case Dali::Actor::Property::POSITION_X:
2373 SetX( property.Get< float >() );
2377 case Dali::Actor::Property::POSITION_Y:
2379 SetY( property.Get< float >() );
2383 case Dali::Actor::Property::POSITION_Z:
2385 SetZ( property.Get< float >() );
2389 case Dali::Actor::Property::ORIENTATION:
2391 SetOrientation( property.Get< Quaternion >() );
2395 case Dali::Actor::Property::SCALE:
2397 SetScale( property.Get< Vector3 >() );
2401 case Dali::Actor::Property::SCALE_X:
2403 SetScaleX( property.Get< float >() );
2407 case Dali::Actor::Property::SCALE_Y:
2409 SetScaleY( property.Get< float >() );
2413 case Dali::Actor::Property::SCALE_Z:
2415 SetScaleZ( property.Get< float >() );
2419 case Dali::Actor::Property::VISIBLE:
2421 SetVisible( property.Get< bool >() );
2425 case Dali::Actor::Property::COLOR:
2427 SetColor( property.Get< Vector4 >() );
2431 case Dali::Actor::Property::COLOR_RED:
2433 SetColorRed( property.Get< float >() );
2437 case Dali::Actor::Property::COLOR_GREEN:
2439 SetColorGreen( property.Get< float >() );
2443 case Dali::Actor::Property::COLOR_BLUE:
2445 SetColorBlue( property.Get< float >() );
2449 case Dali::Actor::Property::COLOR_ALPHA:
2451 SetOpacity( property.Get< float >() );
2455 case Dali::Actor::Property::NAME:
2457 SetName( property.Get< std::string >() );
2461 case Dali::Actor::Property::SENSITIVE:
2463 SetSensitive( property.Get< bool >() );
2467 case Dali::Actor::Property::LEAVE_REQUIRED:
2469 SetLeaveRequired( property.Get< bool >() );
2473 case Dali::Actor::Property::INHERIT_POSITION:
2475 SetInheritPosition( property.Get< bool >() );
2479 case Dali::Actor::Property::INHERIT_ORIENTATION:
2481 SetInheritOrientation( property.Get< bool >() );
2485 case Dali::Actor::Property::INHERIT_SCALE:
2487 SetInheritScale( property.Get< bool >() );
2491 case Dali::Actor::Property::COLOR_MODE:
2493 SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
2497 case Dali::Actor::Property::POSITION_INHERITANCE:
2499 SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
2503 case Dali::Actor::Property::DRAW_MODE:
2505 SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
2509 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2511 SetSizeModeFactor( property.Get< Vector3 >() );
2515 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2517 ResizePolicy::Type type;
2518 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2520 SetResizePolicy( type, Dimension::WIDTH );
2525 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2527 ResizePolicy::Type type;
2528 if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
2530 SetResizePolicy( type, Dimension::HEIGHT );
2535 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2537 SizeScalePolicy::Type type;
2538 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount, type ) )
2540 SetSizeScalePolicy( type );
2545 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2547 if( property.Get< bool >() )
2549 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2554 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2556 if( property.Get< bool >() )
2558 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2563 case Dali::Actor::Property::PADDING:
2565 Vector4 padding = property.Get< Vector4 >();
2566 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2567 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2571 case Dali::Actor::Property::MINIMUM_SIZE:
2573 Vector2 size = property.Get< Vector2 >();
2574 SetMinimumSize( size.x, Dimension::WIDTH );
2575 SetMinimumSize( size.y, Dimension::HEIGHT );
2579 case Dali::Actor::Property::MAXIMUM_SIZE:
2581 Vector2 size = property.Get< Vector2 >();
2582 SetMaximumSize( size.x, Dimension::WIDTH );
2583 SetMaximumSize( size.y, Dimension::HEIGHT );
2589 // this can happen in the case of a non-animatable default property so just do nothing
2595 // TODO: This method needs to be removed
2596 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2598 switch( entry.GetType() )
2600 case Property::BOOLEAN:
2602 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2603 DALI_ASSERT_DEBUG( NULL != property );
2605 // property is being used in a separate thread; queue a message to set the property
2606 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2611 case Property::INTEGER:
2613 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2614 DALI_ASSERT_DEBUG( NULL != property );
2616 // property is being used in a separate thread; queue a message to set the property
2617 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2622 case Property::FLOAT:
2624 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2625 DALI_ASSERT_DEBUG( NULL != property );
2627 // property is being used in a separate thread; queue a message to set the property
2628 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2633 case Property::VECTOR2:
2635 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2636 DALI_ASSERT_DEBUG( NULL != property );
2638 // property is being used in a separate thread; queue a message to set the property
2639 if(entry.componentIndex == 0)
2641 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2643 else if(entry.componentIndex == 1)
2645 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2649 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2655 case Property::VECTOR3:
2657 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2658 DALI_ASSERT_DEBUG( NULL != property );
2660 // property is being used in a separate thread; queue a message to set the property
2661 if(entry.componentIndex == 0)
2663 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2665 else if(entry.componentIndex == 1)
2667 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2669 else if(entry.componentIndex == 2)
2671 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2675 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2681 case Property::VECTOR4:
2683 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2684 DALI_ASSERT_DEBUG( NULL != property );
2686 // property is being used in a separate thread; queue a message to set the property
2687 if(entry.componentIndex == 0)
2689 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
2691 else if(entry.componentIndex == 1)
2693 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
2695 else if(entry.componentIndex == 2)
2697 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
2699 else if(entry.componentIndex == 3)
2701 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
2705 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2711 case Property::ROTATION:
2713 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
2714 DALI_ASSERT_DEBUG( NULL != property );
2716 // property is being used in a separate thread; queue a message to set the property
2717 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
2722 case Property::MATRIX:
2724 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
2725 DALI_ASSERT_DEBUG( NULL != property );
2727 // property is being used in a separate thread; queue a message to set the property
2728 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
2733 case Property::MATRIX3:
2735 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
2736 DALI_ASSERT_DEBUG( NULL != property );
2738 // property is being used in a separate thread; queue a message to set the property
2739 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
2746 DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
2752 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
2754 Property::Value value;
2758 case Dali::Actor::Property::PARENT_ORIGIN:
2760 value = GetCurrentParentOrigin();
2764 case Dali::Actor::Property::PARENT_ORIGIN_X:
2766 value = GetCurrentParentOrigin().x;
2770 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2772 value = GetCurrentParentOrigin().y;
2776 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2778 value = GetCurrentParentOrigin().z;
2782 case Dali::Actor::Property::ANCHOR_POINT:
2784 value = GetCurrentAnchorPoint();
2788 case Dali::Actor::Property::ANCHOR_POINT_X:
2790 value = GetCurrentAnchorPoint().x;
2794 case Dali::Actor::Property::ANCHOR_POINT_Y:
2796 value = GetCurrentAnchorPoint().y;
2800 case Dali::Actor::Property::ANCHOR_POINT_Z:
2802 value = GetCurrentAnchorPoint().z;
2806 case Dali::Actor::Property::SIZE:
2808 value = GetTargetSize();
2812 case Dali::Actor::Property::SIZE_WIDTH:
2814 value = GetTargetSize().width;
2818 case Dali::Actor::Property::SIZE_HEIGHT:
2820 value = GetTargetSize().height;
2824 case Dali::Actor::Property::SIZE_DEPTH:
2826 value = GetTargetSize().depth;
2830 case Dali::Actor::Property::POSITION:
2832 value = GetTargetPosition();
2836 case Dali::Actor::Property::POSITION_X:
2838 value = GetTargetPosition().x;
2842 case Dali::Actor::Property::POSITION_Y:
2844 value = GetTargetPosition().y;
2848 case Dali::Actor::Property::POSITION_Z:
2850 value = GetTargetPosition().z;
2854 case Dali::Actor::Property::WORLD_POSITION:
2856 value = GetCurrentWorldPosition();
2860 case Dali::Actor::Property::WORLD_POSITION_X:
2862 value = GetCurrentWorldPosition().x;
2866 case Dali::Actor::Property::WORLD_POSITION_Y:
2868 value = GetCurrentWorldPosition().y;
2872 case Dali::Actor::Property::WORLD_POSITION_Z:
2874 value = GetCurrentWorldPosition().z;
2878 case Dali::Actor::Property::ORIENTATION:
2880 value = GetCurrentOrientation();
2884 case Dali::Actor::Property::WORLD_ORIENTATION:
2886 value = GetCurrentWorldOrientation();
2890 case Dali::Actor::Property::SCALE:
2892 value = GetCurrentScale();
2896 case Dali::Actor::Property::SCALE_X:
2898 value = GetCurrentScale().x;
2902 case Dali::Actor::Property::SCALE_Y:
2904 value = GetCurrentScale().y;
2908 case Dali::Actor::Property::SCALE_Z:
2910 value = GetCurrentScale().z;
2914 case Dali::Actor::Property::WORLD_SCALE:
2916 value = GetCurrentWorldScale();
2920 case Dali::Actor::Property::VISIBLE:
2922 value = IsVisible();
2926 case Dali::Actor::Property::COLOR:
2928 value = GetCurrentColor();
2932 case Dali::Actor::Property::COLOR_RED:
2934 value = GetCurrentColor().r;
2938 case Dali::Actor::Property::COLOR_GREEN:
2940 value = GetCurrentColor().g;
2944 case Dali::Actor::Property::COLOR_BLUE:
2946 value = GetCurrentColor().b;
2950 case Dali::Actor::Property::COLOR_ALPHA:
2952 value = GetCurrentColor().a;
2956 case Dali::Actor::Property::WORLD_COLOR:
2958 value = GetCurrentWorldColor();
2962 case Dali::Actor::Property::WORLD_MATRIX:
2964 value = GetCurrentWorldMatrix();
2968 case Dali::Actor::Property::NAME:
2974 case Dali::Actor::Property::SENSITIVE:
2976 value = IsSensitive();
2980 case Dali::Actor::Property::LEAVE_REQUIRED:
2982 value = GetLeaveRequired();
2986 case Dali::Actor::Property::INHERIT_POSITION:
2988 value = IsPositionInherited();
2992 case Dali::Actor::Property::INHERIT_ORIENTATION:
2994 value = IsOrientationInherited();
2998 case Dali::Actor::Property::INHERIT_SCALE:
3000 value = IsScaleInherited();
3004 case Dali::Actor::Property::COLOR_MODE:
3006 value = Scripting::GetColorMode( GetColorMode() );
3010 case Dali::Actor::Property::POSITION_INHERITANCE:
3012 value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
3016 case Dali::Actor::Property::DRAW_MODE:
3018 value = Scripting::GetDrawMode( GetDrawMode() );
3022 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3024 value = GetSizeModeFactor();
3028 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3030 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3034 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3036 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
3040 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3042 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
3046 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3048 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3052 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3054 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3058 case Dali::Actor::Property::PADDING:
3060 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3061 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3062 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3066 case Dali::Actor::Property::MINIMUM_SIZE:
3068 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3072 case Dali::Actor::Property::MAXIMUM_SIZE:
3074 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3080 DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
3088 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3093 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3095 // This method should only return an object connected to the scene-graph
3096 return OnStage() ? mNode : NULL;
3099 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3101 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3103 const PropertyBase* property( NULL );
3105 // This method should only return a property of an object connected to the scene-graph
3111 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3113 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3114 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3116 property = animatable->GetSceneGraphProperty();
3118 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3120 CustomPropertyMetadata* custom = FindCustomProperty( index );
3121 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3123 property = custom->GetSceneGraphProperty();
3125 else if( NULL != mNode )
3129 case Dali::Actor::Property::SIZE:
3130 property = &mNode->mSize;
3133 case Dali::Actor::Property::SIZE_WIDTH:
3134 property = &mNode->mSize;
3137 case Dali::Actor::Property::SIZE_HEIGHT:
3138 property = &mNode->mSize;
3141 case Dali::Actor::Property::SIZE_DEPTH:
3142 property = &mNode->mSize;
3145 case Dali::Actor::Property::POSITION:
3146 property = &mNode->mPosition;
3149 case Dali::Actor::Property::POSITION_X:
3150 property = &mNode->mPosition;
3153 case Dali::Actor::Property::POSITION_Y:
3154 property = &mNode->mPosition;
3157 case Dali::Actor::Property::POSITION_Z:
3158 property = &mNode->mPosition;
3161 case Dali::Actor::Property::ORIENTATION:
3162 property = &mNode->mOrientation;
3165 case Dali::Actor::Property::SCALE:
3166 property = &mNode->mScale;
3169 case Dali::Actor::Property::SCALE_X:
3170 property = &mNode->mScale;
3173 case Dali::Actor::Property::SCALE_Y:
3174 property = &mNode->mScale;
3177 case Dali::Actor::Property::SCALE_Z:
3178 property = &mNode->mScale;
3181 case Dali::Actor::Property::VISIBLE:
3182 property = &mNode->mVisible;
3185 case Dali::Actor::Property::COLOR:
3186 property = &mNode->mColor;
3189 case Dali::Actor::Property::COLOR_RED:
3190 property = &mNode->mColor;
3193 case Dali::Actor::Property::COLOR_GREEN:
3194 property = &mNode->mColor;
3197 case Dali::Actor::Property::COLOR_BLUE:
3198 property = &mNode->mColor;
3201 case Dali::Actor::Property::COLOR_ALPHA:
3202 property = &mNode->mColor;
3213 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3215 const PropertyInputImpl* property( NULL );
3217 // This method should only return a property of an object connected to the scene-graph
3223 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3225 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3226 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3228 property = animatable->GetSceneGraphProperty();
3230 else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
3232 CustomPropertyMetadata* custom = FindCustomProperty( index );
3233 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3234 property = custom->GetSceneGraphProperty();
3236 else if( NULL != mNode )
3240 case Dali::Actor::Property::PARENT_ORIGIN:
3241 property = &mNode->mParentOrigin;
3244 case Dali::Actor::Property::PARENT_ORIGIN_X:
3245 property = &mNode->mParentOrigin;
3248 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3249 property = &mNode->mParentOrigin;
3252 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3253 property = &mNode->mParentOrigin;
3256 case Dali::Actor::Property::ANCHOR_POINT:
3257 property = &mNode->mAnchorPoint;
3260 case Dali::Actor::Property::ANCHOR_POINT_X:
3261 property = &mNode->mAnchorPoint;
3264 case Dali::Actor::Property::ANCHOR_POINT_Y:
3265 property = &mNode->mAnchorPoint;
3268 case Dali::Actor::Property::ANCHOR_POINT_Z:
3269 property = &mNode->mAnchorPoint;
3272 case Dali::Actor::Property::SIZE:
3273 property = &mNode->mSize;
3276 case Dali::Actor::Property::SIZE_WIDTH:
3277 property = &mNode->mSize;
3280 case Dali::Actor::Property::SIZE_HEIGHT:
3281 property = &mNode->mSize;
3284 case Dali::Actor::Property::SIZE_DEPTH:
3285 property = &mNode->mSize;
3288 case Dali::Actor::Property::POSITION:
3289 property = &mNode->mPosition;
3292 case Dali::Actor::Property::POSITION_X:
3293 property = &mNode->mPosition;
3296 case Dali::Actor::Property::POSITION_Y:
3297 property = &mNode->mPosition;
3300 case Dali::Actor::Property::POSITION_Z:
3301 property = &mNode->mPosition;
3304 case Dali::Actor::Property::WORLD_POSITION:
3305 property = &mNode->mWorldPosition;
3308 case Dali::Actor::Property::WORLD_POSITION_X:
3309 property = &mNode->mWorldPosition;
3312 case Dali::Actor::Property::WORLD_POSITION_Y:
3313 property = &mNode->mWorldPosition;
3316 case Dali::Actor::Property::WORLD_POSITION_Z:
3317 property = &mNode->mWorldPosition;
3320 case Dali::Actor::Property::ORIENTATION:
3321 property = &mNode->mOrientation;
3324 case Dali::Actor::Property::WORLD_ORIENTATION:
3325 property = &mNode->mWorldOrientation;
3328 case Dali::Actor::Property::SCALE:
3329 property = &mNode->mScale;
3332 case Dali::Actor::Property::SCALE_X:
3333 property = &mNode->mScale;
3336 case Dali::Actor::Property::SCALE_Y:
3337 property = &mNode->mScale;
3340 case Dali::Actor::Property::SCALE_Z:
3341 property = &mNode->mScale;
3344 case Dali::Actor::Property::WORLD_SCALE:
3345 property = &mNode->mWorldScale;
3348 case Dali::Actor::Property::VISIBLE:
3349 property = &mNode->mVisible;
3352 case Dali::Actor::Property::COLOR:
3353 property = &mNode->mColor;
3356 case Dali::Actor::Property::COLOR_RED:
3357 property = &mNode->mColor;
3360 case Dali::Actor::Property::COLOR_GREEN:
3361 property = &mNode->mColor;
3364 case Dali::Actor::Property::COLOR_BLUE:
3365 property = &mNode->mColor;
3368 case Dali::Actor::Property::COLOR_ALPHA:
3369 property = &mNode->mColor;
3372 case Dali::Actor::Property::WORLD_COLOR:
3373 property = &mNode->mWorldColor;
3376 case Dali::Actor::Property::WORLD_MATRIX:
3377 property = &mNode->mWorldMatrix;
3388 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3390 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3392 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3394 // check whether the animatable property is registered already, if not then register one.
3395 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3396 if( animatableProperty )
3398 componentIndex = animatableProperty->componentIndex;
3405 case Dali::Actor::Property::PARENT_ORIGIN_X:
3406 case Dali::Actor::Property::ANCHOR_POINT_X:
3407 case Dali::Actor::Property::SIZE_WIDTH:
3408 case Dali::Actor::Property::POSITION_X:
3409 case Dali::Actor::Property::WORLD_POSITION_X:
3410 case Dali::Actor::Property::SCALE_X:
3411 case Dali::Actor::Property::COLOR_RED:
3417 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3418 case Dali::Actor::Property::ANCHOR_POINT_Y:
3419 case Dali::Actor::Property::SIZE_HEIGHT:
3420 case Dali::Actor::Property::POSITION_Y:
3421 case Dali::Actor::Property::WORLD_POSITION_Y:
3422 case Dali::Actor::Property::SCALE_Y:
3423 case Dali::Actor::Property::COLOR_GREEN:
3429 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3430 case Dali::Actor::Property::ANCHOR_POINT_Z:
3431 case Dali::Actor::Property::SIZE_DEPTH:
3432 case Dali::Actor::Property::POSITION_Z:
3433 case Dali::Actor::Property::WORLD_POSITION_Z:
3434 case Dali::Actor::Property::SCALE_Z:
3435 case Dali::Actor::Property::COLOR_BLUE:
3441 case Dali::Actor::Property::COLOR_ALPHA:
3455 return componentIndex;
3458 void Actor::SetParent( Actor* parent )
3462 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3466 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3469 // Instruct each actor to create a corresponding node in the scene graph
3470 ConnectToStage( parent->GetHierarchyDepth() );
3473 else // parent being set to NULL
3475 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3479 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3482 DALI_ASSERT_ALWAYS( mNode != NULL );
3486 // Disconnect the Node & its children from the scene-graph.
3487 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3490 // Instruct each actor to discard pointers to the scene-graph
3491 DisconnectFromStage();
3496 SceneGraph::Node* Actor::CreateNode() const
3501 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3504 Actor* actor = dynamic_cast< Actor* >( object );
3508 if( 0 == actionName.compare( ACTION_SHOW ) )
3510 actor->SetVisible( true );
3513 else if( 0 == actionName.compare( ACTION_HIDE ) )
3515 actor->SetVisible( false );
3523 void Actor::EnsureRelayoutData()
3525 // Assign relayout data.
3526 if( !mRelayoutData )
3528 mRelayoutData = new RelayoutData();
3532 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3534 // Check if actor is dependent on parent
3535 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3537 if( ( dimension & ( 1 << i ) ) )
3539 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3540 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3550 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3552 // Check if actor is dependent on children
3553 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3555 if( ( dimension & ( 1 << i ) ) )
3557 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3558 switch( resizePolicy )
3560 case ResizePolicy::FIT_TO_CHILDREN:
3561 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3577 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3579 return Actor::RelayoutDependentOnChildren( dimension );
3582 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3584 // Check each possible dimension and see if it is dependent on the input one
3585 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3587 if( dimension & ( 1 << i ) )
3589 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3596 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3598 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3600 if( dimension & ( 1 << i ) )
3602 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3607 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3609 // If more than one dimension is requested, just return the first one found
3610 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3612 if( ( dimension & ( 1 << i ) ) )
3614 return mRelayoutData->negotiatedDimensions[ i ];
3618 return 0.0f; // Default
3621 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3623 EnsureRelayoutData();
3625 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3627 if( dimension & ( 1 << i ) )
3629 mRelayoutData->dimensionPadding[ i ] = padding;
3634 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3636 if ( mRelayoutData )
3638 // If more than one dimension is requested, just return the first one found
3639 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3641 if( ( dimension & ( 1 << i ) ) )
3643 return mRelayoutData->dimensionPadding[ i ];
3648 return GetDefaultDimensionPadding();
3651 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
3653 EnsureRelayoutData();
3655 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3657 if( dimension & ( 1 << i ) )
3659 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3664 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
3666 if ( mRelayoutData )
3668 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3670 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
3680 float Actor::GetHeightForWidthBase( float width )
3682 float height = 0.0f;
3684 const Vector3 naturalSize = GetNaturalSize();
3685 if( naturalSize.width > 0.0f )
3687 height = naturalSize.height * width / naturalSize.width;
3689 else // we treat 0 as 1:1 aspect ratio
3697 float Actor::GetWidthForHeightBase( float height )
3701 const Vector3 naturalSize = GetNaturalSize();
3702 if( naturalSize.height > 0.0f )
3704 width = naturalSize.width * height / naturalSize.height;
3706 else // we treat 0 as 1:1 aspect ratio
3714 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
3716 // Fill to parent, taking size mode factor into account
3717 switch( child.GetResizePolicy( dimension ) )
3719 case ResizePolicy::FILL_TO_PARENT:
3721 return GetLatestSize( dimension );
3724 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3726 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
3729 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3731 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
3736 return GetLatestSize( dimension );
3741 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
3743 // Can be overridden in derived class
3744 return CalculateChildSizeBase( child, dimension );
3747 float Actor::GetHeightForWidth( float width )
3749 // Can be overridden in derived class
3750 return GetHeightForWidthBase( width );
3753 float Actor::GetWidthForHeight( float height )
3755 // Can be overridden in derived class
3756 return GetWidthForHeightBase( height );
3759 float Actor::GetLatestSize( Dimension::Type dimension ) const
3761 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
3764 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
3766 Vector2 padding = GetPadding( dimension );
3768 return GetLatestSize( dimension ) + padding.x + padding.y;
3771 float Actor::NegotiateFromParent( Dimension::Type dimension )
3773 Actor* parent = GetParent();
3776 Vector2 padding( GetPadding( dimension ) );
3777 Vector2 parentPadding( parent->GetPadding( dimension ) );
3778 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
3784 float Actor::NegotiateFromChildren( Dimension::Type dimension )
3786 float maxDimensionPoint = 0.0f;
3788 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3790 ActorPtr child = GetChildAt( i );
3792 if( !child->RelayoutDependentOnParent( dimension ) )
3794 // Calculate the min and max points that the children range across
3795 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
3796 float dimensionSize = child->GetRelayoutSize( dimension );
3797 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
3801 return maxDimensionPoint;
3804 float Actor::GetSize( Dimension::Type dimension ) const
3806 return GetDimensionValue( GetTargetSize(), dimension );
3809 float Actor::GetNaturalSize( Dimension::Type dimension ) const
3811 return GetDimensionValue( GetNaturalSize(), dimension );
3814 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
3816 switch( GetResizePolicy( dimension ) )
3818 case ResizePolicy::USE_NATURAL_SIZE:
3820 return GetNaturalSize( dimension );
3823 case ResizePolicy::FIXED:
3825 return GetDimensionValue( GetPreferredSize(), dimension );
3828 case ResizePolicy::USE_ASSIGNED_SIZE:
3830 return GetDimensionValue( maximumSize, dimension );
3833 case ResizePolicy::FILL_TO_PARENT:
3834 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3835 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3837 return NegotiateFromParent( dimension );
3840 case ResizePolicy::FIT_TO_CHILDREN:
3842 return NegotiateFromChildren( dimension );
3845 case ResizePolicy::DIMENSION_DEPENDENCY:
3847 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
3850 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
3852 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
3855 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
3857 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
3869 return 0.0f; // Default
3872 float Actor::ClampDimension( float size, Dimension::Type dimension )
3874 const float minSize = GetMinimumSize( dimension );
3875 const float maxSize = GetMaximumSize( dimension );
3877 return std::max( minSize, std::min( size, maxSize ) );
3880 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
3882 // Check if it needs to be negotiated
3883 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
3885 // Check that we havn't gotten into an infinite loop
3886 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
3887 bool recursionFound = false;
3888 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
3890 if( *it == searchActor )
3892 recursionFound = true;
3897 if( !recursionFound )
3899 // Record the path that we have taken
3900 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
3902 // Dimension dependency check
3903 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3905 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
3907 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
3909 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
3913 // Parent dependency check
3914 Actor* parent = GetParent();
3915 if( parent && RelayoutDependentOnParent( dimension ) )
3917 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
3920 // Children dependency check
3921 if( RelayoutDependentOnChildren( dimension ) )
3923 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3925 ActorPtr child = GetChildAt( i );
3927 // Only relayout child first if it is not dependent on this actor
3928 if( !child->RelayoutDependentOnParent( dimension ) )
3930 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
3935 // For deriving classes
3936 OnCalculateRelayoutSize( dimension );
3938 // All dependencies checked, calculate the size and set negotiated flag
3939 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
3941 SetNegotiatedDimension( newSize, dimension );
3942 SetLayoutNegotiated( true, dimension );
3944 // For deriving classes
3945 OnLayoutNegotiated( newSize, dimension );
3947 // This actor has been successfully processed, pop it off the recursion stack
3948 recursionStack.pop_back();
3952 // TODO: Break infinite loop
3953 SetLayoutNegotiated( true, dimension );
3958 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
3960 // Negotiate all dimensions that require it
3961 ActorDimensionStack recursionStack;
3963 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3965 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
3968 NegotiateDimension( dimension, allocatedSize, recursionStack );
3972 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
3974 switch( mRelayoutData->sizeSetPolicy )
3976 case SizeScalePolicy::USE_SIZE_SET:
3981 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
3983 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
3984 const Vector3 naturalSize = GetNaturalSize();
3985 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
3987 const float sizeRatio = size.width / size.height;
3988 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
3990 if( naturalSizeRatio < sizeRatio )
3992 return Vector2( naturalSizeRatio * size.height, size.height );
3994 else if( naturalSizeRatio > sizeRatio )
3996 return Vector2( size.width, size.width / naturalSizeRatio );
4007 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4009 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4010 const Vector3 naturalSize = GetNaturalSize();
4011 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4013 const float sizeRatio = size.width / size.height;
4014 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4016 if( naturalSizeRatio < sizeRatio )
4018 return Vector2( size.width, size.width / naturalSizeRatio );
4020 else if( naturalSizeRatio > sizeRatio )
4022 return Vector2( naturalSizeRatio * size.height, size.height );
4041 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4043 // Do the set actor size
4044 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4046 // Adjust for size set policy
4047 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4049 // Lock the flag to stop recursive relayouts on set size
4050 mRelayoutData->insideRelayout = true;
4051 SetSize( negotiatedSize );
4052 mRelayoutData->insideRelayout = false;
4054 // Clear flags for all dimensions
4055 SetLayoutDirty( false );
4057 // Give deriving classes a chance to respond
4058 OnRelayout( negotiatedSize, container );
4060 if( !mOnRelayoutSignal.Empty() )
4062 Dali::Actor handle( this );
4063 mOnRelayoutSignal.Emit( handle );
4067 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4069 // Force a size negotiation for actors that has assigned size during relayout
4070 // This is required as otherwise the flags that force a relayout will not
4071 // necessarilly be set. This will occur if the actor has already been laid out.
4072 // The dirty flags are then cleared. Then if the actor is added back into the
4073 // relayout container afterwards, the dirty flags would still be clear...
4074 // causing a relayout to be skipped. Here we force any actors added to the
4075 // container to be relayed out.
4076 if(GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE)
4078 SetLayoutNegotiated(false, Dimension::WIDTH);
4080 if(GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE)
4082 SetLayoutNegotiated(false, Dimension::HEIGHT);
4085 // Do the negotiation
4086 NegotiateDimensions( allocatedSize );
4088 // Set the actor size
4089 SetNegotiatedSize( container );
4091 // Negotiate down to children
4092 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4094 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4096 ActorPtr child = GetChildAt( i );
4098 // Forces children that have already been laid out to be relayed out
4099 // if they have assigned size during relayout.
4100 if(child->GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE)
4102 child->SetLayoutNegotiated(false, Dimension::WIDTH);
4103 child->SetLayoutDirty(true, Dimension::WIDTH);
4105 if(child->GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE)
4107 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
4108 child->SetLayoutDirty(true, Dimension::HEIGHT);
4111 // Only relayout if required
4112 if( child->RelayoutRequired() )
4114 container.Add( Dali::Actor( child.Get() ), newBounds );
4119 void Actor::RelayoutRequest( Dimension::Type dimension )
4121 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4122 if( relayoutController )
4124 Dali::Actor self( this );
4125 relayoutController->RequestRelayout( self, dimension );
4129 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4133 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4137 void Actor::SetPreferredSize( const Vector2& size )
4139 EnsureRelayoutData();
4141 if( size.width > 0.0f )
4143 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4146 if( size.height > 0.0f )
4148 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4151 mRelayoutData->preferredSize = size;
4156 Vector2 Actor::GetPreferredSize() const
4158 if ( mRelayoutData )
4160 return Vector2( mRelayoutData->preferredSize );
4163 return GetDefaultPreferredSize();
4166 void Actor::SetMinimumSize( 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->minimumSize[ i ] = size;
4181 float Actor::GetMinimumSize( 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->minimumSize[ i ];
4194 return 0.0f; // Default
4197 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4199 EnsureRelayoutData();
4201 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4203 if( dimension & ( 1 << i ) )
4205 mRelayoutData->maximumSize[ i ] = size;
4212 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4214 if ( mRelayoutData )
4216 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4218 if( dimension & ( 1 << i ) )
4220 return mRelayoutData->maximumSize[ i ];
4225 return FLT_MAX; // Default
4228 } // namespace Internal