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( "screenPosition", VECTOR2, false, false, false, Dali::DevelActor::Property::SCREEN_POSITION )
232 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
236 const char* const SIGNAL_TOUCHED = "touched";
237 const char* const SIGNAL_HOVERED = "hovered";
238 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
239 const char* const SIGNAL_ON_STAGE = "onStage";
240 const char* const SIGNAL_OFF_STAGE = "offStage";
241 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
242 const char* const SIGNAL_TOUCH = "touch";
246 const char* const ACTION_SHOW = "show";
247 const char* const ACTION_HIDE = "hide";
249 BaseHandle CreateActor()
251 return Dali::Actor::New();
254 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
256 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
257 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
258 SignalConnectorType signalConnector3( mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal );
259 SignalConnectorType signalConnector4( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
260 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
261 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
262 SignalConnectorType signalConnector7( mType, SIGNAL_TOUCH, &Actor::DoConnectSignal );
264 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
265 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
270 const Vector3& value;
273 DALI_ENUM_TO_STRING_TABLE_BEGIN_WITH_TYPE( AnchorValue, ANCHOR_CONSTANT )
274 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_LEFT )
275 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_CENTER )
276 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_RIGHT )
277 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_LEFT )
278 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER )
279 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_RIGHT )
280 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_LEFT )
281 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_CENTER )
282 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_RIGHT )
283 DALI_ENUM_TO_STRING_TABLE_END( ANCHOR_CONSTANT )
285 DALI_ENUM_TO_STRING_TABLE_BEGIN( COLOR_MODE )
286 DALI_ENUM_TO_STRING( USE_OWN_COLOR )
287 DALI_ENUM_TO_STRING( USE_PARENT_COLOR )
288 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_COLOR )
289 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_ALPHA )
290 DALI_ENUM_TO_STRING_TABLE_END( COLOR_MODE )
292 DALI_ENUM_TO_STRING_TABLE_BEGIN( POSITION_INHERITANCE_MODE )
293 DALI_ENUM_TO_STRING( INHERIT_PARENT_POSITION )
294 DALI_ENUM_TO_STRING( USE_PARENT_POSITION )
295 DALI_ENUM_TO_STRING( USE_PARENT_POSITION_PLUS_LOCAL_POSITION )
296 DALI_ENUM_TO_STRING( DONT_INHERIT_POSITION )
297 DALI_ENUM_TO_STRING_TABLE_END( POSITION_INHERITANCE_MODE )
299 DALI_ENUM_TO_STRING_TABLE_BEGIN( DRAW_MODE )
300 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, NORMAL )
301 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, OVERLAY_2D )
302 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, STENCIL )
303 DALI_ENUM_TO_STRING_TABLE_END( DRAW_MODE )
305 DALI_ENUM_TO_STRING_TABLE_BEGIN( RESIZE_POLICY )
306 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIXED )
307 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_NATURAL_SIZE )
308 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FILL_TO_PARENT )
309 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_RELATIVE_TO_PARENT )
310 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_FIXED_OFFSET_FROM_PARENT )
311 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIT_TO_CHILDREN )
312 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, DIMENSION_DEPENDENCY )
313 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_ASSIGNED_SIZE )
314 DALI_ENUM_TO_STRING_TABLE_END( RESIZE_POLICY )
316 DALI_ENUM_TO_STRING_TABLE_BEGIN( SIZE_SCALE_POLICY )
317 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, USE_SIZE_SET )
318 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FIT_WITH_ASPECT_RATIO )
319 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FILL_WITH_ASPECT_RATIO )
320 DALI_ENUM_TO_STRING_TABLE_END( SIZE_SCALE_POLICY )
322 DALI_ENUM_TO_STRING_TABLE_BEGIN( CLIPPING_MODE )
323 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, DISABLED )
324 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, CLIP_CHILDREN )
325 DALI_ENUM_TO_STRING_TABLE_END( CLIPPING_MODE )
328 bool GetAnchorPointConstant( const std::string& value, Vector3& anchor )
330 for( unsigned int i = 0; i < ANCHOR_CONSTANT_TABLE_COUNT; ++i )
332 size_t sizeIgnored = 0;
333 if( CompareTokens( value.c_str(), ANCHOR_CONSTANT_TABLE[ i ].name, sizeIgnored ) )
335 anchor = ANCHOR_CONSTANT_TABLE[ i ].value;
342 inline bool GetParentOriginConstant( const std::string& value, Vector3& parentOrigin )
344 // Values are the same so just use the same table as anchor-point
345 return GetAnchorPointConstant( value, parentOrigin );
349 * @brief Extract a given dimension from a Vector2
351 * @param[in] values The values to extract from
352 * @param[in] dimension The dimension to extract
353 * @return Return the value for the dimension
355 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
359 case Dimension::WIDTH:
363 case Dimension::HEIGHT:
365 return values.height;
376 * @brief Extract a given dimension from a Vector3
378 * @param[in] values The values to extract from
379 * @param[in] dimension The dimension to extract
380 * @return Return the value for the dimension
382 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
384 return GetDimensionValue( values.GetVectorXY(), dimension );
387 unsigned int GetDepthIndex( uint16_t depth, uint16_t siblingOrder )
389 return depth * Dali::DevelLayer::ACTOR_DEPTH_MULTIPLIER + siblingOrder * Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER;
392 } // unnamed namespace
394 ActorPtr Actor::New()
396 ActorPtr actor( new Actor( BASIC ) );
398 // Second-phase construction
404 const std::string& Actor::GetName() const
409 void Actor::SetName( const std::string& name )
415 // ATTENTION: string for debug purposes is not thread safe.
416 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
420 unsigned int Actor::GetId() const
425 bool Actor::OnStage() const
430 Dali::Layer Actor::GetLayer()
434 // Short-circuit for Layer derived actors
437 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
440 // Find the immediate Layer parent
441 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
443 if( parent->IsLayer() )
445 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
452 void Actor::Add( Actor& child )
454 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
455 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
459 mChildren = new ActorContainer;
462 Actor* const oldParent( child.mParent );
464 // child might already be ours
465 if( this != oldParent )
467 // if we already have parent, unparent us first
470 oldParent->Remove( child ); // This causes OnChildRemove callback
472 // Old parent may need to readjust to missing child
473 if( oldParent->RelayoutDependentOnChildren() )
475 oldParent->RelayoutRequest();
479 // Guard against Add() during previous OnChildRemove callback
482 // Do this first, since user callbacks from within SetParent() may need to remove child
483 mChildren->push_back( ActorPtr( &child ) );
485 // SetParent asserts that child can be added
486 child.SetParent( this );
488 // Notification for derived classes
491 // Only put in a relayout request if there is a suitable dependency
492 if( RelayoutDependentOnChildren() )
500 void Actor::Remove( Actor& child )
502 if( (this == &child) || (!mChildren) )
504 // no children or removing itself
510 // Find the child in mChildren, and unparent it
511 ActorIter end = mChildren->end();
512 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
514 ActorPtr actor = (*iter);
516 if( actor.Get() == &child )
518 // Keep handle for OnChildRemove notification
521 // Do this first, since user callbacks from within SetParent() may need to add the child
522 mChildren->erase( iter );
524 DALI_ASSERT_DEBUG( actor->GetParent() == this );
525 actor->SetParent( NULL );
533 // Only put in a relayout request if there is a suitable dependency
534 if( RelayoutDependentOnChildren() )
540 // Notification for derived classes
541 OnChildRemove( child );
544 void Actor::Unparent()
548 // Remove this actor from the parent. The remove will put a relayout request in for
549 // the parent if required
550 mParent->Remove( *this );
551 // mParent is now NULL!
555 unsigned int Actor::GetChildCount() const
557 return ( NULL != mChildren ) ? mChildren->size() : 0;
560 ActorPtr Actor::GetChildAt( unsigned int index ) const
562 DALI_ASSERT_ALWAYS( index < GetChildCount() );
564 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
567 ActorPtr Actor::FindChildByName( const std::string& actorName )
570 if( actorName == mName )
576 ActorIter end = mChildren->end();
577 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
579 child = (*iter)->FindChildByName( actorName );
590 ActorPtr Actor::FindChildById( const unsigned int id )
599 ActorIter end = mChildren->end();
600 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
602 child = (*iter)->FindChildById( id );
613 void Actor::SetParentOrigin( const Vector3& origin )
617 // mNode is being used in a separate thread; queue a message to set the value & base value
618 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
621 // Cache for event-thread access
624 // not allocated, check if different from default
625 if( ParentOrigin::DEFAULT != origin )
627 mParentOrigin = new Vector3( origin );
632 // check if different from current costs more than just set
633 *mParentOrigin = origin;
637 void Actor::SetParentOriginX( float x )
639 const Vector3& current = GetCurrentParentOrigin();
641 SetParentOrigin( Vector3( x, current.y, current.z ) );
644 void Actor::SetParentOriginY( float y )
646 const Vector3& current = GetCurrentParentOrigin();
648 SetParentOrigin( Vector3( current.x, y, current.z ) );
651 void Actor::SetParentOriginZ( float z )
653 const Vector3& current = GetCurrentParentOrigin();
655 SetParentOrigin( Vector3( current.x, current.y, z ) );
658 const Vector3& Actor::GetCurrentParentOrigin() const
660 // Cached for event-thread access
661 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
664 void Actor::SetAnchorPoint( const Vector3& anchor )
668 // mNode is being used in a separate thread; queue a message to set the value & base value
669 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
672 // Cache for event-thread access
675 // not allocated, check if different from default
676 if( AnchorPoint::DEFAULT != anchor )
678 mAnchorPoint = new Vector3( anchor );
683 // check if different from current costs more than just set
684 *mAnchorPoint = anchor;
688 void Actor::SetAnchorPointX( float x )
690 const Vector3& current = GetCurrentAnchorPoint();
692 SetAnchorPoint( Vector3( x, current.y, current.z ) );
695 void Actor::SetAnchorPointY( float y )
697 const Vector3& current = GetCurrentAnchorPoint();
699 SetAnchorPoint( Vector3( current.x, y, current.z ) );
702 void Actor::SetAnchorPointZ( float z )
704 const Vector3& current = GetCurrentAnchorPoint();
706 SetAnchorPoint( Vector3( current.x, current.y, z ) );
709 const Vector3& Actor::GetCurrentAnchorPoint() const
711 // Cached for event-thread access
712 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
715 void Actor::SetPosition( float x, float y )
717 SetPosition( Vector3( x, y, 0.0f ) );
720 void Actor::SetPosition( float x, float y, float z )
722 SetPosition( Vector3( x, y, z ) );
725 void Actor::SetPosition( const Vector3& position )
727 mTargetPosition = position;
731 // mNode is being used in a separate thread; queue a message to set the value & base value
732 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
736 void Actor::SetX( float x )
738 mTargetPosition.x = x;
742 // mNode is being used in a separate thread; queue a message to set the value & base value
743 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
747 void Actor::SetY( float y )
749 mTargetPosition.y = y;
753 // mNode is being used in a separate thread; queue a message to set the value & base value
754 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
758 void Actor::SetZ( float z )
760 mTargetPosition.z = z;
764 // mNode is being used in a separate thread; queue a message to set the value & base value
765 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
769 void Actor::TranslateBy( const Vector3& distance )
771 mTargetPosition += distance;
775 // mNode is being used in a separate thread; queue a message to set the value & base value
776 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
780 const Vector3& Actor::GetCurrentPosition() const
784 // mNode is being used in a separate thread; copy the value from the previous update
785 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
788 return Vector3::ZERO;
791 const Vector3& Actor::GetTargetPosition() const
793 return mTargetPosition;
796 const Vector3& Actor::GetCurrentWorldPosition() const
800 // mNode is being used in a separate thread; copy the value from the previous update
801 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
804 return Vector3::ZERO;
807 const Vector2 Actor::GetCurrentScreenPosition() const
809 if( OnStage() && NULL != mNode )
811 StagePtr stage = Stage::GetCurrent();
812 Vector3 worldPosition = mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
813 Vector3 actorSize = GetCurrentSize() * GetCurrentScale();
814 Vector2 halfStageSize( stage->GetSize() * 0.5f ); // World position origin is center of stage
815 Vector3 halfActorSize( actorSize * 0.5f );
816 // Anchor point offset first set to TOP_LEFT (0,0.5) then moved to required anchor point.
817 Vector3 anchorPointOffSet = halfActorSize - actorSize * GetCurrentAnchorPoint();
819 return Vector2( halfStageSize.width + worldPosition.x - anchorPointOffSet.x,
820 halfStageSize.height + worldPosition.y - anchorPointOffSet.y );
823 return Vector2::ZERO;
826 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
828 // this flag is not animatable so keep the value
829 mPositionInheritanceMode = mode;
832 // mNode is being used in a separate thread; queue a message to set the value
833 SetInheritPositionMessage( GetEventThreadServices(), *mNode, mode == INHERIT_PARENT_POSITION );
837 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
839 // Cached for event-thread access
840 return mPositionInheritanceMode;
843 void Actor::SetInheritPosition( bool inherit )
845 if( mInheritPosition != inherit && NULL != mNode )
847 // non animateable so keep local copy
848 mInheritPosition = inherit;
849 SetInheritPositionMessage( GetEventThreadServices(), *mNode, inherit );
853 bool Actor::IsPositionInherited() const
855 return mInheritPosition;
858 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
860 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
861 normalizedAxis.Normalize();
863 Quaternion orientation( angle, normalizedAxis );
865 SetOrientation( orientation );
868 void Actor::SetOrientation( const Quaternion& orientation )
872 // mNode is being used in a separate thread; queue a message to set the value & base value
873 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation );
877 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
881 // mNode is being used in a separate thread; queue a message to set the value & base value
882 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, Quaternion(angle, axis) );
886 void Actor::RotateBy( const Quaternion& relativeRotation )
890 // mNode is being used in a separate thread; queue a message to set the value & base value
891 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
895 const Quaternion& Actor::GetCurrentOrientation() const
899 // mNode is being used in a separate thread; copy the value from the previous update
900 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
903 return Quaternion::IDENTITY;
906 const Quaternion& Actor::GetCurrentWorldOrientation() const
910 // mNode is being used in a separate thread; copy the value from the previous update
911 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
914 return Quaternion::IDENTITY;
917 void Actor::SetScale( float scale )
919 SetScale( Vector3( scale, scale, scale ) );
922 void Actor::SetScale( float x, float y, float z )
924 SetScale( Vector3( x, y, z ) );
927 void Actor::SetScale( const Vector3& scale )
931 // mNode is being used in a separate thread; queue a message to set the value & base value
932 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
936 void Actor::SetScaleX( float x )
940 // mNode is being used in a separate thread; queue a message to set the value & base value
941 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
945 void Actor::SetScaleY( float y )
949 // mNode is being used in a separate thread; queue a message to set the value & base value
950 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
954 void Actor::SetScaleZ( float z )
958 // mNode is being used in a separate thread; queue a message to set the value & base value
959 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
963 void Actor::ScaleBy(const Vector3& relativeScale)
967 // mNode is being used in a separate thread; queue a message to set the value & base value
968 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
972 const Vector3& Actor::GetCurrentScale() const
976 // mNode is being used in a separate thread; copy the value from the previous update
977 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
983 const Vector3& Actor::GetCurrentWorldScale() const
987 // mNode is being used in a separate thread; copy the value from the previous update
988 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
994 void Actor::SetInheritScale( bool inherit )
997 if( mInheritScale != inherit && NULL != mNode )
999 // non animateable so keep local copy
1000 mInheritScale = inherit;
1001 // mNode is being used in a separate thread; queue a message to set the value
1002 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
1006 bool Actor::IsScaleInherited() const
1008 return mInheritScale;
1011 Matrix Actor::GetCurrentWorldMatrix() const
1015 return mNode->GetWorldMatrix(0);
1018 return Matrix::IDENTITY;
1021 void Actor::SetVisible( bool visible )
1025 // mNode is being used in a separate thread; queue a message to set the value & base value
1026 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
1030 bool Actor::IsVisible() const
1034 // mNode is being used in a separate thread; copy the value from the previous update
1035 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
1041 void Actor::SetOpacity( float opacity )
1045 // mNode is being used in a separate thread; queue a message to set the value & base value
1046 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
1050 float Actor::GetCurrentOpacity() const
1054 // mNode is being used in a separate thread; copy the value from the previous update
1055 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1061 ClippingMode::Type Actor::GetClippingMode() const
1063 return mClippingMode;
1066 unsigned int Actor::GetSortingDepth()
1068 return GetDepthIndex( mDepth, mSiblingOrder );
1071 const Vector4& Actor::GetCurrentWorldColor() const
1075 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1078 return Color::WHITE;
1081 void Actor::SetColor( const Vector4& color )
1085 // mNode is being used in a separate thread; queue a message to set the value & base value
1086 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1090 void Actor::SetColorRed( float red )
1094 // mNode is being used in a separate thread; queue a message to set the value & base value
1095 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1099 void Actor::SetColorGreen( float green )
1103 // mNode is being used in a separate thread; queue a message to set the value & base value
1104 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1108 void Actor::SetColorBlue( float blue )
1112 // mNode is being used in a separate thread; queue a message to set the value & base value
1113 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1117 const Vector4& Actor::GetCurrentColor() const
1121 // mNode is being used in a separate thread; copy the value from the previous update
1122 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1125 return Color::WHITE;
1128 void Actor::SetInheritOrientation( bool inherit )
1130 if( mInheritOrientation != inherit && NULL != mNode)
1132 // non animateable so keep local copy
1133 mInheritOrientation = inherit;
1134 // mNode is being used in a separate thread; queue a message to set the value
1135 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1139 bool Actor::IsOrientationInherited() const
1141 return mInheritOrientation;
1144 void Actor::SetSizeModeFactor( const Vector3& factor )
1146 EnsureRelayoutData();
1148 mRelayoutData->sizeModeFactor = factor;
1151 const Vector3& Actor::GetSizeModeFactor() const
1153 if ( mRelayoutData )
1155 return mRelayoutData->sizeModeFactor;
1158 return GetDefaultSizeModeFactor();
1161 void Actor::SetColorMode( ColorMode colorMode )
1163 // non animateable so keep local copy
1164 mColorMode = colorMode;
1167 // mNode is being used in a separate thread; queue a message to set the value
1168 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1172 ColorMode Actor::GetColorMode() const
1174 // we have cached copy
1178 void Actor::SetSize( float width, float height )
1180 SetSize( Vector2( width, height ) );
1183 void Actor::SetSize( float width, float height, float depth )
1185 SetSize( Vector3( width, height, depth ) );
1188 void Actor::SetSize( const Vector2& size )
1190 SetSize( Vector3( size.width, size.height, 0.f ) );
1193 void Actor::SetSizeInternal( const Vector2& size )
1195 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1198 void Actor::SetSize( const Vector3& size )
1200 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1202 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1203 SetPreferredSize( size.GetVectorXY() );
1207 SetSizeInternal( size );
1211 void Actor::SetSizeInternal( const Vector3& size )
1213 // dont allow recursive loop
1214 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1215 // 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
1216 if( ( NULL != mNode )&&
1217 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1218 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1219 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1223 // mNode is being used in a separate thread; queue a message to set the value & base value
1224 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
1226 // Notification for derived classes
1227 mInsideOnSizeSet = true;
1228 OnSizeSet( mTargetSize );
1229 mInsideOnSizeSet = false;
1231 // Raise a relayout request if the flag is not locked
1232 if( mRelayoutData && !mRelayoutData->insideRelayout )
1239 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1241 mTargetSize = targetSize;
1243 // Notify deriving classes
1244 OnSizeAnimation( animation, mTargetSize );
1247 void Actor::NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property )
1249 if ( Dali::Actor::Property::SIZE_WIDTH == property )
1251 mTargetSize.width = targetSize;
1253 else if ( Dali::Actor::Property::SIZE_HEIGHT == property )
1255 mTargetSize.height = targetSize;
1257 else if ( Dali::Actor::Property::SIZE_DEPTH == property )
1259 mTargetSize.depth = targetSize;
1261 // Notify deriving classes
1262 OnSizeAnimation( animation, mTargetSize );
1265 void Actor::NotifyPositionAnimation( Animation& animation, const Vector3& targetPosition )
1267 mTargetPosition = targetPosition;
1270 void Actor::NotifyPositionAnimation( Animation& animation, float targetPosition, Property::Index property )
1272 if ( Dali::Actor::Property::POSITION_X == property )
1274 mTargetPosition.x = targetPosition;
1276 else if ( Dali::Actor::Property::POSITION_Y == property )
1278 mTargetPosition.y = targetPosition;
1280 else if ( Dali::Actor::Property::POSITION_Z == property )
1282 mTargetPosition.z = targetPosition;
1286 void Actor::SetWidth( float width )
1288 mTargetSize.width = width;
1292 // mNode is being used in a separate thread; queue a message to set the value & base value
1293 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1297 void Actor::SetHeight( float height )
1299 mTargetSize.height = height;
1303 // mNode is being used in a separate thread; queue a message to set the value & base value
1304 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1308 void Actor::SetDepth( float depth )
1310 mTargetSize.depth = depth;
1314 // mNode is being used in a separate thread; queue a message to set the value & base value
1315 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1319 const Vector3& Actor::GetTargetSize() const
1324 const Vector3& Actor::GetCurrentSize() const
1328 // mNode is being used in a separate thread; copy the value from the previous update
1329 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1332 return Vector3::ZERO;
1335 Vector3 Actor::GetNaturalSize() const
1337 // It is up to deriving classes to return the appropriate natural size
1338 return Vector3( 0.0f, 0.0f, 0.0f );
1341 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1343 EnsureRelayoutData();
1345 ResizePolicy::Type originalWidthPolicy = GetResizePolicy(Dimension::WIDTH);
1346 ResizePolicy::Type originalHeightPolicy = GetResizePolicy(Dimension::HEIGHT);
1348 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1350 if( dimension & ( 1 << i ) )
1352 mRelayoutData->resizePolicies[ i ] = policy;
1356 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1358 if( dimension & Dimension::WIDTH )
1360 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1363 if( dimension & Dimension::HEIGHT )
1365 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1369 // If calling SetResizePolicy, assume we want relayout enabled
1370 SetRelayoutEnabled( true );
1372 // If the resize policy is set to be FIXED, the preferred size
1373 // should be overrided by the target size. Otherwise the target
1374 // size should be overrided by the preferred size.
1376 if( dimension & Dimension::WIDTH )
1378 if( originalWidthPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1380 mRelayoutData->preferredSize.width = mTargetSize.width;
1382 else if( originalWidthPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1384 mTargetSize.width = mRelayoutData->preferredSize.width;
1388 if( dimension & Dimension::HEIGHT )
1390 if( originalHeightPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1392 mRelayoutData->preferredSize.height = mTargetSize.height;
1394 else if( originalHeightPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1396 mTargetSize.height = mRelayoutData->preferredSize.height;
1400 OnSetResizePolicy( policy, dimension );
1402 // Trigger relayout on this control
1406 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1408 if ( mRelayoutData )
1410 // If more than one dimension is requested, just return the first one found
1411 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1413 if( ( dimension & ( 1 << i ) ) )
1415 return mRelayoutData->resizePolicies[ i ];
1420 return ResizePolicy::DEFAULT;
1423 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1425 EnsureRelayoutData();
1427 mRelayoutData->sizeSetPolicy = policy;
1430 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1432 if ( mRelayoutData )
1434 return mRelayoutData->sizeSetPolicy;
1437 return DEFAULT_SIZE_SCALE_POLICY;
1440 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1442 EnsureRelayoutData();
1444 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1446 if( dimension & ( 1 << i ) )
1448 mRelayoutData->dimensionDependencies[ i ] = dependency;
1453 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1455 if ( mRelayoutData )
1457 // If more than one dimension is requested, just return the first one found
1458 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1460 if( ( dimension & ( 1 << i ) ) )
1462 return mRelayoutData->dimensionDependencies[ i ];
1467 return Dimension::ALL_DIMENSIONS; // Default
1470 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1472 // If relayout data has not been allocated yet and the client is requesting
1473 // to disable it, do nothing
1474 if( mRelayoutData || relayoutEnabled )
1476 EnsureRelayoutData();
1478 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1480 mRelayoutData->relayoutEnabled = relayoutEnabled;
1484 bool Actor::IsRelayoutEnabled() const
1486 // Assume that if relayout data has not been allocated yet then
1487 // relayout is disabled
1488 return mRelayoutData && mRelayoutData->relayoutEnabled;
1491 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1493 EnsureRelayoutData();
1495 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1497 if( dimension & ( 1 << i ) )
1499 mRelayoutData->dimensionDirty[ i ] = dirty;
1504 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1506 if ( mRelayoutData )
1508 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1510 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1520 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1522 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1525 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1527 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1530 unsigned int Actor::AddRenderer( Renderer& renderer )
1534 mRenderers = new RendererContainer;
1537 unsigned int index = mRenderers->size();
1538 RendererPtr rendererPtr = RendererPtr( &renderer );
1539 mRenderers->push_back( rendererPtr );
1540 AddRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1544 unsigned int Actor::GetRendererCount() const
1546 unsigned int rendererCount(0);
1549 rendererCount = mRenderers->size();
1552 return rendererCount;
1555 RendererPtr Actor::GetRendererAt( unsigned int index )
1557 RendererPtr renderer;
1558 if( index < GetRendererCount() )
1560 renderer = ( *mRenderers )[ index ];
1566 void Actor::RemoveRenderer( Renderer& renderer )
1570 RendererIter end = mRenderers->end();
1571 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1573 if( (*iter).Get() == &renderer )
1575 mRenderers->erase( iter );
1576 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1583 void Actor::RemoveRenderer( unsigned int index )
1585 if( index < GetRendererCount() )
1587 RendererPtr renderer = ( *mRenderers )[ index ];
1588 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.Get()->GetRendererSceneObject() );
1589 mRenderers->erase( mRenderers->begin()+index );
1593 bool Actor::IsOverlay() const
1595 return ( DrawMode::OVERLAY_2D == mDrawMode );
1598 void Actor::SetDrawMode( DrawMode::Type drawMode )
1600 // this flag is not animatable so keep the value
1601 mDrawMode = drawMode;
1602 if( ( NULL != mNode ) && ( drawMode != DrawMode::STENCIL ) )
1604 // mNode is being used in a separate thread; queue a message to set the value
1605 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1609 DrawMode::Type Actor::GetDrawMode() const
1614 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1616 // only valid when on-stage
1617 StagePtr stage = Stage::GetCurrent();
1618 if( stage && OnStage() )
1620 const RenderTaskList& taskList = stage->GetRenderTaskList();
1622 Vector2 converted( screenX, screenY );
1624 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1625 const int taskCount = taskList.GetTaskCount();
1626 for( int i = taskCount - 1; i >= 0; --i )
1628 Dali::RenderTask task = taskList.GetTask( i );
1629 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1631 // found a task where this conversion was ok so return
1639 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1641 bool retval = false;
1642 // only valid when on-stage
1645 CameraActor* camera = renderTask.GetCameraActor();
1649 renderTask.GetViewport( viewport );
1651 // need to translate coordinates to render tasks coordinate space
1652 Vector2 converted( screenX, screenY );
1653 if( renderTask.TranslateCoordinates( converted ) )
1655 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1662 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1664 // Early-out if mNode is NULL
1670 // Get the ModelView matrix
1672 Matrix::Multiply( modelView, mNode->GetWorldMatrix(0), viewMatrix );
1674 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1675 Matrix invertedMvp( false/*don't init*/);
1676 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1677 bool success = invertedMvp.Invert();
1679 // Convert to GL coordinates
1680 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1685 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1692 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1698 if( XyPlaneIntersect( nearPos, farPos, local ) )
1700 Vector3 size = GetCurrentSize();
1701 localX = local.x + size.x * 0.5f;
1702 localY = local.y + size.y * 0.5f;
1713 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1716 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1718 Mathematical Formulation
1720 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1722 ( p - c ) dot ( p - c ) = r^2
1724 Given a ray with a point of origin 'o', and a direction vector 'd':
1726 ray(t) = o + td, t >= 0
1728 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1730 (o + td - c ) dot ( o + td - c ) = r^2
1732 To solve for t we first expand the above into a more recognisable quadratic equation form
1734 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1743 B = 2( o - c ) dot d
1744 C = ( o - c ) dot ( o - c ) - r^2
1746 which can be solved using a standard quadratic formula.
1748 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1750 Practical Simplification
1752 In a renderer, we often differentiate between world space and object space. In the object space
1753 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1754 into object space, the mathematical solution presented above can be simplified significantly.
1756 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1760 and we can find the t at which the (transformed) ray intersects the sphere by
1762 ( o + td ) dot ( o + td ) = r^2
1764 According to the reasoning above, we expand the above quadratic equation into the general form
1768 which now has coefficients:
1775 // Early out if mNode is NULL
1781 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1783 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1784 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1785 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1787 // Compute the radius is not needed, square radius it's enough.
1788 const Vector3& size( mNode->GetSize( bufferIndex ) );
1790 // Scale the sphere.
1791 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1793 const float width = size.width * scale.width;
1794 const float height = size.height * scale.height;
1796 float squareSphereRadius = 0.5f * ( width * width + height * height );
1798 float a = rayDir.Dot( rayDir ); // a
1799 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1800 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1802 return ( b2 * b2 - a * c ) >= 0.f;
1805 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector2& hitPointLocal, float& distance ) const
1809 if( OnStage() && NULL != mNode )
1811 // Transforms the ray to the local reference system.
1812 // Calculate the inverse of Model matrix
1813 Matrix invModelMatrix( false/*don't init*/);
1815 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1816 invModelMatrix = mNode->GetWorldMatrix(0);
1817 invModelMatrix.Invert();
1819 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1820 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1822 // Test with the actor's XY plane (Normal = 0 0 1 1).
1824 float a = -rayOriginLocal.z;
1825 float b = rayDirLocal.z;
1827 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1829 // Ray travels distance * rayDirLocal to intersect with plane.
1832 const Vector3& size = mNode->GetSize( bufferIndex );
1834 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1835 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1837 // Test with the actor's geometry.
1838 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1845 void Actor::SetLeaveRequired( bool required )
1847 mLeaveRequired = required;
1850 bool Actor::GetLeaveRequired() const
1852 return mLeaveRequired;
1855 void Actor::SetKeyboardFocusable( bool focusable )
1857 mKeyboardFocusable = focusable;
1860 bool Actor::IsKeyboardFocusable() const
1862 return mKeyboardFocusable;
1865 bool Actor::GetTouchRequired() const
1867 return !mTouchedSignal.Empty() || !mTouchSignal.Empty() || mDerivedRequiresTouch;
1870 bool Actor::GetHoverRequired() const
1872 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1875 bool Actor::GetWheelEventRequired() const
1877 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1880 bool Actor::IsHittable() const
1882 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1885 ActorGestureData& Actor::GetGestureData()
1887 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1888 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1889 if( NULL == mGestureData )
1891 mGestureData = new ActorGestureData;
1893 return *mGestureData;
1896 bool Actor::IsGestureRequred( Gesture::Type type ) const
1898 return mGestureData && mGestureData->IsGestureRequred( type );
1901 bool Actor::EmitTouchEventSignal( const TouchEvent& event, const Dali::TouchData& touch )
1903 bool consumed = false;
1905 if( !mTouchSignal.Empty() )
1907 Dali::Actor handle( this );
1908 consumed = mTouchSignal.Emit( handle, touch );
1911 if( !mTouchedSignal.Empty() )
1913 Dali::Actor handle( this );
1914 consumed |= mTouchedSignal.Emit( handle, event );
1919 // Notification for derived classes
1920 consumed = OnTouchEvent( event ); // TODO
1926 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1928 bool consumed = false;
1930 if( !mHoveredSignal.Empty() )
1932 Dali::Actor handle( this );
1933 consumed = mHoveredSignal.Emit( handle, event );
1938 // Notification for derived classes
1939 consumed = OnHoverEvent( event );
1945 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1947 bool consumed = false;
1949 if( !mWheelEventSignal.Empty() )
1951 Dali::Actor handle( this );
1952 consumed = mWheelEventSignal.Emit( handle, event );
1957 // Notification for derived classes
1958 consumed = OnWheelEvent( event );
1964 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
1966 return mTouchedSignal;
1969 Dali::Actor::TouchDataSignalType& Actor::TouchSignal()
1971 return mTouchSignal;
1974 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
1976 return mHoveredSignal;
1979 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
1981 return mWheelEventSignal;
1984 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
1986 return mOnStageSignal;
1989 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
1991 return mOffStageSignal;
1994 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
1996 return mOnRelayoutSignal;
1999 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
2001 bool connected( true );
2002 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
2004 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
2006 actor->TouchedSignal().Connect( tracker, functor );
2008 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
2010 actor->HoveredSignal().Connect( tracker, functor );
2012 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
2014 actor->WheelEventSignal().Connect( tracker, functor );
2016 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
2018 actor->OnStageSignal().Connect( tracker, functor );
2020 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
2022 actor->OffStageSignal().Connect( tracker, functor );
2024 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
2026 actor->OnRelayoutSignal().Connect( tracker, functor );
2028 else if( 0 == signalName.compare( SIGNAL_TOUCH ) )
2030 actor->TouchSignal().Connect( tracker, functor );
2034 // signalName does not match any signal
2041 Actor::Actor( DerivedType derivedType )
2046 mParentOrigin( NULL ),
2047 mAnchorPoint( NULL ),
2048 mRelayoutData( NULL ),
2049 mGestureData( NULL ),
2050 mTargetSize( 0.0f, 0.0f, 0.0f ),
2052 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
2055 mIsRoot( ROOT_LAYER == derivedType ),
2056 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2057 mIsOnStage( false ),
2059 mLeaveRequired( false ),
2060 mKeyboardFocusable( false ),
2061 mDerivedRequiresTouch( false ),
2062 mDerivedRequiresHover( false ),
2063 mDerivedRequiresWheelEvent( false ),
2064 mOnStageSignalled( false ),
2065 mInsideOnSizeSet( false ),
2066 mInheritPosition( true ),
2067 mInheritOrientation( true ),
2068 mInheritScale( true ),
2069 mDrawMode( DrawMode::NORMAL ),
2070 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2071 mColorMode( Node::DEFAULT_COLOR_MODE ),
2072 mClippingMode( ClippingMode::DISABLED )
2076 void Actor::Initialize()
2079 SceneGraph::Node* node = CreateNode();
2081 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
2082 mNode = node; // Keep raw-pointer to Node
2086 GetEventThreadServices().RegisterObject( this );
2091 // Remove mParent pointers from children even if we're destroying core,
2092 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2095 ActorConstIter endIter = mChildren->end();
2096 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2098 (*iter)->SetParent( NULL );
2104 // Guard to allow handle destruction after Core has been destroyed
2105 if( EventThreadServices::IsCoreRunning() )
2109 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2110 mNode = NULL; // Node is about to be destroyed
2113 GetEventThreadServices().UnregisterObject( this );
2116 // Cleanup optional gesture data
2117 delete mGestureData;
2119 // Cleanup optional parent origin and anchor
2120 delete mParentOrigin;
2121 delete mAnchorPoint;
2123 // Delete optional relayout data
2126 delete mRelayoutData;
2130 void Actor::ConnectToStage( unsigned int parentDepth )
2132 // This container is used instead of walking the Actor hierarchy.
2133 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
2134 ActorContainer connectionList;
2136 // This stage is atomic i.e. not interrupted by user callbacks.
2137 RecursiveConnectToStage( connectionList, parentDepth + 1 );
2139 // Notify applications about the newly connected actors.
2140 const ActorIter endIter = connectionList.end();
2141 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2143 (*iter)->NotifyStageConnection();
2149 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth )
2151 DALI_ASSERT_ALWAYS( !OnStage() );
2155 SetDepthIndexMessage( GetEventThreadServices(), *mNode, GetDepthIndex( mDepth, mSiblingOrder ) );
2157 ConnectToSceneGraph();
2159 // Notification for internal derived classes
2160 OnStageConnectionInternal();
2162 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2163 connectionList.push_back( ActorPtr( this ) );
2165 // Recursively connect children
2168 ActorConstIter endIter = mChildren->end();
2169 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2171 (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
2177 * This method is called when the Actor is connected to the Stage.
2178 * The parent must have added its Node to the scene-graph.
2179 * The child must connect its Node to the parent's Node.
2180 * This is recursive; the child calls ConnectToStage() for its children.
2182 void Actor::ConnectToSceneGraph()
2184 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2188 // Reparent Node in next Update
2189 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode );
2192 // Request relayout on all actors that are added to the scenegraph
2195 // Notification for Object::Observers
2199 void Actor::NotifyStageConnection()
2201 // Actors can be removed (in a callback), before the on-stage stage is reported.
2202 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2203 if( OnStage() && !mOnStageSignalled )
2205 // Notification for external (CustomActor) derived classes
2206 OnStageConnectionExternal( mDepth );
2208 if( !mOnStageSignal.Empty() )
2210 Dali::Actor handle( this );
2211 mOnStageSignal.Emit( handle );
2214 // Guard against Remove during callbacks
2217 mOnStageSignalled = true; // signal required next time Actor is removed
2222 void Actor::DisconnectFromStage()
2224 // This container is used instead of walking the Actor hierachy.
2225 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2226 ActorContainer disconnectionList;
2228 // This stage is atomic i.e. not interrupted by user callbacks
2229 RecursiveDisconnectFromStage( disconnectionList );
2231 // Notify applications about the newly disconnected actors.
2232 const ActorIter endIter = disconnectionList.end();
2233 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2235 (*iter)->NotifyStageDisconnection();
2239 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2241 DALI_ASSERT_ALWAYS( OnStage() );
2243 // Recursively disconnect children
2246 ActorConstIter endIter = mChildren->end();
2247 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2249 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2253 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2254 disconnectionList.push_back( ActorPtr( this ) );
2256 // Notification for internal derived classes
2257 OnStageDisconnectionInternal();
2259 DisconnectFromSceneGraph();
2265 * This method is called by an actor or its parent, before a node removal message is sent.
2266 * This is recursive; the child calls DisconnectFromStage() for its children.
2268 void Actor::DisconnectFromSceneGraph()
2270 // Notification for Object::Observers
2271 OnSceneObjectRemove();
2274 void Actor::NotifyStageDisconnection()
2276 // Actors can be added (in a callback), before the off-stage state is reported.
2277 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2278 // only do this step if there is a stage, i.e. Core is not being shut down
2279 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2281 // Notification for external (CustomeActor) derived classes
2282 OnStageDisconnectionExternal();
2284 if( !mOffStageSignal.Empty() )
2286 Dali::Actor handle( this );
2287 mOffStageSignal.Emit( handle );
2290 // Guard against Add during callbacks
2293 mOnStageSignalled = false; // signal required next time Actor is added
2298 bool Actor::IsNodeConnected() const
2300 bool connected( false );
2302 if( OnStage() && ( NULL != mNode ) )
2304 if( IsRoot() || mNode->GetParent() )
2313 unsigned int Actor::GetDefaultPropertyCount() const
2315 return DEFAULT_PROPERTY_COUNT;
2318 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2320 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2322 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2324 indices.PushBack( i );
2328 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2330 if( index < DEFAULT_PROPERTY_COUNT )
2332 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2338 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2340 Property::Index index = Property::INVALID_INDEX;
2342 // Look for name in default properties
2343 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2345 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2346 if( 0 == name.compare( property->name ) )
2356 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2358 if( index < DEFAULT_PROPERTY_COUNT )
2360 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2366 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2368 if( index < DEFAULT_PROPERTY_COUNT )
2370 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2376 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2378 if( index < DEFAULT_PROPERTY_COUNT )
2380 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2386 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2388 if( index < DEFAULT_PROPERTY_COUNT )
2390 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2393 // index out of range...return Property::NONE
2394 return Property::NONE;
2397 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2401 case Dali::Actor::Property::PARENT_ORIGIN:
2403 Property::Type type = property.GetType();
2404 if( type == Property::VECTOR3 )
2406 SetParentOrigin( property.Get< Vector3 >() );
2408 else if ( type == Property::STRING )
2410 std::string parentOriginString;
2411 property.Get( parentOriginString );
2412 Vector3 parentOrigin;
2413 if( GetParentOriginConstant( parentOriginString, parentOrigin ) )
2415 SetParentOrigin( parentOrigin );
2421 case Dali::Actor::Property::PARENT_ORIGIN_X:
2423 SetParentOriginX( property.Get< float >() );
2427 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2429 SetParentOriginY( property.Get< float >() );
2433 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2435 SetParentOriginZ( property.Get< float >() );
2439 case Dali::Actor::Property::ANCHOR_POINT:
2441 Property::Type type = property.GetType();
2442 if( type == Property::VECTOR3 )
2444 SetAnchorPoint( property.Get< Vector3 >() );
2446 else if ( type == Property::STRING )
2448 std::string anchorPointString;
2449 property.Get( anchorPointString );
2451 if( GetAnchorPointConstant( anchorPointString, anchor ) )
2453 SetAnchorPoint( anchor );
2459 case Dali::Actor::Property::ANCHOR_POINT_X:
2461 SetAnchorPointX( property.Get< float >() );
2465 case Dali::Actor::Property::ANCHOR_POINT_Y:
2467 SetAnchorPointY( property.Get< float >() );
2471 case Dali::Actor::Property::ANCHOR_POINT_Z:
2473 SetAnchorPointZ( property.Get< float >() );
2477 case Dali::Actor::Property::SIZE:
2479 SetSize( property.Get< Vector3 >() );
2483 case Dali::Actor::Property::SIZE_WIDTH:
2485 SetWidth( property.Get< float >() );
2489 case Dali::Actor::Property::SIZE_HEIGHT:
2491 SetHeight( property.Get< float >() );
2495 case Dali::Actor::Property::SIZE_DEPTH:
2497 SetDepth( property.Get< float >() );
2501 case Dali::Actor::Property::POSITION:
2503 SetPosition( property.Get< Vector3 >() );
2507 case Dali::Actor::Property::POSITION_X:
2509 SetX( property.Get< float >() );
2513 case Dali::Actor::Property::POSITION_Y:
2515 SetY( property.Get< float >() );
2519 case Dali::Actor::Property::POSITION_Z:
2521 SetZ( property.Get< float >() );
2525 case Dali::Actor::Property::ORIENTATION:
2527 SetOrientation( property.Get< Quaternion >() );
2531 case Dali::Actor::Property::SCALE:
2533 SetScale( property.Get< Vector3 >() );
2537 case Dali::Actor::Property::SCALE_X:
2539 SetScaleX( property.Get< float >() );
2543 case Dali::Actor::Property::SCALE_Y:
2545 SetScaleY( property.Get< float >() );
2549 case Dali::Actor::Property::SCALE_Z:
2551 SetScaleZ( property.Get< float >() );
2555 case Dali::Actor::Property::VISIBLE:
2557 SetVisible( property.Get< bool >() );
2561 case Dali::Actor::Property::COLOR:
2563 SetColor( property.Get< Vector4 >() );
2567 case Dali::Actor::Property::COLOR_RED:
2569 SetColorRed( property.Get< float >() );
2573 case Dali::Actor::Property::COLOR_GREEN:
2575 SetColorGreen( property.Get< float >() );
2579 case Dali::Actor::Property::COLOR_BLUE:
2581 SetColorBlue( property.Get< float >() );
2585 case Dali::Actor::Property::COLOR_ALPHA:
2586 case Dali::DevelActor::Property::OPACITY:
2589 if( property.Get( value ) )
2591 SetOpacity( value );
2596 case Dali::Actor::Property::NAME:
2598 SetName( property.Get< std::string >() );
2602 case Dali::Actor::Property::SENSITIVE:
2604 SetSensitive( property.Get< bool >() );
2608 case Dali::Actor::Property::LEAVE_REQUIRED:
2610 SetLeaveRequired( property.Get< bool >() );
2614 case Dali::Actor::Property::INHERIT_POSITION:
2616 SetInheritPosition( property.Get< bool >() );
2620 case Dali::Actor::Property::INHERIT_ORIENTATION:
2622 SetInheritOrientation( property.Get< bool >() );
2626 case Dali::Actor::Property::INHERIT_SCALE:
2628 SetInheritScale( property.Get< bool >() );
2632 case Dali::Actor::Property::COLOR_MODE:
2634 ColorMode mode = mColorMode;
2635 if ( Scripting::GetEnumerationProperty< ColorMode >( property, COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT, mode ) )
2637 SetColorMode( mode );
2642 case Dali::Actor::Property::POSITION_INHERITANCE:
2644 PositionInheritanceMode mode = mPositionInheritanceMode;
2645 if( Scripting::GetEnumerationProperty< PositionInheritanceMode >( property, POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT, mode ) )
2647 SetPositionInheritanceMode( mode );
2652 case Dali::Actor::Property::DRAW_MODE:
2654 DrawMode::Type mode = mDrawMode;
2655 if( Scripting::GetEnumerationProperty< DrawMode::Type >( property, DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT, mode ) )
2657 SetDrawMode( mode );
2662 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2664 SetSizeModeFactor( property.Get< Vector3 >() );
2668 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2670 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
2671 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2673 SetResizePolicy( type, Dimension::WIDTH );
2678 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2680 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
2681 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2683 SetResizePolicy( type, Dimension::HEIGHT );
2688 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2690 SizeScalePolicy::Type type;
2691 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT, type ) )
2693 SetSizeScalePolicy( type );
2698 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2700 if( property.Get< bool >() )
2702 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2707 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2709 if( property.Get< bool >() )
2711 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2716 case Dali::Actor::Property::PADDING:
2718 Vector4 padding = property.Get< Vector4 >();
2719 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2720 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2724 case Dali::Actor::Property::MINIMUM_SIZE:
2726 Vector2 size = property.Get< Vector2 >();
2727 SetMinimumSize( size.x, Dimension::WIDTH );
2728 SetMinimumSize( size.y, Dimension::HEIGHT );
2732 case Dali::Actor::Property::MAXIMUM_SIZE:
2734 Vector2 size = property.Get< Vector2 >();
2735 SetMaximumSize( size.x, Dimension::WIDTH );
2736 SetMaximumSize( size.y, Dimension::HEIGHT );
2740 case Dali::DevelActor::Property::SIBLING_ORDER:
2744 if( property.Get( value ) )
2746 if( static_cast<unsigned int>(value) != mSiblingOrder )
2748 SetSiblingOrder( value );
2754 case Dali::Actor::Property::CLIPPING_MODE:
2756 ClippingMode::Type convertedValue = mClippingMode;
2757 if( Scripting::GetEnumerationProperty< ClippingMode::Type >( property, CLIPPING_MODE_TABLE, CLIPPING_MODE_TABLE_COUNT, convertedValue ) )
2759 mClippingMode = convertedValue;
2762 SetClippingModeMessage( GetEventThreadServices(), *mNode, mClippingMode );
2770 // this can happen in the case of a non-animatable default property so just do nothing
2776 // TODO: This method needs to be removed
2777 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2779 switch( entry.GetType() )
2781 case Property::BOOLEAN:
2783 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2784 DALI_ASSERT_DEBUG( NULL != property );
2786 // property is being used in a separate thread; queue a message to set the property
2787 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2792 case Property::INTEGER:
2794 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2795 DALI_ASSERT_DEBUG( NULL != property );
2797 // property is being used in a separate thread; queue a message to set the property
2798 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2803 case Property::FLOAT:
2805 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2806 DALI_ASSERT_DEBUG( NULL != property );
2808 // property is being used in a separate thread; queue a message to set the property
2809 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2814 case Property::VECTOR2:
2816 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2817 DALI_ASSERT_DEBUG( NULL != property );
2819 // property is being used in a separate thread; queue a message to set the property
2820 if(entry.componentIndex == 0)
2822 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2824 else if(entry.componentIndex == 1)
2826 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2830 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2836 case Property::VECTOR3:
2838 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2839 DALI_ASSERT_DEBUG( NULL != property );
2841 // property is being used in a separate thread; queue a message to set the property
2842 if(entry.componentIndex == 0)
2844 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2846 else if(entry.componentIndex == 1)
2848 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2850 else if(entry.componentIndex == 2)
2852 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2856 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2862 case Property::VECTOR4:
2864 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2865 DALI_ASSERT_DEBUG( NULL != property );
2867 // property is being used in a separate thread; queue a message to set the property
2868 if(entry.componentIndex == 0)
2870 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
2872 else if(entry.componentIndex == 1)
2874 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
2876 else if(entry.componentIndex == 2)
2878 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
2880 else if(entry.componentIndex == 3)
2882 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
2886 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2892 case Property::ROTATION:
2894 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
2895 DALI_ASSERT_DEBUG( NULL != property );
2897 // property is being used in a separate thread; queue a message to set the property
2898 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
2903 case Property::MATRIX:
2905 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
2906 DALI_ASSERT_DEBUG( NULL != property );
2908 // property is being used in a separate thread; queue a message to set the property
2909 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
2914 case Property::MATRIX3:
2916 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
2917 DALI_ASSERT_DEBUG( NULL != property );
2919 // property is being used in a separate thread; queue a message to set the property
2920 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
2927 // nothing to do for other types
2932 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
2934 Property::Value value;
2936 if( index >= DEFAULT_PROPERTY_COUNT )
2943 case Dali::Actor::Property::PARENT_ORIGIN:
2945 value = GetCurrentParentOrigin();
2949 case Dali::Actor::Property::PARENT_ORIGIN_X:
2951 value = GetCurrentParentOrigin().x;
2955 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2957 value = GetCurrentParentOrigin().y;
2961 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2963 value = GetCurrentParentOrigin().z;
2967 case Dali::Actor::Property::ANCHOR_POINT:
2969 value = GetCurrentAnchorPoint();
2973 case Dali::Actor::Property::ANCHOR_POINT_X:
2975 value = GetCurrentAnchorPoint().x;
2979 case Dali::Actor::Property::ANCHOR_POINT_Y:
2981 value = GetCurrentAnchorPoint().y;
2985 case Dali::Actor::Property::ANCHOR_POINT_Z:
2987 value = GetCurrentAnchorPoint().z;
2991 case Dali::Actor::Property::SIZE:
2993 Vector3 size = GetTargetSize();
2995 // Should return preferred size if size is fixed as set by SetSize
2996 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
2998 size.width = GetPreferredSize().width;
3000 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
3002 size.height = GetPreferredSize().height;
3010 case Dali::Actor::Property::SIZE_WIDTH:
3012 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
3014 // Should return preferred size if size is fixed as set by SetSize
3015 value = GetPreferredSize().width;
3019 value = GetTargetSize().width;
3024 case Dali::Actor::Property::SIZE_HEIGHT:
3026 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
3028 // Should return preferred size if size is fixed as set by SetSize
3029 value = GetPreferredSize().height;
3033 value = GetTargetSize().height;
3038 case Dali::Actor::Property::SIZE_DEPTH:
3040 value = GetTargetSize().depth;
3044 case Dali::Actor::Property::POSITION:
3046 value = GetTargetPosition();
3050 case Dali::Actor::Property::POSITION_X:
3052 value = GetTargetPosition().x;
3056 case Dali::Actor::Property::POSITION_Y:
3058 value = GetTargetPosition().y;
3062 case Dali::Actor::Property::POSITION_Z:
3064 value = GetTargetPosition().z;
3068 case Dali::Actor::Property::WORLD_POSITION:
3070 value = GetCurrentWorldPosition();
3074 case Dali::Actor::Property::WORLD_POSITION_X:
3076 value = GetCurrentWorldPosition().x;
3080 case Dali::Actor::Property::WORLD_POSITION_Y:
3082 value = GetCurrentWorldPosition().y;
3086 case Dali::Actor::Property::WORLD_POSITION_Z:
3088 value = GetCurrentWorldPosition().z;
3092 case Dali::Actor::Property::ORIENTATION:
3094 value = GetCurrentOrientation();
3098 case Dali::Actor::Property::WORLD_ORIENTATION:
3100 value = GetCurrentWorldOrientation();
3104 case Dali::Actor::Property::SCALE:
3106 value = GetCurrentScale();
3110 case Dali::Actor::Property::SCALE_X:
3112 value = GetCurrentScale().x;
3116 case Dali::Actor::Property::SCALE_Y:
3118 value = GetCurrentScale().y;
3122 case Dali::Actor::Property::SCALE_Z:
3124 value = GetCurrentScale().z;
3128 case Dali::Actor::Property::WORLD_SCALE:
3130 value = GetCurrentWorldScale();
3134 case Dali::Actor::Property::VISIBLE:
3136 value = IsVisible();
3140 case Dali::Actor::Property::COLOR:
3142 value = GetCurrentColor();
3146 case Dali::Actor::Property::COLOR_RED:
3148 value = GetCurrentColor().r;
3152 case Dali::Actor::Property::COLOR_GREEN:
3154 value = GetCurrentColor().g;
3158 case Dali::Actor::Property::COLOR_BLUE:
3160 value = GetCurrentColor().b;
3164 case Dali::Actor::Property::COLOR_ALPHA:
3165 case Dali::DevelActor::Property::OPACITY:
3167 value = GetCurrentColor().a;
3171 case Dali::Actor::Property::WORLD_COLOR:
3173 value = GetCurrentWorldColor();
3177 case Dali::Actor::Property::WORLD_MATRIX:
3179 value = GetCurrentWorldMatrix();
3183 case Dali::Actor::Property::NAME:
3189 case Dali::Actor::Property::SENSITIVE:
3191 value = IsSensitive();
3195 case Dali::Actor::Property::LEAVE_REQUIRED:
3197 value = GetLeaveRequired();
3201 case Dali::Actor::Property::INHERIT_POSITION:
3203 value = IsPositionInherited();
3207 case Dali::Actor::Property::INHERIT_ORIENTATION:
3209 value = IsOrientationInherited();
3213 case Dali::Actor::Property::INHERIT_SCALE:
3215 value = IsScaleInherited();
3219 case Dali::Actor::Property::COLOR_MODE:
3221 value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
3225 case Dali::Actor::Property::POSITION_INHERITANCE:
3227 value = Scripting::GetLinearEnumerationName< PositionInheritanceMode >( GetPositionInheritanceMode(), POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT );
3231 case Dali::Actor::Property::DRAW_MODE:
3233 value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
3237 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3239 value = GetSizeModeFactor();
3243 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3245 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3249 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3251 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3255 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3257 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT );
3261 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3263 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3267 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3269 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3273 case Dali::Actor::Property::PADDING:
3275 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3276 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3277 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3281 case Dali::Actor::Property::MINIMUM_SIZE:
3283 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3287 case Dali::Actor::Property::MAXIMUM_SIZE:
3289 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3293 case Dali::DevelActor::Property::SIBLING_ORDER:
3295 value = static_cast<int>(mSiblingOrder);
3299 case Dali::Actor::Property::CLIPPING_MODE:
3301 value = mClippingMode;
3305 case Dali::DevelActor::Property::SCREEN_POSITION:
3307 value = GetCurrentScreenPosition();
3315 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3320 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3322 // This method should only return an object connected to the scene-graph
3323 return OnStage() ? mNode : NULL;
3326 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3328 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3330 const PropertyBase* property( NULL );
3332 // This method should only return a property of an object connected to the scene-graph
3338 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3340 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3341 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3343 property = animatable->GetSceneGraphProperty();
3345 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3346 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3348 CustomPropertyMetadata* custom = FindCustomProperty( index );
3349 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3351 property = custom->GetSceneGraphProperty();
3353 else if( NULL != mNode )
3357 case Dali::Actor::Property::SIZE:
3358 property = &mNode->mSize;
3361 case Dali::Actor::Property::SIZE_WIDTH:
3362 property = &mNode->mSize;
3365 case Dali::Actor::Property::SIZE_HEIGHT:
3366 property = &mNode->mSize;
3369 case Dali::Actor::Property::SIZE_DEPTH:
3370 property = &mNode->mSize;
3373 case Dali::Actor::Property::POSITION:
3374 property = &mNode->mPosition;
3377 case Dali::Actor::Property::POSITION_X:
3378 property = &mNode->mPosition;
3381 case Dali::Actor::Property::POSITION_Y:
3382 property = &mNode->mPosition;
3385 case Dali::Actor::Property::POSITION_Z:
3386 property = &mNode->mPosition;
3389 case Dali::Actor::Property::ORIENTATION:
3390 property = &mNode->mOrientation;
3393 case Dali::Actor::Property::SCALE:
3394 property = &mNode->mScale;
3397 case Dali::Actor::Property::SCALE_X:
3398 property = &mNode->mScale;
3401 case Dali::Actor::Property::SCALE_Y:
3402 property = &mNode->mScale;
3405 case Dali::Actor::Property::SCALE_Z:
3406 property = &mNode->mScale;
3409 case Dali::Actor::Property::VISIBLE:
3410 property = &mNode->mVisible;
3413 case Dali::Actor::Property::COLOR:
3414 property = &mNode->mColor;
3417 case Dali::Actor::Property::COLOR_RED:
3418 property = &mNode->mColor;
3421 case Dali::Actor::Property::COLOR_GREEN:
3422 property = &mNode->mColor;
3425 case Dali::Actor::Property::COLOR_BLUE:
3426 property = &mNode->mColor;
3429 case Dali::Actor::Property::COLOR_ALPHA:
3430 case Dali::DevelActor::Property::OPACITY:
3431 property = &mNode->mColor;
3442 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3444 const PropertyInputImpl* property( NULL );
3446 // This method should only return a property of an object connected to the scene-graph
3452 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3454 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3455 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3457 property = animatable->GetSceneGraphProperty();
3459 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3460 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3462 CustomPropertyMetadata* custom = FindCustomProperty( index );
3463 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3464 property = custom->GetSceneGraphProperty();
3466 else if( NULL != mNode )
3470 case Dali::Actor::Property::PARENT_ORIGIN:
3471 property = &mNode->mParentOrigin;
3474 case Dali::Actor::Property::PARENT_ORIGIN_X:
3475 property = &mNode->mParentOrigin;
3478 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3479 property = &mNode->mParentOrigin;
3482 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3483 property = &mNode->mParentOrigin;
3486 case Dali::Actor::Property::ANCHOR_POINT:
3487 property = &mNode->mAnchorPoint;
3490 case Dali::Actor::Property::ANCHOR_POINT_X:
3491 property = &mNode->mAnchorPoint;
3494 case Dali::Actor::Property::ANCHOR_POINT_Y:
3495 property = &mNode->mAnchorPoint;
3498 case Dali::Actor::Property::ANCHOR_POINT_Z:
3499 property = &mNode->mAnchorPoint;
3502 case Dali::Actor::Property::SIZE:
3503 property = &mNode->mSize;
3506 case Dali::Actor::Property::SIZE_WIDTH:
3507 property = &mNode->mSize;
3510 case Dali::Actor::Property::SIZE_HEIGHT:
3511 property = &mNode->mSize;
3514 case Dali::Actor::Property::SIZE_DEPTH:
3515 property = &mNode->mSize;
3518 case Dali::Actor::Property::POSITION:
3519 property = &mNode->mPosition;
3522 case Dali::Actor::Property::POSITION_X:
3523 property = &mNode->mPosition;
3526 case Dali::Actor::Property::POSITION_Y:
3527 property = &mNode->mPosition;
3530 case Dali::Actor::Property::POSITION_Z:
3531 property = &mNode->mPosition;
3534 case Dali::Actor::Property::WORLD_POSITION:
3535 property = &mNode->mWorldPosition;
3538 case Dali::Actor::Property::WORLD_POSITION_X:
3539 property = &mNode->mWorldPosition;
3542 case Dali::Actor::Property::WORLD_POSITION_Y:
3543 property = &mNode->mWorldPosition;
3546 case Dali::Actor::Property::WORLD_POSITION_Z:
3547 property = &mNode->mWorldPosition;
3550 case Dali::Actor::Property::ORIENTATION:
3551 property = &mNode->mOrientation;
3554 case Dali::Actor::Property::WORLD_ORIENTATION:
3555 property = &mNode->mWorldOrientation;
3558 case Dali::Actor::Property::SCALE:
3559 property = &mNode->mScale;
3562 case Dali::Actor::Property::SCALE_X:
3563 property = &mNode->mScale;
3566 case Dali::Actor::Property::SCALE_Y:
3567 property = &mNode->mScale;
3570 case Dali::Actor::Property::SCALE_Z:
3571 property = &mNode->mScale;
3574 case Dali::Actor::Property::WORLD_SCALE:
3575 property = &mNode->mWorldScale;
3578 case Dali::Actor::Property::VISIBLE:
3579 property = &mNode->mVisible;
3582 case Dali::Actor::Property::COLOR:
3583 property = &mNode->mColor;
3586 case Dali::Actor::Property::COLOR_RED:
3587 property = &mNode->mColor;
3590 case Dali::Actor::Property::COLOR_GREEN:
3591 property = &mNode->mColor;
3594 case Dali::Actor::Property::COLOR_BLUE:
3595 property = &mNode->mColor;
3598 case Dali::Actor::Property::COLOR_ALPHA:
3599 case Dali::DevelActor::Property::OPACITY:
3601 property = &mNode->mColor;
3605 case Dali::Actor::Property::WORLD_COLOR:
3606 property = &mNode->mWorldColor;
3609 case Dali::Actor::Property::WORLD_MATRIX:
3610 property = &mNode->mWorldMatrix;
3621 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3623 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3625 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3627 // check whether the animatable property is registered already, if not then register one.
3628 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3629 if( animatableProperty )
3631 componentIndex = animatableProperty->componentIndex;
3638 case Dali::Actor::Property::PARENT_ORIGIN_X:
3639 case Dali::Actor::Property::ANCHOR_POINT_X:
3640 case Dali::Actor::Property::SIZE_WIDTH:
3641 case Dali::Actor::Property::POSITION_X:
3642 case Dali::Actor::Property::WORLD_POSITION_X:
3643 case Dali::Actor::Property::SCALE_X:
3644 case Dali::Actor::Property::COLOR_RED:
3650 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3651 case Dali::Actor::Property::ANCHOR_POINT_Y:
3652 case Dali::Actor::Property::SIZE_HEIGHT:
3653 case Dali::Actor::Property::POSITION_Y:
3654 case Dali::Actor::Property::WORLD_POSITION_Y:
3655 case Dali::Actor::Property::SCALE_Y:
3656 case Dali::Actor::Property::COLOR_GREEN:
3662 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3663 case Dali::Actor::Property::ANCHOR_POINT_Z:
3664 case Dali::Actor::Property::SIZE_DEPTH:
3665 case Dali::Actor::Property::POSITION_Z:
3666 case Dali::Actor::Property::WORLD_POSITION_Z:
3667 case Dali::Actor::Property::SCALE_Z:
3668 case Dali::Actor::Property::COLOR_BLUE:
3674 case Dali::Actor::Property::COLOR_ALPHA:
3675 case Dali::DevelActor::Property::OPACITY:
3689 return componentIndex;
3692 void Actor::SetParent( Actor* parent )
3696 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3700 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3703 // Instruct each actor to create a corresponding node in the scene graph
3704 ConnectToStage( parent->GetHierarchyDepth() );
3707 // Resolve the name and index for the child properties if any
3708 ResolveChildProperties();
3710 else // parent being set to NULL
3712 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3716 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3719 DALI_ASSERT_ALWAYS( mNode != NULL );
3723 // Disconnect the Node & its children from the scene-graph.
3724 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3727 // Instruct each actor to discard pointers to the scene-graph
3728 DisconnectFromStage();
3733 SceneGraph::Node* Actor::CreateNode() const
3738 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3741 Actor* actor = dynamic_cast< Actor* >( object );
3745 if( 0 == actionName.compare( ACTION_SHOW ) )
3747 actor->SetVisible( true );
3750 else if( 0 == actionName.compare( ACTION_HIDE ) )
3752 actor->SetVisible( false );
3760 void Actor::EnsureRelayoutData()
3762 // Assign relayout data.
3763 if( !mRelayoutData )
3765 mRelayoutData = new RelayoutData();
3769 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3771 // Check if actor is dependent on parent
3772 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3774 if( ( dimension & ( 1 << i ) ) )
3776 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3777 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3787 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3789 // Check if actor is dependent on children
3790 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3792 if( ( dimension & ( 1 << i ) ) )
3794 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3795 switch( resizePolicy )
3797 case ResizePolicy::FIT_TO_CHILDREN:
3798 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
3814 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
3816 return Actor::RelayoutDependentOnChildren( dimension );
3819 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
3821 // Check each possible dimension and see if it is dependent on the input one
3822 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3824 if( dimension & ( 1 << i ) )
3826 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
3833 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
3835 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3837 if( dimension & ( 1 << i ) )
3839 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
3844 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
3846 // If more than one dimension is requested, just return the first one found
3847 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3849 if( ( dimension & ( 1 << i ) ) )
3851 return mRelayoutData->negotiatedDimensions[ i ];
3855 return 0.0f; // Default
3858 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
3860 EnsureRelayoutData();
3862 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3864 if( dimension & ( 1 << i ) )
3866 mRelayoutData->dimensionPadding[ i ] = padding;
3871 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
3873 if ( mRelayoutData )
3875 // If more than one dimension is requested, just return the first one found
3876 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3878 if( ( dimension & ( 1 << i ) ) )
3880 return mRelayoutData->dimensionPadding[ i ];
3885 return GetDefaultDimensionPadding();
3888 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
3890 EnsureRelayoutData();
3892 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3894 if( dimension & ( 1 << i ) )
3896 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
3901 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
3903 if ( mRelayoutData )
3905 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3907 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
3917 float Actor::GetHeightForWidthBase( float width )
3919 float height = 0.0f;
3921 const Vector3 naturalSize = GetNaturalSize();
3922 if( naturalSize.width > 0.0f )
3924 height = naturalSize.height * width / naturalSize.width;
3926 else // we treat 0 as 1:1 aspect ratio
3934 float Actor::GetWidthForHeightBase( float height )
3938 const Vector3 naturalSize = GetNaturalSize();
3939 if( naturalSize.height > 0.0f )
3941 width = naturalSize.width * height / naturalSize.height;
3943 else // we treat 0 as 1:1 aspect ratio
3951 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
3953 // Fill to parent, taking size mode factor into account
3954 switch( child.GetResizePolicy( dimension ) )
3956 case ResizePolicy::FILL_TO_PARENT:
3958 return GetLatestSize( dimension );
3961 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
3963 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
3966 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
3968 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
3973 return GetLatestSize( dimension );
3978 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
3980 // Can be overridden in derived class
3981 return CalculateChildSizeBase( child, dimension );
3984 float Actor::GetHeightForWidth( float width )
3986 // Can be overridden in derived class
3987 return GetHeightForWidthBase( width );
3990 float Actor::GetWidthForHeight( float height )
3992 // Can be overridden in derived class
3993 return GetWidthForHeightBase( height );
3996 float Actor::GetLatestSize( Dimension::Type dimension ) const
3998 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4001 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4003 Vector2 padding = GetPadding( dimension );
4005 return GetLatestSize( dimension ) + padding.x + padding.y;
4008 float Actor::NegotiateFromParent( Dimension::Type dimension )
4010 Actor* parent = GetParent();
4013 Vector2 padding( GetPadding( dimension ) );
4014 Vector2 parentPadding( parent->GetPadding( dimension ) );
4015 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4021 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4023 float maxDimensionPoint = 0.0f;
4025 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4027 ActorPtr child = GetChildAt( i );
4029 if( !child->RelayoutDependentOnParent( dimension ) )
4031 // Calculate the min and max points that the children range across
4032 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
4033 float dimensionSize = child->GetRelayoutSize( dimension );
4034 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4038 return maxDimensionPoint;
4041 float Actor::GetSize( Dimension::Type dimension ) const
4043 return GetDimensionValue( GetTargetSize(), dimension );
4046 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4048 return GetDimensionValue( GetNaturalSize(), dimension );
4051 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4053 switch( GetResizePolicy( dimension ) )
4055 case ResizePolicy::USE_NATURAL_SIZE:
4057 return GetNaturalSize( dimension );
4060 case ResizePolicy::FIXED:
4062 return GetDimensionValue( GetPreferredSize(), dimension );
4065 case ResizePolicy::USE_ASSIGNED_SIZE:
4067 return GetDimensionValue( maximumSize, dimension );
4070 case ResizePolicy::FILL_TO_PARENT:
4071 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4072 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4074 return NegotiateFromParent( dimension );
4077 case ResizePolicy::FIT_TO_CHILDREN:
4079 return NegotiateFromChildren( dimension );
4082 case ResizePolicy::DIMENSION_DEPENDENCY:
4084 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4087 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4089 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4092 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4094 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4106 return 0.0f; // Default
4109 float Actor::ClampDimension( float size, Dimension::Type dimension )
4111 const float minSize = GetMinimumSize( dimension );
4112 const float maxSize = GetMaximumSize( dimension );
4114 return std::max( minSize, std::min( size, maxSize ) );
4117 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4119 // Check if it needs to be negotiated
4120 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4122 // Check that we havn't gotten into an infinite loop
4123 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4124 bool recursionFound = false;
4125 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4127 if( *it == searchActor )
4129 recursionFound = true;
4134 if( !recursionFound )
4136 // Record the path that we have taken
4137 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4139 // Dimension dependency check
4140 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4142 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4144 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4146 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4150 // Parent dependency check
4151 Actor* parent = GetParent();
4152 if( parent && RelayoutDependentOnParent( dimension ) )
4154 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4157 // Children dependency check
4158 if( RelayoutDependentOnChildren( dimension ) )
4160 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4162 ActorPtr child = GetChildAt( i );
4164 // Only relayout child first if it is not dependent on this actor
4165 if( !child->RelayoutDependentOnParent( dimension ) )
4167 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
4172 // For deriving classes
4173 OnCalculateRelayoutSize( dimension );
4175 // All dependencies checked, calculate the size and set negotiated flag
4176 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4178 SetNegotiatedDimension( newSize, dimension );
4179 SetLayoutNegotiated( true, dimension );
4181 // For deriving classes
4182 OnLayoutNegotiated( newSize, dimension );
4184 // This actor has been successfully processed, pop it off the recursion stack
4185 recursionStack.pop_back();
4189 // TODO: Break infinite loop
4190 SetLayoutNegotiated( true, dimension );
4195 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4197 // Negotiate all dimensions that require it
4198 ActorDimensionStack recursionStack;
4200 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4202 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4205 NegotiateDimension( dimension, allocatedSize, recursionStack );
4209 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4211 switch( mRelayoutData->sizeSetPolicy )
4213 case SizeScalePolicy::USE_SIZE_SET:
4218 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4220 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
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( naturalSizeRatio * size.height, size.height );
4231 else if( naturalSizeRatio > sizeRatio )
4233 return Vector2( size.width, size.width / naturalSizeRatio );
4244 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4246 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4247 const Vector3 naturalSize = GetNaturalSize();
4248 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4250 const float sizeRatio = size.width / size.height;
4251 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4253 if( naturalSizeRatio < sizeRatio )
4255 return Vector2( size.width, size.width / naturalSizeRatio );
4257 else if( naturalSizeRatio > sizeRatio )
4259 return Vector2( naturalSizeRatio * size.height, size.height );
4278 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4280 // Do the set actor size
4281 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4283 // Adjust for size set policy
4284 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4286 // Lock the flag to stop recursive relayouts on set size
4287 mRelayoutData->insideRelayout = true;
4288 SetSize( negotiatedSize );
4289 mRelayoutData->insideRelayout = false;
4291 // Clear flags for all dimensions
4292 SetLayoutDirty( false );
4294 // Give deriving classes a chance to respond
4295 OnRelayout( negotiatedSize, container );
4297 if( !mOnRelayoutSignal.Empty() )
4299 Dali::Actor handle( this );
4300 mOnRelayoutSignal.Emit( handle );
4304 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4306 // Force a size negotiation for actors that has assigned size during relayout
4307 // This is required as otherwise the flags that force a relayout will not
4308 // necessarilly be set. This will occur if the actor has already been laid out.
4309 // The dirty flags are then cleared. Then if the actor is added back into the
4310 // relayout container afterwards, the dirty flags would still be clear...
4311 // causing a relayout to be skipped. Here we force any actors added to the
4312 // container to be relayed out.
4313 if(GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE)
4315 SetLayoutNegotiated(false, Dimension::WIDTH);
4317 if(GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE)
4319 SetLayoutNegotiated(false, Dimension::HEIGHT);
4322 // Do the negotiation
4323 NegotiateDimensions( allocatedSize );
4325 // Set the actor size
4326 SetNegotiatedSize( container );
4328 // Negotiate down to children
4329 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4331 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4333 ActorPtr child = GetChildAt( i );
4335 // Forces children that have already been laid out to be relayed out
4336 // if they have assigned size during relayout.
4337 if(child->GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE)
4339 child->SetLayoutNegotiated(false, Dimension::WIDTH);
4340 child->SetLayoutDirty(true, Dimension::WIDTH);
4342 if(child->GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE)
4344 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
4345 child->SetLayoutDirty(true, Dimension::HEIGHT);
4348 // Only relayout if required
4349 if( child->RelayoutRequired() )
4351 container.Add( Dali::Actor( child.Get() ), newBounds );
4356 void Actor::RelayoutRequest( Dimension::Type dimension )
4358 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4359 if( relayoutController )
4361 Dali::Actor self( this );
4362 relayoutController->RequestRelayout( self, dimension );
4366 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4370 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4374 void Actor::SetPreferredSize( const Vector2& size )
4376 EnsureRelayoutData();
4378 if( size.width > 0.0f )
4380 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4383 if( size.height > 0.0f )
4385 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4388 mRelayoutData->preferredSize = size;
4393 Vector2 Actor::GetPreferredSize() const
4395 if ( mRelayoutData )
4397 return Vector2( mRelayoutData->preferredSize );
4400 return GetDefaultPreferredSize();
4403 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4405 EnsureRelayoutData();
4407 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4409 if( dimension & ( 1 << i ) )
4411 mRelayoutData->minimumSize[ i ] = size;
4418 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4420 if ( mRelayoutData )
4422 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4424 if( dimension & ( 1 << i ) )
4426 return mRelayoutData->minimumSize[ i ];
4431 return 0.0f; // Default
4434 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4436 EnsureRelayoutData();
4438 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4440 if( dimension & ( 1 << i ) )
4442 mRelayoutData->maximumSize[ i ] = size;
4449 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4451 if ( mRelayoutData )
4453 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4455 if( dimension & ( 1 << i ) )
4457 return mRelayoutData->maximumSize[ i ];
4462 return FLT_MAX; // Default
4465 Object* Actor::GetParentObject() const
4470 void Actor::SetSiblingOrder( unsigned int order )
4472 mSiblingOrder = std::min( order, static_cast<unsigned int>( DevelLayer::SIBLING_ORDER_MULTIPLIER ) );
4475 SetDepthIndexMessage( GetEventThreadServices(), *mNode, GetDepthIndex( mDepth, mSiblingOrder ) );
4479 void Actor::DefragmentSiblingIndexes( ActorContainer& siblings )
4481 // Sibling index may not be in consecutive order as the sibling range is limited ( DevelLayer::SIBLING_ORDER_MULTIPLIER )
4482 // we need to remove the gaps and ensure the number start from 0 and consecutive hence have a full range.
4484 // Start at index 0, while index <= highest order
4485 // Find next index higher than 0
4486 // if nextHigher > index+1
4487 // set all nextHigher orders to index+1
4489 // Limitation: May reach the ceiling of DevelLayer::SIBLING_ORDER_MULTIPLIER with highest sibling.
4491 ActorIter end = siblings.end();
4492 int highestOrder = 0;
4493 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
4495 ActorPtr sibling = (*iter);
4496 int siblingOrder = sibling->mSiblingOrder;
4497 highestOrder = std::max( highestOrder, siblingOrder );
4500 for ( int index = 0; index <= highestOrder; index++ )
4502 int nextHighest = -1;
4504 // Find Next highest
4505 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
4507 ActorPtr sibling = (*iter);
4508 int siblingOrder = sibling->mSiblingOrder;
4510 if ( siblingOrder > index )
4512 if ( nextHighest == -1 )
4514 nextHighest = siblingOrder;
4516 nextHighest = std::min( nextHighest, siblingOrder );
4520 // Check if a gap exists between indexes, if so set next index to consecutive number
4521 if ( ( nextHighest - index ) > 1 )
4523 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
4525 ActorPtr sibling = (*iter);
4526 int siblingOrder = sibling->mSiblingOrder;
4527 if ( siblingOrder == nextHighest )
4529 sibling->mSiblingOrder = index + 1;
4530 if ( sibling->mSiblingOrder >= Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER )
4532 DALI_LOG_WARNING( "Reached max sibling order level for raising / lowering actors\n" );
4533 sibling->mSiblingOrder = Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER;
4535 sibling->SetSiblingOrder( sibling->mSiblingOrder );
4542 bool Actor::ShiftSiblingsLevels( ActorContainer& siblings, int targetLevelToShiftFrom )
4544 // Allows exclusive levels for an actor by shifting all sibling levels at the target and above by 1
4545 bool defragmentationRequired( false );
4546 ActorIter end = siblings.end();
4547 for( ActorIter iter = siblings.begin(); ( iter != end ) ; ++iter )
4549 // Move actors at nearest order and above up by 1
4550 ActorPtr sibling = (*iter);
4551 if ( sibling != this )
4553 // Iterate through container of actors, any actor with a sibling order of the target or greater should
4554 // be incremented by 1.
4555 if ( sibling->mSiblingOrder >= targetLevelToShiftFrom )
4557 sibling->mSiblingOrder++;
4558 if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
4560 // If a sibling order raises so that it is only 1 from the maximum allowed then set flag so
4561 // can re-order all sibling orders.
4562 defragmentationRequired = true;
4564 sibling->SetSiblingOrder( sibling->mSiblingOrder );
4568 return defragmentationRequired;
4574 1) Check if already at top and nothing to be done.
4575 This Actor can have highest sibling order but if not exclusive then another actor at same sibling
4576 order can be positioned above it due to insertion order of actors.
4577 2) Find nearest sibling level above, these are the siblings this actor needs to be above
4578 3) a) There may be other levels above this target level
4579 b) Increment all sibling levels at the level above nearest(target)
4580 c) Now have a vacant sibling level
4581 4) Set this actor's sibling level to nearest +1 as now vacated.
4583 Note May not just be sibling level + 1 as could be empty levels in-between
4588 ActorC ( sibling level 4 )
4589 ActorB ( sibling level 3 )
4590 ActorA ( sibling level 1 )
4592 2 ) ACTION: Raise A above B
4593 a) Find nearest level above A = Level 3
4594 b) Increment levels above Level 3
4596 ActorC ( sibling level 5 )
4597 ActorB ( sibling level 3 ) NEAREST
4598 ActorA ( sibling level 1 )
4600 3 ) Set Actor A sibling level to nearest +1 as vacant
4602 ActorC ( sibling level 5 )
4603 ActorA ( sibling level 4 )
4604 ActorB ( sibling level 3 )
4606 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4607 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4608 remove any empty sibling order gaps and start from sibling level 0 again.
4609 If the number of actors reaches this maximum and all using exclusive sibling order values then
4610 defragmention will stop and new sibling orders will be set to same max value.
4614 int nearestLevel = mSiblingOrder;
4615 int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
4616 bool defragmentationRequired( false );
4618 ActorContainer* siblings = mParent->mChildren;
4620 // Find Nearest sibling level above this actor
4621 ActorIter end = siblings->end();
4622 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
4624 ActorPtr sibling = (*iter);
4625 if ( sibling != this )
4627 int order = GetSiblingOrder( sibling );
4629 if ( ( order >= mSiblingOrder ) )
4631 int distanceToNextLevel = order - mSiblingOrder;
4632 if ( distanceToNextLevel < shortestDistanceToNextLevel )
4634 nearestLevel = order;
4635 shortestDistanceToNextLevel = distanceToNextLevel;
4641 if ( nearestLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at top
4643 mSiblingOrder = nearestLevel + 1; // Set sibling level to that above the nearest level
4644 defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
4645 // Move current actor to newly vacated order level
4646 SetSiblingOrder( mSiblingOrder );
4647 if ( defragmentationRequired )
4649 DefragmentSiblingIndexes( *siblings );
4652 SetSiblingOrder( mSiblingOrder );
4656 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4663 1) Check if actor already at bottom and if nothing needs to be done
4664 This Actor can have lowest sibling order but if not exclusive then another actor at same sibling
4665 order can be positioned above it due to insertion order of actors so need to move this actor below it.
4666 2) Find nearest sibling level below, this Actor needs to be below it
4667 3) a) Need to vacate a sibling level below nearest for this actor to occupy
4668 b) Shift up all sibling order values of actor at the nearest level and levels above it to vacate a level.
4669 c) Set this actor's sibling level to this newly vacated level.
4670 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4671 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4672 remove any empty sibling order gaps and start from sibling level 0 again.
4673 If the number of actors reaches this maximum and all using exclusive sibling order values then
4674 defragmention will stop and new sibling orders will be set to same max value.
4679 // 1) Find nearest level below
4680 int nearestLevel = mSiblingOrder;
4681 int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
4683 ActorContainer* siblings = mParent->mChildren;
4685 ActorIter end = siblings->end();
4686 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
4688 ActorPtr sibling = (*iter);
4689 if ( sibling != this )
4691 int order = GetSiblingOrder( sibling );
4693 if ( order <= mSiblingOrder )
4695 int distanceToNextLevel = mSiblingOrder - order;
4696 if ( distanceToNextLevel < shortestDistanceToNextLevel )
4698 nearestLevel = order;
4699 shortestDistanceToNextLevel = distanceToNextLevel;
4705 bool defragmentationRequired ( false );
4707 // 2) If actor already not at bottom, raise all actors at required level and above
4708 if ( shortestDistanceToNextLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at bottom
4710 mSiblingOrder = nearestLevel;
4711 defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
4712 // Move current actor to newly vacated order
4713 SetSiblingOrder( mSiblingOrder );
4714 if ( defragmentationRequired )
4716 DefragmentSiblingIndexes( *siblings );
4722 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4726 void Actor::RaiseToTop()
4729 1 ) Find highest sibling order actor
4730 2 ) If highest sibling level not itself then set sibling order to that + 1
4731 3 ) highest sibling order can be same as itself so need to increment over that
4732 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4733 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4734 remove any empty sibling order gaps and start from sibling level 0 again.
4735 If the number of actors reaches this maximum and all using exclusive sibling order values then
4736 defragmention will stop and new sibling orders will be set to same max value.
4743 ActorContainer* siblings = mParent->mChildren;
4745 ActorIter end = siblings->end();
4746 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
4748 ActorPtr sibling = (*iter);
4749 if ( sibling != this )
4751 maxOrder = std::max( GetSiblingOrder( sibling ), maxOrder );
4755 bool defragmentationRequired( false );
4757 if ( maxOrder >= mSiblingOrder )
4759 mSiblingOrder = maxOrder + 1;
4760 if ( mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
4762 defragmentationRequired = true;
4766 SetSiblingOrder( mSiblingOrder );
4768 if ( defragmentationRequired )
4770 DefragmentSiblingIndexes( *siblings );
4775 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4779 void Actor::LowerToBottom()
4782 See Actor::LowerToBottom()
4784 1 ) Check if this actor already at exclusively at the bottom, if so then no more to be done.
4785 2 ) a ) Check if the bottom position 0 is vacant.
4786 b ) If 0 position is not vacant then shift up all sibling order values from 0 and above
4787 c ) 0 sibling position is vacant.
4788 3 ) Set this actor to vacant sibling order 0;
4789 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4790 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4791 remove any empty sibling order gaps and start from sibling level 0 again.
4792 If the number of actors reaches this maximum and all using exclusive sibling order values then
4793 defragmention will stop and new sibling orders will be set to same max value.
4798 bool defragmentationRequired( false );
4799 bool orderZeroFree ( true );
4801 ActorContainer* siblings = mParent->mChildren;
4803 bool actorAtLowestOrder = true;
4804 ActorIter end = siblings->end();
4805 for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
4807 ActorPtr sibling = (*iter);
4808 if ( sibling != this )
4810 int siblingOrder = GetSiblingOrder( sibling );
4811 if ( siblingOrder <= mSiblingOrder )
4813 actorAtLowestOrder = false;
4816 if ( siblingOrder == 0 )
4818 orderZeroFree = false;
4823 if ( ! actorAtLowestOrder )
4825 if ( ! orderZeroFree )
4827 defragmentationRequired = ShiftSiblingsLevels( *siblings, 0 );
4830 SetSiblingOrder( mSiblingOrder );
4832 if ( defragmentationRequired )
4834 DefragmentSiblingIndexes( *siblings );
4840 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4844 void Actor::RaiseAbove( Internal::Actor& target )
4847 1 ) a) Find target actor's sibling order
4848 b) If sibling order of target is the same as this actor then need to this Actor's sibling order
4849 needs to be above it or the insertion order will determine which is drawn on top.
4850 2 ) Shift up by 1 all sibling order greater than target sibling order
4851 3 ) Set this actor to the sibling order to target +1 as will be a newly vacated gap above
4852 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4853 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4854 remove any empty sibling order gaps and start from sibling level 0 again.
4855 If the number of actors reaches this maximum and all using exclusive sibling order values then
4856 defragmention will stop and new sibling orders will be set to same max value.
4861 if ( ValidateActors( *this, target ) )
4863 // Find target's sibling order
4864 // Set actor sibling order to this number +1
4865 int targetSiblingOrder = GetSiblingOrder( &target );
4866 ActorContainer* siblings = mParent->mChildren;
4867 mSiblingOrder = targetSiblingOrder + 1;
4868 bool defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
4870 SetSiblingOrder( mSiblingOrder );
4872 if ( defragmentationRequired )
4874 DefragmentSiblingIndexes( *(mParent->mChildren) );
4880 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4884 void Actor::LowerBelow( Internal::Actor& target )
4887 1 ) a) Find target actor's sibling order
4888 b) If sibling order of target is the same as this actor then need to this Actor's sibling order
4889 needs to be below it or the insertion order will determine which is drawn on top.
4890 2 ) Shift the target sibling order and all sibling orders at that level or above by 1
4891 3 ) Set this actor to the sibling order of the target before it changed.
4892 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4893 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4894 remove any empty sibling order gaps and start from sibling level 0 again.
4895 If the number of actors reaches this maximum and all using exclusive sibling order values then
4896 defragmention will stop and new sibling orders will be set to same max value.
4901 if ( ValidateActors( *this, target ) )
4903 bool defragmentationRequired ( false );
4904 // Find target's sibling order
4905 // Set actor sibling order to target sibling order - 1
4906 int targetSiblingOrder = GetSiblingOrder( &target);
4907 ActorContainer* siblings = mParent->mChildren;
4908 if ( targetSiblingOrder == 0 )
4911 ActorIter end = siblings->end();
4912 for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
4914 ActorPtr sibling = (*iter);
4915 if ( sibling != this )
4917 sibling->mSiblingOrder++;
4918 if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
4920 defragmentationRequired = true;
4922 sibling->SetSiblingOrder( sibling->mSiblingOrder );
4929 defragmentationRequired = ShiftSiblingsLevels( *siblings, targetSiblingOrder );
4931 mSiblingOrder = targetSiblingOrder;
4933 SetSiblingOrder( mSiblingOrder );
4935 if ( defragmentationRequired )
4937 DefragmentSiblingIndexes( *(mParent->mChildren) );
4943 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4947 } // namespace Internal