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 bool ValidateActors( const Internal::Actor& actor, const Internal::Actor& target )
100 bool validTarget = true;
102 if( &actor == &target )
104 DALI_LOG_WARNING( "Source actor and target actor can not be the same, Sibling order not changed.\n" );
107 else if( actor.GetParent() != target.GetParent() )
109 DALI_LOG_WARNING( "Source actor and target actor need to have common parent, Sibling order not changed.\n" );
116 } // unnamed namespace
119 * Struct to collect relayout variables
121 struct Actor::RelayoutData
124 : sizeModeFactor( GetDefaultSizeModeFactor() ), preferredSize( GetDefaultPreferredSize() ), sizeSetPolicy( DEFAULT_SIZE_SCALE_POLICY ), relayoutEnabled( false ), insideRelayout( false )
126 // Set size negotiation defaults
127 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
129 resizePolicies[ i ] = ResizePolicy::DEFAULT;
130 negotiatedDimensions[ i ] = 0.0f;
131 dimensionNegotiated[ i ] = false;
132 dimensionDirty[ i ] = false;
133 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
134 dimensionPadding[ i ] = GetDefaultDimensionPadding();
135 minimumSize[ i ] = 0.0f;
136 maximumSize[ i ] = FLT_MAX;
140 ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies
142 Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies
144 Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
146 float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
148 float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be
149 float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be
151 bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated
152 bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
154 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
156 Vector2 preferredSize; ///< The preferred size of the actor
158 SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
160 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
161 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
164 namespace // unnamed namespace
170 * We want to discourage the use of property strings (minimize string comparisons),
171 * particularly for the default properties.
172 * Name Type writable animatable constraint-input enum for index-checking
174 DALI_PROPERTY_TABLE_BEGIN
175 DALI_PROPERTY( "parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
176 DALI_PROPERTY( "parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
177 DALI_PROPERTY( "parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
178 DALI_PROPERTY( "parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
179 DALI_PROPERTY( "anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
180 DALI_PROPERTY( "anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
181 DALI_PROPERTY( "anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
182 DALI_PROPERTY( "anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
183 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
184 DALI_PROPERTY( "sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
185 DALI_PROPERTY( "sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
186 DALI_PROPERTY( "sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
187 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
188 DALI_PROPERTY( "positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
189 DALI_PROPERTY( "positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
190 DALI_PROPERTY( "positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
191 DALI_PROPERTY( "worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
192 DALI_PROPERTY( "worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
193 DALI_PROPERTY( "worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
194 DALI_PROPERTY( "worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
195 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
196 DALI_PROPERTY( "worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
197 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
198 DALI_PROPERTY( "scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
199 DALI_PROPERTY( "scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
200 DALI_PROPERTY( "scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
201 DALI_PROPERTY( "worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
202 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
203 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
204 DALI_PROPERTY( "colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
205 DALI_PROPERTY( "colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
206 DALI_PROPERTY( "colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
207 DALI_PROPERTY( "colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
208 DALI_PROPERTY( "worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
209 DALI_PROPERTY( "worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
210 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
211 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
212 DALI_PROPERTY( "leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
213 DALI_PROPERTY( "inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
214 DALI_PROPERTY( "inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
215 DALI_PROPERTY( "colorMode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
216 DALI_PROPERTY( "positionInheritance", STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE )
217 DALI_PROPERTY( "drawMode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
218 DALI_PROPERTY( "sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
219 DALI_PROPERTY( "widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
220 DALI_PROPERTY( "heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
221 DALI_PROPERTY( "sizeScalePolicy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
222 DALI_PROPERTY( "widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
223 DALI_PROPERTY( "heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
224 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
225 DALI_PROPERTY( "minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
226 DALI_PROPERTY( "maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
227 DALI_PROPERTY( "inheritPosition", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_POSITION )
228 DALI_PROPERTY( "clippingMode", STRING, true, false, false, Dali::Actor::Property::CLIPPING_MODE )
229 DALI_PROPERTY( "siblingOrder", INTEGER, true, false, false, Dali::DevelActor::Property::SIBLING_ORDER )
230 DALI_PROPERTY( "opacity", FLOAT, true, true, true, Dali::DevelActor::Property::OPACITY )
231 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
235 const char* const SIGNAL_TOUCHED = "touched";
236 const char* const SIGNAL_HOVERED = "hovered";
237 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
238 const char* const SIGNAL_ON_STAGE = "onStage";
239 const char* const SIGNAL_OFF_STAGE = "offStage";
240 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
241 const char* const SIGNAL_TOUCH = "touch";
245 const char* const ACTION_SHOW = "show";
246 const char* const ACTION_HIDE = "hide";
248 BaseHandle CreateActor()
250 return Dali::Actor::New();
253 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
255 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
256 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
257 SignalConnectorType signalConnector3( mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal );
258 SignalConnectorType signalConnector4( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
259 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
260 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
261 SignalConnectorType signalConnector7( mType, SIGNAL_TOUCH, &Actor::DoConnectSignal );
263 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
264 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
269 const Vector3& value;
272 DALI_ENUM_TO_STRING_TABLE_BEGIN_WITH_TYPE( AnchorValue, ANCHOR_CONSTANT )
273 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_LEFT )
274 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_CENTER )
275 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_RIGHT )
276 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_LEFT )
277 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER )
278 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_RIGHT )
279 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_LEFT )
280 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_CENTER )
281 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_RIGHT )
282 DALI_ENUM_TO_STRING_TABLE_END( ANCHOR_CONSTANT )
284 DALI_ENUM_TO_STRING_TABLE_BEGIN( COLOR_MODE )
285 DALI_ENUM_TO_STRING( USE_OWN_COLOR )
286 DALI_ENUM_TO_STRING( USE_PARENT_COLOR )
287 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_COLOR )
288 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_ALPHA )
289 DALI_ENUM_TO_STRING_TABLE_END( COLOR_MODE )
291 DALI_ENUM_TO_STRING_TABLE_BEGIN( POSITION_INHERITANCE_MODE )
292 DALI_ENUM_TO_STRING( INHERIT_PARENT_POSITION )
293 DALI_ENUM_TO_STRING( USE_PARENT_POSITION )
294 DALI_ENUM_TO_STRING( USE_PARENT_POSITION_PLUS_LOCAL_POSITION )
295 DALI_ENUM_TO_STRING( DONT_INHERIT_POSITION )
296 DALI_ENUM_TO_STRING_TABLE_END( POSITION_INHERITANCE_MODE )
298 DALI_ENUM_TO_STRING_TABLE_BEGIN( DRAW_MODE )
299 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, NORMAL )
300 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, OVERLAY_2D )
301 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, STENCIL )
302 DALI_ENUM_TO_STRING_TABLE_END( DRAW_MODE )
304 DALI_ENUM_TO_STRING_TABLE_BEGIN( RESIZE_POLICY )
305 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIXED )
306 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_NATURAL_SIZE )
307 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FILL_TO_PARENT )
308 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_RELATIVE_TO_PARENT )
309 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_FIXED_OFFSET_FROM_PARENT )
310 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIT_TO_CHILDREN )
311 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, DIMENSION_DEPENDENCY )
312 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_ASSIGNED_SIZE )
313 DALI_ENUM_TO_STRING_TABLE_END( RESIZE_POLICY )
315 DALI_ENUM_TO_STRING_TABLE_BEGIN( SIZE_SCALE_POLICY )
316 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, USE_SIZE_SET )
317 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FIT_WITH_ASPECT_RATIO )
318 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FILL_WITH_ASPECT_RATIO )
319 DALI_ENUM_TO_STRING_TABLE_END( SIZE_SCALE_POLICY )
321 DALI_ENUM_TO_STRING_TABLE_BEGIN( CLIPPING_MODE )
322 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, DISABLED )
323 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, CLIP_CHILDREN )
324 DALI_ENUM_TO_STRING_TABLE_END( CLIPPING_MODE )
327 bool GetAnchorPointConstant( const std::string& value, Vector3& anchor )
329 for( unsigned int i = 0; i < ANCHOR_CONSTANT_TABLE_COUNT; ++i )
331 size_t sizeIgnored = 0;
332 if( CompareTokens( value.c_str(), ANCHOR_CONSTANT_TABLE[ i ].name, sizeIgnored ) )
334 anchor = ANCHOR_CONSTANT_TABLE[ i ].value;
341 inline bool GetParentOriginConstant( const std::string& value, Vector3& parentOrigin )
343 // Values are the same so just use the same table as anchor-point
344 return GetAnchorPointConstant( value, parentOrigin );
348 * @brief Extract a given dimension from a Vector2
350 * @param[in] values The values to extract from
351 * @param[in] dimension The dimension to extract
352 * @return Return the value for the dimension
354 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
358 case Dimension::WIDTH:
362 case Dimension::HEIGHT:
364 return values.height;
375 * @brief Extract a given dimension from a Vector3
377 * @param[in] values The values to extract from
378 * @param[in] dimension The dimension to extract
379 * @return Return the value for the dimension
381 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
383 return GetDimensionValue( values.GetVectorXY(), dimension );
386 unsigned int GetDepthIndex( uint16_t depth, uint16_t siblingOrder )
388 return depth * Dali::DevelLayer::ACTOR_DEPTH_MULTIPLIER + siblingOrder * Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER;
391 } // unnamed namespace
393 ActorPtr Actor::New()
395 ActorPtr actor( new Actor( BASIC ) );
397 // Second-phase construction
403 const std::string& Actor::GetName() const
408 void Actor::SetName( const std::string& name )
414 // ATTENTION: string for debug purposes is not thread safe.
415 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
419 unsigned int Actor::GetId() const
424 bool Actor::OnStage() const
429 Dali::Layer Actor::GetLayer()
433 // Short-circuit for Layer derived actors
436 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
439 // Find the immediate Layer parent
440 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
442 if( parent->IsLayer() )
444 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
451 void Actor::Add( Actor& child )
453 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
454 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
458 mChildren = new ActorContainer;
461 Actor* const oldParent( child.mParent );
463 // child might already be ours
464 if( this != oldParent )
466 // if we already have parent, unparent us first
469 oldParent->Remove( child ); // This causes OnChildRemove callback
471 // Old parent may need to readjust to missing child
472 if( oldParent->RelayoutDependentOnChildren() )
474 oldParent->RelayoutRequest();
478 // Guard against Add() during previous OnChildRemove callback
481 // Do this first, since user callbacks from within SetParent() may need to remove child
482 mChildren->push_back( ActorPtr( &child ) );
484 // SetParent asserts that child can be added
485 child.SetParent( this );
487 // Notification for derived classes
490 // Only put in a relayout request if there is a suitable dependency
491 if( RelayoutDependentOnChildren() )
499 void Actor::Remove( Actor& child )
501 if( (this == &child) || (!mChildren) )
503 // no children or removing itself
509 // Find the child in mChildren, and unparent it
510 ActorIter end = mChildren->end();
511 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
513 ActorPtr actor = (*iter);
515 if( actor.Get() == &child )
517 // Keep handle for OnChildRemove notification
520 // Do this first, since user callbacks from within SetParent() may need to add the child
521 mChildren->erase( iter );
523 DALI_ASSERT_DEBUG( actor->GetParent() == this );
524 actor->SetParent( NULL );
532 // Only put in a relayout request if there is a suitable dependency
533 if( RelayoutDependentOnChildren() )
539 // Notification for derived classes
540 OnChildRemove( child );
543 void Actor::Unparent()
547 // Remove this actor from the parent. The remove will put a relayout request in for
548 // the parent if required
549 mParent->Remove( *this );
550 // mParent is now NULL!
554 unsigned int Actor::GetChildCount() const
556 return ( NULL != mChildren ) ? mChildren->size() : 0;
559 ActorPtr Actor::GetChildAt( unsigned int index ) const
561 DALI_ASSERT_ALWAYS( index < GetChildCount() );
563 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
566 ActorPtr Actor::FindChildByName( const std::string& actorName )
569 if( actorName == mName )
575 ActorIter end = mChildren->end();
576 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
578 child = (*iter)->FindChildByName( actorName );
589 ActorPtr Actor::FindChildById( const unsigned int id )
598 ActorIter end = mChildren->end();
599 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
601 child = (*iter)->FindChildById( id );
612 void Actor::SetParentOrigin( const Vector3& origin )
616 // mNode is being used in a separate thread; queue a message to set the value & base value
617 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
620 // Cache for event-thread access
623 // not allocated, check if different from default
624 if( ParentOrigin::DEFAULT != origin )
626 mParentOrigin = new Vector3( origin );
631 // check if different from current costs more than just set
632 *mParentOrigin = origin;
636 void Actor::SetParentOriginX( float x )
638 const Vector3& current = GetCurrentParentOrigin();
640 SetParentOrigin( Vector3( x, current.y, current.z ) );
643 void Actor::SetParentOriginY( float y )
645 const Vector3& current = GetCurrentParentOrigin();
647 SetParentOrigin( Vector3( current.x, y, current.z ) );
650 void Actor::SetParentOriginZ( float z )
652 const Vector3& current = GetCurrentParentOrigin();
654 SetParentOrigin( Vector3( current.x, current.y, z ) );
657 const Vector3& Actor::GetCurrentParentOrigin() const
659 // Cached for event-thread access
660 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
663 void Actor::SetAnchorPoint( const Vector3& anchor )
667 // mNode is being used in a separate thread; queue a message to set the value & base value
668 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
671 // Cache for event-thread access
674 // not allocated, check if different from default
675 if( AnchorPoint::DEFAULT != anchor )
677 mAnchorPoint = new Vector3( anchor );
682 // check if different from current costs more than just set
683 *mAnchorPoint = anchor;
687 void Actor::SetAnchorPointX( float x )
689 const Vector3& current = GetCurrentAnchorPoint();
691 SetAnchorPoint( Vector3( x, current.y, current.z ) );
694 void Actor::SetAnchorPointY( float y )
696 const Vector3& current = GetCurrentAnchorPoint();
698 SetAnchorPoint( Vector3( current.x, y, current.z ) );
701 void Actor::SetAnchorPointZ( float z )
703 const Vector3& current = GetCurrentAnchorPoint();
705 SetAnchorPoint( Vector3( current.x, current.y, z ) );
708 const Vector3& Actor::GetCurrentAnchorPoint() const
710 // Cached for event-thread access
711 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
714 void Actor::SetPosition( float x, float y )
716 SetPosition( Vector3( x, y, 0.0f ) );
719 void Actor::SetPosition( float x, float y, float z )
721 SetPosition( Vector3( x, y, z ) );
724 void Actor::SetPosition( const Vector3& position )
726 mTargetPosition = position;
730 // mNode is being used in a separate thread; queue a message to set the value & base value
731 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
735 void Actor::SetX( float x )
737 mTargetPosition.x = x;
741 // mNode is being used in a separate thread; queue a message to set the value & base value
742 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
746 void Actor::SetY( float y )
748 mTargetPosition.y = y;
752 // mNode is being used in a separate thread; queue a message to set the value & base value
753 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
757 void Actor::SetZ( float z )
759 mTargetPosition.z = z;
763 // mNode is being used in a separate thread; queue a message to set the value & base value
764 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
768 void Actor::TranslateBy( const Vector3& distance )
770 mTargetPosition += distance;
774 // mNode is being used in a separate thread; queue a message to set the value & base value
775 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
779 const Vector3& Actor::GetCurrentPosition() const
783 // mNode is being used in a separate thread; copy the value from the previous update
784 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
787 return Vector3::ZERO;
790 const Vector3& Actor::GetTargetPosition() const
792 return mTargetPosition;
795 const Vector3& Actor::GetCurrentWorldPosition() const
799 // mNode is being used in a separate thread; copy the value from the previous update
800 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
803 return Vector3::ZERO;
806 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
808 // this flag is not animatable so keep the value
809 mPositionInheritanceMode = mode;
812 // mNode is being used in a separate thread; queue a message to set the value
813 SetInheritPositionMessage( GetEventThreadServices(), *mNode, mode == INHERIT_PARENT_POSITION );
817 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
819 // Cached for event-thread access
820 return mPositionInheritanceMode;
823 void Actor::SetInheritPosition( bool inherit )
825 if( mInheritPosition != inherit && NULL != mNode )
827 // non animateable so keep local copy
828 mInheritPosition = inherit;
829 SetInheritPositionMessage( GetEventThreadServices(), *mNode, inherit );
833 bool Actor::IsPositionInherited() const
835 return mInheritPosition;
838 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
840 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
841 normalizedAxis.Normalize();
843 Quaternion orientation( angle, normalizedAxis );
845 SetOrientation( orientation );
848 void Actor::SetOrientation( const Quaternion& orientation )
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>::Bake, orientation );
857 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
861 // mNode is being used in a separate thread; queue a message to set the value & base value
862 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, Quaternion(angle, axis) );
866 void Actor::RotateBy( const Quaternion& relativeRotation )
870 // mNode is being used in a separate thread; queue a message to set the value & base value
871 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
875 const Quaternion& Actor::GetCurrentOrientation() const
879 // mNode is being used in a separate thread; copy the value from the previous update
880 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
883 return Quaternion::IDENTITY;
886 const Quaternion& Actor::GetCurrentWorldOrientation() const
890 // mNode is being used in a separate thread; copy the value from the previous update
891 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
894 return Quaternion::IDENTITY;
897 void Actor::SetScale( float scale )
899 SetScale( Vector3( scale, scale, scale ) );
902 void Actor::SetScale( float x, float y, float z )
904 SetScale( Vector3( x, y, z ) );
907 void Actor::SetScale( const Vector3& scale )
911 // mNode is being used in a separate thread; queue a message to set the value & base value
912 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
916 void Actor::SetScaleX( float x )
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>::BakeX, x );
925 void Actor::SetScaleY( float y )
929 // mNode is being used in a separate thread; queue a message to set the value & base value
930 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
934 void Actor::SetScaleZ( float z )
938 // mNode is being used in a separate thread; queue a message to set the value & base value
939 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
943 void Actor::ScaleBy(const Vector3& relativeScale)
947 // mNode is being used in a separate thread; queue a message to set the value & base value
948 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
952 const Vector3& Actor::GetCurrentScale() const
956 // mNode is being used in a separate thread; copy the value from the previous update
957 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
963 const Vector3& Actor::GetCurrentWorldScale() const
967 // mNode is being used in a separate thread; copy the value from the previous update
968 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
974 void Actor::SetInheritScale( bool inherit )
977 if( mInheritScale != inherit && NULL != mNode )
979 // non animateable so keep local copy
980 mInheritScale = inherit;
981 // mNode is being used in a separate thread; queue a message to set the value
982 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
986 bool Actor::IsScaleInherited() const
988 return mInheritScale;
991 Matrix Actor::GetCurrentWorldMatrix() const
995 return mNode->GetWorldMatrix(0);
998 return Matrix::IDENTITY;
1001 void Actor::SetVisible( bool visible )
1005 // mNode is being used in a separate thread; queue a message to set the value & base value
1006 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
1010 bool Actor::IsVisible() const
1014 // mNode is being used in a separate thread; copy the value from the previous update
1015 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
1021 void Actor::SetOpacity( float opacity )
1025 // mNode is being used in a separate thread; queue a message to set the value & base value
1026 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
1030 float Actor::GetCurrentOpacity() const
1034 // mNode is being used in a separate thread; copy the value from the previous update
1035 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1041 ClippingMode::Type Actor::GetClippingMode() const
1043 return mClippingMode;
1046 unsigned int Actor::GetSortingDepth()
1048 return GetDepthIndex( mDepth, mSiblingOrder );
1051 const Vector4& Actor::GetCurrentWorldColor() const
1055 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1058 return Color::WHITE;
1061 void Actor::SetColor( const Vector4& color )
1065 // mNode is being used in a separate thread; queue a message to set the value & base value
1066 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1070 void Actor::SetColorRed( float red )
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>::BakeX, red );
1079 void Actor::SetColorGreen( float green )
1083 // mNode is being used in a separate thread; queue a message to set the value & base value
1084 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1088 void Actor::SetColorBlue( float blue )
1092 // mNode is being used in a separate thread; queue a message to set the value & base value
1093 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1097 const Vector4& Actor::GetCurrentColor() const
1101 // mNode is being used in a separate thread; copy the value from the previous update
1102 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1105 return Color::WHITE;
1108 void Actor::SetInheritOrientation( bool inherit )
1110 if( mInheritOrientation != inherit && NULL != mNode)
1112 // non animateable so keep local copy
1113 mInheritOrientation = inherit;
1114 // mNode is being used in a separate thread; queue a message to set the value
1115 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1119 bool Actor::IsOrientationInherited() const
1121 return mInheritOrientation;
1124 void Actor::SetSizeModeFactor( const Vector3& factor )
1126 EnsureRelayoutData();
1128 mRelayoutData->sizeModeFactor = factor;
1131 const Vector3& Actor::GetSizeModeFactor() const
1133 if ( mRelayoutData )
1135 return mRelayoutData->sizeModeFactor;
1138 return GetDefaultSizeModeFactor();
1141 void Actor::SetColorMode( ColorMode colorMode )
1143 // non animateable so keep local copy
1144 mColorMode = colorMode;
1147 // mNode is being used in a separate thread; queue a message to set the value
1148 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1152 ColorMode Actor::GetColorMode() const
1154 // we have cached copy
1158 void Actor::SetSize( float width, float height )
1160 SetSize( Vector2( width, height ) );
1163 void Actor::SetSize( float width, float height, float depth )
1165 SetSize( Vector3( width, height, depth ) );
1168 void Actor::SetSize( const Vector2& size )
1170 SetSize( Vector3( size.width, size.height, 0.f ) );
1173 void Actor::SetSizeInternal( const Vector2& size )
1175 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1178 void Actor::SetSize( const Vector3& size )
1180 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1182 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1183 SetPreferredSize( size.GetVectorXY() );
1187 SetSizeInternal( size );
1191 void Actor::SetSizeInternal( const Vector3& size )
1193 // dont allow recursive loop
1194 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1195 // 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
1196 if( ( NULL != mNode )&&
1197 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1198 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1199 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1203 // mNode is being used in a separate thread; queue a message to set the value & base value
1204 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
1206 // Notification for derived classes
1207 mInsideOnSizeSet = true;
1208 OnSizeSet( mTargetSize );
1209 mInsideOnSizeSet = false;
1211 // Raise a relayout request if the flag is not locked
1212 if( mRelayoutData && !mRelayoutData->insideRelayout )
1219 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1221 mTargetSize = targetSize;
1223 // Notify deriving classes
1224 OnSizeAnimation( animation, mTargetSize );
1227 void Actor::NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property )
1229 if ( Dali::Actor::Property::SIZE_WIDTH == property )
1231 mTargetSize.width = targetSize;
1233 else if ( Dali::Actor::Property::SIZE_HEIGHT == property )
1235 mTargetSize.height = targetSize;
1237 else if ( Dali::Actor::Property::SIZE_DEPTH == property )
1239 mTargetSize.depth = targetSize;
1241 // Notify deriving classes
1242 OnSizeAnimation( animation, mTargetSize );
1245 void Actor::NotifyPositionAnimation( Animation& animation, const Vector3& targetPosition )
1247 mTargetPosition = targetPosition;
1250 void Actor::NotifyPositionAnimation( Animation& animation, float targetPosition, Property::Index property )
1252 if ( Dali::Actor::Property::POSITION_X == property )
1254 mTargetPosition.x = targetPosition;
1256 else if ( Dali::Actor::Property::POSITION_Y == property )
1258 mTargetPosition.y = targetPosition;
1260 else if ( Dali::Actor::Property::POSITION_Z == property )
1262 mTargetPosition.z = targetPosition;
1266 void Actor::SetWidth( float width )
1268 mTargetSize.width = width;
1272 // mNode is being used in a separate thread; queue a message to set the value & base value
1273 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1277 void Actor::SetHeight( float height )
1279 mTargetSize.height = height;
1283 // mNode is being used in a separate thread; queue a message to set the value & base value
1284 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1288 void Actor::SetDepth( float depth )
1290 mTargetSize.depth = depth;
1294 // mNode is being used in a separate thread; queue a message to set the value & base value
1295 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1299 const Vector3& Actor::GetTargetSize() const
1304 const Vector3& Actor::GetCurrentSize() const
1308 // mNode is being used in a separate thread; copy the value from the previous update
1309 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1312 return Vector3::ZERO;
1315 Vector3 Actor::GetNaturalSize() const
1317 // It is up to deriving classes to return the appropriate natural size
1318 return Vector3( 0.0f, 0.0f, 0.0f );
1321 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1323 EnsureRelayoutData();
1325 ResizePolicy::Type originalWidthPolicy = GetResizePolicy(Dimension::WIDTH);
1326 ResizePolicy::Type originalHeightPolicy = GetResizePolicy(Dimension::HEIGHT);
1328 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1330 if( dimension & ( 1 << i ) )
1332 mRelayoutData->resizePolicies[ i ] = policy;
1336 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1338 if( dimension & Dimension::WIDTH )
1340 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1343 if( dimension & Dimension::HEIGHT )
1345 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1349 // If calling SetResizePolicy, assume we want relayout enabled
1350 SetRelayoutEnabled( true );
1352 // If the resize policy is set to be FIXED, the preferred size
1353 // should be overrided by the target size. Otherwise the target
1354 // size should be overrided by the preferred size.
1356 if( dimension & Dimension::WIDTH )
1358 if( originalWidthPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1360 mRelayoutData->preferredSize.width = mTargetSize.width;
1362 else if( originalWidthPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1364 mTargetSize.width = mRelayoutData->preferredSize.width;
1368 if( dimension & Dimension::HEIGHT )
1370 if( originalHeightPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1372 mRelayoutData->preferredSize.height = mTargetSize.height;
1374 else if( originalHeightPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1376 mTargetSize.height = mRelayoutData->preferredSize.height;
1380 OnSetResizePolicy( policy, dimension );
1382 // Trigger relayout on this control
1386 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1388 if ( mRelayoutData )
1390 // If more than one dimension is requested, just return the first one found
1391 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1393 if( ( dimension & ( 1 << i ) ) )
1395 return mRelayoutData->resizePolicies[ i ];
1400 return ResizePolicy::DEFAULT;
1403 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1405 EnsureRelayoutData();
1407 mRelayoutData->sizeSetPolicy = policy;
1410 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1412 if ( mRelayoutData )
1414 return mRelayoutData->sizeSetPolicy;
1417 return DEFAULT_SIZE_SCALE_POLICY;
1420 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1422 EnsureRelayoutData();
1424 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1426 if( dimension & ( 1 << i ) )
1428 mRelayoutData->dimensionDependencies[ i ] = dependency;
1433 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1435 if ( mRelayoutData )
1437 // If more than one dimension is requested, just return the first one found
1438 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1440 if( ( dimension & ( 1 << i ) ) )
1442 return mRelayoutData->dimensionDependencies[ i ];
1447 return Dimension::ALL_DIMENSIONS; // Default
1450 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1452 // If relayout data has not been allocated yet and the client is requesting
1453 // to disable it, do nothing
1454 if( mRelayoutData || relayoutEnabled )
1456 EnsureRelayoutData();
1458 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1460 mRelayoutData->relayoutEnabled = relayoutEnabled;
1464 bool Actor::IsRelayoutEnabled() const
1466 // Assume that if relayout data has not been allocated yet then
1467 // relayout is disabled
1468 return mRelayoutData && mRelayoutData->relayoutEnabled;
1471 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1473 EnsureRelayoutData();
1475 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1477 if( dimension & ( 1 << i ) )
1479 mRelayoutData->dimensionDirty[ i ] = dirty;
1484 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1486 if ( mRelayoutData )
1488 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1490 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1500 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1502 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1505 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1507 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1510 unsigned int Actor::AddRenderer( Renderer& renderer )
1514 mRenderers = new RendererContainer;
1517 unsigned int index = mRenderers->size();
1518 RendererPtr rendererPtr = RendererPtr( &renderer );
1519 mRenderers->push_back( rendererPtr );
1520 AddRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1524 unsigned int Actor::GetRendererCount() const
1526 unsigned int rendererCount(0);
1529 rendererCount = mRenderers->size();
1532 return rendererCount;
1535 RendererPtr Actor::GetRendererAt( unsigned int index )
1537 RendererPtr renderer;
1538 if( index < GetRendererCount() )
1540 renderer = ( *mRenderers )[ index ];
1546 void Actor::RemoveRenderer( Renderer& renderer )
1550 RendererIter end = mRenderers->end();
1551 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1553 if( (*iter).Get() == &renderer )
1555 mRenderers->erase( iter );
1556 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1563 void Actor::RemoveRenderer( unsigned int index )
1565 if( index < GetRendererCount() )
1567 RendererPtr renderer = ( *mRenderers )[ index ];
1568 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.Get()->GetRendererSceneObject() );
1569 mRenderers->erase( mRenderers->begin()+index );
1573 bool Actor::IsOverlay() const
1575 return ( DrawMode::OVERLAY_2D == mDrawMode );
1578 void Actor::SetDrawMode( DrawMode::Type drawMode )
1580 // this flag is not animatable so keep the value
1581 mDrawMode = drawMode;
1582 if( ( NULL != mNode ) && ( drawMode != DrawMode::STENCIL ) )
1584 // mNode is being used in a separate thread; queue a message to set the value
1585 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1589 DrawMode::Type Actor::GetDrawMode() const
1594 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1596 // only valid when on-stage
1597 StagePtr stage = Stage::GetCurrent();
1598 if( stage && OnStage() )
1600 const RenderTaskList& taskList = stage->GetRenderTaskList();
1602 Vector2 converted( screenX, screenY );
1604 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1605 const int taskCount = taskList.GetTaskCount();
1606 for( int i = taskCount - 1; i >= 0; --i )
1608 Dali::RenderTask task = taskList.GetTask( i );
1609 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1611 // found a task where this conversion was ok so return
1619 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1621 bool retval = false;
1622 // only valid when on-stage
1625 CameraActor* camera = renderTask.GetCameraActor();
1629 renderTask.GetViewport( viewport );
1631 // need to translate coordinates to render tasks coordinate space
1632 Vector2 converted( screenX, screenY );
1633 if( renderTask.TranslateCoordinates( converted ) )
1635 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1642 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1644 // Early-out if mNode is NULL
1650 // Get the ModelView matrix
1652 Matrix::Multiply( modelView, mNode->GetWorldMatrix(0), viewMatrix );
1654 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1655 Matrix invertedMvp( false/*don't init*/);
1656 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1657 bool success = invertedMvp.Invert();
1659 // Convert to GL coordinates
1660 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1665 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1672 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1678 if( XyPlaneIntersect( nearPos, farPos, local ) )
1680 Vector3 size = GetCurrentSize();
1681 localX = local.x + size.x * 0.5f;
1682 localY = local.y + size.y * 0.5f;
1693 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1696 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1698 Mathematical Formulation
1700 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1702 ( p - c ) dot ( p - c ) = r^2
1704 Given a ray with a point of origin 'o', and a direction vector 'd':
1706 ray(t) = o + td, t >= 0
1708 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1710 (o + td - c ) dot ( o + td - c ) = r^2
1712 To solve for t we first expand the above into a more recognisable quadratic equation form
1714 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1723 B = 2( o - c ) dot d
1724 C = ( o - c ) dot ( o - c ) - r^2
1726 which can be solved using a standard quadratic formula.
1728 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1730 Practical Simplification
1732 In a renderer, we often differentiate between world space and object space. In the object space
1733 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1734 into object space, the mathematical solution presented above can be simplified significantly.
1736 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1740 and we can find the t at which the (transformed) ray intersects the sphere by
1742 ( o + td ) dot ( o + td ) = r^2
1744 According to the reasoning above, we expand the above quadratic equation into the general form
1748 which now has coefficients:
1755 // Early out if mNode is NULL
1761 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1763 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1764 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1765 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1767 // Compute the radius is not needed, square radius it's enough.
1768 const Vector3& size( mNode->GetSize( bufferIndex ) );
1770 // Scale the sphere.
1771 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1773 const float width = size.width * scale.width;
1774 const float height = size.height * scale.height;
1776 float squareSphereRadius = 0.5f * ( width * width + height * height );
1778 float a = rayDir.Dot( rayDir ); // a
1779 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1780 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1782 return ( b2 * b2 - a * c ) >= 0.f;
1785 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector2& hitPointLocal, float& distance ) const
1789 if( OnStage() && NULL != mNode )
1791 // Transforms the ray to the local reference system.
1792 // Calculate the inverse of Model matrix
1793 Matrix invModelMatrix( false/*don't init*/);
1795 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1796 invModelMatrix = mNode->GetWorldMatrix(0);
1797 invModelMatrix.Invert();
1799 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1800 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1802 // Test with the actor's XY plane (Normal = 0 0 1 1).
1804 float a = -rayOriginLocal.z;
1805 float b = rayDirLocal.z;
1807 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1809 // Ray travels distance * rayDirLocal to intersect with plane.
1812 const Vector3& size = mNode->GetSize( bufferIndex );
1814 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1815 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1817 // Test with the actor's geometry.
1818 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1825 void Actor::SetLeaveRequired( bool required )
1827 mLeaveRequired = required;
1830 bool Actor::GetLeaveRequired() const
1832 return mLeaveRequired;
1835 void Actor::SetKeyboardFocusable( bool focusable )
1837 mKeyboardFocusable = focusable;
1840 bool Actor::IsKeyboardFocusable() const
1842 return mKeyboardFocusable;
1845 bool Actor::GetTouchRequired() const
1847 return !mTouchedSignal.Empty() || !mTouchSignal.Empty() || mDerivedRequiresTouch;
1850 bool Actor::GetHoverRequired() const
1852 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1855 bool Actor::GetWheelEventRequired() const
1857 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1860 bool Actor::IsHittable() const
1862 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1865 ActorGestureData& Actor::GetGestureData()
1867 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1868 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1869 if( NULL == mGestureData )
1871 mGestureData = new ActorGestureData;
1873 return *mGestureData;
1876 bool Actor::IsGestureRequred( Gesture::Type type ) const
1878 return mGestureData && mGestureData->IsGestureRequred( type );
1881 bool Actor::EmitTouchEventSignal( const TouchEvent& event, const Dali::TouchData& touch )
1883 bool consumed = false;
1885 if( !mTouchSignal.Empty() )
1887 Dali::Actor handle( this );
1888 consumed = mTouchSignal.Emit( handle, touch );
1891 if( !mTouchedSignal.Empty() )
1893 Dali::Actor handle( this );
1894 consumed |= mTouchedSignal.Emit( handle, event );
1899 // Notification for derived classes
1900 consumed = OnTouchEvent( event ); // TODO
1906 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1908 bool consumed = false;
1910 if( !mHoveredSignal.Empty() )
1912 Dali::Actor handle( this );
1913 consumed = mHoveredSignal.Emit( handle, event );
1918 // Notification for derived classes
1919 consumed = OnHoverEvent( event );
1925 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1927 bool consumed = false;
1929 if( !mWheelEventSignal.Empty() )
1931 Dali::Actor handle( this );
1932 consumed = mWheelEventSignal.Emit( handle, event );
1937 // Notification for derived classes
1938 consumed = OnWheelEvent( event );
1944 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
1946 return mTouchedSignal;
1949 Dali::Actor::TouchDataSignalType& Actor::TouchSignal()
1951 return mTouchSignal;
1954 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
1956 return mHoveredSignal;
1959 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
1961 return mWheelEventSignal;
1964 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
1966 return mOnStageSignal;
1969 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
1971 return mOffStageSignal;
1974 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
1976 return mOnRelayoutSignal;
1979 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1981 bool connected( true );
1982 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
1984 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1986 actor->TouchedSignal().Connect( tracker, functor );
1988 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1990 actor->HoveredSignal().Connect( tracker, functor );
1992 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1994 actor->WheelEventSignal().Connect( tracker, functor );
1996 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
1998 actor->OnStageSignal().Connect( tracker, functor );
2000 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
2002 actor->OffStageSignal().Connect( tracker, functor );
2004 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
2006 actor->OnRelayoutSignal().Connect( tracker, functor );
2008 else if( 0 == signalName.compare( SIGNAL_TOUCH ) )
2010 actor->TouchSignal().Connect( tracker, functor );
2014 // signalName does not match any signal
2021 Actor::Actor( DerivedType derivedType )
2026 mParentOrigin( NULL ),
2027 mAnchorPoint( NULL ),
2028 mRelayoutData( NULL ),
2029 mGestureData( NULL ),
2030 mTargetSize( 0.0f, 0.0f, 0.0f ),
2032 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
2035 mIsRoot( ROOT_LAYER == derivedType ),
2036 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2037 mIsOnStage( false ),
2039 mLeaveRequired( false ),
2040 mKeyboardFocusable( false ),
2041 mDerivedRequiresTouch( false ),
2042 mDerivedRequiresHover( false ),
2043 mDerivedRequiresWheelEvent( false ),
2044 mOnStageSignalled( false ),
2045 mInsideOnSizeSet( false ),
2046 mInheritPosition( true ),
2047 mInheritOrientation( true ),
2048 mInheritScale( true ),
2049 mDrawMode( DrawMode::NORMAL ),
2050 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2051 mColorMode( Node::DEFAULT_COLOR_MODE ),
2052 mClippingMode( ClippingMode::DISABLED )
2056 void Actor::Initialize()
2059 SceneGraph::Node* node = CreateNode();
2061 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
2062 mNode = node; // Keep raw-pointer to Node
2066 GetEventThreadServices().RegisterObject( this );
2071 // Remove mParent pointers from children even if we're destroying core,
2072 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2075 ActorConstIter endIter = mChildren->end();
2076 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2078 (*iter)->SetParent( NULL );
2084 // Guard to allow handle destruction after Core has been destroyed
2085 if( EventThreadServices::IsCoreRunning() )
2089 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2090 mNode = NULL; // Node is about to be destroyed
2093 GetEventThreadServices().UnregisterObject( this );
2096 // Cleanup optional gesture data
2097 delete mGestureData;
2099 // Cleanup optional parent origin and anchor
2100 delete mParentOrigin;
2101 delete mAnchorPoint;
2103 // Delete optional relayout data
2106 delete mRelayoutData;
2110 void Actor::ConnectToStage( unsigned int parentDepth )
2112 // This container is used instead of walking the Actor hierarchy.
2113 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
2114 ActorContainer connectionList;
2116 // This stage is atomic i.e. not interrupted by user callbacks.
2117 RecursiveConnectToStage( connectionList, parentDepth + 1 );
2119 // Notify applications about the newly connected actors.
2120 const ActorIter endIter = connectionList.end();
2121 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2123 (*iter)->NotifyStageConnection();
2129 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth )
2131 DALI_ASSERT_ALWAYS( !OnStage() );
2135 SetDepthIndexMessage( GetEventThreadServices(), *mNode, GetDepthIndex( mDepth, mSiblingOrder ) );
2137 ConnectToSceneGraph();
2139 // Notification for internal derived classes
2140 OnStageConnectionInternal();
2142 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2143 connectionList.push_back( ActorPtr( this ) );
2145 // Recursively connect children
2148 ActorConstIter endIter = mChildren->end();
2149 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2151 (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
2157 * This method is called when the Actor is connected to the Stage.
2158 * The parent must have added its Node to the scene-graph.
2159 * The child must connect its Node to the parent's Node.
2160 * This is recursive; the child calls ConnectToStage() for its children.
2162 void Actor::ConnectToSceneGraph()
2164 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2168 // Reparent Node in next Update
2169 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode );
2172 // Request relayout on all actors that are added to the scenegraph
2175 // Notification for Object::Observers
2179 void Actor::NotifyStageConnection()
2181 // Actors can be removed (in a callback), before the on-stage stage is reported.
2182 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2183 if( OnStage() && !mOnStageSignalled )
2185 // Notification for external (CustomActor) derived classes
2186 OnStageConnectionExternal( mDepth );
2188 if( !mOnStageSignal.Empty() )
2190 Dali::Actor handle( this );
2191 mOnStageSignal.Emit( handle );
2194 // Guard against Remove during callbacks
2197 mOnStageSignalled = true; // signal required next time Actor is removed
2202 void Actor::DisconnectFromStage()
2204 // This container is used instead of walking the Actor hierachy.
2205 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2206 ActorContainer disconnectionList;
2208 // This stage is atomic i.e. not interrupted by user callbacks
2209 RecursiveDisconnectFromStage( disconnectionList );
2211 // Notify applications about the newly disconnected actors.
2212 const ActorIter endIter = disconnectionList.end();
2213 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2215 (*iter)->NotifyStageDisconnection();
2219 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2221 DALI_ASSERT_ALWAYS( OnStage() );
2223 // Recursively disconnect children
2226 ActorConstIter endIter = mChildren->end();
2227 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2229 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2233 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2234 disconnectionList.push_back( ActorPtr( this ) );
2236 // Notification for internal derived classes
2237 OnStageDisconnectionInternal();
2239 DisconnectFromSceneGraph();
2245 * This method is called by an actor or its parent, before a node removal message is sent.
2246 * This is recursive; the child calls DisconnectFromStage() for its children.
2248 void Actor::DisconnectFromSceneGraph()
2250 // Notification for Object::Observers
2251 OnSceneObjectRemove();
2254 void Actor::NotifyStageDisconnection()
2256 // Actors can be added (in a callback), before the off-stage state is reported.
2257 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2258 // only do this step if there is a stage, i.e. Core is not being shut down
2259 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2261 // Notification for external (CustomeActor) derived classes
2262 OnStageDisconnectionExternal();
2264 if( !mOffStageSignal.Empty() )
2266 Dali::Actor handle( this );
2267 mOffStageSignal.Emit( handle );
2270 // Guard against Add during callbacks
2273 mOnStageSignalled = false; // signal required next time Actor is added
2278 bool Actor::IsNodeConnected() const
2280 bool connected( false );
2282 if( OnStage() && ( NULL != mNode ) )
2284 if( IsRoot() || mNode->GetParent() )
2293 unsigned int Actor::GetDefaultPropertyCount() const
2295 return DEFAULT_PROPERTY_COUNT;
2298 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2300 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2302 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2304 indices.PushBack( i );
2308 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2310 if( index < DEFAULT_PROPERTY_COUNT )
2312 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2318 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2320 Property::Index index = Property::INVALID_INDEX;
2322 // Look for name in default properties
2323 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2325 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2326 if( 0 == name.compare( property->name ) )
2336 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2338 if( index < DEFAULT_PROPERTY_COUNT )
2340 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2346 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2348 if( index < DEFAULT_PROPERTY_COUNT )
2350 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2356 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2358 if( index < DEFAULT_PROPERTY_COUNT )
2360 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2366 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2368 if( index < DEFAULT_PROPERTY_COUNT )
2370 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2373 // index out of range...return Property::NONE
2374 return Property::NONE;
2377 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2381 case Dali::Actor::Property::PARENT_ORIGIN:
2383 Property::Type type = property.GetType();
2384 if( type == Property::VECTOR3 )
2386 SetParentOrigin( property.Get< Vector3 >() );
2388 else if ( type == Property::STRING )
2390 std::string parentOriginString;
2391 property.Get( parentOriginString );
2392 Vector3 parentOrigin;
2393 if( GetParentOriginConstant( parentOriginString, parentOrigin ) )
2395 SetParentOrigin( parentOrigin );
2401 case Dali::Actor::Property::PARENT_ORIGIN_X:
2403 SetParentOriginX( property.Get< float >() );
2407 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2409 SetParentOriginY( property.Get< float >() );
2413 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2415 SetParentOriginZ( property.Get< float >() );
2419 case Dali::Actor::Property::ANCHOR_POINT:
2421 Property::Type type = property.GetType();
2422 if( type == Property::VECTOR3 )
2424 SetAnchorPoint( property.Get< Vector3 >() );
2426 else if ( type == Property::STRING )
2428 std::string anchorPointString;
2429 property.Get( anchorPointString );
2431 if( GetAnchorPointConstant( anchorPointString, anchor ) )
2433 SetAnchorPoint( anchor );
2439 case Dali::Actor::Property::ANCHOR_POINT_X:
2441 SetAnchorPointX( property.Get< float >() );
2445 case Dali::Actor::Property::ANCHOR_POINT_Y:
2447 SetAnchorPointY( property.Get< float >() );
2451 case Dali::Actor::Property::ANCHOR_POINT_Z:
2453 SetAnchorPointZ( property.Get< float >() );
2457 case Dali::Actor::Property::SIZE:
2459 SetSize( property.Get< Vector3 >() );
2463 case Dali::Actor::Property::SIZE_WIDTH:
2465 SetWidth( property.Get< float >() );
2469 case Dali::Actor::Property::SIZE_HEIGHT:
2471 SetHeight( property.Get< float >() );
2475 case Dali::Actor::Property::SIZE_DEPTH:
2477 SetDepth( property.Get< float >() );
2481 case Dali::Actor::Property::POSITION:
2483 SetPosition( property.Get< Vector3 >() );
2487 case Dali::Actor::Property::POSITION_X:
2489 SetX( property.Get< float >() );
2493 case Dali::Actor::Property::POSITION_Y:
2495 SetY( property.Get< float >() );
2499 case Dali::Actor::Property::POSITION_Z:
2501 SetZ( property.Get< float >() );
2505 case Dali::Actor::Property::ORIENTATION:
2507 SetOrientation( property.Get< Quaternion >() );
2511 case Dali::Actor::Property::SCALE:
2513 SetScale( property.Get< Vector3 >() );
2517 case Dali::Actor::Property::SCALE_X:
2519 SetScaleX( property.Get< float >() );
2523 case Dali::Actor::Property::SCALE_Y:
2525 SetScaleY( property.Get< float >() );
2529 case Dali::Actor::Property::SCALE_Z:
2531 SetScaleZ( property.Get< float >() );
2535 case Dali::Actor::Property::VISIBLE:
2537 SetVisible( property.Get< bool >() );
2541 case Dali::Actor::Property::COLOR:
2543 SetColor( property.Get< Vector4 >() );
2547 case Dali::Actor::Property::COLOR_RED:
2549 SetColorRed( property.Get< float >() );
2553 case Dali::Actor::Property::COLOR_GREEN:
2555 SetColorGreen( property.Get< float >() );
2559 case Dali::Actor::Property::COLOR_BLUE:
2561 SetColorBlue( property.Get< float >() );
2565 case Dali::Actor::Property::COLOR_ALPHA:
2566 case Dali::DevelActor::Property::OPACITY:
2569 if( property.Get( value ) )
2571 SetOpacity( value );
2576 case Dali::Actor::Property::NAME:
2578 SetName( property.Get< std::string >() );
2582 case Dali::Actor::Property::SENSITIVE:
2584 SetSensitive( property.Get< bool >() );
2588 case Dali::Actor::Property::LEAVE_REQUIRED:
2590 SetLeaveRequired( property.Get< bool >() );
2594 case Dali::Actor::Property::INHERIT_POSITION:
2596 SetInheritPosition( property.Get< bool >() );
2600 case Dali::Actor::Property::INHERIT_ORIENTATION:
2602 SetInheritOrientation( property.Get< bool >() );
2606 case Dali::Actor::Property::INHERIT_SCALE:
2608 SetInheritScale( property.Get< bool >() );
2612 case Dali::Actor::Property::COLOR_MODE:
2614 ColorMode mode = mColorMode;
2615 if ( Scripting::GetEnumerationProperty< ColorMode >( property, COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT, mode ) )
2617 SetColorMode( mode );
2622 case Dali::Actor::Property::POSITION_INHERITANCE:
2624 PositionInheritanceMode mode = mPositionInheritanceMode;
2625 if( Scripting::GetEnumerationProperty< PositionInheritanceMode >( property, POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT, mode ) )
2627 SetPositionInheritanceMode( mode );
2632 case Dali::Actor::Property::DRAW_MODE:
2634 DrawMode::Type mode = mDrawMode;
2635 if( Scripting::GetEnumerationProperty< DrawMode::Type >( property, DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT, mode ) )
2637 SetDrawMode( mode );
2642 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2644 SetSizeModeFactor( property.Get< Vector3 >() );
2648 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2650 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
2651 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2653 SetResizePolicy( type, Dimension::WIDTH );
2658 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2660 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
2661 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2663 SetResizePolicy( type, Dimension::HEIGHT );
2668 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2670 SizeScalePolicy::Type type;
2671 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT, type ) )
2673 SetSizeScalePolicy( type );
2678 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2680 if( property.Get< bool >() )
2682 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2687 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2689 if( property.Get< bool >() )
2691 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2696 case Dali::Actor::Property::PADDING:
2698 Vector4 padding = property.Get< Vector4 >();
2699 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2700 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2704 case Dali::Actor::Property::MINIMUM_SIZE:
2706 Vector2 size = property.Get< Vector2 >();
2707 SetMinimumSize( size.x, Dimension::WIDTH );
2708 SetMinimumSize( size.y, Dimension::HEIGHT );
2712 case Dali::Actor::Property::MAXIMUM_SIZE:
2714 Vector2 size = property.Get< Vector2 >();
2715 SetMaximumSize( size.x, Dimension::WIDTH );
2716 SetMaximumSize( size.y, Dimension::HEIGHT );
2720 case Dali::DevelActor::Property::SIBLING_ORDER:
2724 if( property.Get( value ) )
2726 if( static_cast<unsigned int>(value) != mSiblingOrder )
2728 SetSiblingOrder( value );
2734 case Dali::Actor::Property::CLIPPING_MODE:
2736 ClippingMode::Type convertedValue = mClippingMode;
2737 if( Scripting::GetEnumerationProperty< ClippingMode::Type >( property, CLIPPING_MODE_TABLE, CLIPPING_MODE_TABLE_COUNT, convertedValue ) )
2739 mClippingMode = convertedValue;
2742 SetClippingModeMessage( GetEventThreadServices(), *mNode, mClippingMode );
2750 // this can happen in the case of a non-animatable default property so just do nothing
2756 // TODO: This method needs to be removed
2757 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2759 switch( entry.GetType() )
2761 case Property::BOOLEAN:
2763 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2764 DALI_ASSERT_DEBUG( NULL != property );
2766 // property is being used in a separate thread; queue a message to set the property
2767 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2772 case Property::INTEGER:
2774 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2775 DALI_ASSERT_DEBUG( NULL != property );
2777 // property is being used in a separate thread; queue a message to set the property
2778 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2783 case Property::FLOAT:
2785 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2786 DALI_ASSERT_DEBUG( NULL != property );
2788 // property is being used in a separate thread; queue a message to set the property
2789 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2794 case Property::VECTOR2:
2796 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2797 DALI_ASSERT_DEBUG( NULL != property );
2799 // property is being used in a separate thread; queue a message to set the property
2800 if(entry.componentIndex == 0)
2802 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2804 else if(entry.componentIndex == 1)
2806 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2810 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2816 case Property::VECTOR3:
2818 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2819 DALI_ASSERT_DEBUG( NULL != property );
2821 // property is being used in a separate thread; queue a message to set the property
2822 if(entry.componentIndex == 0)
2824 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2826 else if(entry.componentIndex == 1)
2828 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2830 else if(entry.componentIndex == 2)
2832 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2836 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2842 case Property::VECTOR4:
2844 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2845 DALI_ASSERT_DEBUG( NULL != property );
2847 // property is being used in a separate thread; queue a message to set the property
2848 if(entry.componentIndex == 0)
2850 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
2852 else if(entry.componentIndex == 1)
2854 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
2856 else if(entry.componentIndex == 2)
2858 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
2860 else if(entry.componentIndex == 3)
2862 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
2866 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2872 case Property::ROTATION:
2874 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
2875 DALI_ASSERT_DEBUG( NULL != property );
2877 // property is being used in a separate thread; queue a message to set the property
2878 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
2883 case Property::MATRIX:
2885 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
2886 DALI_ASSERT_DEBUG( NULL != property );
2888 // property is being used in a separate thread; queue a message to set the property
2889 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
2894 case Property::MATRIX3:
2896 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
2897 DALI_ASSERT_DEBUG( NULL != property );
2899 // property is being used in a separate thread; queue a message to set the property
2900 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
2907 // nothing to do for other types
2912 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
2914 Property::Value value;
2916 if( index >= DEFAULT_PROPERTY_COUNT )
2923 case Dali::Actor::Property::PARENT_ORIGIN:
2925 value = GetCurrentParentOrigin();
2929 case Dali::Actor::Property::PARENT_ORIGIN_X:
2931 value = GetCurrentParentOrigin().x;
2935 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2937 value = GetCurrentParentOrigin().y;
2941 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2943 value = GetCurrentParentOrigin().z;
2947 case Dali::Actor::Property::ANCHOR_POINT:
2949 value = GetCurrentAnchorPoint();
2953 case Dali::Actor::Property::ANCHOR_POINT_X:
2955 value = GetCurrentAnchorPoint().x;
2959 case Dali::Actor::Property::ANCHOR_POINT_Y:
2961 value = GetCurrentAnchorPoint().y;
2965 case Dali::Actor::Property::ANCHOR_POINT_Z:
2967 value = GetCurrentAnchorPoint().z;
2971 case Dali::Actor::Property::SIZE:
2973 Vector3 size = GetTargetSize();
2975 // Should return preferred size if size is fixed as set by SetSize
2976 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
2978 size.width = GetPreferredSize().width;
2980 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
2982 size.height = GetPreferredSize().height;
2990 case Dali::Actor::Property::SIZE_WIDTH:
2992 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
2994 // Should return preferred size if size is fixed as set by SetSize
2995 value = GetPreferredSize().width;
2999 value = GetTargetSize().width;
3004 case Dali::Actor::Property::SIZE_HEIGHT:
3006 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
3008 // Should return preferred size if size is fixed as set by SetSize
3009 value = GetPreferredSize().height;
3013 value = GetTargetSize().height;
3018 case Dali::Actor::Property::SIZE_DEPTH:
3020 value = GetTargetSize().depth;
3024 case Dali::Actor::Property::POSITION:
3026 value = GetTargetPosition();
3030 case Dali::Actor::Property::POSITION_X:
3032 value = GetTargetPosition().x;
3036 case Dali::Actor::Property::POSITION_Y:
3038 value = GetTargetPosition().y;
3042 case Dali::Actor::Property::POSITION_Z:
3044 value = GetTargetPosition().z;
3048 case Dali::Actor::Property::WORLD_POSITION:
3050 value = GetCurrentWorldPosition();
3054 case Dali::Actor::Property::WORLD_POSITION_X:
3056 value = GetCurrentWorldPosition().x;
3060 case Dali::Actor::Property::WORLD_POSITION_Y:
3062 value = GetCurrentWorldPosition().y;
3066 case Dali::Actor::Property::WORLD_POSITION_Z:
3068 value = GetCurrentWorldPosition().z;
3072 case Dali::Actor::Property::ORIENTATION:
3074 value = GetCurrentOrientation();
3078 case Dali::Actor::Property::WORLD_ORIENTATION:
3080 value = GetCurrentWorldOrientation();
3084 case Dali::Actor::Property::SCALE:
3086 value = GetCurrentScale();
3090 case Dali::Actor::Property::SCALE_X:
3092 value = GetCurrentScale().x;
3096 case Dali::Actor::Property::SCALE_Y:
3098 value = GetCurrentScale().y;
3102 case Dali::Actor::Property::SCALE_Z:
3104 value = GetCurrentScale().z;
3108 case Dali::Actor::Property::WORLD_SCALE:
3110 value = GetCurrentWorldScale();
3114 case Dali::Actor::Property::VISIBLE:
3116 value = IsVisible();
3120 case Dali::Actor::Property::COLOR:
3122 value = GetCurrentColor();
3126 case Dali::Actor::Property::COLOR_RED:
3128 value = GetCurrentColor().r;
3132 case Dali::Actor::Property::COLOR_GREEN:
3134 value = GetCurrentColor().g;
3138 case Dali::Actor::Property::COLOR_BLUE:
3140 value = GetCurrentColor().b;
3144 case Dali::Actor::Property::COLOR_ALPHA:
3145 case Dali::DevelActor::Property::OPACITY:
3147 value = GetCurrentColor().a;
3151 case Dali::Actor::Property::WORLD_COLOR:
3153 value = GetCurrentWorldColor();
3157 case Dali::Actor::Property::WORLD_MATRIX:
3159 value = GetCurrentWorldMatrix();
3163 case Dali::Actor::Property::NAME:
3169 case Dali::Actor::Property::SENSITIVE:
3171 value = IsSensitive();
3175 case Dali::Actor::Property::LEAVE_REQUIRED:
3177 value = GetLeaveRequired();
3181 case Dali::Actor::Property::INHERIT_POSITION:
3183 value = IsPositionInherited();
3187 case Dali::Actor::Property::INHERIT_ORIENTATION:
3189 value = IsOrientationInherited();
3193 case Dali::Actor::Property::INHERIT_SCALE:
3195 value = IsScaleInherited();
3199 case Dali::Actor::Property::COLOR_MODE:
3201 value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
3205 case Dali::Actor::Property::POSITION_INHERITANCE:
3207 value = Scripting::GetLinearEnumerationName< PositionInheritanceMode >( GetPositionInheritanceMode(), POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT );
3211 case Dali::Actor::Property::DRAW_MODE:
3213 value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
3217 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3219 value = GetSizeModeFactor();
3223 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3225 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3229 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3231 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3235 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3237 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT );
3241 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3243 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3247 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3249 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3253 case Dali::Actor::Property::PADDING:
3255 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3256 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3257 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3261 case Dali::Actor::Property::MINIMUM_SIZE:
3263 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3267 case Dali::Actor::Property::MAXIMUM_SIZE:
3269 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3273 case Dali::DevelActor::Property::SIBLING_ORDER:
3275 value = static_cast<int>(mSiblingOrder);
3279 case Dali::Actor::Property::CLIPPING_MODE:
3281 value = mClippingMode;
3289 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3294 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3296 // This method should only return an object connected to the scene-graph
3297 return OnStage() ? mNode : NULL;
3300 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3302 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3304 const PropertyBase* property( NULL );
3306 // This method should only return a property of an object connected to the scene-graph
3312 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3314 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3315 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3317 property = animatable->GetSceneGraphProperty();
3319 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3320 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3322 CustomPropertyMetadata* custom = FindCustomProperty( index );
3323 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3325 property = custom->GetSceneGraphProperty();
3327 else if( NULL != mNode )
3331 case Dali::Actor::Property::SIZE:
3332 property = &mNode->mSize;
3335 case Dali::Actor::Property::SIZE_WIDTH:
3336 property = &mNode->mSize;
3339 case Dali::Actor::Property::SIZE_HEIGHT:
3340 property = &mNode->mSize;
3343 case Dali::Actor::Property::SIZE_DEPTH:
3344 property = &mNode->mSize;
3347 case Dali::Actor::Property::POSITION:
3348 property = &mNode->mPosition;
3351 case Dali::Actor::Property::POSITION_X:
3352 property = &mNode->mPosition;
3355 case Dali::Actor::Property::POSITION_Y:
3356 property = &mNode->mPosition;
3359 case Dali::Actor::Property::POSITION_Z:
3360 property = &mNode->mPosition;
3363 case Dali::Actor::Property::ORIENTATION:
3364 property = &mNode->mOrientation;
3367 case Dali::Actor::Property::SCALE:
3368 property = &mNode->mScale;
3371 case Dali::Actor::Property::SCALE_X:
3372 property = &mNode->mScale;
3375 case Dali::Actor::Property::SCALE_Y:
3376 property = &mNode->mScale;
3379 case Dali::Actor::Property::SCALE_Z:
3380 property = &mNode->mScale;
3383 case Dali::Actor::Property::VISIBLE:
3384 property = &mNode->mVisible;
3387 case Dali::Actor::Property::COLOR:
3388 property = &mNode->mColor;
3391 case Dali::Actor::Property::COLOR_RED:
3392 property = &mNode->mColor;
3395 case Dali::Actor::Property::COLOR_GREEN:
3396 property = &mNode->mColor;
3399 case Dali::Actor::Property::COLOR_BLUE:
3400 property = &mNode->mColor;
3403 case Dali::Actor::Property::COLOR_ALPHA:
3404 case Dali::DevelActor::Property::OPACITY:
3405 property = &mNode->mColor;
3416 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3418 const PropertyInputImpl* property( NULL );
3420 // This method should only return a property of an object connected to the scene-graph
3426 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3428 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3429 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3431 property = animatable->GetSceneGraphProperty();
3433 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3434 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3436 CustomPropertyMetadata* custom = FindCustomProperty( index );
3437 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3438 property = custom->GetSceneGraphProperty();
3440 else if( NULL != mNode )
3444 case Dali::Actor::Property::PARENT_ORIGIN:
3445 property = &mNode->mParentOrigin;
3448 case Dali::Actor::Property::PARENT_ORIGIN_X:
3449 property = &mNode->mParentOrigin;
3452 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3453 property = &mNode->mParentOrigin;
3456 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3457 property = &mNode->mParentOrigin;
3460 case Dali::Actor::Property::ANCHOR_POINT:
3461 property = &mNode->mAnchorPoint;
3464 case Dali::Actor::Property::ANCHOR_POINT_X:
3465 property = &mNode->mAnchorPoint;
3468 case Dali::Actor::Property::ANCHOR_POINT_Y:
3469 property = &mNode->mAnchorPoint;
3472 case Dali::Actor::Property::ANCHOR_POINT_Z:
3473 property = &mNode->mAnchorPoint;
3476 case Dali::Actor::Property::SIZE:
3477 property = &mNode->mSize;
3480 case Dali::Actor::Property::SIZE_WIDTH:
3481 property = &mNode->mSize;
3484 case Dali::Actor::Property::SIZE_HEIGHT:
3485 property = &mNode->mSize;
3488 case Dali::Actor::Property::SIZE_DEPTH:
3489 property = &mNode->mSize;
3492 case Dali::Actor::Property::POSITION:
3493 property = &mNode->mPosition;
3496 case Dali::Actor::Property::POSITION_X:
3497 property = &mNode->mPosition;
3500 case Dali::Actor::Property::POSITION_Y:
3501 property = &mNode->mPosition;
3504 case Dali::Actor::Property::POSITION_Z:
3505 property = &mNode->mPosition;
3508 case Dali::Actor::Property::WORLD_POSITION:
3509 property = &mNode->mWorldPosition;
3512 case Dali::Actor::Property::WORLD_POSITION_X:
3513 property = &mNode->mWorldPosition;
3516 case Dali::Actor::Property::WORLD_POSITION_Y:
3517 property = &mNode->mWorldPosition;
3520 case Dali::Actor::Property::WORLD_POSITION_Z:
3521 property = &mNode->mWorldPosition;
3524 case Dali::Actor::Property::ORIENTATION:
3525 property = &mNode->mOrientation;
3528 case Dali::Actor::Property::WORLD_ORIENTATION:
3529 property = &mNode->mWorldOrientation;
3532 case Dali::Actor::Property::SCALE:
3533 property = &mNode->mScale;
3536 case Dali::Actor::Property::SCALE_X:
3537 property = &mNode->mScale;
3540 case Dali::Actor::Property::SCALE_Y:
3541 property = &mNode->mScale;
3544 case Dali::Actor::Property::SCALE_Z:
3545 property = &mNode->mScale;
3548 case Dali::Actor::Property::WORLD_SCALE:
3549 property = &mNode->mWorldScale;
3552 case Dali::Actor::Property::VISIBLE:
3553 property = &mNode->mVisible;
3556 case Dali::Actor::Property::COLOR:
3557 property = &mNode->mColor;
3560 case Dali::Actor::Property::COLOR_RED:
3561 property = &mNode->mColor;
3564 case Dali::Actor::Property::COLOR_GREEN:
3565 property = &mNode->mColor;
3568 case Dali::Actor::Property::COLOR_BLUE:
3569 property = &mNode->mColor;
3572 case Dali::Actor::Property::COLOR_ALPHA:
3573 case Dali::DevelActor::Property::OPACITY:
3575 property = &mNode->mColor;
3579 case Dali::Actor::Property::WORLD_COLOR:
3580 property = &mNode->mWorldColor;
3583 case Dali::Actor::Property::WORLD_MATRIX:
3584 property = &mNode->mWorldMatrix;
3595 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3597 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3599 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3601 // check whether the animatable property is registered already, if not then register one.
3602 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3603 if( animatableProperty )
3605 componentIndex = animatableProperty->componentIndex;
3612 case Dali::Actor::Property::PARENT_ORIGIN_X:
3613 case Dali::Actor::Property::ANCHOR_POINT_X:
3614 case Dali::Actor::Property::SIZE_WIDTH:
3615 case Dali::Actor::Property::POSITION_X:
3616 case Dali::Actor::Property::WORLD_POSITION_X:
3617 case Dali::Actor::Property::SCALE_X:
3618 case Dali::Actor::Property::COLOR_RED:
3624 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3625 case Dali::Actor::Property::ANCHOR_POINT_Y:
3626 case Dali::Actor::Property::SIZE_HEIGHT:
3627 case Dali::Actor::Property::POSITION_Y:
3628 case Dali::Actor::Property::WORLD_POSITION_Y:
3629 case Dali::Actor::Property::SCALE_Y:
3630 case Dali::Actor::Property::COLOR_GREEN:
3636 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3637 case Dali::Actor::Property::ANCHOR_POINT_Z:
3638 case Dali::Actor::Property::SIZE_DEPTH:
3639 case Dali::Actor::Property::POSITION_Z:
3640 case Dali::Actor::Property::WORLD_POSITION_Z:
3641 case Dali::Actor::Property::SCALE_Z:
3642 case Dali::Actor::Property::COLOR_BLUE:
3648 case Dali::Actor::Property::COLOR_ALPHA:
3649 case Dali::DevelActor::Property::OPACITY:
3663 return componentIndex;
3666 void Actor::SetParent( Actor* parent )
3670 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3674 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3677 // Instruct each actor to create a corresponding node in the scene graph
3678 ConnectToStage( parent->GetHierarchyDepth() );
3681 // Resolve the name and index for the child properties if any
3682 ResolveChildProperties();
3684 else // parent being set to NULL
3686 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3690 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3693 DALI_ASSERT_ALWAYS( mNode != NULL );
3697 // Disconnect the Node & its children from the scene-graph.
3698 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3701 // Instruct each actor to discard pointers to the scene-graph
3702 DisconnectFromStage();
3707 SceneGraph::Node* Actor::CreateNode() const
3712 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3715 Actor* actor = dynamic_cast< Actor* >( object );
3719 if( 0 == actionName.compare( ACTION_SHOW ) )
3721 actor->SetVisible( true );
3724 else if( 0 == actionName.compare( ACTION_HIDE ) )
3726 actor->SetVisible( false );
3734 void Actor::EnsureRelayoutData()
3736 // Assign relayout data.
3737 if( !mRelayoutData )
3739 mRelayoutData = new RelayoutData();
3743 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3745 // Check if actor is dependent on parent
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 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3761 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3763 // Check if actor is dependent on children
3764 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3766 if( ( dimension & ( 1 << i ) ) )
3768 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3769 switch( resizePolicy )
3771 case ResizePolicy::FIT_TO_CHILDREN:
3772 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3788 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3790 return Actor::RelayoutDependentOnChildren( dimension );
3793 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3795 // Check each possible dimension and see if it is dependent on the input one
3796 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3798 if( dimension & ( 1 << i ) )
3800 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3807 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3809 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3811 if( dimension & ( 1 << i ) )
3813 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3818 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3820 // If more than one dimension is requested, just return the first one found
3821 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3823 if( ( dimension & ( 1 << i ) ) )
3825 return mRelayoutData->negotiatedDimensions[ i ];
3829 return 0.0f; // Default
3832 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3834 EnsureRelayoutData();
3836 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3838 if( dimension & ( 1 << i ) )
3840 mRelayoutData->dimensionPadding[ i ] = padding;
3845 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3847 if ( mRelayoutData )
3849 // If more than one dimension is requested, just return the first one found
3850 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3852 if( ( dimension & ( 1 << i ) ) )
3854 return mRelayoutData->dimensionPadding[ i ];
3859 return GetDefaultDimensionPadding();
3862 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
3864 EnsureRelayoutData();
3866 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3868 if( dimension & ( 1 << i ) )
3870 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3875 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
3877 if ( mRelayoutData )
3879 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3881 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
3891 float Actor::GetHeightForWidthBase( float width )
3893 float height = 0.0f;
3895 const Vector3 naturalSize = GetNaturalSize();
3896 if( naturalSize.width > 0.0f )
3898 height = naturalSize.height * width / naturalSize.width;
3900 else // we treat 0 as 1:1 aspect ratio
3908 float Actor::GetWidthForHeightBase( float height )
3912 const Vector3 naturalSize = GetNaturalSize();
3913 if( naturalSize.height > 0.0f )
3915 width = naturalSize.width * height / naturalSize.height;
3917 else // we treat 0 as 1:1 aspect ratio
3925 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
3927 // Fill to parent, taking size mode factor into account
3928 switch( child.GetResizePolicy( dimension ) )
3930 case ResizePolicy::FILL_TO_PARENT:
3932 return GetLatestSize( dimension );
3935 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3937 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
3940 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3942 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
3947 return GetLatestSize( dimension );
3952 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
3954 // Can be overridden in derived class
3955 return CalculateChildSizeBase( child, dimension );
3958 float Actor::GetHeightForWidth( float width )
3960 // Can be overridden in derived class
3961 return GetHeightForWidthBase( width );
3964 float Actor::GetWidthForHeight( float height )
3966 // Can be overridden in derived class
3967 return GetWidthForHeightBase( height );
3970 float Actor::GetLatestSize( Dimension::Type dimension ) const
3972 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
3975 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
3977 Vector2 padding = GetPadding( dimension );
3979 return GetLatestSize( dimension ) + padding.x + padding.y;
3982 float Actor::NegotiateFromParent( Dimension::Type dimension )
3984 Actor* parent = GetParent();
3987 Vector2 padding( GetPadding( dimension ) );
3988 Vector2 parentPadding( parent->GetPadding( dimension ) );
3989 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
3995 float Actor::NegotiateFromChildren( Dimension::Type dimension )
3997 float maxDimensionPoint = 0.0f;
3999 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4001 ActorPtr child = GetChildAt( i );
4003 if( !child->RelayoutDependentOnParent( dimension ) )
4005 // Calculate the min and max points that the children range across
4006 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
4007 float dimensionSize = child->GetRelayoutSize( dimension );
4008 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4012 return maxDimensionPoint;
4015 float Actor::GetSize( Dimension::Type dimension ) const
4017 return GetDimensionValue( GetTargetSize(), dimension );
4020 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4022 return GetDimensionValue( GetNaturalSize(), dimension );
4025 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4027 switch( GetResizePolicy( dimension ) )
4029 case ResizePolicy::USE_NATURAL_SIZE:
4031 return GetNaturalSize( dimension );
4034 case ResizePolicy::FIXED:
4036 return GetDimensionValue( GetPreferredSize(), dimension );
4039 case ResizePolicy::USE_ASSIGNED_SIZE:
4041 return GetDimensionValue( maximumSize, dimension );
4044 case ResizePolicy::FILL_TO_PARENT:
4045 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4046 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4048 return NegotiateFromParent( dimension );
4051 case ResizePolicy::FIT_TO_CHILDREN:
4053 return NegotiateFromChildren( dimension );
4056 case ResizePolicy::DIMENSION_DEPENDENCY:
4058 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4061 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4063 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4066 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4068 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4080 return 0.0f; // Default
4083 float Actor::ClampDimension( float size, Dimension::Type dimension )
4085 const float minSize = GetMinimumSize( dimension );
4086 const float maxSize = GetMaximumSize( dimension );
4088 return std::max( minSize, std::min( size, maxSize ) );
4091 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4093 // Check if it needs to be negotiated
4094 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4096 // Check that we havn't gotten into an infinite loop
4097 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4098 bool recursionFound = false;
4099 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4101 if( *it == searchActor )
4103 recursionFound = true;
4108 if( !recursionFound )
4110 // Record the path that we have taken
4111 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4113 // Dimension dependency check
4114 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4116 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4118 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4120 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4124 // Parent dependency check
4125 Actor* parent = GetParent();
4126 if( parent && RelayoutDependentOnParent( dimension ) )
4128 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4131 // Children dependency check
4132 if( RelayoutDependentOnChildren( dimension ) )
4134 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4136 ActorPtr child = GetChildAt( i );
4138 // Only relayout child first if it is not dependent on this actor
4139 if( !child->RelayoutDependentOnParent( dimension ) )
4141 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
4146 // For deriving classes
4147 OnCalculateRelayoutSize( dimension );
4149 // All dependencies checked, calculate the size and set negotiated flag
4150 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4152 SetNegotiatedDimension( newSize, dimension );
4153 SetLayoutNegotiated( true, dimension );
4155 // For deriving classes
4156 OnLayoutNegotiated( newSize, dimension );
4158 // This actor has been successfully processed, pop it off the recursion stack
4159 recursionStack.pop_back();
4163 // TODO: Break infinite loop
4164 SetLayoutNegotiated( true, dimension );
4169 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4171 // Negotiate all dimensions that require it
4172 ActorDimensionStack recursionStack;
4174 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4176 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4179 NegotiateDimension( dimension, allocatedSize, recursionStack );
4183 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4185 switch( mRelayoutData->sizeSetPolicy )
4187 case SizeScalePolicy::USE_SIZE_SET:
4192 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4194 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4195 const Vector3 naturalSize = GetNaturalSize();
4196 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4198 const float sizeRatio = size.width / size.height;
4199 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4201 if( naturalSizeRatio < sizeRatio )
4203 return Vector2( naturalSizeRatio * size.height, size.height );
4205 else if( naturalSizeRatio > sizeRatio )
4207 return Vector2( size.width, size.width / naturalSizeRatio );
4218 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4220 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4221 const Vector3 naturalSize = GetNaturalSize();
4222 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4224 const float sizeRatio = size.width / size.height;
4225 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4227 if( naturalSizeRatio < sizeRatio )
4229 return Vector2( size.width, size.width / naturalSizeRatio );
4231 else if( naturalSizeRatio > sizeRatio )
4233 return Vector2( naturalSizeRatio * size.height, size.height );
4252 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4254 // Do the set actor size
4255 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4257 // Adjust for size set policy
4258 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4260 // Lock the flag to stop recursive relayouts on set size
4261 mRelayoutData->insideRelayout = true;
4262 SetSize( negotiatedSize );
4263 mRelayoutData->insideRelayout = false;
4265 // Clear flags for all dimensions
4266 SetLayoutDirty( false );
4268 // Give deriving classes a chance to respond
4269 OnRelayout( negotiatedSize, container );
4271 if( !mOnRelayoutSignal.Empty() )
4273 Dali::Actor handle( this );
4274 mOnRelayoutSignal.Emit( handle );
4278 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4280 // Force a size negotiation for actors that has assigned size during relayout
4281 // This is required as otherwise the flags that force a relayout will not
4282 // necessarilly be set. This will occur if the actor has already been laid out.
4283 // The dirty flags are then cleared. Then if the actor is added back into the
4284 // relayout container afterwards, the dirty flags would still be clear...
4285 // causing a relayout to be skipped. Here we force any actors added to the
4286 // container to be relayed out.
4287 if(GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE)
4289 SetLayoutNegotiated(false, Dimension::WIDTH);
4291 if(GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE)
4293 SetLayoutNegotiated(false, Dimension::HEIGHT);
4296 // Do the negotiation
4297 NegotiateDimensions( allocatedSize );
4299 // Set the actor size
4300 SetNegotiatedSize( container );
4302 // Negotiate down to children
4303 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4305 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4307 ActorPtr child = GetChildAt( i );
4309 // Forces children that have already been laid out to be relayed out
4310 // if they have assigned size during relayout.
4311 if(child->GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE)
4313 child->SetLayoutNegotiated(false, Dimension::WIDTH);
4314 child->SetLayoutDirty(true, Dimension::WIDTH);
4316 if(child->GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE)
4318 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
4319 child->SetLayoutDirty(true, Dimension::HEIGHT);
4322 // Only relayout if required
4323 if( child->RelayoutRequired() )
4325 container.Add( Dali::Actor( child.Get() ), newBounds );
4330 void Actor::RelayoutRequest( Dimension::Type dimension )
4332 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4333 if( relayoutController )
4335 Dali::Actor self( this );
4336 relayoutController->RequestRelayout( self, dimension );
4340 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4344 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4348 void Actor::SetPreferredSize( const Vector2& size )
4350 EnsureRelayoutData();
4352 if( size.width > 0.0f )
4354 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4357 if( size.height > 0.0f )
4359 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4362 mRelayoutData->preferredSize = size;
4367 Vector2 Actor::GetPreferredSize() const
4369 if ( mRelayoutData )
4371 return Vector2( mRelayoutData->preferredSize );
4374 return GetDefaultPreferredSize();
4377 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4379 EnsureRelayoutData();
4381 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4383 if( dimension & ( 1 << i ) )
4385 mRelayoutData->minimumSize[ i ] = size;
4392 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4394 if ( mRelayoutData )
4396 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4398 if( dimension & ( 1 << i ) )
4400 return mRelayoutData->minimumSize[ i ];
4405 return 0.0f; // Default
4408 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4410 EnsureRelayoutData();
4412 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4414 if( dimension & ( 1 << i ) )
4416 mRelayoutData->maximumSize[ i ] = size;
4423 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4425 if ( mRelayoutData )
4427 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4429 if( dimension & ( 1 << i ) )
4431 return mRelayoutData->maximumSize[ i ];
4436 return FLT_MAX; // Default
4439 Object* Actor::GetParentObject() const
4444 void Actor::SetSiblingOrder( unsigned int order )
4446 mSiblingOrder = std::min( order, static_cast<unsigned int>( DevelLayer::SIBLING_ORDER_MULTIPLIER ) );
4449 SetDepthIndexMessage( GetEventThreadServices(), *mNode, GetDepthIndex( mDepth, mSiblingOrder ) );
4453 void Actor::DefragmentSiblingIndexes( ActorContainer& siblings )
4455 // Sibling index may not be in consecutive order as the sibling range is limited ( DevelLayer::SIBLING_ORDER_MULTIPLIER )
4456 // we need to remove the gaps and ensure the number start from 0 and consecutive hence have a full range.
4458 // Start at index 0, while index <= highest order
4459 // Find next index higher than 0
4460 // if nextHigher > index+1
4461 // set all nextHigher orders to index+1
4463 // Limitation: May reach the ceiling of DevelLayer::SIBLING_ORDER_MULTIPLIER with highest sibling.
4465 ActorIter end = siblings.end();
4466 int highestOrder = 0;
4467 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
4469 ActorPtr sibling = (*iter);
4470 int siblingOrder = sibling->mSiblingOrder;
4471 highestOrder = std::max( highestOrder, siblingOrder );
4474 for ( int index = 0; index <= highestOrder; index++ )
4476 int nextHighest = -1;
4478 // Find Next highest
4479 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
4481 ActorPtr sibling = (*iter);
4482 int siblingOrder = sibling->mSiblingOrder;
4484 if ( siblingOrder > index )
4486 if ( nextHighest == -1 )
4488 nextHighest = siblingOrder;
4490 nextHighest = std::min( nextHighest, siblingOrder );
4494 // Check if a gap exists between indexes, if so set next index to consecutive number
4495 if ( ( nextHighest - index ) > 1 )
4497 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
4499 ActorPtr sibling = (*iter);
4500 int siblingOrder = sibling->mSiblingOrder;
4501 if ( siblingOrder == nextHighest )
4503 sibling->mSiblingOrder = index + 1;
4504 if ( sibling->mSiblingOrder >= Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER )
4506 DALI_LOG_WARNING( "Reached max sibling order level for raising / lowering actors\n" );
4507 sibling->mSiblingOrder = Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER;
4509 sibling->SetSiblingOrder( sibling->mSiblingOrder );
4516 bool Actor::ShiftSiblingsLevels( ActorContainer& siblings, int targetLevelToShiftFrom )
4518 // Allows exclusive levels for an actor by shifting all sibling levels at the target and above by 1
4519 bool defragmentationRequired( false );
4520 ActorIter end = siblings.end();
4521 for( ActorIter iter = siblings.begin(); ( iter != end ) ; ++iter )
4523 // Move actors at nearest order and above up by 1
4524 ActorPtr sibling = (*iter);
4525 if ( sibling != this )
4527 // Iterate through container of actors, any actor with a sibling order of the target or greater should
4528 // be incremented by 1.
4529 if ( sibling->mSiblingOrder >= targetLevelToShiftFrom )
4531 sibling->mSiblingOrder++;
4532 if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
4534 // If a sibling order raises so that it is only 1 from the maximum allowed then set flag so
4535 // can re-order all sibling orders.
4536 defragmentationRequired = true;
4538 sibling->SetSiblingOrder( sibling->mSiblingOrder );
4542 return defragmentationRequired;
4548 1) Check if already at top and nothing to be done.
4549 This Actor can have highest sibling order but if not exclusive then another actor at same sibling
4550 order can be positioned above it due to insertion order of actors.
4551 2) Find nearest sibling level above, these are the siblings this actor needs to be above
4552 3) a) There may be other levels above this target level
4553 b) Increment all sibling levels at the level above nearest(target)
4554 c) Now have a vacant sibling level
4555 4) Set this actor's sibling level to nearest +1 as now vacated.
4557 Note May not just be sibling level + 1 as could be empty levels in-between
4562 ActorC ( sibling level 4 )
4563 ActorB ( sibling level 3 )
4564 ActorA ( sibling level 1 )
4566 2 ) ACTION: Raise A above B
4567 a) Find nearest level above A = Level 3
4568 b) Increment levels above Level 3
4570 ActorC ( sibling level 5 )
4571 ActorB ( sibling level 3 ) NEAREST
4572 ActorA ( sibling level 1 )
4574 3 ) Set Actor A sibling level to nearest +1 as vacant
4576 ActorC ( sibling level 5 )
4577 ActorA ( sibling level 4 )
4578 ActorB ( sibling level 3 )
4580 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4581 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4582 remove any empty sibling order gaps and start from sibling level 0 again.
4583 If the number of actors reaches this maximum and all using exclusive sibling order values then
4584 defragmention will stop and new sibling orders will be set to same max value.
4588 int nearestLevel = mSiblingOrder;
4589 int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
4590 bool defragmentationRequired( false );
4592 ActorContainer* siblings = mParent->mChildren;
4594 // Find Nearest sibling level above this actor
4595 ActorIter end = siblings->end();
4596 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
4598 ActorPtr sibling = (*iter);
4599 if ( sibling != this )
4601 int order = GetSiblingOrder( sibling );
4603 if ( ( order >= mSiblingOrder ) )
4605 int distanceToNextLevel = order - mSiblingOrder;
4606 if ( distanceToNextLevel < shortestDistanceToNextLevel )
4608 nearestLevel = order;
4609 shortestDistanceToNextLevel = distanceToNextLevel;
4615 if ( nearestLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at top
4617 mSiblingOrder = nearestLevel + 1; // Set sibling level to that above the nearest level
4618 defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
4619 // Move current actor to newly vacated order level
4620 SetSiblingOrder( mSiblingOrder );
4621 if ( defragmentationRequired )
4623 DefragmentSiblingIndexes( *siblings );
4626 SetSiblingOrder( mSiblingOrder );
4630 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4637 1) Check if actor already at bottom and if nothing needs to be done
4638 This Actor can have lowest sibling order but if not exclusive then another actor at same sibling
4639 order can be positioned above it due to insertion order of actors so need to move this actor below it.
4640 2) Find nearest sibling level below, this Actor needs to be below it
4641 3) a) Need to vacate a sibling level below nearest for this actor to occupy
4642 b) Shift up all sibling order values of actor at the nearest level and levels above it to vacate a level.
4643 c) Set this actor's sibling level to this newly vacated level.
4644 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4645 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4646 remove any empty sibling order gaps and start from sibling level 0 again.
4647 If the number of actors reaches this maximum and all using exclusive sibling order values then
4648 defragmention will stop and new sibling orders will be set to same max value.
4653 // 1) Find nearest level below
4654 int nearestLevel = mSiblingOrder;
4655 int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
4657 ActorContainer* siblings = mParent->mChildren;
4659 ActorIter end = siblings->end();
4660 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
4662 ActorPtr sibling = (*iter);
4663 if ( sibling != this )
4665 int order = GetSiblingOrder( sibling );
4667 if ( order <= mSiblingOrder )
4669 int distanceToNextLevel = mSiblingOrder - order;
4670 if ( distanceToNextLevel < shortestDistanceToNextLevel )
4672 nearestLevel = order;
4673 shortestDistanceToNextLevel = distanceToNextLevel;
4679 bool defragmentationRequired ( false );
4681 // 2) If actor already not at bottom, raise all actors at required level and above
4682 if ( shortestDistanceToNextLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at bottom
4684 mSiblingOrder = nearestLevel;
4685 defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
4686 // Move current actor to newly vacated order
4687 SetSiblingOrder( mSiblingOrder );
4688 if ( defragmentationRequired )
4690 DefragmentSiblingIndexes( *siblings );
4696 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4700 void Actor::RaiseToTop()
4703 1 ) Find highest sibling order actor
4704 2 ) If highest sibling level not itself then set sibling order to that + 1
4705 3 ) highest sibling order can be same as itself so need to increment over that
4706 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4707 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4708 remove any empty sibling order gaps and start from sibling level 0 again.
4709 If the number of actors reaches this maximum and all using exclusive sibling order values then
4710 defragmention will stop and new sibling orders will be set to same max value.
4717 ActorContainer* siblings = mParent->mChildren;
4719 ActorIter end = siblings->end();
4720 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
4722 ActorPtr sibling = (*iter);
4723 if ( sibling != this )
4725 maxOrder = std::max( GetSiblingOrder( sibling ), maxOrder );
4729 bool defragmentationRequired( false );
4731 if ( maxOrder >= mSiblingOrder )
4733 mSiblingOrder = maxOrder + 1;
4734 if ( mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
4736 defragmentationRequired = true;
4740 SetSiblingOrder( mSiblingOrder );
4742 if ( defragmentationRequired )
4744 DefragmentSiblingIndexes( *siblings );
4749 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4753 void Actor::LowerToBottom()
4756 See Actor::LowerToBottom()
4758 1 ) Check if this actor already at exclusively at the bottom, if so then no more to be done.
4759 2 ) a ) Check if the bottom position 0 is vacant.
4760 b ) If 0 position is not vacant then shift up all sibling order values from 0 and above
4761 c ) 0 sibling position is vacant.
4762 3 ) Set this actor to vacant sibling order 0;
4763 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4764 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4765 remove any empty sibling order gaps and start from sibling level 0 again.
4766 If the number of actors reaches this maximum and all using exclusive sibling order values then
4767 defragmention will stop and new sibling orders will be set to same max value.
4772 bool defragmentationRequired( false );
4773 bool orderZeroFree ( true );
4775 ActorContainer* siblings = mParent->mChildren;
4777 bool actorAtLowestOrder = true;
4778 ActorIter end = siblings->end();
4779 for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
4781 ActorPtr sibling = (*iter);
4782 if ( sibling != this )
4784 int siblingOrder = GetSiblingOrder( sibling );
4785 if ( siblingOrder <= mSiblingOrder )
4787 actorAtLowestOrder = false;
4790 if ( siblingOrder == 0 )
4792 orderZeroFree = false;
4797 if ( ! actorAtLowestOrder )
4799 if ( ! orderZeroFree )
4801 defragmentationRequired = ShiftSiblingsLevels( *siblings, 0 );
4804 SetSiblingOrder( mSiblingOrder );
4806 if ( defragmentationRequired )
4808 DefragmentSiblingIndexes( *siblings );
4814 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4818 void Actor::RaiseAbove( Internal::Actor& target )
4821 1 ) a) Find target actor's sibling order
4822 b) If sibling order of target is the same as this actor then need to this Actor's sibling order
4823 needs to be above it or the insertion order will determine which is drawn on top.
4824 2 ) Shift up by 1 all sibling order greater than target sibling order
4825 3 ) Set this actor to the sibling order to target +1 as will be a newly vacated gap above
4826 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4827 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4828 remove any empty sibling order gaps and start from sibling level 0 again.
4829 If the number of actors reaches this maximum and all using exclusive sibling order values then
4830 defragmention will stop and new sibling orders will be set to same max value.
4835 if ( ValidateActors( *this, target ) )
4837 // Find target's sibling order
4838 // Set actor sibling order to this number +1
4839 int targetSiblingOrder = GetSiblingOrder( &target );
4840 ActorContainer* siblings = mParent->mChildren;
4841 mSiblingOrder = targetSiblingOrder + 1;
4842 bool defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
4844 SetSiblingOrder( mSiblingOrder );
4846 if ( defragmentationRequired )
4848 DefragmentSiblingIndexes( *(mParent->mChildren) );
4854 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4858 void Actor::LowerBelow( Internal::Actor& target )
4861 1 ) a) Find target actor's sibling order
4862 b) If sibling order of target is the same as this actor then need to this Actor's sibling order
4863 needs to be below it or the insertion order will determine which is drawn on top.
4864 2 ) Shift the target sibling order and all sibling orders at that level or above by 1
4865 3 ) Set this actor to the sibling order of the target before it changed.
4866 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4867 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4868 remove any empty sibling order gaps and start from sibling level 0 again.
4869 If the number of actors reaches this maximum and all using exclusive sibling order values then
4870 defragmention will stop and new sibling orders will be set to same max value.
4875 if ( ValidateActors( *this, target ) )
4877 bool defragmentationRequired ( false );
4878 // Find target's sibling order
4879 // Set actor sibling order to target sibling order - 1
4880 int targetSiblingOrder = GetSiblingOrder( &target);
4881 ActorContainer* siblings = mParent->mChildren;
4882 if ( targetSiblingOrder == 0 )
4885 ActorIter end = siblings->end();
4886 for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
4888 ActorPtr sibling = (*iter);
4889 if ( sibling != this )
4891 sibling->mSiblingOrder++;
4892 if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
4894 defragmentationRequired = true;
4896 sibling->SetSiblingOrder( sibling->mSiblingOrder );
4903 defragmentationRequired = ShiftSiblingsLevels( *siblings, targetSiblingOrder );
4905 mSiblingOrder = targetSiblingOrder;
4907 SetSiblingOrder( mSiblingOrder );
4909 if ( defragmentationRequired )
4911 DefragmentSiblingIndexes( *(mParent->mChildren) );
4917 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4921 } // namespace Internal