2 * Copyright (c) 2017 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>
27 #include <dali/devel-api/actors/layer-devel.h>
28 #include <dali/public-api/common/dali-common.h>
29 #include <dali/public-api/common/constants.h>
30 #include <dali/public-api/events/touch-data.h>
31 #include <dali/public-api/math/vector2.h>
32 #include <dali/public-api/math/vector3.h>
33 #include <dali/public-api/math/radian.h>
34 #include <dali/public-api/object/type-registry.h>
35 #include <dali/devel-api/actors/actor-devel.h>
36 #include <dali/devel-api/scripting/scripting.h>
37 #include <dali/internal/common/internal-constants.h>
38 #include <dali/internal/event/common/event-thread-services.h>
39 #include <dali/internal/event/render-tasks/render-task-impl.h>
40 #include <dali/internal/event/actors/camera-actor-impl.h>
41 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
42 #include <dali/internal/event/common/property-helper.h>
43 #include <dali/internal/event/common/stage-impl.h>
44 #include <dali/internal/event/common/type-info-impl.h>
45 #include <dali/internal/event/animation/constraint-impl.h>
46 #include <dali/internal/event/common/projection.h>
47 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
48 #include <dali/internal/update/common/animatable-property.h>
49 #include <dali/internal/update/nodes/node-messages.h>
50 #include <dali/internal/update/nodes/node-declarations.h>
51 #include <dali/internal/update/animation/scene-graph-constraint.h>
52 #include <dali/internal/event/events/actor-gesture-data.h>
53 #include <dali/internal/common/message.h>
54 #include <dali/integration-api/debug.h>
56 using Dali::Internal::SceneGraph::Node;
57 using Dali::Internal::SceneGraph::AnimatableProperty;
58 using Dali::Internal::SceneGraph::PropertyBase;
66 unsigned int Actor::mActorCounter = 0;
70 /// Using a function because of library initialisation order. Vector3::ONE may not have been initialised yet.
71 inline const Vector3& GetDefaultSizeModeFactor()
76 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
77 inline const Vector2& GetDefaultPreferredSize()
82 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
83 inline const Vector2& GetDefaultDimensionPadding()
88 const SizeScalePolicy::Type DEFAULT_SIZE_SCALE_POLICY = SizeScalePolicy::USE_SIZE_SET;
90 int GetSiblingOrder( ActorPtr actor )
92 Property::Value value = actor->GetProperty(Dali::DevelActor::Property::SIBLING_ORDER );
98 } // unnamed namespace
101 * Struct to collect relayout variables
103 struct Actor::RelayoutData
106 : sizeModeFactor( GetDefaultSizeModeFactor() ), preferredSize( GetDefaultPreferredSize() ), sizeSetPolicy( DEFAULT_SIZE_SCALE_POLICY ), relayoutEnabled( false ), insideRelayout( false )
108 // Set size negotiation defaults
109 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
111 resizePolicies[ i ] = ResizePolicy::DEFAULT;
112 negotiatedDimensions[ i ] = 0.0f;
113 dimensionNegotiated[ i ] = false;
114 dimensionDirty[ i ] = false;
115 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
116 dimensionPadding[ i ] = GetDefaultDimensionPadding();
117 minimumSize[ i ] = 0.0f;
118 maximumSize[ i ] = FLT_MAX;
122 ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies
124 Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies
126 Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
128 float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
130 float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be
131 float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be
133 bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated
134 bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
136 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
138 Vector2 preferredSize; ///< The preferred size of the actor
140 SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
142 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
143 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
146 namespace // unnamed namespace
152 * We want to discourage the use of property strings (minimize string comparisons),
153 * particularly for the default properties.
154 * Name Type writable animatable constraint-input enum for index-checking
156 DALI_PROPERTY_TABLE_BEGIN
157 DALI_PROPERTY( "parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
158 DALI_PROPERTY( "parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
159 DALI_PROPERTY( "parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
160 DALI_PROPERTY( "parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
161 DALI_PROPERTY( "anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
162 DALI_PROPERTY( "anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
163 DALI_PROPERTY( "anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
164 DALI_PROPERTY( "anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
165 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
166 DALI_PROPERTY( "sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
167 DALI_PROPERTY( "sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
168 DALI_PROPERTY( "sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
169 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
170 DALI_PROPERTY( "positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
171 DALI_PROPERTY( "positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
172 DALI_PROPERTY( "positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
173 DALI_PROPERTY( "worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
174 DALI_PROPERTY( "worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
175 DALI_PROPERTY( "worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
176 DALI_PROPERTY( "worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
177 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
178 DALI_PROPERTY( "worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
179 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
180 DALI_PROPERTY( "scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
181 DALI_PROPERTY( "scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
182 DALI_PROPERTY( "scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
183 DALI_PROPERTY( "worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
184 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
185 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
186 DALI_PROPERTY( "colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
187 DALI_PROPERTY( "colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
188 DALI_PROPERTY( "colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
189 DALI_PROPERTY( "colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
190 DALI_PROPERTY( "worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
191 DALI_PROPERTY( "worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
192 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
193 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
194 DALI_PROPERTY( "leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
195 DALI_PROPERTY( "inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
196 DALI_PROPERTY( "inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
197 DALI_PROPERTY( "colorMode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
198 DALI_PROPERTY( "positionInheritance", STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE )
199 DALI_PROPERTY( "drawMode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
200 DALI_PROPERTY( "sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
201 DALI_PROPERTY( "widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
202 DALI_PROPERTY( "heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
203 DALI_PROPERTY( "sizeScalePolicy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
204 DALI_PROPERTY( "widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
205 DALI_PROPERTY( "heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
206 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
207 DALI_PROPERTY( "minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
208 DALI_PROPERTY( "maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
209 DALI_PROPERTY( "inheritPosition", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_POSITION )
210 DALI_PROPERTY( "clippingMode", STRING, true, false, false, Dali::Actor::Property::CLIPPING_MODE )
211 DALI_PROPERTY( "siblingOrder", INTEGER, true, false, false, Dali::DevelActor::Property::SIBLING_ORDER )
212 DALI_PROPERTY( "opacity", FLOAT, true, true, true, Dali::DevelActor::Property::OPACITY )
213 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
217 const char* const SIGNAL_TOUCHED = "touched";
218 const char* const SIGNAL_HOVERED = "hovered";
219 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
220 const char* const SIGNAL_ON_STAGE = "onStage";
221 const char* const SIGNAL_OFF_STAGE = "offStage";
222 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
223 const char* const SIGNAL_TOUCH = "touch";
227 const char* const ACTION_SHOW = "show";
228 const char* const ACTION_HIDE = "hide";
230 BaseHandle CreateActor()
232 return Dali::Actor::New();
235 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
237 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
238 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
239 SignalConnectorType signalConnector3( mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal );
240 SignalConnectorType signalConnector4( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
241 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
242 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
243 SignalConnectorType signalConnector7( mType, SIGNAL_TOUCH, &Actor::DoConnectSignal );
245 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
246 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
251 const Vector3& value;
254 DALI_ENUM_TO_STRING_TABLE_BEGIN_WITH_TYPE( AnchorValue, ANCHOR_CONSTANT )
255 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_LEFT )
256 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_CENTER )
257 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_RIGHT )
258 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_LEFT )
259 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER )
260 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_RIGHT )
261 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_LEFT )
262 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_CENTER )
263 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_RIGHT )
264 DALI_ENUM_TO_STRING_TABLE_END( ANCHOR_CONSTANT )
266 DALI_ENUM_TO_STRING_TABLE_BEGIN( COLOR_MODE )
267 DALI_ENUM_TO_STRING( USE_OWN_COLOR )
268 DALI_ENUM_TO_STRING( USE_PARENT_COLOR )
269 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_COLOR )
270 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_ALPHA )
271 DALI_ENUM_TO_STRING_TABLE_END( COLOR_MODE )
273 DALI_ENUM_TO_STRING_TABLE_BEGIN( POSITION_INHERITANCE_MODE )
274 DALI_ENUM_TO_STRING( INHERIT_PARENT_POSITION )
275 DALI_ENUM_TO_STRING( USE_PARENT_POSITION )
276 DALI_ENUM_TO_STRING( USE_PARENT_POSITION_PLUS_LOCAL_POSITION )
277 DALI_ENUM_TO_STRING( DONT_INHERIT_POSITION )
278 DALI_ENUM_TO_STRING_TABLE_END( POSITION_INHERITANCE_MODE )
280 DALI_ENUM_TO_STRING_TABLE_BEGIN( DRAW_MODE )
281 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, NORMAL )
282 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, OVERLAY_2D )
283 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, STENCIL )
284 DALI_ENUM_TO_STRING_TABLE_END( DRAW_MODE )
286 DALI_ENUM_TO_STRING_TABLE_BEGIN( RESIZE_POLICY )
287 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIXED )
288 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_NATURAL_SIZE )
289 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FILL_TO_PARENT )
290 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_RELATIVE_TO_PARENT )
291 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_FIXED_OFFSET_FROM_PARENT )
292 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIT_TO_CHILDREN )
293 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, DIMENSION_DEPENDENCY )
294 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_ASSIGNED_SIZE )
295 DALI_ENUM_TO_STRING_TABLE_END( RESIZE_POLICY )
297 DALI_ENUM_TO_STRING_TABLE_BEGIN( SIZE_SCALE_POLICY )
298 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, USE_SIZE_SET )
299 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FIT_WITH_ASPECT_RATIO )
300 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FILL_WITH_ASPECT_RATIO )
301 DALI_ENUM_TO_STRING_TABLE_END( SIZE_SCALE_POLICY )
303 DALI_ENUM_TO_STRING_TABLE_BEGIN( CLIPPING_MODE )
304 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, DISABLED )
305 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, CLIP_CHILDREN )
306 DALI_ENUM_TO_STRING_TABLE_END( CLIPPING_MODE )
309 bool GetAnchorPointConstant( const std::string& value, Vector3& anchor )
311 for( unsigned int i = 0; i < ANCHOR_CONSTANT_TABLE_COUNT; ++i )
313 size_t sizeIgnored = 0;
314 if( CompareTokens( value.c_str(), ANCHOR_CONSTANT_TABLE[ i ].name, sizeIgnored ) )
316 anchor = ANCHOR_CONSTANT_TABLE[ i ].value;
323 inline bool GetParentOriginConstant( const std::string& value, Vector3& parentOrigin )
325 // Values are the same so just use the same table as anchor-point
326 return GetAnchorPointConstant( value, parentOrigin );
330 * @brief Extract a given dimension from a Vector2
332 * @param[in] values The values to extract from
333 * @param[in] dimension The dimension to extract
334 * @return Return the value for the dimension
336 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
340 case Dimension::WIDTH:
344 case Dimension::HEIGHT:
346 return values.height;
357 * @brief Extract a given dimension from a Vector3
359 * @param[in] values The values to extract from
360 * @param[in] dimension The dimension to extract
361 * @return Return the value for the dimension
363 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
365 return GetDimensionValue( values.GetVectorXY(), dimension );
368 unsigned int GetDepthIndex( uint16_t depth, uint16_t siblingOrder )
370 return depth * Dali::DevelLayer::ACTOR_DEPTH_MULTIPLIER + siblingOrder * Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER;
373 } // unnamed namespace
375 ActorPtr Actor::New()
377 ActorPtr actor( new Actor( BASIC ) );
379 // Second-phase construction
385 const std::string& Actor::GetName() const
390 void Actor::SetName( const std::string& name )
396 // ATTENTION: string for debug purposes is not thread safe.
397 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
401 unsigned int Actor::GetId() const
406 bool Actor::OnStage() const
411 Dali::Layer Actor::GetLayer()
415 // Short-circuit for Layer derived actors
418 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
421 // Find the immediate Layer parent
422 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
424 if( parent->IsLayer() )
426 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
433 void Actor::Add( Actor& child )
435 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
436 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
440 mChildren = new ActorContainer;
443 Actor* const oldParent( child.mParent );
445 // child might already be ours
446 if( this != oldParent )
448 // if we already have parent, unparent us first
451 oldParent->Remove( child ); // This causes OnChildRemove callback
453 // Old parent may need to readjust to missing child
454 if( oldParent->RelayoutDependentOnChildren() )
456 oldParent->RelayoutRequest();
460 // Guard against Add() during previous OnChildRemove callback
463 // Do this first, since user callbacks from within SetParent() may need to remove child
464 mChildren->push_back( ActorPtr( &child ) );
466 // SetParent asserts that child can be added
467 child.SetParent( this );
469 // Notification for derived classes
472 // Only put in a relayout request if there is a suitable dependency
473 if( RelayoutDependentOnChildren() )
481 void Actor::Remove( Actor& child )
483 if( (this == &child) || (!mChildren) )
485 // no children or removing itself
491 // Find the child in mChildren, and unparent it
492 ActorIter end = mChildren->end();
493 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
495 ActorPtr actor = (*iter);
497 if( actor.Get() == &child )
499 // Keep handle for OnChildRemove notification
502 // Do this first, since user callbacks from within SetParent() may need to add the child
503 mChildren->erase( iter );
505 DALI_ASSERT_DEBUG( actor->GetParent() == this );
506 actor->SetParent( NULL );
514 // Only put in a relayout request if there is a suitable dependency
515 if( RelayoutDependentOnChildren() )
521 // Notification for derived classes
522 OnChildRemove( child );
525 void Actor::Unparent()
529 // Remove this actor from the parent. The remove will put a relayout request in for
530 // the parent if required
531 mParent->Remove( *this );
532 // mParent is now NULL!
536 unsigned int Actor::GetChildCount() const
538 return ( NULL != mChildren ) ? mChildren->size() : 0;
541 ActorPtr Actor::GetChildAt( unsigned int index ) const
543 DALI_ASSERT_ALWAYS( index < GetChildCount() );
545 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
548 ActorPtr Actor::FindChildByName( const std::string& actorName )
551 if( actorName == mName )
557 ActorIter end = mChildren->end();
558 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
560 child = (*iter)->FindChildByName( actorName );
571 ActorPtr Actor::FindChildById( const unsigned int id )
580 ActorIter end = mChildren->end();
581 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
583 child = (*iter)->FindChildById( id );
594 void Actor::SetParentOrigin( const Vector3& origin )
598 // mNode is being used in a separate thread; queue a message to set the value & base value
599 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
602 // Cache for event-thread access
605 // not allocated, check if different from default
606 if( ParentOrigin::DEFAULT != origin )
608 mParentOrigin = new Vector3( origin );
613 // check if different from current costs more than just set
614 *mParentOrigin = origin;
618 void Actor::SetParentOriginX( float x )
620 const Vector3& current = GetCurrentParentOrigin();
622 SetParentOrigin( Vector3( x, current.y, current.z ) );
625 void Actor::SetParentOriginY( float y )
627 const Vector3& current = GetCurrentParentOrigin();
629 SetParentOrigin( Vector3( current.x, y, current.z ) );
632 void Actor::SetParentOriginZ( float z )
634 const Vector3& current = GetCurrentParentOrigin();
636 SetParentOrigin( Vector3( current.x, current.y, z ) );
639 const Vector3& Actor::GetCurrentParentOrigin() const
641 // Cached for event-thread access
642 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
645 void Actor::SetAnchorPoint( const Vector3& anchor )
649 // mNode is being used in a separate thread; queue a message to set the value & base value
650 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
653 // Cache for event-thread access
656 // not allocated, check if different from default
657 if( AnchorPoint::DEFAULT != anchor )
659 mAnchorPoint = new Vector3( anchor );
664 // check if different from current costs more than just set
665 *mAnchorPoint = anchor;
669 void Actor::SetAnchorPointX( float x )
671 const Vector3& current = GetCurrentAnchorPoint();
673 SetAnchorPoint( Vector3( x, current.y, current.z ) );
676 void Actor::SetAnchorPointY( float y )
678 const Vector3& current = GetCurrentAnchorPoint();
680 SetAnchorPoint( Vector3( current.x, y, current.z ) );
683 void Actor::SetAnchorPointZ( float z )
685 const Vector3& current = GetCurrentAnchorPoint();
687 SetAnchorPoint( Vector3( current.x, current.y, z ) );
690 const Vector3& Actor::GetCurrentAnchorPoint() const
692 // Cached for event-thread access
693 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
696 void Actor::SetPosition( float x, float y )
698 SetPosition( Vector3( x, y, 0.0f ) );
701 void Actor::SetPosition( float x, float y, float z )
703 SetPosition( Vector3( x, y, z ) );
706 void Actor::SetPosition( const Vector3& position )
708 mTargetPosition = position;
712 // mNode is being used in a separate thread; queue a message to set the value & base value
713 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
717 void Actor::SetX( float x )
719 mTargetPosition.x = x;
723 // mNode is being used in a separate thread; queue a message to set the value & base value
724 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
728 void Actor::SetY( float y )
730 mTargetPosition.y = y;
734 // mNode is being used in a separate thread; queue a message to set the value & base value
735 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
739 void Actor::SetZ( float z )
741 mTargetPosition.z = z;
745 // mNode is being used in a separate thread; queue a message to set the value & base value
746 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
750 void Actor::TranslateBy( const Vector3& distance )
752 mTargetPosition += distance;
756 // mNode is being used in a separate thread; queue a message to set the value & base value
757 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
761 const Vector3& Actor::GetCurrentPosition() const
765 // mNode is being used in a separate thread; copy the value from the previous update
766 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
769 return Vector3::ZERO;
772 const Vector3& Actor::GetTargetPosition() const
774 return mTargetPosition;
777 const Vector3& Actor::GetCurrentWorldPosition() const
781 // mNode is being used in a separate thread; copy the value from the previous update
782 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
785 return Vector3::ZERO;
788 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
790 // this flag is not animatable so keep the value
791 mPositionInheritanceMode = mode;
794 // mNode is being used in a separate thread; queue a message to set the value
795 SetInheritPositionMessage( GetEventThreadServices(), *mNode, mode == INHERIT_PARENT_POSITION );
799 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
801 // Cached for event-thread access
802 return mPositionInheritanceMode;
805 void Actor::SetInheritPosition( bool inherit )
807 if( mInheritPosition != inherit && NULL != mNode )
809 // non animateable so keep local copy
810 mInheritPosition = inherit;
811 SetInheritPositionMessage( GetEventThreadServices(), *mNode, inherit );
815 bool Actor::IsPositionInherited() const
817 return mInheritPosition;
820 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
822 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
823 normalizedAxis.Normalize();
825 Quaternion orientation( angle, normalizedAxis );
827 SetOrientation( orientation );
830 void Actor::SetOrientation( const Quaternion& orientation )
834 // mNode is being used in a separate thread; queue a message to set the value & base value
835 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation );
839 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
843 // mNode is being used in a separate thread; queue a message to set the value & base value
844 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, Quaternion(angle, axis) );
848 void Actor::RotateBy( const Quaternion& relativeRotation )
852 // mNode is being used in a separate thread; queue a message to set the value & base value
853 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
857 const Quaternion& Actor::GetCurrentOrientation() const
861 // mNode is being used in a separate thread; copy the value from the previous update
862 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
865 return Quaternion::IDENTITY;
868 const Quaternion& Actor::GetCurrentWorldOrientation() const
872 // mNode is being used in a separate thread; copy the value from the previous update
873 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
876 return Quaternion::IDENTITY;
879 void Actor::SetScale( float scale )
881 SetScale( Vector3( scale, scale, scale ) );
884 void Actor::SetScale( float x, float y, float z )
886 SetScale( Vector3( x, y, z ) );
889 void Actor::SetScale( const Vector3& scale )
893 // mNode is being used in a separate thread; queue a message to set the value & base value
894 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
898 void Actor::SetScaleX( float x )
902 // mNode is being used in a separate thread; queue a message to set the value & base value
903 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
907 void Actor::SetScaleY( float y )
911 // mNode is being used in a separate thread; queue a message to set the value & base value
912 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
916 void Actor::SetScaleZ( float z )
920 // mNode is being used in a separate thread; queue a message to set the value & base value
921 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
925 void Actor::ScaleBy(const Vector3& relativeScale)
929 // mNode is being used in a separate thread; queue a message to set the value & base value
930 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
934 const Vector3& Actor::GetCurrentScale() const
938 // mNode is being used in a separate thread; copy the value from the previous update
939 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
945 const Vector3& Actor::GetCurrentWorldScale() const
949 // mNode is being used in a separate thread; copy the value from the previous update
950 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
956 void Actor::SetInheritScale( bool inherit )
959 if( mInheritScale != inherit && NULL != mNode )
961 // non animateable so keep local copy
962 mInheritScale = inherit;
963 // mNode is being used in a separate thread; queue a message to set the value
964 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
968 bool Actor::IsScaleInherited() const
970 return mInheritScale;
973 Matrix Actor::GetCurrentWorldMatrix() const
977 return mNode->GetWorldMatrix(0);
980 return Matrix::IDENTITY;
983 void Actor::SetVisible( bool visible )
987 // mNode is being used in a separate thread; queue a message to set the value & base value
988 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
992 bool Actor::IsVisible() const
996 // mNode is being used in a separate thread; copy the value from the previous update
997 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
1003 void Actor::SetOpacity( float opacity )
1007 // mNode is being used in a separate thread; queue a message to set the value & base value
1008 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
1012 float Actor::GetCurrentOpacity() const
1016 // mNode is being used in a separate thread; copy the value from the previous update
1017 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1023 ClippingMode::Type Actor::GetClippingMode() const
1025 return mClippingMode;
1028 unsigned int Actor::GetSortingDepth()
1030 return GetDepthIndex( mDepth, mSiblingOrder );
1033 const Vector4& Actor::GetCurrentWorldColor() const
1037 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1040 return Color::WHITE;
1043 void Actor::SetColor( const Vector4& color )
1047 // mNode is being used in a separate thread; queue a message to set the value & base value
1048 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1052 void Actor::SetColorRed( float red )
1056 // mNode is being used in a separate thread; queue a message to set the value & base value
1057 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1061 void Actor::SetColorGreen( float green )
1065 // mNode is being used in a separate thread; queue a message to set the value & base value
1066 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1070 void Actor::SetColorBlue( float blue )
1074 // mNode is being used in a separate thread; queue a message to set the value & base value
1075 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1079 const Vector4& Actor::GetCurrentColor() const
1083 // mNode is being used in a separate thread; copy the value from the previous update
1084 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1087 return Color::WHITE;
1090 void Actor::SetInheritOrientation( bool inherit )
1092 if( mInheritOrientation != inherit && NULL != mNode)
1094 // non animateable so keep local copy
1095 mInheritOrientation = inherit;
1096 // mNode is being used in a separate thread; queue a message to set the value
1097 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1101 bool Actor::IsOrientationInherited() const
1103 return mInheritOrientation;
1106 void Actor::SetSizeModeFactor( const Vector3& factor )
1108 EnsureRelayoutData();
1110 mRelayoutData->sizeModeFactor = factor;
1113 const Vector3& Actor::GetSizeModeFactor() const
1115 if ( mRelayoutData )
1117 return mRelayoutData->sizeModeFactor;
1120 return GetDefaultSizeModeFactor();
1123 void Actor::SetColorMode( ColorMode colorMode )
1125 // non animateable so keep local copy
1126 mColorMode = colorMode;
1129 // mNode is being used in a separate thread; queue a message to set the value
1130 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1134 ColorMode Actor::GetColorMode() const
1136 // we have cached copy
1140 void Actor::SetSize( float width, float height )
1142 SetSize( Vector2( width, height ) );
1145 void Actor::SetSize( float width, float height, float depth )
1147 SetSize( Vector3( width, height, depth ) );
1150 void Actor::SetSize( const Vector2& size )
1152 SetSize( Vector3( size.width, size.height, 0.f ) );
1155 void Actor::SetSizeInternal( const Vector2& size )
1157 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1160 void Actor::SetSize( const Vector3& size )
1162 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1164 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1165 SetPreferredSize( size.GetVectorXY() );
1169 SetSizeInternal( size );
1173 void Actor::SetSizeInternal( const Vector3& size )
1175 // dont allow recursive loop
1176 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1177 // 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
1178 if( ( NULL != mNode )&&
1179 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1180 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1181 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1185 // mNode is being used in a separate thread; queue a message to set the value & base value
1186 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
1188 // Notification for derived classes
1189 mInsideOnSizeSet = true;
1190 OnSizeSet( mTargetSize );
1191 mInsideOnSizeSet = false;
1193 // Raise a relayout request if the flag is not locked
1194 if( mRelayoutData && !mRelayoutData->insideRelayout )
1201 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1203 mTargetSize = targetSize;
1205 // Notify deriving classes
1206 OnSizeAnimation( animation, mTargetSize );
1209 void Actor::NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property )
1211 if ( Dali::Actor::Property::SIZE_WIDTH == property )
1213 mTargetSize.width = targetSize;
1215 else if ( Dali::Actor::Property::SIZE_HEIGHT == property )
1217 mTargetSize.height = targetSize;
1219 else if ( Dali::Actor::Property::SIZE_DEPTH == property )
1221 mTargetSize.depth = targetSize;
1223 // Notify deriving classes
1224 OnSizeAnimation( animation, mTargetSize );
1227 void Actor::NotifyPositionAnimation( Animation& animation, const Vector3& targetPosition )
1229 mTargetPosition = targetPosition;
1232 void Actor::NotifyPositionAnimation( Animation& animation, float targetPosition, Property::Index property )
1234 if ( Dali::Actor::Property::POSITION_X == property )
1236 mTargetPosition.x = targetPosition;
1238 else if ( Dali::Actor::Property::POSITION_Y == property )
1240 mTargetPosition.y = targetPosition;
1242 else if ( Dali::Actor::Property::POSITION_Z == property )
1244 mTargetPosition.z = targetPosition;
1248 void Actor::SetWidth( float width )
1250 mTargetSize.width = width;
1254 // mNode is being used in a separate thread; queue a message to set the value & base value
1255 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1259 void Actor::SetHeight( float height )
1261 mTargetSize.height = height;
1265 // mNode is being used in a separate thread; queue a message to set the value & base value
1266 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1270 void Actor::SetDepth( float depth )
1272 mTargetSize.depth = depth;
1276 // mNode is being used in a separate thread; queue a message to set the value & base value
1277 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1281 const Vector3& Actor::GetTargetSize() const
1286 const Vector3& Actor::GetCurrentSize() const
1290 // mNode is being used in a separate thread; copy the value from the previous update
1291 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1294 return Vector3::ZERO;
1297 Vector3 Actor::GetNaturalSize() const
1299 // It is up to deriving classes to return the appropriate natural size
1300 return Vector3( 0.0f, 0.0f, 0.0f );
1303 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1305 EnsureRelayoutData();
1307 ResizePolicy::Type originalWidthPolicy = GetResizePolicy(Dimension::WIDTH);
1308 ResizePolicy::Type originalHeightPolicy = GetResizePolicy(Dimension::HEIGHT);
1310 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1312 if( dimension & ( 1 << i ) )
1314 mRelayoutData->resizePolicies[ i ] = policy;
1318 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1320 if( dimension & Dimension::WIDTH )
1322 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1325 if( dimension & Dimension::HEIGHT )
1327 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1331 // If calling SetResizePolicy, assume we want relayout enabled
1332 SetRelayoutEnabled( true );
1334 // If the resize policy is set to be FIXED, the preferred size
1335 // should be overrided by the target size. Otherwise the target
1336 // size should be overrided by the preferred size.
1338 if( dimension & Dimension::WIDTH )
1340 if( originalWidthPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1342 mRelayoutData->preferredSize.width = mTargetSize.width;
1344 else if( originalWidthPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1346 mTargetSize.width = mRelayoutData->preferredSize.width;
1350 if( dimension & Dimension::HEIGHT )
1352 if( originalHeightPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1354 mRelayoutData->preferredSize.height = mTargetSize.height;
1356 else if( originalHeightPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1358 mTargetSize.height = mRelayoutData->preferredSize.height;
1362 OnSetResizePolicy( policy, dimension );
1364 // Trigger relayout on this control
1368 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1370 if ( mRelayoutData )
1372 // If more than one dimension is requested, just return the first one found
1373 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1375 if( ( dimension & ( 1 << i ) ) )
1377 return mRelayoutData->resizePolicies[ i ];
1382 return ResizePolicy::DEFAULT;
1385 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1387 EnsureRelayoutData();
1389 mRelayoutData->sizeSetPolicy = policy;
1392 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1394 if ( mRelayoutData )
1396 return mRelayoutData->sizeSetPolicy;
1399 return DEFAULT_SIZE_SCALE_POLICY;
1402 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1404 EnsureRelayoutData();
1406 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1408 if( dimension & ( 1 << i ) )
1410 mRelayoutData->dimensionDependencies[ i ] = dependency;
1415 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1417 if ( mRelayoutData )
1419 // If more than one dimension is requested, just return the first one found
1420 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1422 if( ( dimension & ( 1 << i ) ) )
1424 return mRelayoutData->dimensionDependencies[ i ];
1429 return Dimension::ALL_DIMENSIONS; // Default
1432 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1434 // If relayout data has not been allocated yet and the client is requesting
1435 // to disable it, do nothing
1436 if( mRelayoutData || relayoutEnabled )
1438 EnsureRelayoutData();
1440 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1442 mRelayoutData->relayoutEnabled = relayoutEnabled;
1446 bool Actor::IsRelayoutEnabled() const
1448 // Assume that if relayout data has not been allocated yet then
1449 // relayout is disabled
1450 return mRelayoutData && mRelayoutData->relayoutEnabled;
1453 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1455 EnsureRelayoutData();
1457 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1459 if( dimension & ( 1 << i ) )
1461 mRelayoutData->dimensionDirty[ i ] = dirty;
1466 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1468 if ( mRelayoutData )
1470 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1472 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1482 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1484 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1487 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1489 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1492 unsigned int Actor::AddRenderer( Renderer& renderer )
1496 mRenderers = new RendererContainer;
1499 unsigned int index = mRenderers->size();
1500 RendererPtr rendererPtr = RendererPtr( &renderer );
1501 mRenderers->push_back( rendererPtr );
1502 AddRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1506 unsigned int Actor::GetRendererCount() const
1508 unsigned int rendererCount(0);
1511 rendererCount = mRenderers->size();
1514 return rendererCount;
1517 RendererPtr Actor::GetRendererAt( unsigned int index )
1519 RendererPtr renderer;
1520 if( index < GetRendererCount() )
1522 renderer = ( *mRenderers )[ index ];
1528 void Actor::RemoveRenderer( Renderer& renderer )
1532 RendererIter end = mRenderers->end();
1533 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1535 if( (*iter).Get() == &renderer )
1537 mRenderers->erase( iter );
1538 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1545 void Actor::RemoveRenderer( unsigned int index )
1547 if( index < GetRendererCount() )
1549 RendererPtr renderer = ( *mRenderers )[ index ];
1550 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.Get()->GetRendererSceneObject() );
1551 mRenderers->erase( mRenderers->begin()+index );
1555 bool Actor::IsOverlay() const
1557 return ( DrawMode::OVERLAY_2D == mDrawMode );
1560 void Actor::SetDrawMode( DrawMode::Type drawMode )
1562 // this flag is not animatable so keep the value
1563 mDrawMode = drawMode;
1564 if( ( NULL != mNode ) && ( drawMode != DrawMode::STENCIL ) )
1566 // mNode is being used in a separate thread; queue a message to set the value
1567 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1571 DrawMode::Type Actor::GetDrawMode() const
1576 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1578 // only valid when on-stage
1579 StagePtr stage = Stage::GetCurrent();
1580 if( stage && OnStage() )
1582 const RenderTaskList& taskList = stage->GetRenderTaskList();
1584 Vector2 converted( screenX, screenY );
1586 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1587 const int taskCount = taskList.GetTaskCount();
1588 for( int i = taskCount - 1; i >= 0; --i )
1590 Dali::RenderTask task = taskList.GetTask( i );
1591 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1593 // found a task where this conversion was ok so return
1601 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1603 bool retval = false;
1604 // only valid when on-stage
1607 CameraActor* camera = renderTask.GetCameraActor();
1611 renderTask.GetViewport( viewport );
1613 // need to translate coordinates to render tasks coordinate space
1614 Vector2 converted( screenX, screenY );
1615 if( renderTask.TranslateCoordinates( converted ) )
1617 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1624 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1626 // Early-out if mNode is NULL
1632 // Get the ModelView matrix
1634 Matrix::Multiply( modelView, mNode->GetWorldMatrix(0), viewMatrix );
1636 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1637 Matrix invertedMvp( false/*don't init*/);
1638 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1639 bool success = invertedMvp.Invert();
1641 // Convert to GL coordinates
1642 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1647 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1654 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1660 if( XyPlaneIntersect( nearPos, farPos, local ) )
1662 Vector3 size = GetCurrentSize();
1663 localX = local.x + size.x * 0.5f;
1664 localY = local.y + size.y * 0.5f;
1675 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1678 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1680 Mathematical Formulation
1682 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1684 ( p - c ) dot ( p - c ) = r^2
1686 Given a ray with a point of origin 'o', and a direction vector 'd':
1688 ray(t) = o + td, t >= 0
1690 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1692 (o + td - c ) dot ( o + td - c ) = r^2
1694 To solve for t we first expand the above into a more recognisable quadratic equation form
1696 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1705 B = 2( o - c ) dot d
1706 C = ( o - c ) dot ( o - c ) - r^2
1708 which can be solved using a standard quadratic formula.
1710 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1712 Practical Simplification
1714 In a renderer, we often differentiate between world space and object space. In the object space
1715 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1716 into object space, the mathematical solution presented above can be simplified significantly.
1718 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1722 and we can find the t at which the (transformed) ray intersects the sphere by
1724 ( o + td ) dot ( o + td ) = r^2
1726 According to the reasoning above, we expand the above quadratic equation into the general form
1730 which now has coefficients:
1737 // Early out if mNode is NULL
1743 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1745 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1746 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1747 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1749 // Compute the radius is not needed, square radius it's enough.
1750 const Vector3& size( mNode->GetSize( bufferIndex ) );
1752 // Scale the sphere.
1753 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1755 const float width = size.width * scale.width;
1756 const float height = size.height * scale.height;
1758 float squareSphereRadius = 0.5f * ( width * width + height * height );
1760 float a = rayDir.Dot( rayDir ); // a
1761 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1762 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1764 return ( b2 * b2 - a * c ) >= 0.f;
1767 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector2& hitPointLocal, float& distance ) const
1771 if( OnStage() && NULL != mNode )
1773 // Transforms the ray to the local reference system.
1774 // Calculate the inverse of Model matrix
1775 Matrix invModelMatrix( false/*don't init*/);
1777 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1778 invModelMatrix = mNode->GetWorldMatrix(0);
1779 invModelMatrix.Invert();
1781 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1782 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1784 // Test with the actor's XY plane (Normal = 0 0 1 1).
1786 float a = -rayOriginLocal.z;
1787 float b = rayDirLocal.z;
1789 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1791 // Ray travels distance * rayDirLocal to intersect with plane.
1794 const Vector3& size = mNode->GetSize( bufferIndex );
1796 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1797 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1799 // Test with the actor's geometry.
1800 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1807 void Actor::SetLeaveRequired( bool required )
1809 mLeaveRequired = required;
1812 bool Actor::GetLeaveRequired() const
1814 return mLeaveRequired;
1817 void Actor::SetKeyboardFocusable( bool focusable )
1819 mKeyboardFocusable = focusable;
1822 bool Actor::IsKeyboardFocusable() const
1824 return mKeyboardFocusable;
1827 bool Actor::GetTouchRequired() const
1829 return !mTouchedSignal.Empty() || !mTouchSignal.Empty() || mDerivedRequiresTouch;
1832 bool Actor::GetHoverRequired() const
1834 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1837 bool Actor::GetWheelEventRequired() const
1839 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1842 bool Actor::IsHittable() const
1844 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1847 ActorGestureData& Actor::GetGestureData()
1849 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1850 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1851 if( NULL == mGestureData )
1853 mGestureData = new ActorGestureData;
1855 return *mGestureData;
1858 bool Actor::IsGestureRequred( Gesture::Type type ) const
1860 return mGestureData && mGestureData->IsGestureRequred( type );
1863 bool Actor::EmitTouchEventSignal( const TouchEvent& event, const Dali::TouchData& touch )
1865 bool consumed = false;
1867 if( !mTouchSignal.Empty() )
1869 Dali::Actor handle( this );
1870 consumed = mTouchSignal.Emit( handle, touch );
1873 if( !mTouchedSignal.Empty() )
1875 Dali::Actor handle( this );
1876 consumed |= mTouchedSignal.Emit( handle, event );
1881 // Notification for derived classes
1882 consumed = OnTouchEvent( event ); // TODO
1888 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1890 bool consumed = false;
1892 if( !mHoveredSignal.Empty() )
1894 Dali::Actor handle( this );
1895 consumed = mHoveredSignal.Emit( handle, event );
1900 // Notification for derived classes
1901 consumed = OnHoverEvent( event );
1907 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1909 bool consumed = false;
1911 if( !mWheelEventSignal.Empty() )
1913 Dali::Actor handle( this );
1914 consumed = mWheelEventSignal.Emit( handle, event );
1919 // Notification for derived classes
1920 consumed = OnWheelEvent( event );
1926 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
1928 return mTouchedSignal;
1931 Dali::Actor::TouchDataSignalType& Actor::TouchSignal()
1933 return mTouchSignal;
1936 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
1938 return mHoveredSignal;
1941 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
1943 return mWheelEventSignal;
1946 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
1948 return mOnStageSignal;
1951 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
1953 return mOffStageSignal;
1956 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
1958 return mOnRelayoutSignal;
1961 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1963 bool connected( true );
1964 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
1966 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1968 actor->TouchedSignal().Connect( tracker, functor );
1970 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1972 actor->HoveredSignal().Connect( tracker, functor );
1974 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1976 actor->WheelEventSignal().Connect( tracker, functor );
1978 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
1980 actor->OnStageSignal().Connect( tracker, functor );
1982 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
1984 actor->OffStageSignal().Connect( tracker, functor );
1986 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
1988 actor->OnRelayoutSignal().Connect( tracker, functor );
1990 else if( 0 == signalName.compare( SIGNAL_TOUCH ) )
1992 actor->TouchSignal().Connect( tracker, functor );
1996 // signalName does not match any signal
2003 Actor::Actor( DerivedType derivedType )
2008 mParentOrigin( NULL ),
2009 mAnchorPoint( NULL ),
2010 mRelayoutData( NULL ),
2011 mGestureData( NULL ),
2012 mTargetSize( 0.0f, 0.0f, 0.0f ),
2014 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
2017 mIsRoot( ROOT_LAYER == derivedType ),
2018 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2019 mIsOnStage( false ),
2021 mLeaveRequired( false ),
2022 mKeyboardFocusable( false ),
2023 mDerivedRequiresTouch( false ),
2024 mDerivedRequiresHover( false ),
2025 mDerivedRequiresWheelEvent( false ),
2026 mOnStageSignalled( false ),
2027 mInsideOnSizeSet( false ),
2028 mInheritPosition( true ),
2029 mInheritOrientation( true ),
2030 mInheritScale( true ),
2031 mDrawMode( DrawMode::NORMAL ),
2032 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2033 mColorMode( Node::DEFAULT_COLOR_MODE ),
2034 mClippingMode( ClippingMode::DISABLED )
2038 void Actor::Initialize()
2041 SceneGraph::Node* node = CreateNode();
2043 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
2044 mNode = node; // Keep raw-pointer to Node
2048 GetEventThreadServices().RegisterObject( this );
2053 // Remove mParent pointers from children even if we're destroying core,
2054 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2057 ActorConstIter endIter = mChildren->end();
2058 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2060 (*iter)->SetParent( NULL );
2066 // Guard to allow handle destruction after Core has been destroyed
2067 if( EventThreadServices::IsCoreRunning() )
2071 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2072 mNode = NULL; // Node is about to be destroyed
2075 GetEventThreadServices().UnregisterObject( this );
2078 // Cleanup optional gesture data
2079 delete mGestureData;
2081 // Cleanup optional parent origin and anchor
2082 delete mParentOrigin;
2083 delete mAnchorPoint;
2085 // Delete optional relayout data
2088 delete mRelayoutData;
2092 void Actor::ConnectToStage( unsigned int parentDepth )
2094 // This container is used instead of walking the Actor hierarchy.
2095 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
2096 ActorContainer connectionList;
2098 // This stage is atomic i.e. not interrupted by user callbacks.
2099 RecursiveConnectToStage( connectionList, parentDepth + 1 );
2101 // Notify applications about the newly connected actors.
2102 const ActorIter endIter = connectionList.end();
2103 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2105 (*iter)->NotifyStageConnection();
2111 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth )
2113 DALI_ASSERT_ALWAYS( !OnStage() );
2117 SetDepthIndexMessage( GetEventThreadServices(), *mNode, GetDepthIndex( mDepth, mSiblingOrder ) );
2119 ConnectToSceneGraph();
2121 // Notification for internal derived classes
2122 OnStageConnectionInternal();
2124 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2125 connectionList.push_back( ActorPtr( this ) );
2127 // Recursively connect children
2130 ActorConstIter endIter = mChildren->end();
2131 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2133 (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
2139 * This method is called when the Actor is connected to the Stage.
2140 * The parent must have added its Node to the scene-graph.
2141 * The child must connect its Node to the parent's Node.
2142 * This is recursive; the child calls ConnectToStage() for its children.
2144 void Actor::ConnectToSceneGraph()
2146 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2150 // Reparent Node in next Update
2151 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode );
2154 // Request relayout on all actors that are added to the scenegraph
2157 // Notification for Object::Observers
2161 void Actor::NotifyStageConnection()
2163 // Actors can be removed (in a callback), before the on-stage stage is reported.
2164 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2165 if( OnStage() && !mOnStageSignalled )
2167 // Notification for external (CustomActor) derived classes
2168 OnStageConnectionExternal( mDepth );
2170 if( !mOnStageSignal.Empty() )
2172 Dali::Actor handle( this );
2173 mOnStageSignal.Emit( handle );
2176 // Guard against Remove during callbacks
2179 mOnStageSignalled = true; // signal required next time Actor is removed
2184 void Actor::DisconnectFromStage()
2186 // This container is used instead of walking the Actor hierachy.
2187 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2188 ActorContainer disconnectionList;
2190 // This stage is atomic i.e. not interrupted by user callbacks
2191 RecursiveDisconnectFromStage( disconnectionList );
2193 // Notify applications about the newly disconnected actors.
2194 const ActorIter endIter = disconnectionList.end();
2195 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2197 (*iter)->NotifyStageDisconnection();
2201 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2203 DALI_ASSERT_ALWAYS( OnStage() );
2205 // Recursively disconnect children
2208 ActorConstIter endIter = mChildren->end();
2209 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2211 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2215 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2216 disconnectionList.push_back( ActorPtr( this ) );
2218 // Notification for internal derived classes
2219 OnStageDisconnectionInternal();
2221 DisconnectFromSceneGraph();
2227 * This method is called by an actor or its parent, before a node removal message is sent.
2228 * This is recursive; the child calls DisconnectFromStage() for its children.
2230 void Actor::DisconnectFromSceneGraph()
2232 // Notification for Object::Observers
2233 OnSceneObjectRemove();
2236 void Actor::NotifyStageDisconnection()
2238 // Actors can be added (in a callback), before the off-stage state is reported.
2239 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2240 // only do this step if there is a stage, i.e. Core is not being shut down
2241 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2243 // Notification for external (CustomeActor) derived classes
2244 OnStageDisconnectionExternal();
2246 if( !mOffStageSignal.Empty() )
2248 Dali::Actor handle( this );
2249 mOffStageSignal.Emit( handle );
2252 // Guard against Add during callbacks
2255 mOnStageSignalled = false; // signal required next time Actor is added
2260 bool Actor::IsNodeConnected() const
2262 bool connected( false );
2264 if( OnStage() && ( NULL != mNode ) )
2266 if( IsRoot() || mNode->GetParent() )
2275 unsigned int Actor::GetDefaultPropertyCount() const
2277 return DEFAULT_PROPERTY_COUNT;
2280 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2282 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2284 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2286 indices.PushBack( i );
2290 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2292 if( index < DEFAULT_PROPERTY_COUNT )
2294 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2300 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2302 Property::Index index = Property::INVALID_INDEX;
2304 // Look for name in default properties
2305 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2307 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2308 if( 0 == name.compare( property->name ) )
2318 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2320 if( index < DEFAULT_PROPERTY_COUNT )
2322 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2328 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2330 if( index < DEFAULT_PROPERTY_COUNT )
2332 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2338 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2340 if( index < DEFAULT_PROPERTY_COUNT )
2342 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2348 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2350 if( index < DEFAULT_PROPERTY_COUNT )
2352 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2355 // index out of range...return Property::NONE
2356 return Property::NONE;
2359 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2363 case Dali::Actor::Property::PARENT_ORIGIN:
2365 Property::Type type = property.GetType();
2366 if( type == Property::VECTOR3 )
2368 SetParentOrigin( property.Get< Vector3 >() );
2370 else if ( type == Property::STRING )
2372 std::string parentOriginString;
2373 property.Get( parentOriginString );
2374 Vector3 parentOrigin;
2375 if( GetParentOriginConstant( parentOriginString, parentOrigin ) )
2377 SetParentOrigin( parentOrigin );
2383 case Dali::Actor::Property::PARENT_ORIGIN_X:
2385 SetParentOriginX( property.Get< float >() );
2389 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2391 SetParentOriginY( property.Get< float >() );
2395 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2397 SetParentOriginZ( property.Get< float >() );
2401 case Dali::Actor::Property::ANCHOR_POINT:
2403 Property::Type type = property.GetType();
2404 if( type == Property::VECTOR3 )
2406 SetAnchorPoint( property.Get< Vector3 >() );
2408 else if ( type == Property::STRING )
2410 std::string anchorPointString;
2411 property.Get( anchorPointString );
2413 if( GetAnchorPointConstant( anchorPointString, anchor ) )
2415 SetAnchorPoint( anchor );
2421 case Dali::Actor::Property::ANCHOR_POINT_X:
2423 SetAnchorPointX( property.Get< float >() );
2427 case Dali::Actor::Property::ANCHOR_POINT_Y:
2429 SetAnchorPointY( property.Get< float >() );
2433 case Dali::Actor::Property::ANCHOR_POINT_Z:
2435 SetAnchorPointZ( property.Get< float >() );
2439 case Dali::Actor::Property::SIZE:
2441 SetSize( property.Get< Vector3 >() );
2445 case Dali::Actor::Property::SIZE_WIDTH:
2447 SetWidth( property.Get< float >() );
2451 case Dali::Actor::Property::SIZE_HEIGHT:
2453 SetHeight( property.Get< float >() );
2457 case Dali::Actor::Property::SIZE_DEPTH:
2459 SetDepth( property.Get< float >() );
2463 case Dali::Actor::Property::POSITION:
2465 SetPosition( property.Get< Vector3 >() );
2469 case Dali::Actor::Property::POSITION_X:
2471 SetX( property.Get< float >() );
2475 case Dali::Actor::Property::POSITION_Y:
2477 SetY( property.Get< float >() );
2481 case Dali::Actor::Property::POSITION_Z:
2483 SetZ( property.Get< float >() );
2487 case Dali::Actor::Property::ORIENTATION:
2489 SetOrientation( property.Get< Quaternion >() );
2493 case Dali::Actor::Property::SCALE:
2495 SetScale( property.Get< Vector3 >() );
2499 case Dali::Actor::Property::SCALE_X:
2501 SetScaleX( property.Get< float >() );
2505 case Dali::Actor::Property::SCALE_Y:
2507 SetScaleY( property.Get< float >() );
2511 case Dali::Actor::Property::SCALE_Z:
2513 SetScaleZ( property.Get< float >() );
2517 case Dali::Actor::Property::VISIBLE:
2519 SetVisible( property.Get< bool >() );
2523 case Dali::Actor::Property::COLOR:
2525 SetColor( property.Get< Vector4 >() );
2529 case Dali::Actor::Property::COLOR_RED:
2531 SetColorRed( property.Get< float >() );
2535 case Dali::Actor::Property::COLOR_GREEN:
2537 SetColorGreen( property.Get< float >() );
2541 case Dali::Actor::Property::COLOR_BLUE:
2543 SetColorBlue( property.Get< float >() );
2547 case Dali::Actor::Property::COLOR_ALPHA:
2548 case Dali::DevelActor::Property::OPACITY:
2551 if( property.Get( value ) )
2553 SetOpacity( value );
2558 case Dali::Actor::Property::NAME:
2560 SetName( property.Get< std::string >() );
2564 case Dali::Actor::Property::SENSITIVE:
2566 SetSensitive( property.Get< bool >() );
2570 case Dali::Actor::Property::LEAVE_REQUIRED:
2572 SetLeaveRequired( property.Get< bool >() );
2576 case Dali::Actor::Property::INHERIT_POSITION:
2578 SetInheritPosition( property.Get< bool >() );
2582 case Dali::Actor::Property::INHERIT_ORIENTATION:
2584 SetInheritOrientation( property.Get< bool >() );
2588 case Dali::Actor::Property::INHERIT_SCALE:
2590 SetInheritScale( property.Get< bool >() );
2594 case Dali::Actor::Property::COLOR_MODE:
2596 ColorMode mode = mColorMode;
2597 if ( Scripting::GetEnumerationProperty< ColorMode >( property, COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT, mode ) )
2599 SetColorMode( mode );
2604 case Dali::Actor::Property::POSITION_INHERITANCE:
2606 PositionInheritanceMode mode = mPositionInheritanceMode;
2607 if( Scripting::GetEnumerationProperty< PositionInheritanceMode >( property, POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT, mode ) )
2609 SetPositionInheritanceMode( mode );
2614 case Dali::Actor::Property::DRAW_MODE:
2616 DrawMode::Type mode = mDrawMode;
2617 if( Scripting::GetEnumerationProperty< DrawMode::Type >( property, DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT, mode ) )
2619 SetDrawMode( mode );
2624 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2626 SetSizeModeFactor( property.Get< Vector3 >() );
2630 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2632 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
2633 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2635 SetResizePolicy( type, Dimension::WIDTH );
2640 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2642 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
2643 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2645 SetResizePolicy( type, Dimension::HEIGHT );
2650 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2652 SizeScalePolicy::Type type;
2653 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT, type ) )
2655 SetSizeScalePolicy( type );
2660 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2662 if( property.Get< bool >() )
2664 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2669 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2671 if( property.Get< bool >() )
2673 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2678 case Dali::Actor::Property::PADDING:
2680 Vector4 padding = property.Get< Vector4 >();
2681 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2682 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2686 case Dali::Actor::Property::MINIMUM_SIZE:
2688 Vector2 size = property.Get< Vector2 >();
2689 SetMinimumSize( size.x, Dimension::WIDTH );
2690 SetMinimumSize( size.y, Dimension::HEIGHT );
2694 case Dali::Actor::Property::MAXIMUM_SIZE:
2696 Vector2 size = property.Get< Vector2 >();
2697 SetMaximumSize( size.x, Dimension::WIDTH );
2698 SetMaximumSize( size.y, Dimension::HEIGHT );
2702 case Dali::DevelActor::Property::SIBLING_ORDER:
2706 if( property.Get( value ) )
2708 if( static_cast<unsigned int>(value) != mSiblingOrder )
2710 SetSiblingOrder( value );
2716 case Dali::Actor::Property::CLIPPING_MODE:
2718 ClippingMode::Type convertedValue = mClippingMode;
2719 if( Scripting::GetEnumerationProperty< ClippingMode::Type >( property, CLIPPING_MODE_TABLE, CLIPPING_MODE_TABLE_COUNT, convertedValue ) )
2721 mClippingMode = convertedValue;
2724 SetClippingModeMessage( GetEventThreadServices(), *mNode, mClippingMode );
2732 // this can happen in the case of a non-animatable default property so just do nothing
2738 // TODO: This method needs to be removed
2739 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2741 switch( entry.GetType() )
2743 case Property::BOOLEAN:
2745 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2746 DALI_ASSERT_DEBUG( NULL != property );
2748 // property is being used in a separate thread; queue a message to set the property
2749 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2754 case Property::INTEGER:
2756 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2757 DALI_ASSERT_DEBUG( NULL != property );
2759 // property is being used in a separate thread; queue a message to set the property
2760 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2765 case Property::FLOAT:
2767 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2768 DALI_ASSERT_DEBUG( NULL != property );
2770 // property is being used in a separate thread; queue a message to set the property
2771 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2776 case Property::VECTOR2:
2778 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2779 DALI_ASSERT_DEBUG( NULL != property );
2781 // property is being used in a separate thread; queue a message to set the property
2782 if(entry.componentIndex == 0)
2784 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2786 else if(entry.componentIndex == 1)
2788 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2792 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2798 case Property::VECTOR3:
2800 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2801 DALI_ASSERT_DEBUG( NULL != property );
2803 // property is being used in a separate thread; queue a message to set the property
2804 if(entry.componentIndex == 0)
2806 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2808 else if(entry.componentIndex == 1)
2810 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2812 else if(entry.componentIndex == 2)
2814 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2818 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2824 case Property::VECTOR4:
2826 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2827 DALI_ASSERT_DEBUG( NULL != property );
2829 // property is being used in a separate thread; queue a message to set the property
2830 if(entry.componentIndex == 0)
2832 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
2834 else if(entry.componentIndex == 1)
2836 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
2838 else if(entry.componentIndex == 2)
2840 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
2842 else if(entry.componentIndex == 3)
2844 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
2848 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2854 case Property::ROTATION:
2856 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
2857 DALI_ASSERT_DEBUG( NULL != property );
2859 // property is being used in a separate thread; queue a message to set the property
2860 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
2865 case Property::MATRIX:
2867 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
2868 DALI_ASSERT_DEBUG( NULL != property );
2870 // property is being used in a separate thread; queue a message to set the property
2871 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
2876 case Property::MATRIX3:
2878 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
2879 DALI_ASSERT_DEBUG( NULL != property );
2881 // property is being used in a separate thread; queue a message to set the property
2882 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
2889 // nothing to do for other types
2894 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
2896 Property::Value value;
2898 if( index >= DEFAULT_PROPERTY_COUNT )
2905 case Dali::Actor::Property::PARENT_ORIGIN:
2907 value = GetCurrentParentOrigin();
2911 case Dali::Actor::Property::PARENT_ORIGIN_X:
2913 value = GetCurrentParentOrigin().x;
2917 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2919 value = GetCurrentParentOrigin().y;
2923 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2925 value = GetCurrentParentOrigin().z;
2929 case Dali::Actor::Property::ANCHOR_POINT:
2931 value = GetCurrentAnchorPoint();
2935 case Dali::Actor::Property::ANCHOR_POINT_X:
2937 value = GetCurrentAnchorPoint().x;
2941 case Dali::Actor::Property::ANCHOR_POINT_Y:
2943 value = GetCurrentAnchorPoint().y;
2947 case Dali::Actor::Property::ANCHOR_POINT_Z:
2949 value = GetCurrentAnchorPoint().z;
2953 case Dali::Actor::Property::SIZE:
2955 Vector3 size = GetTargetSize();
2957 // Should return preferred size if size is fixed as set by SetSize
2958 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
2960 size.width = GetPreferredSize().width;
2962 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
2964 size.height = GetPreferredSize().height;
2972 case Dali::Actor::Property::SIZE_WIDTH:
2974 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
2976 // Should return preferred size if size is fixed as set by SetSize
2977 value = GetPreferredSize().width;
2981 value = GetTargetSize().width;
2986 case Dali::Actor::Property::SIZE_HEIGHT:
2988 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
2990 // Should return preferred size if size is fixed as set by SetSize
2991 value = GetPreferredSize().height;
2995 value = GetTargetSize().height;
3000 case Dali::Actor::Property::SIZE_DEPTH:
3002 value = GetTargetSize().depth;
3006 case Dali::Actor::Property::POSITION:
3008 value = GetTargetPosition();
3012 case Dali::Actor::Property::POSITION_X:
3014 value = GetTargetPosition().x;
3018 case Dali::Actor::Property::POSITION_Y:
3020 value = GetTargetPosition().y;
3024 case Dali::Actor::Property::POSITION_Z:
3026 value = GetTargetPosition().z;
3030 case Dali::Actor::Property::WORLD_POSITION:
3032 value = GetCurrentWorldPosition();
3036 case Dali::Actor::Property::WORLD_POSITION_X:
3038 value = GetCurrentWorldPosition().x;
3042 case Dali::Actor::Property::WORLD_POSITION_Y:
3044 value = GetCurrentWorldPosition().y;
3048 case Dali::Actor::Property::WORLD_POSITION_Z:
3050 value = GetCurrentWorldPosition().z;
3054 case Dali::Actor::Property::ORIENTATION:
3056 value = GetCurrentOrientation();
3060 case Dali::Actor::Property::WORLD_ORIENTATION:
3062 value = GetCurrentWorldOrientation();
3066 case Dali::Actor::Property::SCALE:
3068 value = GetCurrentScale();
3072 case Dali::Actor::Property::SCALE_X:
3074 value = GetCurrentScale().x;
3078 case Dali::Actor::Property::SCALE_Y:
3080 value = GetCurrentScale().y;
3084 case Dali::Actor::Property::SCALE_Z:
3086 value = GetCurrentScale().z;
3090 case Dali::Actor::Property::WORLD_SCALE:
3092 value = GetCurrentWorldScale();
3096 case Dali::Actor::Property::VISIBLE:
3098 value = IsVisible();
3102 case Dali::Actor::Property::COLOR:
3104 value = GetCurrentColor();
3108 case Dali::Actor::Property::COLOR_RED:
3110 value = GetCurrentColor().r;
3114 case Dali::Actor::Property::COLOR_GREEN:
3116 value = GetCurrentColor().g;
3120 case Dali::Actor::Property::COLOR_BLUE:
3122 value = GetCurrentColor().b;
3126 case Dali::Actor::Property::COLOR_ALPHA:
3127 case Dali::DevelActor::Property::OPACITY:
3129 value = GetCurrentColor().a;
3133 case Dali::Actor::Property::WORLD_COLOR:
3135 value = GetCurrentWorldColor();
3139 case Dali::Actor::Property::WORLD_MATRIX:
3141 value = GetCurrentWorldMatrix();
3145 case Dali::Actor::Property::NAME:
3151 case Dali::Actor::Property::SENSITIVE:
3153 value = IsSensitive();
3157 case Dali::Actor::Property::LEAVE_REQUIRED:
3159 value = GetLeaveRequired();
3163 case Dali::Actor::Property::INHERIT_POSITION:
3165 value = IsPositionInherited();
3169 case Dali::Actor::Property::INHERIT_ORIENTATION:
3171 value = IsOrientationInherited();
3175 case Dali::Actor::Property::INHERIT_SCALE:
3177 value = IsScaleInherited();
3181 case Dali::Actor::Property::COLOR_MODE:
3183 value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
3187 case Dali::Actor::Property::POSITION_INHERITANCE:
3189 value = Scripting::GetLinearEnumerationName< PositionInheritanceMode >( GetPositionInheritanceMode(), POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT );
3193 case Dali::Actor::Property::DRAW_MODE:
3195 value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
3199 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3201 value = GetSizeModeFactor();
3205 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3207 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3211 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3213 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3217 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3219 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT );
3223 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3225 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3229 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3231 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3235 case Dali::Actor::Property::PADDING:
3237 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3238 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3239 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3243 case Dali::Actor::Property::MINIMUM_SIZE:
3245 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3249 case Dali::Actor::Property::MAXIMUM_SIZE:
3251 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3255 case Dali::DevelActor::Property::SIBLING_ORDER:
3257 value = static_cast<int>(mSiblingOrder);
3261 case Dali::Actor::Property::CLIPPING_MODE:
3263 value = mClippingMode;
3271 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3276 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3278 // This method should only return an object connected to the scene-graph
3279 return OnStage() ? mNode : NULL;
3282 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3284 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3286 const PropertyBase* property( NULL );
3288 // This method should only return a property of an object connected to the scene-graph
3294 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3296 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3297 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3299 property = animatable->GetSceneGraphProperty();
3301 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3302 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3304 CustomPropertyMetadata* custom = FindCustomProperty( index );
3305 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3307 property = custom->GetSceneGraphProperty();
3309 else if( NULL != mNode )
3313 case Dali::Actor::Property::SIZE:
3314 property = &mNode->mSize;
3317 case Dali::Actor::Property::SIZE_WIDTH:
3318 property = &mNode->mSize;
3321 case Dali::Actor::Property::SIZE_HEIGHT:
3322 property = &mNode->mSize;
3325 case Dali::Actor::Property::SIZE_DEPTH:
3326 property = &mNode->mSize;
3329 case Dali::Actor::Property::POSITION:
3330 property = &mNode->mPosition;
3333 case Dali::Actor::Property::POSITION_X:
3334 property = &mNode->mPosition;
3337 case Dali::Actor::Property::POSITION_Y:
3338 property = &mNode->mPosition;
3341 case Dali::Actor::Property::POSITION_Z:
3342 property = &mNode->mPosition;
3345 case Dali::Actor::Property::ORIENTATION:
3346 property = &mNode->mOrientation;
3349 case Dali::Actor::Property::SCALE:
3350 property = &mNode->mScale;
3353 case Dali::Actor::Property::SCALE_X:
3354 property = &mNode->mScale;
3357 case Dali::Actor::Property::SCALE_Y:
3358 property = &mNode->mScale;
3361 case Dali::Actor::Property::SCALE_Z:
3362 property = &mNode->mScale;
3365 case Dali::Actor::Property::VISIBLE:
3366 property = &mNode->mVisible;
3369 case Dali::Actor::Property::COLOR:
3370 property = &mNode->mColor;
3373 case Dali::Actor::Property::COLOR_RED:
3374 property = &mNode->mColor;
3377 case Dali::Actor::Property::COLOR_GREEN:
3378 property = &mNode->mColor;
3381 case Dali::Actor::Property::COLOR_BLUE:
3382 property = &mNode->mColor;
3385 case Dali::Actor::Property::COLOR_ALPHA:
3386 case Dali::DevelActor::Property::OPACITY:
3387 property = &mNode->mColor;
3398 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3400 const PropertyInputImpl* property( NULL );
3402 // This method should only return a property of an object connected to the scene-graph
3408 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3410 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3411 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3413 property = animatable->GetSceneGraphProperty();
3415 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3416 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3418 CustomPropertyMetadata* custom = FindCustomProperty( index );
3419 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3420 property = custom->GetSceneGraphProperty();
3422 else if( NULL != mNode )
3426 case Dali::Actor::Property::PARENT_ORIGIN:
3427 property = &mNode->mParentOrigin;
3430 case Dali::Actor::Property::PARENT_ORIGIN_X:
3431 property = &mNode->mParentOrigin;
3434 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3435 property = &mNode->mParentOrigin;
3438 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3439 property = &mNode->mParentOrigin;
3442 case Dali::Actor::Property::ANCHOR_POINT:
3443 property = &mNode->mAnchorPoint;
3446 case Dali::Actor::Property::ANCHOR_POINT_X:
3447 property = &mNode->mAnchorPoint;
3450 case Dali::Actor::Property::ANCHOR_POINT_Y:
3451 property = &mNode->mAnchorPoint;
3454 case Dali::Actor::Property::ANCHOR_POINT_Z:
3455 property = &mNode->mAnchorPoint;
3458 case Dali::Actor::Property::SIZE:
3459 property = &mNode->mSize;
3462 case Dali::Actor::Property::SIZE_WIDTH:
3463 property = &mNode->mSize;
3466 case Dali::Actor::Property::SIZE_HEIGHT:
3467 property = &mNode->mSize;
3470 case Dali::Actor::Property::SIZE_DEPTH:
3471 property = &mNode->mSize;
3474 case Dali::Actor::Property::POSITION:
3475 property = &mNode->mPosition;
3478 case Dali::Actor::Property::POSITION_X:
3479 property = &mNode->mPosition;
3482 case Dali::Actor::Property::POSITION_Y:
3483 property = &mNode->mPosition;
3486 case Dali::Actor::Property::POSITION_Z:
3487 property = &mNode->mPosition;
3490 case Dali::Actor::Property::WORLD_POSITION:
3491 property = &mNode->mWorldPosition;
3494 case Dali::Actor::Property::WORLD_POSITION_X:
3495 property = &mNode->mWorldPosition;
3498 case Dali::Actor::Property::WORLD_POSITION_Y:
3499 property = &mNode->mWorldPosition;
3502 case Dali::Actor::Property::WORLD_POSITION_Z:
3503 property = &mNode->mWorldPosition;
3506 case Dali::Actor::Property::ORIENTATION:
3507 property = &mNode->mOrientation;
3510 case Dali::Actor::Property::WORLD_ORIENTATION:
3511 property = &mNode->mWorldOrientation;
3514 case Dali::Actor::Property::SCALE:
3515 property = &mNode->mScale;
3518 case Dali::Actor::Property::SCALE_X:
3519 property = &mNode->mScale;
3522 case Dali::Actor::Property::SCALE_Y:
3523 property = &mNode->mScale;
3526 case Dali::Actor::Property::SCALE_Z:
3527 property = &mNode->mScale;
3530 case Dali::Actor::Property::WORLD_SCALE:
3531 property = &mNode->mWorldScale;
3534 case Dali::Actor::Property::VISIBLE:
3535 property = &mNode->mVisible;
3538 case Dali::Actor::Property::COLOR:
3539 property = &mNode->mColor;
3542 case Dali::Actor::Property::COLOR_RED:
3543 property = &mNode->mColor;
3546 case Dali::Actor::Property::COLOR_GREEN:
3547 property = &mNode->mColor;
3550 case Dali::Actor::Property::COLOR_BLUE:
3551 property = &mNode->mColor;
3554 case Dali::Actor::Property::COLOR_ALPHA:
3555 case Dali::DevelActor::Property::OPACITY:
3557 property = &mNode->mColor;
3561 case Dali::Actor::Property::WORLD_COLOR:
3562 property = &mNode->mWorldColor;
3565 case Dali::Actor::Property::WORLD_MATRIX:
3566 property = &mNode->mWorldMatrix;
3577 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3579 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3581 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3583 // check whether the animatable property is registered already, if not then register one.
3584 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3585 if( animatableProperty )
3587 componentIndex = animatableProperty->componentIndex;
3594 case Dali::Actor::Property::PARENT_ORIGIN_X:
3595 case Dali::Actor::Property::ANCHOR_POINT_X:
3596 case Dali::Actor::Property::SIZE_WIDTH:
3597 case Dali::Actor::Property::POSITION_X:
3598 case Dali::Actor::Property::WORLD_POSITION_X:
3599 case Dali::Actor::Property::SCALE_X:
3600 case Dali::Actor::Property::COLOR_RED:
3606 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3607 case Dali::Actor::Property::ANCHOR_POINT_Y:
3608 case Dali::Actor::Property::SIZE_HEIGHT:
3609 case Dali::Actor::Property::POSITION_Y:
3610 case Dali::Actor::Property::WORLD_POSITION_Y:
3611 case Dali::Actor::Property::SCALE_Y:
3612 case Dali::Actor::Property::COLOR_GREEN:
3618 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3619 case Dali::Actor::Property::ANCHOR_POINT_Z:
3620 case Dali::Actor::Property::SIZE_DEPTH:
3621 case Dali::Actor::Property::POSITION_Z:
3622 case Dali::Actor::Property::WORLD_POSITION_Z:
3623 case Dali::Actor::Property::SCALE_Z:
3624 case Dali::Actor::Property::COLOR_BLUE:
3630 case Dali::Actor::Property::COLOR_ALPHA:
3631 case Dali::DevelActor::Property::OPACITY:
3645 return componentIndex;
3648 void Actor::SetParent( Actor* parent )
3652 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3656 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3659 // Instruct each actor to create a corresponding node in the scene graph
3660 ConnectToStage( parent->GetHierarchyDepth() );
3663 // Resolve the name and index for the child properties if any
3664 ResolveChildProperties();
3666 else // parent being set to NULL
3668 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3672 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3675 DALI_ASSERT_ALWAYS( mNode != NULL );
3679 // Disconnect the Node & its children from the scene-graph.
3680 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3683 // Instruct each actor to discard pointers to the scene-graph
3684 DisconnectFromStage();
3689 SceneGraph::Node* Actor::CreateNode() const
3694 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3697 Actor* actor = dynamic_cast< Actor* >( object );
3701 if( 0 == actionName.compare( ACTION_SHOW ) )
3703 actor->SetVisible( true );
3706 else if( 0 == actionName.compare( ACTION_HIDE ) )
3708 actor->SetVisible( false );
3716 void Actor::EnsureRelayoutData()
3718 // Assign relayout data.
3719 if( !mRelayoutData )
3721 mRelayoutData = new RelayoutData();
3725 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3727 // Check if actor is dependent on parent
3728 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3730 if( ( dimension & ( 1 << i ) ) )
3732 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3733 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3743 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3745 // Check if actor is dependent on children
3746 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3748 if( ( dimension & ( 1 << i ) ) )
3750 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3751 switch( resizePolicy )
3753 case ResizePolicy::FIT_TO_CHILDREN:
3754 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3770 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3772 return Actor::RelayoutDependentOnChildren( dimension );
3775 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3777 // Check each possible dimension and see if it is dependent on the input one
3778 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3780 if( dimension & ( 1 << i ) )
3782 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3789 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3791 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3793 if( dimension & ( 1 << i ) )
3795 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3800 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3802 // If more than one dimension is requested, just return the first one found
3803 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3805 if( ( dimension & ( 1 << i ) ) )
3807 return mRelayoutData->negotiatedDimensions[ i ];
3811 return 0.0f; // Default
3814 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3816 EnsureRelayoutData();
3818 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3820 if( dimension & ( 1 << i ) )
3822 mRelayoutData->dimensionPadding[ i ] = padding;
3827 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3829 if ( mRelayoutData )
3831 // If more than one dimension is requested, just return the first one found
3832 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3834 if( ( dimension & ( 1 << i ) ) )
3836 return mRelayoutData->dimensionPadding[ i ];
3841 return GetDefaultDimensionPadding();
3844 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
3846 EnsureRelayoutData();
3848 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3850 if( dimension & ( 1 << i ) )
3852 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3857 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
3859 if ( mRelayoutData )
3861 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3863 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
3873 float Actor::GetHeightForWidthBase( float width )
3875 float height = 0.0f;
3877 const Vector3 naturalSize = GetNaturalSize();
3878 if( naturalSize.width > 0.0f )
3880 height = naturalSize.height * width / naturalSize.width;
3882 else // we treat 0 as 1:1 aspect ratio
3890 float Actor::GetWidthForHeightBase( float height )
3894 const Vector3 naturalSize = GetNaturalSize();
3895 if( naturalSize.height > 0.0f )
3897 width = naturalSize.width * height / naturalSize.height;
3899 else // we treat 0 as 1:1 aspect ratio
3907 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
3909 // Fill to parent, taking size mode factor into account
3910 switch( child.GetResizePolicy( dimension ) )
3912 case ResizePolicy::FILL_TO_PARENT:
3914 return GetLatestSize( dimension );
3917 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3919 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
3922 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3924 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
3929 return GetLatestSize( dimension );
3934 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
3936 // Can be overridden in derived class
3937 return CalculateChildSizeBase( child, dimension );
3940 float Actor::GetHeightForWidth( float width )
3942 // Can be overridden in derived class
3943 return GetHeightForWidthBase( width );
3946 float Actor::GetWidthForHeight( float height )
3948 // Can be overridden in derived class
3949 return GetWidthForHeightBase( height );
3952 float Actor::GetLatestSize( Dimension::Type dimension ) const
3954 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
3957 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
3959 Vector2 padding = GetPadding( dimension );
3961 return GetLatestSize( dimension ) + padding.x + padding.y;
3964 float Actor::NegotiateFromParent( Dimension::Type dimension )
3966 Actor* parent = GetParent();
3969 Vector2 padding( GetPadding( dimension ) );
3970 Vector2 parentPadding( parent->GetPadding( dimension ) );
3971 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
3977 float Actor::NegotiateFromChildren( Dimension::Type dimension )
3979 float maxDimensionPoint = 0.0f;
3981 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
3983 ActorPtr child = GetChildAt( i );
3985 if( !child->RelayoutDependentOnParent( dimension ) )
3987 // Calculate the min and max points that the children range across
3988 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
3989 float dimensionSize = child->GetRelayoutSize( dimension );
3990 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
3994 return maxDimensionPoint;
3997 float Actor::GetSize( Dimension::Type dimension ) const
3999 return GetDimensionValue( GetTargetSize(), dimension );
4002 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4004 return GetDimensionValue( GetNaturalSize(), dimension );
4007 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4009 switch( GetResizePolicy( dimension ) )
4011 case ResizePolicy::USE_NATURAL_SIZE:
4013 return GetNaturalSize( dimension );
4016 case ResizePolicy::FIXED:
4018 return GetDimensionValue( GetPreferredSize(), dimension );
4021 case ResizePolicy::USE_ASSIGNED_SIZE:
4023 return GetDimensionValue( maximumSize, dimension );
4026 case ResizePolicy::FILL_TO_PARENT:
4027 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4028 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4030 return NegotiateFromParent( dimension );
4033 case ResizePolicy::FIT_TO_CHILDREN:
4035 return NegotiateFromChildren( dimension );
4038 case ResizePolicy::DIMENSION_DEPENDENCY:
4040 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4043 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4045 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4048 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4050 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4062 return 0.0f; // Default
4065 float Actor::ClampDimension( float size, Dimension::Type dimension )
4067 const float minSize = GetMinimumSize( dimension );
4068 const float maxSize = GetMaximumSize( dimension );
4070 return std::max( minSize, std::min( size, maxSize ) );
4073 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4075 // Check if it needs to be negotiated
4076 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4078 // Check that we havn't gotten into an infinite loop
4079 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4080 bool recursionFound = false;
4081 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4083 if( *it == searchActor )
4085 recursionFound = true;
4090 if( !recursionFound )
4092 // Record the path that we have taken
4093 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4095 // Dimension dependency check
4096 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4098 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4100 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4102 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4106 // Parent dependency check
4107 Actor* parent = GetParent();
4108 if( parent && RelayoutDependentOnParent( dimension ) )
4110 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4113 // Children dependency check
4114 if( RelayoutDependentOnChildren( dimension ) )
4116 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4118 ActorPtr child = GetChildAt( i );
4120 // Only relayout child first if it is not dependent on this actor
4121 if( !child->RelayoutDependentOnParent( dimension ) )
4123 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
4128 // For deriving classes
4129 OnCalculateRelayoutSize( dimension );
4131 // All dependencies checked, calculate the size and set negotiated flag
4132 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4134 SetNegotiatedDimension( newSize, dimension );
4135 SetLayoutNegotiated( true, dimension );
4137 // For deriving classes
4138 OnLayoutNegotiated( newSize, dimension );
4140 // This actor has been successfully processed, pop it off the recursion stack
4141 recursionStack.pop_back();
4145 // TODO: Break infinite loop
4146 SetLayoutNegotiated( true, dimension );
4151 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4153 // Negotiate all dimensions that require it
4154 ActorDimensionStack recursionStack;
4156 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4158 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4161 NegotiateDimension( dimension, allocatedSize, recursionStack );
4165 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4167 switch( mRelayoutData->sizeSetPolicy )
4169 case SizeScalePolicy::USE_SIZE_SET:
4174 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4176 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4177 const Vector3 naturalSize = GetNaturalSize();
4178 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4180 const float sizeRatio = size.width / size.height;
4181 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4183 if( naturalSizeRatio < sizeRatio )
4185 return Vector2( naturalSizeRatio * size.height, size.height );
4187 else if( naturalSizeRatio > sizeRatio )
4189 return Vector2( size.width, size.width / naturalSizeRatio );
4200 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4202 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4203 const Vector3 naturalSize = GetNaturalSize();
4204 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4206 const float sizeRatio = size.width / size.height;
4207 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4209 if( naturalSizeRatio < sizeRatio )
4211 return Vector2( size.width, size.width / naturalSizeRatio );
4213 else if( naturalSizeRatio > sizeRatio )
4215 return Vector2( naturalSizeRatio * size.height, size.height );
4234 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4236 // Do the set actor size
4237 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4239 // Adjust for size set policy
4240 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4242 // Lock the flag to stop recursive relayouts on set size
4243 mRelayoutData->insideRelayout = true;
4244 SetSize( negotiatedSize );
4245 mRelayoutData->insideRelayout = false;
4247 // Clear flags for all dimensions
4248 SetLayoutDirty( false );
4250 // Give deriving classes a chance to respond
4251 OnRelayout( negotiatedSize, container );
4253 if( !mOnRelayoutSignal.Empty() )
4255 Dali::Actor handle( this );
4256 mOnRelayoutSignal.Emit( handle );
4260 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4262 // Force a size negotiation for actors that has assigned size during relayout
4263 // This is required as otherwise the flags that force a relayout will not
4264 // necessarilly be set. This will occur if the actor has already been laid out.
4265 // The dirty flags are then cleared. Then if the actor is added back into the
4266 // relayout container afterwards, the dirty flags would still be clear...
4267 // causing a relayout to be skipped. Here we force any actors added to the
4268 // container to be relayed out.
4269 if(GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE)
4271 SetLayoutNegotiated(false, Dimension::WIDTH);
4273 if(GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE)
4275 SetLayoutNegotiated(false, Dimension::HEIGHT);
4278 // Do the negotiation
4279 NegotiateDimensions( allocatedSize );
4281 // Set the actor size
4282 SetNegotiatedSize( container );
4284 // Negotiate down to children
4285 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4287 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4289 ActorPtr child = GetChildAt( i );
4291 // Forces children that have already been laid out to be relayed out
4292 // if they have assigned size during relayout.
4293 if(child->GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE)
4295 child->SetLayoutNegotiated(false, Dimension::WIDTH);
4296 child->SetLayoutDirty(true, Dimension::WIDTH);
4298 if(child->GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE)
4300 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
4301 child->SetLayoutDirty(true, Dimension::HEIGHT);
4304 // Only relayout if required
4305 if( child->RelayoutRequired() )
4307 container.Add( Dali::Actor( child.Get() ), newBounds );
4312 void Actor::RelayoutRequest( Dimension::Type dimension )
4314 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4315 if( relayoutController )
4317 Dali::Actor self( this );
4318 relayoutController->RequestRelayout( self, dimension );
4322 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4326 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4330 void Actor::SetPreferredSize( const Vector2& size )
4332 EnsureRelayoutData();
4334 if( size.width > 0.0f )
4336 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4339 if( size.height > 0.0f )
4341 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4344 mRelayoutData->preferredSize = size;
4349 Vector2 Actor::GetPreferredSize() const
4351 if ( mRelayoutData )
4353 return Vector2( mRelayoutData->preferredSize );
4356 return GetDefaultPreferredSize();
4359 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4361 EnsureRelayoutData();
4363 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4365 if( dimension & ( 1 << i ) )
4367 mRelayoutData->minimumSize[ i ] = size;
4374 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4376 if ( mRelayoutData )
4378 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4380 if( dimension & ( 1 << i ) )
4382 return mRelayoutData->minimumSize[ i ];
4387 return 0.0f; // Default
4390 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4392 EnsureRelayoutData();
4394 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4396 if( dimension & ( 1 << i ) )
4398 mRelayoutData->maximumSize[ i ] = size;
4405 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4407 if ( mRelayoutData )
4409 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4411 if( dimension & ( 1 << i ) )
4413 return mRelayoutData->maximumSize[ i ];
4418 return FLT_MAX; // Default
4421 Object* Actor::GetParentObject() const
4426 void Actor::SetSiblingOrder( unsigned int order )
4428 mSiblingOrder = std::min( order, static_cast<unsigned int>( DevelLayer::SIBLING_ORDER_MULTIPLIER ) );
4431 SetDepthIndexMessage( GetEventThreadServices(), *mNode, GetDepthIndex( mDepth, mSiblingOrder ) );
4435 void Actor::DefragmentSiblingIndexes( ActorContainer& siblings )
4437 // Sibling index may not be in consecutive order as the sibling range is limited ( DevelLayer::SIBLING_ORDER_MULTIPLIER )
4438 // we need to remove the gaps and ensure the number start from 0 and consecutive hence have a full range.
4440 // Start at index 0, while index <= highest order
4441 // Find next index higher than 0
4442 // if nextHigher > index+1
4443 // set all nextHigher orders to index+1
4445 // Limitation: May reach the ceiling of DevelLayer::SIBLING_ORDER_MULTIPLIER with highest sibling.
4447 ActorIter end = siblings.end();
4448 int highestOrder = 0;
4449 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
4451 ActorPtr sibling = (*iter);
4452 int siblingOrder = sibling->mSiblingOrder;
4453 highestOrder = std::max( highestOrder, siblingOrder );
4456 for ( int index = 0; index <= highestOrder; index++ )
4458 int nextHighest = -1;
4460 // Find Next highest
4461 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
4463 ActorPtr sibling = (*iter);
4464 int siblingOrder = sibling->mSiblingOrder;
4466 if ( siblingOrder > index )
4468 if ( nextHighest == -1 )
4470 nextHighest = siblingOrder;
4472 nextHighest = std::min( nextHighest, siblingOrder );
4476 // Check if a gap exists between indexes, if so set next index to consecutive number
4477 if ( ( nextHighest - index ) > 1 )
4479 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
4481 ActorPtr sibling = (*iter);
4482 int siblingOrder = sibling->mSiblingOrder;
4483 if ( siblingOrder == nextHighest )
4485 sibling->mSiblingOrder = index + 1;
4486 if ( sibling->mSiblingOrder >= Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER )
4488 DALI_LOG_WARNING( "Reached max sibling order level for raising / lowering actors\n" );
4489 sibling->mSiblingOrder = Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER;
4491 sibling->SetSiblingOrder( sibling->mSiblingOrder );
4498 bool Actor::ShiftSiblingsLevels( ActorContainer& siblings, int targetLevelToShiftFrom )
4500 // Allows exclusive levels for an actor by shifting all sibling levels at the target and above by 1
4501 bool defragmentationRequired( false );
4502 ActorIter end = siblings.end();
4503 for( ActorIter iter = siblings.begin(); ( iter != end ) ; ++iter )
4505 // Move actors at nearest order and above up by 1
4506 ActorPtr sibling = (*iter);
4507 if ( sibling != this )
4509 // Iterate through container of actors, any actor with a sibling order of the target or greater should
4510 // be incremented by 1.
4511 if ( sibling->mSiblingOrder >= targetLevelToShiftFrom )
4513 sibling->mSiblingOrder++;
4514 if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
4516 // If a sibling order raises so that it is only 1 from the maximum allowed then set flag so
4517 // can re-order all sibling orders.
4518 defragmentationRequired = true;
4520 sibling->SetSiblingOrder( sibling->mSiblingOrder );
4524 return defragmentationRequired;
4530 1) Check if already at top and nothing to be done.
4531 This Actor can have highest sibling order but if not exclusive then another actor at same sibling
4532 order can be positioned above it due to insertion order of actors.
4533 2) Find nearest sibling level above, these are the siblings this actor needs to be above
4534 3) a) There may be other levels above this target level
4535 b) Increment all sibling levels at the level above nearest(target)
4536 c) Now have a vacant sibling level
4537 4) Set this actor's sibling level to nearest +1 as now vacated.
4539 Note May not just be sibling level + 1 as could be empty levels in-between
4544 ActorC ( sibling level 4 )
4545 ActorB ( sibling level 3 )
4546 ActorA ( sibling level 1 )
4548 2 ) ACTION: Raise A above B
4549 a) Find nearest level above A = Level 3
4550 b) Increment levels above Level 3
4552 ActorC ( sibling level 5 )
4553 ActorB ( sibling level 3 ) NEAREST
4554 ActorA ( sibling level 1 )
4556 3 ) Set Actor A sibling level to nearest +1 as vacant
4558 ActorC ( sibling level 5 )
4559 ActorA ( sibling level 4 )
4560 ActorB ( sibling level 3 )
4562 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4563 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4564 remove any empty sibling order gaps and start from sibling level 0 again.
4565 If the number of actors reaches this maximum and all using exclusive sibling order values then
4566 defragmention will stop and new sibling orders will be set to same max value.
4570 int nearestLevel = mSiblingOrder;
4571 int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
4572 bool defragmentationRequired( false );
4574 ActorContainer* siblings = mParent->mChildren;
4576 // Find Nearest sibling level above this actor
4577 ActorIter end = siblings->end();
4578 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
4580 ActorPtr sibling = (*iter);
4581 if ( sibling != this )
4583 int order = GetSiblingOrder( sibling );
4585 if ( ( order >= mSiblingOrder ) )
4587 int distanceToNextLevel = order - mSiblingOrder;
4588 if ( distanceToNextLevel < shortestDistanceToNextLevel )
4590 nearestLevel = order;
4591 shortestDistanceToNextLevel = distanceToNextLevel;
4597 if ( nearestLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at top
4599 mSiblingOrder = nearestLevel + 1; // Set sibling level to that above the nearest level
4600 defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
4601 // Move current actor to newly vacated order level
4602 SetSiblingOrder( mSiblingOrder );
4603 if ( defragmentationRequired )
4605 DefragmentSiblingIndexes( *siblings );
4608 SetSiblingOrder( mSiblingOrder );
4615 1) Check if actor already at bottom and if nothing needs to be done
4616 This Actor can have lowest sibling order but if not exclusive then another actor at same sibling
4617 order can be positioned above it due to insertion order of actors so need to move this actor below it.
4618 2) Find nearest sibling level below, this Actor needs to be below it
4619 3) a) Need to vacate a sibling level below nearest for this actor to occupy
4620 b) Shift up all sibling order values of actor at the nearest level and levels above it to vacate a level.
4621 c) Set this actor's sibling level to this newly vacated level.
4622 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4623 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4624 remove any empty sibling order gaps and start from sibling level 0 again.
4625 If the number of actors reaches this maximum and all using exclusive sibling order values then
4626 defragmention will stop and new sibling orders will be set to same max value.
4631 // 1) Find nearest level below
4632 int nearestLevel = mSiblingOrder;
4633 int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
4635 ActorContainer* siblings = mParent->mChildren;
4637 ActorIter end = siblings->end();
4638 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
4640 ActorPtr sibling = (*iter);
4641 if ( sibling != this )
4643 int order = GetSiblingOrder( sibling );
4645 if ( order <= mSiblingOrder )
4647 int distanceToNextLevel = mSiblingOrder - order;
4648 if ( distanceToNextLevel < shortestDistanceToNextLevel )
4650 nearestLevel = order;
4651 shortestDistanceToNextLevel = distanceToNextLevel;
4657 bool defragmentationRequired ( false );
4659 // 2) If actor already not at bottom, raise all actors at required level and above
4660 if ( shortestDistanceToNextLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at bottom
4662 mSiblingOrder = nearestLevel;
4663 defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
4664 // Move current actor to newly vacated order
4665 SetSiblingOrder( mSiblingOrder );
4666 if ( defragmentationRequired )
4668 DefragmentSiblingIndexes( *siblings );
4674 void Actor::RaiseToTop()
4677 1 ) Find highest sibling order actor
4678 2 ) If highest sibling level not itself then set sibling order to that + 1
4679 3 ) highest sibling order can be same as itself so need to increment over that
4680 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4681 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4682 remove any empty sibling order gaps and start from sibling level 0 again.
4683 If the number of actors reaches this maximum and all using exclusive sibling order values then
4684 defragmention will stop and new sibling orders will be set to same max value.
4691 ActorContainer* siblings = mParent->mChildren;
4693 ActorIter end = siblings->end();
4694 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
4696 ActorPtr sibling = (*iter);
4697 if ( sibling != this )
4699 maxOrder = std::max( GetSiblingOrder( sibling ), maxOrder );
4703 bool defragmentationRequired( false );
4705 if ( maxOrder >= mSiblingOrder )
4707 mSiblingOrder = maxOrder + 1;
4708 if ( mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
4710 defragmentationRequired = true;
4714 SetSiblingOrder( mSiblingOrder );
4716 if ( defragmentationRequired )
4718 DefragmentSiblingIndexes( *siblings );
4723 void Actor::LowerToBottom()
4726 See Actor::LowerToBottom()
4728 1 ) Check if this actor already at exclusively at the bottom, if so then no more to be done.
4729 2 ) a ) Check if the bottom position 0 is vacant.
4730 b ) If 0 position is not vacant then shift up all sibling order values from 0 and above
4731 c ) 0 sibling position is vacant.
4732 3 ) Set this actor to vacant sibling order 0;
4733 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4734 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4735 remove any empty sibling order gaps and start from sibling level 0 again.
4736 If the number of actors reaches this maximum and all using exclusive sibling order values then
4737 defragmention will stop and new sibling orders will be set to same max value.
4742 bool defragmentationRequired( false );
4743 bool orderZeroFree ( true );
4745 ActorContainer* siblings = mParent->mChildren;
4747 bool actorAtLowestOrder = true;
4748 ActorIter end = siblings->end();
4749 for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
4751 ActorPtr sibling = (*iter);
4752 if ( sibling != this )
4754 int siblingOrder = GetSiblingOrder( sibling );
4755 if ( siblingOrder <= mSiblingOrder )
4757 actorAtLowestOrder = false;
4760 if ( siblingOrder == 0 )
4762 orderZeroFree = false;
4767 if ( ! actorAtLowestOrder )
4769 if ( ! orderZeroFree )
4771 defragmentationRequired = ShiftSiblingsLevels( *siblings, 0 );
4774 SetSiblingOrder( mSiblingOrder );
4776 if ( defragmentationRequired )
4778 DefragmentSiblingIndexes( *siblings );
4784 void Actor::RaiseAbove( Dali::Actor target )
4787 1 ) a) Find target actor's sibling order
4788 b) If sibling order of target is the same as this actor then need to this Actor's sibling order
4789 needs to be above it or the insertion order will determine which is drawn on top.
4790 2 ) Shift up by 1 all sibling order greater than target sibling order
4791 3 ) Set this actor to the sibling order to target +1 as will be a newly vacated gap above
4792 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4793 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4794 remove any empty sibling order gaps and start from sibling level 0 again.
4795 If the number of actors reaches this maximum and all using exclusive sibling order values then
4796 defragmention will stop and new sibling orders will be set to same max value.
4799 if ( this != target )
4801 // Find target's sibling order
4802 // Set actor sibling order to this number +1
4803 int targetSiblingOrder = GetSiblingOrder( &GetImplementation( target ) );
4804 ActorContainer* siblings = mParent->mChildren;
4805 mSiblingOrder = targetSiblingOrder + 1;
4806 bool defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
4808 SetSiblingOrder( mSiblingOrder );
4810 if ( defragmentationRequired )
4812 DefragmentSiblingIndexes( *(mParent->mChildren) );
4817 void Actor::LowerBelow( Dali::Actor target )
4820 1 ) a) Find target actor's sibling order
4821 b) If sibling order of target is the same as this actor then need to this Actor's sibling order
4822 needs to be below it or the insertion order will determine which is drawn on top.
4823 2 ) Shift the target sibling order and all sibling orders at that level or above by 1
4824 3 ) Set this actor to the sibling order of the target before it changed.
4825 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4826 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4827 remove any empty sibling order gaps and start from sibling level 0 again.
4828 If the number of actors reaches this maximum and all using exclusive sibling order values then
4829 defragmention will stop and new sibling orders will be set to same max value.
4832 if ( this != target )
4834 bool defragmentationRequired ( false );
4835 // Find target's sibling order
4836 // Set actor sibling order to target sibling order - 1
4837 int targetSiblingOrder = GetSiblingOrder( &GetImplementation( target ) );
4838 ActorContainer* siblings = mParent->mChildren;
4839 if ( targetSiblingOrder == 0 )
4842 ActorIter end = siblings->end();
4843 for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
4845 ActorPtr sibling = (*iter);
4846 if ( sibling != this )
4848 sibling->mSiblingOrder++;
4849 if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
4851 defragmentationRequired = true;
4853 sibling->SetSiblingOrder( sibling->mSiblingOrder );
4860 defragmentationRequired = ShiftSiblingsLevels( *siblings, targetSiblingOrder );
4862 mSiblingOrder = targetSiblingOrder;
4864 SetSiblingOrder( mSiblingOrder );
4866 if ( defragmentationRequired )
4868 DefragmentSiblingIndexes( *(mParent->mChildren) );
4873 } // namespace Internal