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( "positionUsesAnchorPoint", BOOLEAN, true, false, false, Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT )
233 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
237 const char* const SIGNAL_TOUCHED = "touched";
238 const char* const SIGNAL_HOVERED = "hovered";
239 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
240 const char* const SIGNAL_ON_STAGE = "onStage";
241 const char* const SIGNAL_OFF_STAGE = "offStage";
242 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
243 const char* const SIGNAL_TOUCH = "touch";
247 const char* const ACTION_SHOW = "show";
248 const char* const ACTION_HIDE = "hide";
250 BaseHandle CreateActor()
252 return Dali::Actor::New();
255 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
257 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
258 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
259 SignalConnectorType signalConnector3( mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal );
260 SignalConnectorType signalConnector4( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
261 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
262 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
263 SignalConnectorType signalConnector7( mType, SIGNAL_TOUCH, &Actor::DoConnectSignal );
265 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
266 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
271 const Vector3& value;
274 DALI_ENUM_TO_STRING_TABLE_BEGIN_WITH_TYPE( AnchorValue, ANCHOR_CONSTANT )
275 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_LEFT )
276 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_CENTER )
277 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_RIGHT )
278 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_LEFT )
279 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER )
280 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_RIGHT )
281 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_LEFT )
282 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_CENTER )
283 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_RIGHT )
284 DALI_ENUM_TO_STRING_TABLE_END( ANCHOR_CONSTANT )
286 DALI_ENUM_TO_STRING_TABLE_BEGIN( COLOR_MODE )
287 DALI_ENUM_TO_STRING( USE_OWN_COLOR )
288 DALI_ENUM_TO_STRING( USE_PARENT_COLOR )
289 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_COLOR )
290 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_ALPHA )
291 DALI_ENUM_TO_STRING_TABLE_END( COLOR_MODE )
293 DALI_ENUM_TO_STRING_TABLE_BEGIN( POSITION_INHERITANCE_MODE )
294 DALI_ENUM_TO_STRING( INHERIT_PARENT_POSITION )
295 DALI_ENUM_TO_STRING( USE_PARENT_POSITION )
296 DALI_ENUM_TO_STRING( USE_PARENT_POSITION_PLUS_LOCAL_POSITION )
297 DALI_ENUM_TO_STRING( DONT_INHERIT_POSITION )
298 DALI_ENUM_TO_STRING_TABLE_END( POSITION_INHERITANCE_MODE )
300 DALI_ENUM_TO_STRING_TABLE_BEGIN( DRAW_MODE )
301 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, NORMAL )
302 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, OVERLAY_2D )
303 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, STENCIL )
304 DALI_ENUM_TO_STRING_TABLE_END( DRAW_MODE )
306 DALI_ENUM_TO_STRING_TABLE_BEGIN( RESIZE_POLICY )
307 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIXED )
308 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_NATURAL_SIZE )
309 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FILL_TO_PARENT )
310 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_RELATIVE_TO_PARENT )
311 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_FIXED_OFFSET_FROM_PARENT )
312 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIT_TO_CHILDREN )
313 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, DIMENSION_DEPENDENCY )
314 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_ASSIGNED_SIZE )
315 DALI_ENUM_TO_STRING_TABLE_END( RESIZE_POLICY )
317 DALI_ENUM_TO_STRING_TABLE_BEGIN( SIZE_SCALE_POLICY )
318 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, USE_SIZE_SET )
319 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FIT_WITH_ASPECT_RATIO )
320 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FILL_WITH_ASPECT_RATIO )
321 DALI_ENUM_TO_STRING_TABLE_END( SIZE_SCALE_POLICY )
323 DALI_ENUM_TO_STRING_TABLE_BEGIN( CLIPPING_MODE )
324 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, DISABLED )
325 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, CLIP_CHILDREN )
326 DALI_ENUM_TO_STRING_TABLE_END( CLIPPING_MODE )
329 bool GetAnchorPointConstant( const std::string& value, Vector3& anchor )
331 for( unsigned int i = 0; i < ANCHOR_CONSTANT_TABLE_COUNT; ++i )
333 size_t sizeIgnored = 0;
334 if( CompareTokens( value.c_str(), ANCHOR_CONSTANT_TABLE[ i ].name, sizeIgnored ) )
336 anchor = ANCHOR_CONSTANT_TABLE[ i ].value;
343 inline bool GetParentOriginConstant( const std::string& value, Vector3& parentOrigin )
345 // Values are the same so just use the same table as anchor-point
346 return GetAnchorPointConstant( value, parentOrigin );
350 * @brief Extract a given dimension from a Vector2
352 * @param[in] values The values to extract from
353 * @param[in] dimension The dimension to extract
354 * @return Return the value for the dimension
356 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
360 case Dimension::WIDTH:
364 case Dimension::HEIGHT:
366 return values.height;
377 * @brief Extract a given dimension from a Vector3
379 * @param[in] values The values to extract from
380 * @param[in] dimension The dimension to extract
381 * @return Return the value for the dimension
383 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
385 return GetDimensionValue( values.GetVectorXY(), dimension );
388 unsigned int GetDepthIndex( uint16_t depth, uint16_t siblingOrder )
390 return depth * Dali::DevelLayer::ACTOR_DEPTH_MULTIPLIER + siblingOrder * Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER;
394 * @brief Recursively emits the visibility-changed-signal on the actor tree.
395 * @param[in] actor The actor to emit the signal on
396 * @param[in] visible The new visibility of the actor
397 * @param[in] type Whether the actor's visible property has changed or a parent's
399 void EmitVisibilityChangedSignalRecursively( ActorPtr actor, bool visible, DevelActor::VisibilityChange::Type type )
403 actor->EmitVisibilityChangedSignal( visible, type );
405 if( actor->GetChildCount() > 0 )
407 ActorContainer& children = actor->GetChildrenInternal();
408 for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter )
410 EmitVisibilityChangedSignalRecursively( *iter, visible, DevelActor::VisibilityChange::PARENT );
416 } // unnamed namespace
418 ActorPtr Actor::New()
420 ActorPtr actor( new Actor( BASIC ) );
422 // Second-phase construction
428 const std::string& Actor::GetName() const
433 void Actor::SetName( const std::string& name )
439 // ATTENTION: string for debug purposes is not thread safe.
440 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
444 unsigned int Actor::GetId() const
449 bool Actor::OnStage() const
454 Dali::Layer Actor::GetLayer()
458 // Short-circuit for Layer derived actors
461 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
464 // Find the immediate Layer parent
465 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
467 if( parent->IsLayer() )
469 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
476 void Actor::Add( Actor& child )
478 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
479 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
483 mChildren = new ActorContainer;
486 Actor* const oldParent( child.mParent );
488 // child might already be ours
489 if( this != oldParent )
491 // if we already have parent, unparent us first
494 oldParent->Remove( child ); // This causes OnChildRemove callback
496 // Old parent may need to readjust to missing child
497 if( oldParent->RelayoutDependentOnChildren() )
499 oldParent->RelayoutRequest();
503 // Guard against Add() during previous OnChildRemove callback
506 // Do this first, since user callbacks from within SetParent() may need to remove child
507 mChildren->push_back( ActorPtr( &child ) );
509 // SetParent asserts that child can be added
510 child.SetParent( this );
512 // Notification for derived classes
515 // Only put in a relayout request if there is a suitable dependency
516 if( RelayoutDependentOnChildren() )
524 void Actor::Remove( Actor& child )
526 if( (this == &child) || (!mChildren) )
528 // no children or removing itself
534 // Find the child in mChildren, and unparent it
535 ActorIter end = mChildren->end();
536 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
538 ActorPtr actor = (*iter);
540 if( actor.Get() == &child )
542 // Keep handle for OnChildRemove notification
545 // Do this first, since user callbacks from within SetParent() may need to add the child
546 mChildren->erase( iter );
548 DALI_ASSERT_DEBUG( actor->GetParent() == this );
549 actor->SetParent( NULL );
557 // Only put in a relayout request if there is a suitable dependency
558 if( RelayoutDependentOnChildren() )
564 // Notification for derived classes
565 OnChildRemove( child );
568 void Actor::Unparent()
572 // Remove this actor from the parent. The remove will put a relayout request in for
573 // the parent if required
574 mParent->Remove( *this );
575 // mParent is now NULL!
579 unsigned int Actor::GetChildCount() const
581 return ( NULL != mChildren ) ? mChildren->size() : 0;
584 ActorPtr Actor::GetChildAt( unsigned int index ) const
586 DALI_ASSERT_ALWAYS( index < GetChildCount() );
588 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
591 ActorPtr Actor::FindChildByName( const std::string& actorName )
594 if( actorName == mName )
600 ActorIter end = mChildren->end();
601 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
603 child = (*iter)->FindChildByName( actorName );
614 ActorPtr Actor::FindChildById( const unsigned int id )
623 ActorIter end = mChildren->end();
624 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
626 child = (*iter)->FindChildById( id );
637 void Actor::SetParentOrigin( const Vector3& origin )
641 // mNode is being used in a separate thread; queue a message to set the value & base value
642 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
645 // Cache for event-thread access
648 // not allocated, check if different from default
649 if( ParentOrigin::DEFAULT != origin )
651 mParentOrigin = new Vector3( origin );
656 // check if different from current costs more than just set
657 *mParentOrigin = origin;
661 void Actor::SetParentOriginX( float x )
663 const Vector3& current = GetCurrentParentOrigin();
665 SetParentOrigin( Vector3( x, current.y, current.z ) );
668 void Actor::SetParentOriginY( float y )
670 const Vector3& current = GetCurrentParentOrigin();
672 SetParentOrigin( Vector3( current.x, y, current.z ) );
675 void Actor::SetParentOriginZ( float z )
677 const Vector3& current = GetCurrentParentOrigin();
679 SetParentOrigin( Vector3( current.x, current.y, z ) );
682 const Vector3& Actor::GetCurrentParentOrigin() const
684 // Cached for event-thread access
685 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
688 void Actor::SetAnchorPoint( const Vector3& anchor )
692 // mNode is being used in a separate thread; queue a message to set the value & base value
693 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
696 // Cache for event-thread access
699 // not allocated, check if different from default
700 if( AnchorPoint::DEFAULT != anchor )
702 mAnchorPoint = new Vector3( anchor );
707 // check if different from current costs more than just set
708 *mAnchorPoint = anchor;
712 void Actor::SetAnchorPointX( float x )
714 const Vector3& current = GetCurrentAnchorPoint();
716 SetAnchorPoint( Vector3( x, current.y, current.z ) );
719 void Actor::SetAnchorPointY( float y )
721 const Vector3& current = GetCurrentAnchorPoint();
723 SetAnchorPoint( Vector3( current.x, y, current.z ) );
726 void Actor::SetAnchorPointZ( float z )
728 const Vector3& current = GetCurrentAnchorPoint();
730 SetAnchorPoint( Vector3( current.x, current.y, z ) );
733 const Vector3& Actor::GetCurrentAnchorPoint() const
735 // Cached for event-thread access
736 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
739 void Actor::SetPosition( float x, float y )
741 SetPosition( Vector3( x, y, 0.0f ) );
744 void Actor::SetPosition( float x, float y, float z )
746 SetPosition( Vector3( x, y, z ) );
749 void Actor::SetPosition( const Vector3& position )
751 mTargetPosition = position;
755 // mNode is being used in a separate thread; queue a message to set the value & base value
756 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
760 void Actor::SetX( float x )
762 mTargetPosition.x = x;
766 // mNode is being used in a separate thread; queue a message to set the value & base value
767 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
771 void Actor::SetY( float y )
773 mTargetPosition.y = y;
777 // mNode is being used in a separate thread; queue a message to set the value & base value
778 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
782 void Actor::SetZ( float z )
784 mTargetPosition.z = z;
788 // mNode is being used in a separate thread; queue a message to set the value & base value
789 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
793 void Actor::TranslateBy( const Vector3& distance )
795 mTargetPosition += distance;
799 // mNode is being used in a separate thread; queue a message to set the value & base value
800 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
804 const Vector3& Actor::GetCurrentPosition() const
808 // mNode is being used in a separate thread; copy the value from the previous update
809 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
812 return Vector3::ZERO;
815 const Vector3& Actor::GetTargetPosition() const
817 return mTargetPosition;
820 const Vector3& Actor::GetCurrentWorldPosition() const
824 // mNode is being used in a separate thread; copy the value from the previous update
825 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
828 return Vector3::ZERO;
831 const Vector2 Actor::GetCurrentScreenPosition() const
833 if( OnStage() && NULL != mNode )
835 StagePtr stage = Stage::GetCurrent();
836 Vector3 worldPosition = mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
837 Vector3 actorSize = GetCurrentSize() * GetCurrentScale();
838 Vector2 halfStageSize( stage->GetSize() * 0.5f ); // World position origin is center of stage
839 Vector3 halfActorSize( actorSize * 0.5f );
840 Vector3 anchorPointOffSet = halfActorSize - actorSize * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
842 return Vector2( halfStageSize.width + worldPosition.x - anchorPointOffSet.x,
843 halfStageSize.height + worldPosition.y - anchorPointOffSet.y );
846 return Vector2::ZERO;
849 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
851 // this flag is not animatable so keep the value
852 mPositionInheritanceMode = mode;
855 // mNode is being used in a separate thread; queue a message to set the value
856 SetInheritPositionMessage( GetEventThreadServices(), *mNode, mode == INHERIT_PARENT_POSITION );
860 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
862 // Cached for event-thread access
863 return mPositionInheritanceMode;
866 void Actor::SetInheritPosition( bool inherit )
868 if( mInheritPosition != inherit && NULL != mNode )
870 // non animateable so keep local copy
871 mInheritPosition = inherit;
872 SetInheritPositionMessage( GetEventThreadServices(), *mNode, inherit );
876 bool Actor::IsPositionInherited() const
878 return mInheritPosition;
881 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
883 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
884 normalizedAxis.Normalize();
886 Quaternion orientation( angle, normalizedAxis );
888 SetOrientation( orientation );
891 void Actor::SetOrientation( const Quaternion& orientation )
893 mTargetOrientation = orientation;
897 // mNode is being used in a separate thread; queue a message to set the value & base value
898 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation );
902 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
904 RotateBy( Quaternion(angle, axis) );
907 void Actor::RotateBy( const Quaternion& relativeRotation )
909 mTargetOrientation *= Quaternion( relativeRotation );
913 // mNode is being used in a separate thread; queue a message to set the value & base value
914 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
918 const Quaternion& Actor::GetCurrentOrientation() const
922 // mNode is being used in a separate thread; copy the value from the previous update
923 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
926 return Quaternion::IDENTITY;
929 const Quaternion& Actor::GetCurrentWorldOrientation() const
933 // mNode is being used in a separate thread; copy the value from the previous update
934 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
937 return Quaternion::IDENTITY;
940 void Actor::SetScale( float scale )
942 SetScale( Vector3( scale, scale, scale ) );
945 void Actor::SetScale( float x, float y, float z )
947 SetScale( Vector3( x, y, z ) );
950 void Actor::SetScale( const Vector3& scale )
952 mTargetScale = scale;
956 // mNode is being used in a separate thread; queue a message to set the value & base value
957 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
961 void Actor::SetScaleX( float x )
967 // mNode is being used in a separate thread; queue a message to set the value & base value
968 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
972 void Actor::SetScaleY( float y )
978 // mNode is being used in a separate thread; queue a message to set the value & base value
979 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
983 void Actor::SetScaleZ( float z )
989 // mNode is being used in a separate thread; queue a message to set the value & base value
990 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
994 void Actor::ScaleBy(const Vector3& relativeScale)
996 mTargetScale *= relativeScale;
1000 // mNode is being used in a separate thread; queue a message to set the value & base value
1001 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
1005 const Vector3& Actor::GetCurrentScale() const
1009 // mNode is being used in a separate thread; copy the value from the previous update
1010 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
1013 return Vector3::ONE;
1016 const Vector3& Actor::GetCurrentWorldScale() const
1020 // mNode is being used in a separate thread; copy the value from the previous update
1021 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
1024 return Vector3::ONE;
1027 void Actor::SetInheritScale( bool inherit )
1030 if( mInheritScale != inherit && NULL != mNode )
1032 // non animateable so keep local copy
1033 mInheritScale = inherit;
1034 // mNode is being used in a separate thread; queue a message to set the value
1035 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
1039 bool Actor::IsScaleInherited() const
1041 return mInheritScale;
1044 Matrix Actor::GetCurrentWorldMatrix() const
1048 return mNode->GetWorldMatrix(0);
1051 return Matrix::IDENTITY;
1054 void Actor::SetVisible( bool visible )
1056 if( mVisible != visible )
1060 // mNode is being used in a separate thread; queue a message to set the value & base value
1061 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
1066 // Emit the signal on this actor and all its children
1067 EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
1071 bool Actor::IsVisible() const
1075 // mNode is being used in a separate thread; copy the value from the previous update
1076 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
1082 void Actor::SetOpacity( float opacity )
1084 mTargetColor.a = opacity;
1088 // mNode is being used in a separate thread; queue a message to set the value & base value
1089 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
1093 float Actor::GetCurrentOpacity() const
1097 // mNode is being used in a separate thread; copy the value from the previous update
1098 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1104 ClippingMode::Type Actor::GetClippingMode() const
1106 return mClippingMode;
1109 unsigned int Actor::GetSortingDepth()
1111 return GetDepthIndex( mDepth, mSiblingOrder );
1114 const Vector4& Actor::GetCurrentWorldColor() const
1118 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1121 return Color::WHITE;
1124 void Actor::SetColor( const Vector4& color )
1126 mTargetColor = color;
1130 // mNode is being used in a separate thread; queue a message to set the value & base value
1131 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1135 void Actor::SetColorRed( float red )
1137 mTargetColor.r = red;
1141 // mNode is being used in a separate thread; queue a message to set the value & base value
1142 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1146 void Actor::SetColorGreen( float green )
1148 mTargetColor.g = green;
1152 // mNode is being used in a separate thread; queue a message to set the value & base value
1153 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1157 void Actor::SetColorBlue( float blue )
1159 mTargetColor.b = blue;
1163 // mNode is being used in a separate thread; queue a message to set the value & base value
1164 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1168 const Vector4& Actor::GetCurrentColor() const
1172 // mNode is being used in a separate thread; copy the value from the previous update
1173 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1176 return Color::WHITE;
1179 void Actor::SetInheritOrientation( bool inherit )
1181 if( mInheritOrientation != inherit && NULL != mNode)
1183 // non animateable so keep local copy
1184 mInheritOrientation = inherit;
1185 // mNode is being used in a separate thread; queue a message to set the value
1186 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1190 bool Actor::IsOrientationInherited() const
1192 return mInheritOrientation;
1195 void Actor::SetSizeModeFactor( const Vector3& factor )
1197 EnsureRelayoutData();
1199 mRelayoutData->sizeModeFactor = factor;
1202 const Vector3& Actor::GetSizeModeFactor() const
1204 if ( mRelayoutData )
1206 return mRelayoutData->sizeModeFactor;
1209 return GetDefaultSizeModeFactor();
1212 void Actor::SetColorMode( ColorMode colorMode )
1214 // non animateable so keep local copy
1215 mColorMode = colorMode;
1218 // mNode is being used in a separate thread; queue a message to set the value
1219 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1223 ColorMode Actor::GetColorMode() const
1225 // we have cached copy
1229 void Actor::SetSize( float width, float height )
1231 SetSize( Vector2( width, height ) );
1234 void Actor::SetSize( float width, float height, float depth )
1236 SetSize( Vector3( width, height, depth ) );
1239 void Actor::SetSize( const Vector2& size )
1241 SetSize( Vector3( size.width, size.height, 0.f ) );
1244 void Actor::SetSizeInternal( const Vector2& size )
1246 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1249 void Actor::SetSize( const Vector3& size )
1251 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1253 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1254 SetPreferredSize( size.GetVectorXY() );
1258 SetSizeInternal( size );
1262 void Actor::SetSizeInternal( const Vector3& size )
1264 // dont allow recursive loop
1265 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1266 // 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
1267 if( ( NULL != mNode )&&
1268 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1269 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1270 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1274 // mNode is being used in a separate thread; queue a message to set the value & base value
1275 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
1277 // Notification for derived classes
1278 mInsideOnSizeSet = true;
1279 OnSizeSet( mTargetSize );
1280 mInsideOnSizeSet = false;
1282 // Raise a relayout request if the flag is not locked
1283 if( mRelayoutData && !mRelayoutData->insideRelayout )
1290 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1292 mTargetSize = targetSize;
1294 // Notify deriving classes
1295 OnSizeAnimation( animation, mTargetSize );
1298 void Actor::NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property )
1300 if ( Dali::Actor::Property::SIZE_WIDTH == property )
1302 mTargetSize.width = targetSize;
1304 else if ( Dali::Actor::Property::SIZE_HEIGHT == property )
1306 mTargetSize.height = targetSize;
1308 else if ( Dali::Actor::Property::SIZE_DEPTH == property )
1310 mTargetSize.depth = targetSize;
1312 // Notify deriving classes
1313 OnSizeAnimation( animation, mTargetSize );
1316 void Actor::NotifyPositionAnimation( Animation& animation, const Vector3& targetPosition )
1318 mTargetPosition = targetPosition;
1321 void Actor::NotifyPositionAnimation( Animation& animation, float targetPosition, Property::Index property )
1323 if ( Dali::Actor::Property::POSITION_X == property )
1325 mTargetPosition.x = targetPosition;
1327 else if ( Dali::Actor::Property::POSITION_Y == property )
1329 mTargetPosition.y = targetPosition;
1331 else if ( Dali::Actor::Property::POSITION_Z == property )
1333 mTargetPosition.z = targetPosition;
1337 void Actor::SetWidth( float width )
1339 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1341 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
1342 mRelayoutData->preferredSize.width = width;
1346 mTargetSize.width = width;
1350 // mNode is being used in a separate thread; queue a message to set the value & base value
1351 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1358 void Actor::SetHeight( float height )
1360 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1362 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
1363 mRelayoutData->preferredSize.height = height;
1367 mTargetSize.height = height;
1371 // mNode is being used in a separate thread; queue a message to set the value & base value
1372 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1379 void Actor::SetDepth( float depth )
1381 mTargetSize.depth = depth;
1385 // mNode is being used in a separate thread; queue a message to set the value & base value
1386 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1390 const Vector3& Actor::GetTargetSize() const
1395 const Vector3& Actor::GetCurrentSize() const
1399 // mNode is being used in a separate thread; copy the value from the previous update
1400 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1403 return Vector3::ZERO;
1406 Vector3 Actor::GetNaturalSize() const
1408 // It is up to deriving classes to return the appropriate natural size
1409 return Vector3( 0.0f, 0.0f, 0.0f );
1412 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1414 EnsureRelayoutData();
1416 ResizePolicy::Type originalWidthPolicy = GetResizePolicy(Dimension::WIDTH);
1417 ResizePolicy::Type originalHeightPolicy = GetResizePolicy(Dimension::HEIGHT);
1419 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1421 if( dimension & ( 1 << i ) )
1423 mRelayoutData->resizePolicies[ i ] = policy;
1427 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1429 if( dimension & Dimension::WIDTH )
1431 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1434 if( dimension & Dimension::HEIGHT )
1436 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1440 // If calling SetResizePolicy, assume we want relayout enabled
1441 SetRelayoutEnabled( true );
1443 // If the resize policy is set to be FIXED, the preferred size
1444 // should be overrided by the target size. Otherwise the target
1445 // size should be overrided by the preferred size.
1447 if( dimension & Dimension::WIDTH )
1449 if( originalWidthPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1451 mRelayoutData->preferredSize.width = mTargetSize.width;
1453 else if( originalWidthPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1455 mTargetSize.width = mRelayoutData->preferredSize.width;
1459 if( dimension & Dimension::HEIGHT )
1461 if( originalHeightPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1463 mRelayoutData->preferredSize.height = mTargetSize.height;
1465 else if( originalHeightPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1467 mTargetSize.height = mRelayoutData->preferredSize.height;
1471 OnSetResizePolicy( policy, dimension );
1473 // Trigger relayout on this control
1477 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1479 if ( mRelayoutData )
1481 // If more than one dimension is requested, just return the first one found
1482 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1484 if( ( dimension & ( 1 << i ) ) )
1486 return mRelayoutData->resizePolicies[ i ];
1491 return ResizePolicy::DEFAULT;
1494 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1496 EnsureRelayoutData();
1498 mRelayoutData->sizeSetPolicy = policy;
1501 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1503 if ( mRelayoutData )
1505 return mRelayoutData->sizeSetPolicy;
1508 return DEFAULT_SIZE_SCALE_POLICY;
1511 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1513 EnsureRelayoutData();
1515 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1517 if( dimension & ( 1 << i ) )
1519 mRelayoutData->dimensionDependencies[ i ] = dependency;
1524 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1526 if ( mRelayoutData )
1528 // If more than one dimension is requested, just return the first one found
1529 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1531 if( ( dimension & ( 1 << i ) ) )
1533 return mRelayoutData->dimensionDependencies[ i ];
1538 return Dimension::ALL_DIMENSIONS; // Default
1541 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1543 // If relayout data has not been allocated yet and the client is requesting
1544 // to disable it, do nothing
1545 if( mRelayoutData || relayoutEnabled )
1547 EnsureRelayoutData();
1549 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1551 mRelayoutData->relayoutEnabled = relayoutEnabled;
1555 bool Actor::IsRelayoutEnabled() const
1557 // Assume that if relayout data has not been allocated yet then
1558 // relayout is disabled
1559 return mRelayoutData && mRelayoutData->relayoutEnabled;
1562 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1564 EnsureRelayoutData();
1566 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1568 if( dimension & ( 1 << i ) )
1570 mRelayoutData->dimensionDirty[ i ] = dirty;
1575 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1577 if ( mRelayoutData )
1579 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1581 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1591 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1593 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1596 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1598 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1601 unsigned int Actor::AddRenderer( Renderer& renderer )
1605 mRenderers = new RendererContainer;
1608 unsigned int index = mRenderers->size();
1609 RendererPtr rendererPtr = RendererPtr( &renderer );
1610 mRenderers->push_back( rendererPtr );
1611 AddRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1615 unsigned int Actor::GetRendererCount() const
1617 unsigned int rendererCount(0);
1620 rendererCount = mRenderers->size();
1623 return rendererCount;
1626 RendererPtr Actor::GetRendererAt( unsigned int index )
1628 RendererPtr renderer;
1629 if( index < GetRendererCount() )
1631 renderer = ( *mRenderers )[ index ];
1637 void Actor::RemoveRenderer( Renderer& renderer )
1641 RendererIter end = mRenderers->end();
1642 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1644 if( (*iter).Get() == &renderer )
1646 mRenderers->erase( iter );
1647 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1654 void Actor::RemoveRenderer( unsigned int index )
1656 if( index < GetRendererCount() )
1658 RendererPtr renderer = ( *mRenderers )[ index ];
1659 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.Get()->GetRendererSceneObject() );
1660 mRenderers->erase( mRenderers->begin()+index );
1664 bool Actor::IsOverlay() const
1666 return ( DrawMode::OVERLAY_2D == mDrawMode );
1669 void Actor::SetDrawMode( DrawMode::Type drawMode )
1671 // this flag is not animatable so keep the value
1672 mDrawMode = drawMode;
1673 if( ( NULL != mNode ) && ( drawMode != DrawMode::STENCIL ) )
1675 // mNode is being used in a separate thread; queue a message to set the value
1676 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1680 DrawMode::Type Actor::GetDrawMode() const
1685 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1687 // only valid when on-stage
1688 StagePtr stage = Stage::GetCurrent();
1689 if( stage && OnStage() )
1691 const RenderTaskList& taskList = stage->GetRenderTaskList();
1693 Vector2 converted( screenX, screenY );
1695 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1696 const int taskCount = taskList.GetTaskCount();
1697 for( int i = taskCount - 1; i >= 0; --i )
1699 Dali::RenderTask task = taskList.GetTask( i );
1700 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1702 // found a task where this conversion was ok so return
1710 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1712 bool retval = false;
1713 // only valid when on-stage
1716 CameraActor* camera = renderTask.GetCameraActor();
1720 renderTask.GetViewport( viewport );
1722 // need to translate coordinates to render tasks coordinate space
1723 Vector2 converted( screenX, screenY );
1724 if( renderTask.TranslateCoordinates( converted ) )
1726 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1733 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1735 // Early-out if mNode is NULL
1741 // Get the ModelView matrix
1743 Matrix::Multiply( modelView, mNode->GetWorldMatrix(0), viewMatrix );
1745 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1746 Matrix invertedMvp( false/*don't init*/);
1747 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1748 bool success = invertedMvp.Invert();
1750 // Convert to GL coordinates
1751 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1756 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1763 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1769 if( XyPlaneIntersect( nearPos, farPos, local ) )
1771 Vector3 size = GetCurrentSize();
1772 localX = local.x + size.x * 0.5f;
1773 localY = local.y + size.y * 0.5f;
1784 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1787 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1789 Mathematical Formulation
1791 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1793 ( p - c ) dot ( p - c ) = r^2
1795 Given a ray with a point of origin 'o', and a direction vector 'd':
1797 ray(t) = o + td, t >= 0
1799 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1801 (o + td - c ) dot ( o + td - c ) = r^2
1803 To solve for t we first expand the above into a more recognisable quadratic equation form
1805 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1814 B = 2( o - c ) dot d
1815 C = ( o - c ) dot ( o - c ) - r^2
1817 which can be solved using a standard quadratic formula.
1819 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1821 Practical Simplification
1823 In a renderer, we often differentiate between world space and object space. In the object space
1824 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1825 into object space, the mathematical solution presented above can be simplified significantly.
1827 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1831 and we can find the t at which the (transformed) ray intersects the sphere by
1833 ( o + td ) dot ( o + td ) = r^2
1835 According to the reasoning above, we expand the above quadratic equation into the general form
1839 which now has coefficients:
1846 // Early out if mNode is NULL
1852 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1854 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1855 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1856 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1858 // Compute the radius is not needed, square radius it's enough.
1859 const Vector3& size( mNode->GetSize( bufferIndex ) );
1861 // Scale the sphere.
1862 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1864 const float width = size.width * scale.width;
1865 const float height = size.height * scale.height;
1867 float squareSphereRadius = 0.5f * ( width * width + height * height );
1869 float a = rayDir.Dot( rayDir ); // a
1870 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1871 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1873 return ( b2 * b2 - a * c ) >= 0.f;
1876 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector2& hitPointLocal, float& distance ) const
1880 if( OnStage() && NULL != mNode )
1882 // Transforms the ray to the local reference system.
1883 // Calculate the inverse of Model matrix
1884 Matrix invModelMatrix( false/*don't init*/);
1886 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1887 invModelMatrix = mNode->GetWorldMatrix(0);
1888 invModelMatrix.Invert();
1890 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1891 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1893 // Test with the actor's XY plane (Normal = 0 0 1 1).
1895 float a = -rayOriginLocal.z;
1896 float b = rayDirLocal.z;
1898 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1900 // Ray travels distance * rayDirLocal to intersect with plane.
1903 const Vector3& size = mNode->GetSize( bufferIndex );
1905 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1906 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1908 // Test with the actor's geometry.
1909 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1916 void Actor::SetLeaveRequired( bool required )
1918 mLeaveRequired = required;
1921 bool Actor::GetLeaveRequired() const
1923 return mLeaveRequired;
1926 void Actor::SetKeyboardFocusable( bool focusable )
1928 mKeyboardFocusable = focusable;
1931 bool Actor::IsKeyboardFocusable() const
1933 return mKeyboardFocusable;
1936 bool Actor::GetTouchRequired() const
1938 return !mTouchedSignal.Empty() || !mTouchSignal.Empty() || mDerivedRequiresTouch;
1941 bool Actor::GetHoverRequired() const
1943 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1946 bool Actor::GetWheelEventRequired() const
1948 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1951 bool Actor::IsHittable() const
1953 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1956 ActorGestureData& Actor::GetGestureData()
1958 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1959 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1960 if( NULL == mGestureData )
1962 mGestureData = new ActorGestureData;
1964 return *mGestureData;
1967 bool Actor::IsGestureRequred( Gesture::Type type ) const
1969 return mGestureData && mGestureData->IsGestureRequred( type );
1972 bool Actor::EmitTouchEventSignal( const TouchEvent& event, const Dali::TouchData& touch )
1974 bool consumed = false;
1976 if( !mTouchSignal.Empty() )
1978 Dali::Actor handle( this );
1979 consumed = mTouchSignal.Emit( handle, touch );
1982 if( !mTouchedSignal.Empty() )
1984 Dali::Actor handle( this );
1985 consumed |= mTouchedSignal.Emit( handle, event );
1990 // Notification for derived classes
1991 consumed = OnTouchEvent( event ); // TODO
1997 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1999 bool consumed = false;
2001 if( !mHoveredSignal.Empty() )
2003 Dali::Actor handle( this );
2004 consumed = mHoveredSignal.Emit( handle, event );
2009 // Notification for derived classes
2010 consumed = OnHoverEvent( event );
2016 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
2018 bool consumed = false;
2020 if( !mWheelEventSignal.Empty() )
2022 Dali::Actor handle( this );
2023 consumed = mWheelEventSignal.Emit( handle, event );
2028 // Notification for derived classes
2029 consumed = OnWheelEvent( event );
2035 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
2037 if( ! mVisibilityChangedSignal.Empty() )
2039 Dali::Actor handle( this );
2040 mVisibilityChangedSignal.Emit( handle, visible, type );
2044 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
2046 return mTouchedSignal;
2049 Dali::Actor::TouchDataSignalType& Actor::TouchSignal()
2051 return mTouchSignal;
2054 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
2056 return mHoveredSignal;
2059 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
2061 return mWheelEventSignal;
2064 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
2066 return mOnStageSignal;
2069 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
2071 return mOffStageSignal;
2074 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
2076 return mOnRelayoutSignal;
2079 DevelActor::VisibilityChangedSignalType& Actor::VisibilityChangedSignal()
2081 return mVisibilityChangedSignal;
2084 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
2086 bool connected( true );
2087 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
2089 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
2091 actor->TouchedSignal().Connect( tracker, functor );
2093 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
2095 actor->HoveredSignal().Connect( tracker, functor );
2097 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
2099 actor->WheelEventSignal().Connect( tracker, functor );
2101 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
2103 actor->OnStageSignal().Connect( tracker, functor );
2105 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
2107 actor->OffStageSignal().Connect( tracker, functor );
2109 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
2111 actor->OnRelayoutSignal().Connect( tracker, functor );
2113 else if( 0 == signalName.compare( SIGNAL_TOUCH ) )
2115 actor->TouchSignal().Connect( tracker, functor );
2119 // signalName does not match any signal
2126 Actor::Actor( DerivedType derivedType )
2131 mParentOrigin( NULL ),
2132 mAnchorPoint( NULL ),
2133 mRelayoutData( NULL ),
2134 mGestureData( NULL ),
2135 mTargetOrientation( Quaternion::IDENTITY ),
2136 mTargetColor( Color::WHITE ),
2137 mTargetSize( Vector3::ZERO ),
2138 mTargetPosition( Vector3::ZERO ),
2139 mTargetScale( Vector3::ONE ),
2141 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
2144 mIsRoot( ROOT_LAYER == derivedType ),
2145 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2146 mIsOnStage( false ),
2148 mLeaveRequired( false ),
2149 mKeyboardFocusable( false ),
2150 mDerivedRequiresTouch( false ),
2151 mDerivedRequiresHover( false ),
2152 mDerivedRequiresWheelEvent( false ),
2153 mOnStageSignalled( false ),
2154 mInsideOnSizeSet( false ),
2155 mInheritPosition( true ),
2156 mInheritOrientation( true ),
2157 mInheritScale( true ),
2158 mPositionUsesAnchorPoint( true ),
2160 mDrawMode( DrawMode::NORMAL ),
2161 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2162 mColorMode( Node::DEFAULT_COLOR_MODE ),
2163 mClippingMode( ClippingMode::DISABLED )
2167 void Actor::Initialize()
2170 SceneGraph::Node* node = CreateNode();
2172 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
2173 mNode = node; // Keep raw-pointer to Node
2177 GetEventThreadServices().RegisterObject( this );
2182 // Remove mParent pointers from children even if we're destroying core,
2183 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2186 ActorConstIter endIter = mChildren->end();
2187 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2189 (*iter)->SetParent( NULL );
2195 // Guard to allow handle destruction after Core has been destroyed
2196 if( EventThreadServices::IsCoreRunning() )
2200 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2201 mNode = NULL; // Node is about to be destroyed
2204 GetEventThreadServices().UnregisterObject( this );
2207 // Cleanup optional gesture data
2208 delete mGestureData;
2210 // Cleanup optional parent origin and anchor
2211 delete mParentOrigin;
2212 delete mAnchorPoint;
2214 // Delete optional relayout data
2217 delete mRelayoutData;
2221 void Actor::ConnectToStage( unsigned int parentDepth )
2223 // This container is used instead of walking the Actor hierarchy.
2224 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
2225 ActorContainer connectionList;
2227 // This stage is atomic i.e. not interrupted by user callbacks.
2228 RecursiveConnectToStage( connectionList, parentDepth + 1 );
2230 // Notify applications about the newly connected actors.
2231 const ActorIter endIter = connectionList.end();
2232 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2234 (*iter)->NotifyStageConnection();
2240 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth )
2242 DALI_ASSERT_ALWAYS( !OnStage() );
2246 SetDepthIndexMessage( GetEventThreadServices(), *mNode, GetDepthIndex( mDepth, mSiblingOrder ) );
2248 ConnectToSceneGraph();
2250 // Notification for internal derived classes
2251 OnStageConnectionInternal();
2253 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2254 connectionList.push_back( ActorPtr( this ) );
2256 // Recursively connect children
2259 ActorConstIter endIter = mChildren->end();
2260 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2262 (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
2268 * This method is called when the Actor is connected to the Stage.
2269 * The parent must have added its Node to the scene-graph.
2270 * The child must connect its Node to the parent's Node.
2271 * This is recursive; the child calls ConnectToStage() for its children.
2273 void Actor::ConnectToSceneGraph()
2275 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2279 // Reparent Node in next Update
2280 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode );
2283 // Request relayout on all actors that are added to the scenegraph
2286 // Notification for Object::Observers
2290 void Actor::NotifyStageConnection()
2292 // Actors can be removed (in a callback), before the on-stage stage is reported.
2293 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2294 if( OnStage() && !mOnStageSignalled )
2296 // Notification for external (CustomActor) derived classes
2297 OnStageConnectionExternal( mDepth );
2299 if( !mOnStageSignal.Empty() )
2301 Dali::Actor handle( this );
2302 mOnStageSignal.Emit( handle );
2305 // Guard against Remove during callbacks
2308 mOnStageSignalled = true; // signal required next time Actor is removed
2313 void Actor::DisconnectFromStage()
2315 // This container is used instead of walking the Actor hierachy.
2316 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2317 ActorContainer disconnectionList;
2319 // This stage is atomic i.e. not interrupted by user callbacks
2320 RecursiveDisconnectFromStage( disconnectionList );
2322 // Notify applications about the newly disconnected actors.
2323 const ActorIter endIter = disconnectionList.end();
2324 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2326 (*iter)->NotifyStageDisconnection();
2330 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2332 DALI_ASSERT_ALWAYS( OnStage() );
2334 // Recursively disconnect children
2337 ActorConstIter endIter = mChildren->end();
2338 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2340 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2344 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2345 disconnectionList.push_back( ActorPtr( this ) );
2347 // Notification for internal derived classes
2348 OnStageDisconnectionInternal();
2350 DisconnectFromSceneGraph();
2356 * This method is called by an actor or its parent, before a node removal message is sent.
2357 * This is recursive; the child calls DisconnectFromStage() for its children.
2359 void Actor::DisconnectFromSceneGraph()
2361 // Notification for Object::Observers
2362 OnSceneObjectRemove();
2365 void Actor::NotifyStageDisconnection()
2367 // Actors can be added (in a callback), before the off-stage state is reported.
2368 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2369 // only do this step if there is a stage, i.e. Core is not being shut down
2370 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2372 // Notification for external (CustomeActor) derived classes
2373 OnStageDisconnectionExternal();
2375 if( !mOffStageSignal.Empty() )
2377 Dali::Actor handle( this );
2378 mOffStageSignal.Emit( handle );
2381 // Guard against Add during callbacks
2384 mOnStageSignalled = false; // signal required next time Actor is added
2389 bool Actor::IsNodeConnected() const
2391 bool connected( false );
2393 if( OnStage() && ( NULL != mNode ) )
2395 if( IsRoot() || mNode->GetParent() )
2404 unsigned int Actor::GetDefaultPropertyCount() const
2406 return DEFAULT_PROPERTY_COUNT;
2409 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2411 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2413 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2415 indices.PushBack( i );
2419 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2421 if( index < DEFAULT_PROPERTY_COUNT )
2423 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2429 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2431 Property::Index index = Property::INVALID_INDEX;
2433 // Look for name in default properties
2434 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2436 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2437 if( 0 == name.compare( property->name ) )
2447 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2449 if( index < DEFAULT_PROPERTY_COUNT )
2451 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2457 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2459 if( index < DEFAULT_PROPERTY_COUNT )
2461 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2467 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2469 if( index < DEFAULT_PROPERTY_COUNT )
2471 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2477 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2479 if( index < DEFAULT_PROPERTY_COUNT )
2481 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2484 // index out of range...return Property::NONE
2485 return Property::NONE;
2488 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2492 case Dali::Actor::Property::PARENT_ORIGIN:
2494 Property::Type type = property.GetType();
2495 if( type == Property::VECTOR3 )
2497 SetParentOrigin( property.Get< Vector3 >() );
2499 else if ( type == Property::STRING )
2501 std::string parentOriginString;
2502 property.Get( parentOriginString );
2503 Vector3 parentOrigin;
2504 if( GetParentOriginConstant( parentOriginString, parentOrigin ) )
2506 SetParentOrigin( parentOrigin );
2512 case Dali::Actor::Property::PARENT_ORIGIN_X:
2514 SetParentOriginX( property.Get< float >() );
2518 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2520 SetParentOriginY( property.Get< float >() );
2524 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2526 SetParentOriginZ( property.Get< float >() );
2530 case Dali::Actor::Property::ANCHOR_POINT:
2532 Property::Type type = property.GetType();
2533 if( type == Property::VECTOR3 )
2535 SetAnchorPoint( property.Get< Vector3 >() );
2537 else if ( type == Property::STRING )
2539 std::string anchorPointString;
2540 property.Get( anchorPointString );
2542 if( GetAnchorPointConstant( anchorPointString, anchor ) )
2544 SetAnchorPoint( anchor );
2550 case Dali::Actor::Property::ANCHOR_POINT_X:
2552 SetAnchorPointX( property.Get< float >() );
2556 case Dali::Actor::Property::ANCHOR_POINT_Y:
2558 SetAnchorPointY( property.Get< float >() );
2562 case Dali::Actor::Property::ANCHOR_POINT_Z:
2564 SetAnchorPointZ( property.Get< float >() );
2568 case Dali::Actor::Property::SIZE:
2570 SetSize( property.Get< Vector3 >() );
2574 case Dali::Actor::Property::SIZE_WIDTH:
2576 SetWidth( property.Get< float >() );
2580 case Dali::Actor::Property::SIZE_HEIGHT:
2582 SetHeight( property.Get< float >() );
2586 case Dali::Actor::Property::SIZE_DEPTH:
2588 SetDepth( property.Get< float >() );
2592 case Dali::Actor::Property::POSITION:
2594 SetPosition( property.Get< Vector3 >() );
2598 case Dali::Actor::Property::POSITION_X:
2600 SetX( property.Get< float >() );
2604 case Dali::Actor::Property::POSITION_Y:
2606 SetY( property.Get< float >() );
2610 case Dali::Actor::Property::POSITION_Z:
2612 SetZ( property.Get< float >() );
2616 case Dali::Actor::Property::ORIENTATION:
2618 SetOrientation( property.Get< Quaternion >() );
2622 case Dali::Actor::Property::SCALE:
2624 SetScale( property.Get< Vector3 >() );
2628 case Dali::Actor::Property::SCALE_X:
2630 SetScaleX( property.Get< float >() );
2634 case Dali::Actor::Property::SCALE_Y:
2636 SetScaleY( property.Get< float >() );
2640 case Dali::Actor::Property::SCALE_Z:
2642 SetScaleZ( property.Get< float >() );
2646 case Dali::Actor::Property::VISIBLE:
2648 SetVisible( property.Get< bool >() );
2652 case Dali::Actor::Property::COLOR:
2654 SetColor( property.Get< Vector4 >() );
2658 case Dali::Actor::Property::COLOR_RED:
2660 SetColorRed( property.Get< float >() );
2664 case Dali::Actor::Property::COLOR_GREEN:
2666 SetColorGreen( property.Get< float >() );
2670 case Dali::Actor::Property::COLOR_BLUE:
2672 SetColorBlue( property.Get< float >() );
2676 case Dali::Actor::Property::COLOR_ALPHA:
2677 case Dali::DevelActor::Property::OPACITY:
2680 if( property.Get( value ) )
2682 SetOpacity( value );
2687 case Dali::Actor::Property::NAME:
2689 SetName( property.Get< std::string >() );
2693 case Dali::Actor::Property::SENSITIVE:
2695 SetSensitive( property.Get< bool >() );
2699 case Dali::Actor::Property::LEAVE_REQUIRED:
2701 SetLeaveRequired( property.Get< bool >() );
2705 case Dali::Actor::Property::INHERIT_POSITION:
2707 SetInheritPosition( property.Get< bool >() );
2711 case Dali::Actor::Property::INHERIT_ORIENTATION:
2713 SetInheritOrientation( property.Get< bool >() );
2717 case Dali::Actor::Property::INHERIT_SCALE:
2719 SetInheritScale( property.Get< bool >() );
2723 case Dali::Actor::Property::COLOR_MODE:
2725 ColorMode mode = mColorMode;
2726 if ( Scripting::GetEnumerationProperty< ColorMode >( property, COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT, mode ) )
2728 SetColorMode( mode );
2733 case Dali::Actor::Property::POSITION_INHERITANCE:
2735 PositionInheritanceMode mode = mPositionInheritanceMode;
2736 if( Scripting::GetEnumerationProperty< PositionInheritanceMode >( property, POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT, mode ) )
2738 SetPositionInheritanceMode( mode );
2743 case Dali::Actor::Property::DRAW_MODE:
2745 DrawMode::Type mode = mDrawMode;
2746 if( Scripting::GetEnumerationProperty< DrawMode::Type >( property, DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT, mode ) )
2748 SetDrawMode( mode );
2753 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2755 SetSizeModeFactor( property.Get< Vector3 >() );
2759 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2761 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
2762 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2764 SetResizePolicy( type, Dimension::WIDTH );
2769 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2771 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
2772 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2774 SetResizePolicy( type, Dimension::HEIGHT );
2779 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2781 SizeScalePolicy::Type type;
2782 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT, type ) )
2784 SetSizeScalePolicy( type );
2789 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2791 if( property.Get< bool >() )
2793 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2798 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2800 if( property.Get< bool >() )
2802 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2807 case Dali::Actor::Property::PADDING:
2809 Vector4 padding = property.Get< Vector4 >();
2810 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2811 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2815 case Dali::Actor::Property::MINIMUM_SIZE:
2817 Vector2 size = property.Get< Vector2 >();
2818 SetMinimumSize( size.x, Dimension::WIDTH );
2819 SetMinimumSize( size.y, Dimension::HEIGHT );
2823 case Dali::Actor::Property::MAXIMUM_SIZE:
2825 Vector2 size = property.Get< Vector2 >();
2826 SetMaximumSize( size.x, Dimension::WIDTH );
2827 SetMaximumSize( size.y, Dimension::HEIGHT );
2831 case Dali::DevelActor::Property::SIBLING_ORDER:
2835 if( property.Get( value ) )
2837 if( static_cast<unsigned int>(value) != mSiblingOrder )
2839 SetSiblingOrder( value );
2845 case Dali::Actor::Property::CLIPPING_MODE:
2847 ClippingMode::Type convertedValue = mClippingMode;
2848 if( Scripting::GetEnumerationProperty< ClippingMode::Type >( property, CLIPPING_MODE_TABLE, CLIPPING_MODE_TABLE_COUNT, convertedValue ) )
2850 mClippingMode = convertedValue;
2853 SetClippingModeMessage( GetEventThreadServices(), *mNode, mClippingMode );
2859 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
2862 if( property.Get( value ) && value != mPositionUsesAnchorPoint )
2864 mPositionUsesAnchorPoint = value;
2867 SetPositionUsesAnchorPointMessage( GetEventThreadServices(), *mNode, mPositionUsesAnchorPoint );
2875 // this can happen in the case of a non-animatable default property so just do nothing
2881 // TODO: This method needs to be removed
2882 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2884 switch( entry.GetType() )
2886 case Property::BOOLEAN:
2888 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2889 DALI_ASSERT_DEBUG( NULL != property );
2891 // property is being used in a separate thread; queue a message to set the property
2892 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2897 case Property::INTEGER:
2899 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2900 DALI_ASSERT_DEBUG( NULL != property );
2902 // property is being used in a separate thread; queue a message to set the property
2903 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2908 case Property::FLOAT:
2910 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2911 DALI_ASSERT_DEBUG( NULL != property );
2913 // property is being used in a separate thread; queue a message to set the property
2914 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2919 case Property::VECTOR2:
2921 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2922 DALI_ASSERT_DEBUG( NULL != property );
2924 // property is being used in a separate thread; queue a message to set the property
2925 if(entry.componentIndex == 0)
2927 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2929 else if(entry.componentIndex == 1)
2931 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2935 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2941 case Property::VECTOR3:
2943 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2944 DALI_ASSERT_DEBUG( NULL != property );
2946 // property is being used in a separate thread; queue a message to set the property
2947 if(entry.componentIndex == 0)
2949 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2951 else if(entry.componentIndex == 1)
2953 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2955 else if(entry.componentIndex == 2)
2957 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2961 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2967 case Property::VECTOR4:
2969 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2970 DALI_ASSERT_DEBUG( NULL != property );
2972 // property is being used in a separate thread; queue a message to set the property
2973 if(entry.componentIndex == 0)
2975 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
2977 else if(entry.componentIndex == 1)
2979 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
2981 else if(entry.componentIndex == 2)
2983 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
2985 else if(entry.componentIndex == 3)
2987 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
2991 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2997 case Property::ROTATION:
2999 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3000 DALI_ASSERT_DEBUG( NULL != property );
3002 // property is being used in a separate thread; queue a message to set the property
3003 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3008 case Property::MATRIX:
3010 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3011 DALI_ASSERT_DEBUG( NULL != property );
3013 // property is being used in a separate thread; queue a message to set the property
3014 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3019 case Property::MATRIX3:
3021 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3022 DALI_ASSERT_DEBUG( NULL != property );
3024 // property is being used in a separate thread; queue a message to set the property
3025 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3032 // nothing to do for other types
3037 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3039 Property::Value value;
3041 if( ! GetCachedPropertyValue( index, value ) )
3043 // If property value is not stored in the event-side, then it must be a scene-graph only property
3044 GetCurrentPropertyValue( index, value );
3050 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
3052 Property::Value value;
3054 if( ! GetCurrentPropertyValue( index, value ) )
3056 // If unable to retrieve scene-graph property value, then it must be an event-side only property
3057 GetCachedPropertyValue( index, value );
3063 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3068 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3070 // This method should only return an object connected to the scene-graph
3071 return OnStage() ? mNode : NULL;
3074 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3076 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3078 const PropertyBase* property( NULL );
3080 // This method should only return a property of an object connected to the scene-graph
3086 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3088 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3089 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3091 property = animatable->GetSceneGraphProperty();
3093 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3094 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3096 CustomPropertyMetadata* custom = FindCustomProperty( index );
3097 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3099 property = custom->GetSceneGraphProperty();
3101 else if( NULL != mNode )
3105 case Dali::Actor::Property::SIZE:
3106 property = &mNode->mSize;
3109 case Dali::Actor::Property::SIZE_WIDTH:
3110 property = &mNode->mSize;
3113 case Dali::Actor::Property::SIZE_HEIGHT:
3114 property = &mNode->mSize;
3117 case Dali::Actor::Property::SIZE_DEPTH:
3118 property = &mNode->mSize;
3121 case Dali::Actor::Property::POSITION:
3122 property = &mNode->mPosition;
3125 case Dali::Actor::Property::POSITION_X:
3126 property = &mNode->mPosition;
3129 case Dali::Actor::Property::POSITION_Y:
3130 property = &mNode->mPosition;
3133 case Dali::Actor::Property::POSITION_Z:
3134 property = &mNode->mPosition;
3137 case Dali::Actor::Property::ORIENTATION:
3138 property = &mNode->mOrientation;
3141 case Dali::Actor::Property::SCALE:
3142 property = &mNode->mScale;
3145 case Dali::Actor::Property::SCALE_X:
3146 property = &mNode->mScale;
3149 case Dali::Actor::Property::SCALE_Y:
3150 property = &mNode->mScale;
3153 case Dali::Actor::Property::SCALE_Z:
3154 property = &mNode->mScale;
3157 case Dali::Actor::Property::VISIBLE:
3158 property = &mNode->mVisible;
3161 case Dali::Actor::Property::COLOR:
3162 property = &mNode->mColor;
3165 case Dali::Actor::Property::COLOR_RED:
3166 property = &mNode->mColor;
3169 case Dali::Actor::Property::COLOR_GREEN:
3170 property = &mNode->mColor;
3173 case Dali::Actor::Property::COLOR_BLUE:
3174 property = &mNode->mColor;
3177 case Dali::Actor::Property::COLOR_ALPHA:
3178 case Dali::DevelActor::Property::OPACITY:
3179 property = &mNode->mColor;
3190 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3192 const PropertyInputImpl* property( NULL );
3194 // This method should only return a property of an object connected to the scene-graph
3200 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3202 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3203 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3205 property = animatable->GetSceneGraphProperty();
3207 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3208 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3210 CustomPropertyMetadata* custom = FindCustomProperty( index );
3211 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3212 property = custom->GetSceneGraphProperty();
3214 else if( NULL != mNode )
3218 case Dali::Actor::Property::PARENT_ORIGIN:
3219 property = &mNode->mParentOrigin;
3222 case Dali::Actor::Property::PARENT_ORIGIN_X:
3223 property = &mNode->mParentOrigin;
3226 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3227 property = &mNode->mParentOrigin;
3230 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3231 property = &mNode->mParentOrigin;
3234 case Dali::Actor::Property::ANCHOR_POINT:
3235 property = &mNode->mAnchorPoint;
3238 case Dali::Actor::Property::ANCHOR_POINT_X:
3239 property = &mNode->mAnchorPoint;
3242 case Dali::Actor::Property::ANCHOR_POINT_Y:
3243 property = &mNode->mAnchorPoint;
3246 case Dali::Actor::Property::ANCHOR_POINT_Z:
3247 property = &mNode->mAnchorPoint;
3250 case Dali::Actor::Property::SIZE:
3251 property = &mNode->mSize;
3254 case Dali::Actor::Property::SIZE_WIDTH:
3255 property = &mNode->mSize;
3258 case Dali::Actor::Property::SIZE_HEIGHT:
3259 property = &mNode->mSize;
3262 case Dali::Actor::Property::SIZE_DEPTH:
3263 property = &mNode->mSize;
3266 case Dali::Actor::Property::POSITION:
3267 property = &mNode->mPosition;
3270 case Dali::Actor::Property::POSITION_X:
3271 property = &mNode->mPosition;
3274 case Dali::Actor::Property::POSITION_Y:
3275 property = &mNode->mPosition;
3278 case Dali::Actor::Property::POSITION_Z:
3279 property = &mNode->mPosition;
3282 case Dali::Actor::Property::WORLD_POSITION:
3283 property = &mNode->mWorldPosition;
3286 case Dali::Actor::Property::WORLD_POSITION_X:
3287 property = &mNode->mWorldPosition;
3290 case Dali::Actor::Property::WORLD_POSITION_Y:
3291 property = &mNode->mWorldPosition;
3294 case Dali::Actor::Property::WORLD_POSITION_Z:
3295 property = &mNode->mWorldPosition;
3298 case Dali::Actor::Property::ORIENTATION:
3299 property = &mNode->mOrientation;
3302 case Dali::Actor::Property::WORLD_ORIENTATION:
3303 property = &mNode->mWorldOrientation;
3306 case Dali::Actor::Property::SCALE:
3307 property = &mNode->mScale;
3310 case Dali::Actor::Property::SCALE_X:
3311 property = &mNode->mScale;
3314 case Dali::Actor::Property::SCALE_Y:
3315 property = &mNode->mScale;
3318 case Dali::Actor::Property::SCALE_Z:
3319 property = &mNode->mScale;
3322 case Dali::Actor::Property::WORLD_SCALE:
3323 property = &mNode->mWorldScale;
3326 case Dali::Actor::Property::VISIBLE:
3327 property = &mNode->mVisible;
3330 case Dali::Actor::Property::COLOR:
3331 property = &mNode->mColor;
3334 case Dali::Actor::Property::COLOR_RED:
3335 property = &mNode->mColor;
3338 case Dali::Actor::Property::COLOR_GREEN:
3339 property = &mNode->mColor;
3342 case Dali::Actor::Property::COLOR_BLUE:
3343 property = &mNode->mColor;
3346 case Dali::Actor::Property::COLOR_ALPHA:
3347 case Dali::DevelActor::Property::OPACITY:
3349 property = &mNode->mColor;
3353 case Dali::Actor::Property::WORLD_COLOR:
3354 property = &mNode->mWorldColor;
3357 case Dali::Actor::Property::WORLD_MATRIX:
3358 property = &mNode->mWorldMatrix;
3369 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3371 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3373 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3375 // check whether the animatable property is registered already, if not then register one.
3376 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3377 if( animatableProperty )
3379 componentIndex = animatableProperty->componentIndex;
3386 case Dali::Actor::Property::PARENT_ORIGIN_X:
3387 case Dali::Actor::Property::ANCHOR_POINT_X:
3388 case Dali::Actor::Property::SIZE_WIDTH:
3389 case Dali::Actor::Property::POSITION_X:
3390 case Dali::Actor::Property::WORLD_POSITION_X:
3391 case Dali::Actor::Property::SCALE_X:
3392 case Dali::Actor::Property::COLOR_RED:
3398 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3399 case Dali::Actor::Property::ANCHOR_POINT_Y:
3400 case Dali::Actor::Property::SIZE_HEIGHT:
3401 case Dali::Actor::Property::POSITION_Y:
3402 case Dali::Actor::Property::WORLD_POSITION_Y:
3403 case Dali::Actor::Property::SCALE_Y:
3404 case Dali::Actor::Property::COLOR_GREEN:
3410 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3411 case Dali::Actor::Property::ANCHOR_POINT_Z:
3412 case Dali::Actor::Property::SIZE_DEPTH:
3413 case Dali::Actor::Property::POSITION_Z:
3414 case Dali::Actor::Property::WORLD_POSITION_Z:
3415 case Dali::Actor::Property::SCALE_Z:
3416 case Dali::Actor::Property::COLOR_BLUE:
3422 case Dali::Actor::Property::COLOR_ALPHA:
3423 case Dali::DevelActor::Property::OPACITY:
3437 return componentIndex;
3440 void Actor::SetParent( Actor* parent )
3444 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3448 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3451 // Instruct each actor to create a corresponding node in the scene graph
3452 ConnectToStage( parent->GetHierarchyDepth() );
3455 // Resolve the name and index for the child properties if any
3456 ResolveChildProperties();
3458 else // parent being set to NULL
3460 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3464 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3467 DALI_ASSERT_ALWAYS( mNode != NULL );
3471 // Disconnect the Node & its children from the scene-graph.
3472 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3475 // Instruct each actor to discard pointers to the scene-graph
3476 DisconnectFromStage();
3481 SceneGraph::Node* Actor::CreateNode() const
3486 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3489 Actor* actor = dynamic_cast< Actor* >( object );
3493 if( 0 == actionName.compare( ACTION_SHOW ) )
3495 actor->SetVisible( true );
3498 else if( 0 == actionName.compare( ACTION_HIDE ) )
3500 actor->SetVisible( false );
3508 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
3510 bool valueSet = true;
3514 case Dali::Actor::Property::PARENT_ORIGIN:
3516 value = GetCurrentParentOrigin();
3520 case Dali::Actor::Property::PARENT_ORIGIN_X:
3522 value = GetCurrentParentOrigin().x;
3526 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3528 value = GetCurrentParentOrigin().y;
3532 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3534 value = GetCurrentParentOrigin().z;
3538 case Dali::Actor::Property::ANCHOR_POINT:
3540 value = GetCurrentAnchorPoint();
3544 case Dali::Actor::Property::ANCHOR_POINT_X:
3546 value = GetCurrentAnchorPoint().x;
3550 case Dali::Actor::Property::ANCHOR_POINT_Y:
3552 value = GetCurrentAnchorPoint().y;
3556 case Dali::Actor::Property::ANCHOR_POINT_Z:
3558 value = GetCurrentAnchorPoint().z;
3562 case Dali::Actor::Property::SIZE:
3564 Vector3 size = GetTargetSize();
3566 // Should return preferred size if size is fixed as set by SetSize
3567 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
3569 size.width = GetPreferredSize().width;
3571 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
3573 size.height = GetPreferredSize().height;
3581 case Dali::Actor::Property::SIZE_WIDTH:
3583 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
3585 // Should return preferred size if size is fixed as set by SetSize
3586 value = GetPreferredSize().width;
3590 value = GetTargetSize().width;
3595 case Dali::Actor::Property::SIZE_HEIGHT:
3597 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
3599 // Should return preferred size if size is fixed as set by SetSize
3600 value = GetPreferredSize().height;
3604 value = GetTargetSize().height;
3609 case Dali::Actor::Property::SIZE_DEPTH:
3611 value = GetTargetSize().depth;
3615 case Dali::Actor::Property::POSITION:
3617 value = GetTargetPosition();
3621 case Dali::Actor::Property::POSITION_X:
3623 value = GetTargetPosition().x;
3627 case Dali::Actor::Property::POSITION_Y:
3629 value = GetTargetPosition().y;
3633 case Dali::Actor::Property::POSITION_Z:
3635 value = GetTargetPosition().z;
3639 case Dali::Actor::Property::ORIENTATION:
3641 value = mTargetOrientation;
3645 case Dali::Actor::Property::SCALE:
3647 value = mTargetScale;
3651 case Dali::Actor::Property::SCALE_X:
3653 value = mTargetScale.x;
3657 case Dali::Actor::Property::SCALE_Y:
3659 value = mTargetScale.y;
3663 case Dali::Actor::Property::SCALE_Z:
3665 value = mTargetScale.z;
3669 case Dali::Actor::Property::VISIBLE:
3675 case Dali::Actor::Property::COLOR:
3677 value = mTargetColor;
3681 case Dali::Actor::Property::COLOR_RED:
3683 value = mTargetColor.r;
3687 case Dali::Actor::Property::COLOR_GREEN:
3689 value = mTargetColor.g;
3693 case Dali::Actor::Property::COLOR_BLUE:
3695 value = mTargetColor.b;
3699 case Dali::Actor::Property::COLOR_ALPHA:
3700 case Dali::DevelActor::Property::OPACITY:
3702 value = mTargetColor.a;
3706 case Dali::Actor::Property::NAME:
3712 case Dali::Actor::Property::SENSITIVE:
3714 value = IsSensitive();
3718 case Dali::Actor::Property::LEAVE_REQUIRED:
3720 value = GetLeaveRequired();
3724 case Dali::Actor::Property::INHERIT_POSITION:
3726 value = IsPositionInherited();
3730 case Dali::Actor::Property::INHERIT_ORIENTATION:
3732 value = IsOrientationInherited();
3736 case Dali::Actor::Property::INHERIT_SCALE:
3738 value = IsScaleInherited();
3742 case Dali::Actor::Property::COLOR_MODE:
3744 value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
3748 case Dali::Actor::Property::POSITION_INHERITANCE:
3750 value = Scripting::GetLinearEnumerationName< PositionInheritanceMode >( GetPositionInheritanceMode(), POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT );
3754 case Dali::Actor::Property::DRAW_MODE:
3756 value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
3760 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3762 value = GetSizeModeFactor();
3766 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3768 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3772 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3774 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3778 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3780 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT );
3784 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3786 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3790 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3792 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3796 case Dali::Actor::Property::PADDING:
3798 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3799 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3800 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3804 case Dali::Actor::Property::MINIMUM_SIZE:
3806 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3810 case Dali::Actor::Property::MAXIMUM_SIZE:
3812 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3816 case Dali::Actor::Property::CLIPPING_MODE:
3818 value = mClippingMode;
3822 case Dali::DevelActor::Property::SIBLING_ORDER:
3824 value = static_cast<int>(mSiblingOrder);
3828 case Dali::DevelActor::Property::SCREEN_POSITION:
3830 value = GetCurrentScreenPosition();
3834 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
3836 value = mPositionUsesAnchorPoint;
3842 // Must be a scene-graph only property
3851 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
3853 bool valueSet = true;
3857 case Dali::Actor::Property::SIZE:
3859 value = GetCurrentSize();
3863 case Dali::Actor::Property::SIZE_WIDTH:
3865 value = GetCurrentSize().width;
3869 case Dali::Actor::Property::SIZE_HEIGHT:
3871 value = GetCurrentSize().height;
3875 case Dali::Actor::Property::SIZE_DEPTH:
3877 value = GetCurrentSize().depth;
3881 case Dali::Actor::Property::POSITION:
3883 value = GetCurrentPosition();
3887 case Dali::Actor::Property::POSITION_X:
3889 value = GetCurrentPosition().x;
3893 case Dali::Actor::Property::POSITION_Y:
3895 value = GetCurrentPosition().y;
3899 case Dali::Actor::Property::POSITION_Z:
3901 value = GetCurrentPosition().z;
3905 case Dali::Actor::Property::WORLD_POSITION:
3907 value = GetCurrentWorldPosition();
3911 case Dali::Actor::Property::WORLD_POSITION_X:
3913 value = GetCurrentWorldPosition().x;
3917 case Dali::Actor::Property::WORLD_POSITION_Y:
3919 value = GetCurrentWorldPosition().y;
3923 case Dali::Actor::Property::WORLD_POSITION_Z:
3925 value = GetCurrentWorldPosition().z;
3929 case Dali::Actor::Property::ORIENTATION:
3931 value = GetCurrentOrientation();
3935 case Dali::Actor::Property::WORLD_ORIENTATION:
3937 value = GetCurrentWorldOrientation();
3941 case Dali::Actor::Property::SCALE:
3943 value = GetCurrentScale();
3947 case Dali::Actor::Property::SCALE_X:
3949 value = GetCurrentScale().x;
3953 case Dali::Actor::Property::SCALE_Y:
3955 value = GetCurrentScale().y;
3959 case Dali::Actor::Property::SCALE_Z:
3961 value = GetCurrentScale().z;
3965 case Dali::Actor::Property::WORLD_SCALE:
3967 value = GetCurrentWorldScale();
3971 case Dali::Actor::Property::COLOR:
3973 value = GetCurrentColor();
3977 case Dali::Actor::Property::COLOR_RED:
3979 value = GetCurrentColor().r;
3983 case Dali::Actor::Property::COLOR_GREEN:
3985 value = GetCurrentColor().g;
3989 case Dali::Actor::Property::COLOR_BLUE:
3991 value = GetCurrentColor().b;
3995 case Dali::Actor::Property::COLOR_ALPHA:
3996 case Dali::DevelActor::Property::OPACITY:
3998 value = GetCurrentColor().a;
4002 case Dali::Actor::Property::WORLD_COLOR:
4004 value = GetCurrentWorldColor();
4008 case Dali::Actor::Property::WORLD_MATRIX:
4010 value = GetCurrentWorldMatrix();
4016 // Must be an event-side only property
4025 void Actor::EnsureRelayoutData()
4027 // Assign relayout data.
4028 if( !mRelayoutData )
4030 mRelayoutData = new RelayoutData();
4034 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
4036 // Check if actor is dependent on parent
4037 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4039 if( ( dimension & ( 1 << i ) ) )
4041 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4042 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
4052 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
4054 // Check if actor is dependent on children
4055 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4057 if( ( dimension & ( 1 << i ) ) )
4059 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4060 switch( resizePolicy )
4062 case ResizePolicy::FIT_TO_CHILDREN:
4063 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
4079 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
4081 return Actor::RelayoutDependentOnChildren( dimension );
4084 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
4086 // Check each possible dimension and see if it is dependent on the input one
4087 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4089 if( dimension & ( 1 << i ) )
4091 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
4098 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
4100 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4102 if( dimension & ( 1 << i ) )
4104 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
4109 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
4111 // If more than one dimension is requested, just return the first one found
4112 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4114 if( ( dimension & ( 1 << i ) ) )
4116 return mRelayoutData->negotiatedDimensions[ i ];
4120 return 0.0f; // Default
4123 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
4125 EnsureRelayoutData();
4127 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4129 if( dimension & ( 1 << i ) )
4131 mRelayoutData->dimensionPadding[ i ] = padding;
4136 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4138 if ( mRelayoutData )
4140 // If more than one dimension is requested, just return the first one found
4141 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4143 if( ( dimension & ( 1 << i ) ) )
4145 return mRelayoutData->dimensionPadding[ i ];
4150 return GetDefaultDimensionPadding();
4153 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4155 EnsureRelayoutData();
4157 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4159 if( dimension & ( 1 << i ) )
4161 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4166 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4168 if ( mRelayoutData )
4170 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4172 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4182 float Actor::GetHeightForWidthBase( float width )
4184 float height = 0.0f;
4186 const Vector3 naturalSize = GetNaturalSize();
4187 if( naturalSize.width > 0.0f )
4189 height = naturalSize.height * width / naturalSize.width;
4191 else // we treat 0 as 1:1 aspect ratio
4199 float Actor::GetWidthForHeightBase( float height )
4203 const Vector3 naturalSize = GetNaturalSize();
4204 if( naturalSize.height > 0.0f )
4206 width = naturalSize.width * height / naturalSize.height;
4208 else // we treat 0 as 1:1 aspect ratio
4216 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4218 // Fill to parent, taking size mode factor into account
4219 switch( child.GetResizePolicy( dimension ) )
4221 case ResizePolicy::FILL_TO_PARENT:
4223 return GetLatestSize( dimension );
4226 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4228 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4231 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4233 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4238 return GetLatestSize( dimension );
4243 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4245 // Can be overridden in derived class
4246 return CalculateChildSizeBase( child, dimension );
4249 float Actor::GetHeightForWidth( float width )
4251 // Can be overridden in derived class
4252 return GetHeightForWidthBase( width );
4255 float Actor::GetWidthForHeight( float height )
4257 // Can be overridden in derived class
4258 return GetWidthForHeightBase( height );
4261 float Actor::GetLatestSize( Dimension::Type dimension ) const
4263 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4266 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4268 Vector2 padding = GetPadding( dimension );
4270 return GetLatestSize( dimension ) + padding.x + padding.y;
4273 float Actor::NegotiateFromParent( Dimension::Type dimension )
4275 Actor* parent = GetParent();
4278 Vector2 padding( GetPadding( dimension ) );
4279 Vector2 parentPadding( parent->GetPadding( dimension ) );
4280 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4286 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4288 float maxDimensionPoint = 0.0f;
4290 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4292 ActorPtr child = GetChildAt( i );
4294 if( !child->RelayoutDependentOnParent( dimension ) )
4296 // Calculate the min and max points that the children range across
4297 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
4298 float dimensionSize = child->GetRelayoutSize( dimension );
4299 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4303 return maxDimensionPoint;
4306 float Actor::GetSize( Dimension::Type dimension ) const
4308 return GetDimensionValue( GetTargetSize(), dimension );
4311 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4313 return GetDimensionValue( GetNaturalSize(), dimension );
4316 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4318 switch( GetResizePolicy( dimension ) )
4320 case ResizePolicy::USE_NATURAL_SIZE:
4322 return GetNaturalSize( dimension );
4325 case ResizePolicy::FIXED:
4327 return GetDimensionValue( GetPreferredSize(), dimension );
4330 case ResizePolicy::USE_ASSIGNED_SIZE:
4332 return GetDimensionValue( maximumSize, dimension );
4335 case ResizePolicy::FILL_TO_PARENT:
4336 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4337 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4339 return NegotiateFromParent( dimension );
4342 case ResizePolicy::FIT_TO_CHILDREN:
4344 return NegotiateFromChildren( dimension );
4347 case ResizePolicy::DIMENSION_DEPENDENCY:
4349 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4352 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4354 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4357 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4359 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4371 return 0.0f; // Default
4374 float Actor::ClampDimension( float size, Dimension::Type dimension )
4376 const float minSize = GetMinimumSize( dimension );
4377 const float maxSize = GetMaximumSize( dimension );
4379 return std::max( minSize, std::min( size, maxSize ) );
4382 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4384 // Check if it needs to be negotiated
4385 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4387 // Check that we havn't gotten into an infinite loop
4388 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4389 bool recursionFound = false;
4390 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4392 if( *it == searchActor )
4394 recursionFound = true;
4399 if( !recursionFound )
4401 // Record the path that we have taken
4402 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4404 // Dimension dependency check
4405 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4407 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4409 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4411 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4415 // Parent dependency check
4416 Actor* parent = GetParent();
4417 if( parent && RelayoutDependentOnParent( dimension ) )
4419 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4422 // Children dependency check
4423 if( RelayoutDependentOnChildren( dimension ) )
4425 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4427 ActorPtr child = GetChildAt( i );
4429 // Only relayout child first if it is not dependent on this actor
4430 if( !child->RelayoutDependentOnParent( dimension ) )
4432 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
4437 // For deriving classes
4438 OnCalculateRelayoutSize( dimension );
4440 // All dependencies checked, calculate the size and set negotiated flag
4441 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4443 SetNegotiatedDimension( newSize, dimension );
4444 SetLayoutNegotiated( true, dimension );
4446 // For deriving classes
4447 OnLayoutNegotiated( newSize, dimension );
4449 // This actor has been successfully processed, pop it off the recursion stack
4450 recursionStack.pop_back();
4454 // TODO: Break infinite loop
4455 SetLayoutNegotiated( true, dimension );
4460 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4462 // Negotiate all dimensions that require it
4463 ActorDimensionStack recursionStack;
4465 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4467 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4470 NegotiateDimension( dimension, allocatedSize, recursionStack );
4474 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4476 switch( mRelayoutData->sizeSetPolicy )
4478 case SizeScalePolicy::USE_SIZE_SET:
4483 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4485 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4486 const Vector3 naturalSize = GetNaturalSize();
4487 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4489 const float sizeRatio = size.width / size.height;
4490 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4492 if( naturalSizeRatio < sizeRatio )
4494 return Vector2( naturalSizeRatio * size.height, size.height );
4496 else if( naturalSizeRatio > sizeRatio )
4498 return Vector2( size.width, size.width / naturalSizeRatio );
4509 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4511 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4512 const Vector3 naturalSize = GetNaturalSize();
4513 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4515 const float sizeRatio = size.width / size.height;
4516 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4518 if( naturalSizeRatio < sizeRatio )
4520 return Vector2( size.width, size.width / naturalSizeRatio );
4522 else if( naturalSizeRatio > sizeRatio )
4524 return Vector2( naturalSizeRatio * size.height, size.height );
4543 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4545 // Do the set actor size
4546 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4548 // Adjust for size set policy
4549 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4551 // Lock the flag to stop recursive relayouts on set size
4552 mRelayoutData->insideRelayout = true;
4553 SetSize( negotiatedSize );
4554 mRelayoutData->insideRelayout = false;
4556 // Clear flags for all dimensions
4557 SetLayoutDirty( false );
4559 // Give deriving classes a chance to respond
4560 OnRelayout( negotiatedSize, container );
4562 if( !mOnRelayoutSignal.Empty() )
4564 Dali::Actor handle( this );
4565 mOnRelayoutSignal.Emit( handle );
4569 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4571 // Force a size negotiation for actors that has assigned size during relayout
4572 // This is required as otherwise the flags that force a relayout will not
4573 // necessarilly be set. This will occur if the actor has already been laid out.
4574 // The dirty flags are then cleared. Then if the actor is added back into the
4575 // relayout container afterwards, the dirty flags would still be clear...
4576 // causing a relayout to be skipped. Here we force any actors added to the
4577 // container to be relayed out.
4578 if(GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE)
4580 SetLayoutNegotiated(false, Dimension::WIDTH);
4582 if(GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE)
4584 SetLayoutNegotiated(false, Dimension::HEIGHT);
4587 // Do the negotiation
4588 NegotiateDimensions( allocatedSize );
4590 // Set the actor size
4591 SetNegotiatedSize( container );
4593 // Negotiate down to children
4594 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4596 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4598 ActorPtr child = GetChildAt( i );
4600 // Forces children that have already been laid out to be relayed out
4601 // if they have assigned size during relayout.
4602 if(child->GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE)
4604 child->SetLayoutNegotiated(false, Dimension::WIDTH);
4605 child->SetLayoutDirty(true, Dimension::WIDTH);
4607 if(child->GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE)
4609 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
4610 child->SetLayoutDirty(true, Dimension::HEIGHT);
4613 // Only relayout if required
4614 if( child->RelayoutRequired() )
4616 container.Add( Dali::Actor( child.Get() ), newBounds );
4621 void Actor::RelayoutRequest( Dimension::Type dimension )
4623 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4624 if( relayoutController )
4626 Dali::Actor self( this );
4627 relayoutController->RequestRelayout( self, dimension );
4631 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4635 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4639 void Actor::SetPreferredSize( const Vector2& size )
4641 EnsureRelayoutData();
4643 if( size.width > 0.0f )
4645 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4648 if( size.height > 0.0f )
4650 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4653 mRelayoutData->preferredSize = size;
4658 Vector2 Actor::GetPreferredSize() const
4660 if ( mRelayoutData )
4662 return Vector2( mRelayoutData->preferredSize );
4665 return GetDefaultPreferredSize();
4668 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4670 EnsureRelayoutData();
4672 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4674 if( dimension & ( 1 << i ) )
4676 mRelayoutData->minimumSize[ i ] = size;
4683 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4685 if ( mRelayoutData )
4687 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4689 if( dimension & ( 1 << i ) )
4691 return mRelayoutData->minimumSize[ i ];
4696 return 0.0f; // Default
4699 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4701 EnsureRelayoutData();
4703 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4705 if( dimension & ( 1 << i ) )
4707 mRelayoutData->maximumSize[ i ] = size;
4714 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4716 if ( mRelayoutData )
4718 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4720 if( dimension & ( 1 << i ) )
4722 return mRelayoutData->maximumSize[ i ];
4727 return FLT_MAX; // Default
4730 Object* Actor::GetParentObject() const
4735 void Actor::SetSiblingOrder( unsigned int order )
4737 mSiblingOrder = std::min( order, static_cast<unsigned int>( DevelLayer::SIBLING_ORDER_MULTIPLIER ) );
4740 SetDepthIndexMessage( GetEventThreadServices(), *mNode, GetDepthIndex( mDepth, mSiblingOrder ) );
4744 void Actor::DefragmentSiblingIndexes( ActorContainer& siblings )
4746 // Sibling index may not be in consecutive order as the sibling range is limited ( DevelLayer::SIBLING_ORDER_MULTIPLIER )
4747 // we need to remove the gaps and ensure the number start from 0 and consecutive hence have a full range.
4749 // Start at index 0, while index <= highest order
4750 // Find next index higher than 0
4751 // if nextHigher > index+1
4752 // set all nextHigher orders to index+1
4754 // Limitation: May reach the ceiling of DevelLayer::SIBLING_ORDER_MULTIPLIER with highest sibling.
4756 ActorIter end = siblings.end();
4757 int highestOrder = 0;
4758 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
4760 ActorPtr sibling = (*iter);
4761 int siblingOrder = sibling->mSiblingOrder;
4762 highestOrder = std::max( highestOrder, siblingOrder );
4765 for ( int index = 0; index <= highestOrder; index++ )
4767 int nextHighest = -1;
4769 // Find Next highest
4770 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
4772 ActorPtr sibling = (*iter);
4773 int siblingOrder = sibling->mSiblingOrder;
4775 if ( siblingOrder > index )
4777 if ( nextHighest == -1 )
4779 nextHighest = siblingOrder;
4781 nextHighest = std::min( nextHighest, siblingOrder );
4785 // Check if a gap exists between indexes, if so set next index to consecutive number
4786 if ( ( nextHighest - index ) > 1 )
4788 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
4790 ActorPtr sibling = (*iter);
4791 int siblingOrder = sibling->mSiblingOrder;
4792 if ( siblingOrder == nextHighest )
4794 sibling->mSiblingOrder = index + 1;
4795 if ( sibling->mSiblingOrder >= Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER )
4797 DALI_LOG_WARNING( "Reached max sibling order level for raising / lowering actors\n" );
4798 sibling->mSiblingOrder = Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER;
4800 sibling->SetSiblingOrder( sibling->mSiblingOrder );
4807 bool Actor::ShiftSiblingsLevels( ActorContainer& siblings, int targetLevelToShiftFrom )
4809 // Allows exclusive levels for an actor by shifting all sibling levels at the target and above by 1
4810 bool defragmentationRequired( false );
4811 ActorIter end = siblings.end();
4812 for( ActorIter iter = siblings.begin(); ( iter != end ) ; ++iter )
4814 // Move actors at nearest order and above up by 1
4815 ActorPtr sibling = (*iter);
4816 if ( sibling != this )
4818 // Iterate through container of actors, any actor with a sibling order of the target or greater should
4819 // be incremented by 1.
4820 if ( sibling->mSiblingOrder >= targetLevelToShiftFrom )
4822 sibling->mSiblingOrder++;
4823 if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
4825 // If a sibling order raises so that it is only 1 from the maximum allowed then set flag so
4826 // can re-order all sibling orders.
4827 defragmentationRequired = true;
4829 sibling->SetSiblingOrder( sibling->mSiblingOrder );
4833 return defragmentationRequired;
4839 1) Check if already at top and nothing to be done.
4840 This Actor can have highest sibling order but if not exclusive then another actor at same sibling
4841 order can be positioned above it due to insertion order of actors.
4842 2) Find nearest sibling level above, these are the siblings this actor needs to be above
4843 3) a) There may be other levels above this target level
4844 b) Increment all sibling levels at the level above nearest(target)
4845 c) Now have a vacant sibling level
4846 4) Set this actor's sibling level to nearest +1 as now vacated.
4848 Note May not just be sibling level + 1 as could be empty levels in-between
4853 ActorC ( sibling level 4 )
4854 ActorB ( sibling level 3 )
4855 ActorA ( sibling level 1 )
4857 2 ) ACTION: Raise A above B
4858 a) Find nearest level above A = Level 3
4859 b) Increment levels above Level 3
4861 ActorC ( sibling level 5 )
4862 ActorB ( sibling level 3 ) NEAREST
4863 ActorA ( sibling level 1 )
4865 3 ) Set Actor A sibling level to nearest +1 as vacant
4867 ActorC ( sibling level 5 )
4868 ActorA ( sibling level 4 )
4869 ActorB ( sibling level 3 )
4871 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4872 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4873 remove any empty sibling order gaps and start from sibling level 0 again.
4874 If the number of actors reaches this maximum and all using exclusive sibling order values then
4875 defragmention will stop and new sibling orders will be set to same max value.
4879 int nearestLevel = mSiblingOrder;
4880 int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
4881 bool defragmentationRequired( false );
4883 ActorContainer* siblings = mParent->mChildren;
4885 // Find Nearest sibling level above this actor
4886 ActorIter end = siblings->end();
4887 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
4889 ActorPtr sibling = (*iter);
4890 if ( sibling != this )
4892 int order = GetSiblingOrder( sibling );
4894 if ( ( order >= mSiblingOrder ) )
4896 int distanceToNextLevel = order - mSiblingOrder;
4897 if ( distanceToNextLevel < shortestDistanceToNextLevel )
4899 nearestLevel = order;
4900 shortestDistanceToNextLevel = distanceToNextLevel;
4906 if ( nearestLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at top
4908 mSiblingOrder = nearestLevel + 1; // Set sibling level to that above the nearest level
4909 defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
4910 // Move current actor to newly vacated order level
4911 SetSiblingOrder( mSiblingOrder );
4912 if ( defragmentationRequired )
4914 DefragmentSiblingIndexes( *siblings );
4917 SetSiblingOrder( mSiblingOrder );
4921 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4928 1) Check if actor already at bottom and if nothing needs to be done
4929 This Actor can have lowest sibling order but if not exclusive then another actor at same sibling
4930 order can be positioned above it due to insertion order of actors so need to move this actor below it.
4931 2) Find nearest sibling level below, this Actor needs to be below it
4932 3) a) Need to vacate a sibling level below nearest for this actor to occupy
4933 b) Shift up all sibling order values of actor at the nearest level and levels above it to vacate a level.
4934 c) Set this actor's sibling level to this newly vacated level.
4935 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4936 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4937 remove any empty sibling order gaps and start from sibling level 0 again.
4938 If the number of actors reaches this maximum and all using exclusive sibling order values then
4939 defragmention will stop and new sibling orders will be set to same max value.
4944 // 1) Find nearest level below
4945 int nearestLevel = mSiblingOrder;
4946 int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
4948 ActorContainer* siblings = mParent->mChildren;
4950 ActorIter end = siblings->end();
4951 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
4953 ActorPtr sibling = (*iter);
4954 if ( sibling != this )
4956 int order = GetSiblingOrder( sibling );
4958 if ( order <= mSiblingOrder )
4960 int distanceToNextLevel = mSiblingOrder - order;
4961 if ( distanceToNextLevel < shortestDistanceToNextLevel )
4963 nearestLevel = order;
4964 shortestDistanceToNextLevel = distanceToNextLevel;
4970 bool defragmentationRequired ( false );
4972 // 2) If actor already not at bottom, raise all actors at required level and above
4973 if ( shortestDistanceToNextLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at bottom
4975 mSiblingOrder = nearestLevel;
4976 defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
4977 // Move current actor to newly vacated order
4978 SetSiblingOrder( mSiblingOrder );
4979 if ( defragmentationRequired )
4981 DefragmentSiblingIndexes( *siblings );
4987 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4991 void Actor::RaiseToTop()
4994 1 ) Find highest sibling order actor
4995 2 ) If highest sibling level not itself then set sibling order to that + 1
4996 3 ) highest sibling order can be same as itself so need to increment over that
4997 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4998 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4999 remove any empty sibling order gaps and start from sibling level 0 again.
5000 If the number of actors reaches this maximum and all using exclusive sibling order values then
5001 defragmention will stop and new sibling orders will be set to same max value.
5008 ActorContainer* siblings = mParent->mChildren;
5010 ActorIter end = siblings->end();
5011 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
5013 ActorPtr sibling = (*iter);
5014 if ( sibling != this )
5016 maxOrder = std::max( GetSiblingOrder( sibling ), maxOrder );
5020 bool defragmentationRequired( false );
5022 if ( maxOrder >= mSiblingOrder )
5024 mSiblingOrder = maxOrder + 1;
5025 if ( mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
5027 defragmentationRequired = true;
5031 SetSiblingOrder( mSiblingOrder );
5033 if ( defragmentationRequired )
5035 DefragmentSiblingIndexes( *siblings );
5040 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5044 void Actor::LowerToBottom()
5047 See Actor::LowerToBottom()
5049 1 ) Check if this actor already at exclusively at the bottom, if so then no more to be done.
5050 2 ) a ) Check if the bottom position 0 is vacant.
5051 b ) If 0 position is not vacant then shift up all sibling order values from 0 and above
5052 c ) 0 sibling position is vacant.
5053 3 ) Set this actor to vacant sibling order 0;
5054 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5055 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5056 remove any empty sibling order gaps and start from sibling level 0 again.
5057 If the number of actors reaches this maximum and all using exclusive sibling order values then
5058 defragmention will stop and new sibling orders will be set to same max value.
5063 bool defragmentationRequired( false );
5064 bool orderZeroFree ( true );
5066 ActorContainer* siblings = mParent->mChildren;
5068 bool actorAtLowestOrder = true;
5069 ActorIter end = siblings->end();
5070 for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
5072 ActorPtr sibling = (*iter);
5073 if ( sibling != this )
5075 int siblingOrder = GetSiblingOrder( sibling );
5076 if ( siblingOrder <= mSiblingOrder )
5078 actorAtLowestOrder = false;
5081 if ( siblingOrder == 0 )
5083 orderZeroFree = false;
5088 if ( ! actorAtLowestOrder )
5090 if ( ! orderZeroFree )
5092 defragmentationRequired = ShiftSiblingsLevels( *siblings, 0 );
5095 SetSiblingOrder( mSiblingOrder );
5097 if ( defragmentationRequired )
5099 DefragmentSiblingIndexes( *siblings );
5105 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5109 void Actor::RaiseAbove( Internal::Actor& target )
5112 1 ) a) Find target actor's sibling order
5113 b) If sibling order of target is the same as this actor then need to this Actor's sibling order
5114 needs to be above it or the insertion order will determine which is drawn on top.
5115 2 ) Shift up by 1 all sibling order greater than target sibling order
5116 3 ) Set this actor to the sibling order to target +1 as will be a newly vacated gap above
5117 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5118 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5119 remove any empty sibling order gaps and start from sibling level 0 again.
5120 If the number of actors reaches this maximum and all using exclusive sibling order values then
5121 defragmention will stop and new sibling orders will be set to same max value.
5126 if ( ValidateActors( *this, target ) )
5128 // Find target's sibling order
5129 // Set actor sibling order to this number +1
5130 int targetSiblingOrder = GetSiblingOrder( &target );
5131 ActorContainer* siblings = mParent->mChildren;
5132 mSiblingOrder = targetSiblingOrder + 1;
5133 bool defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
5135 SetSiblingOrder( mSiblingOrder );
5137 if ( defragmentationRequired )
5139 DefragmentSiblingIndexes( *(mParent->mChildren) );
5145 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5149 void Actor::LowerBelow( Internal::Actor& target )
5152 1 ) a) Find target actor's sibling order
5153 b) If sibling order of target is the same as this actor then need to this Actor's sibling order
5154 needs to be below it or the insertion order will determine which is drawn on top.
5155 2 ) Shift the target sibling order and all sibling orders at that level or above by 1
5156 3 ) Set this actor to the sibling order of the target before it changed.
5157 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5158 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5159 remove any empty sibling order gaps and start from sibling level 0 again.
5160 If the number of actors reaches this maximum and all using exclusive sibling order values then
5161 defragmention will stop and new sibling orders will be set to same max value.
5166 if ( ValidateActors( *this, target ) )
5168 bool defragmentationRequired ( false );
5169 // Find target's sibling order
5170 // Set actor sibling order to target sibling order - 1
5171 int targetSiblingOrder = GetSiblingOrder( &target);
5172 ActorContainer* siblings = mParent->mChildren;
5173 if ( targetSiblingOrder == 0 )
5176 ActorIter end = siblings->end();
5177 for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
5179 ActorPtr sibling = (*iter);
5180 if ( sibling != this )
5182 sibling->mSiblingOrder++;
5183 if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
5185 defragmentationRequired = true;
5187 sibling->SetSiblingOrder( sibling->mSiblingOrder );
5194 defragmentationRequired = ShiftSiblingsLevels( *siblings, targetSiblingOrder );
5196 mSiblingOrder = targetSiblingOrder;
5198 SetSiblingOrder( mSiblingOrder );
5200 if ( defragmentationRequired )
5202 DefragmentSiblingIndexes( *(mParent->mChildren) );
5208 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5212 } // namespace Internal