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 Vector3 Actor::GetTargetSize() const
1392 Vector3 size = mTargetSize;
1394 // Should return preferred size if size is fixed as set by SetSize
1395 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
1397 size.width = GetPreferredSize().width;
1399 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
1401 size.height = GetPreferredSize().height;
1407 const Vector3& Actor::GetCurrentSize() const
1411 // mNode is being used in a separate thread; copy the value from the previous update
1412 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1415 return Vector3::ZERO;
1418 Vector3 Actor::GetNaturalSize() const
1420 // It is up to deriving classes to return the appropriate natural size
1421 return Vector3( 0.0f, 0.0f, 0.0f );
1424 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1426 EnsureRelayoutData();
1428 ResizePolicy::Type originalWidthPolicy = GetResizePolicy(Dimension::WIDTH);
1429 ResizePolicy::Type originalHeightPolicy = GetResizePolicy(Dimension::HEIGHT);
1431 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1433 if( dimension & ( 1 << i ) )
1435 mRelayoutData->resizePolicies[ i ] = policy;
1439 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1441 if( dimension & Dimension::WIDTH )
1443 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1446 if( dimension & Dimension::HEIGHT )
1448 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1452 // If calling SetResizePolicy, assume we want relayout enabled
1453 SetRelayoutEnabled( true );
1455 // If the resize policy is set to be FIXED, the preferred size
1456 // should be overrided by the target size. Otherwise the target
1457 // size should be overrided by the preferred size.
1459 if( dimension & Dimension::WIDTH )
1461 if( originalWidthPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1463 mRelayoutData->preferredSize.width = mTargetSize.width;
1465 else if( originalWidthPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1467 mTargetSize.width = mRelayoutData->preferredSize.width;
1471 if( dimension & Dimension::HEIGHT )
1473 if( originalHeightPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1475 mRelayoutData->preferredSize.height = mTargetSize.height;
1477 else if( originalHeightPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1479 mTargetSize.height = mRelayoutData->preferredSize.height;
1483 OnSetResizePolicy( policy, dimension );
1485 // Trigger relayout on this control
1489 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1491 if ( mRelayoutData )
1493 // If more than one dimension is requested, just return the first one found
1494 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1496 if( ( dimension & ( 1 << i ) ) )
1498 return mRelayoutData->resizePolicies[ i ];
1503 return ResizePolicy::DEFAULT;
1506 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1508 EnsureRelayoutData();
1510 mRelayoutData->sizeSetPolicy = policy;
1513 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1515 if ( mRelayoutData )
1517 return mRelayoutData->sizeSetPolicy;
1520 return DEFAULT_SIZE_SCALE_POLICY;
1523 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1525 EnsureRelayoutData();
1527 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1529 if( dimension & ( 1 << i ) )
1531 mRelayoutData->dimensionDependencies[ i ] = dependency;
1536 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1538 if ( mRelayoutData )
1540 // If more than one dimension is requested, just return the first one found
1541 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1543 if( ( dimension & ( 1 << i ) ) )
1545 return mRelayoutData->dimensionDependencies[ i ];
1550 return Dimension::ALL_DIMENSIONS; // Default
1553 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1555 // If relayout data has not been allocated yet and the client is requesting
1556 // to disable it, do nothing
1557 if( mRelayoutData || relayoutEnabled )
1559 EnsureRelayoutData();
1561 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1563 mRelayoutData->relayoutEnabled = relayoutEnabled;
1567 bool Actor::IsRelayoutEnabled() const
1569 // Assume that if relayout data has not been allocated yet then
1570 // relayout is disabled
1571 return mRelayoutData && mRelayoutData->relayoutEnabled;
1574 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1576 EnsureRelayoutData();
1578 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1580 if( dimension & ( 1 << i ) )
1582 mRelayoutData->dimensionDirty[ i ] = dirty;
1587 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1589 if ( mRelayoutData )
1591 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1593 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1603 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1605 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1608 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1610 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1613 unsigned int Actor::AddRenderer( Renderer& renderer )
1617 mRenderers = new RendererContainer;
1620 unsigned int index = mRenderers->size();
1621 RendererPtr rendererPtr = RendererPtr( &renderer );
1622 mRenderers->push_back( rendererPtr );
1623 AddRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1627 unsigned int Actor::GetRendererCount() const
1629 unsigned int rendererCount(0);
1632 rendererCount = mRenderers->size();
1635 return rendererCount;
1638 RendererPtr Actor::GetRendererAt( unsigned int index )
1640 RendererPtr renderer;
1641 if( index < GetRendererCount() )
1643 renderer = ( *mRenderers )[ index ];
1649 void Actor::RemoveRenderer( Renderer& renderer )
1653 RendererIter end = mRenderers->end();
1654 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1656 if( (*iter).Get() == &renderer )
1658 mRenderers->erase( iter );
1659 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1666 void Actor::RemoveRenderer( unsigned int index )
1668 if( index < GetRendererCount() )
1670 RendererPtr renderer = ( *mRenderers )[ index ];
1671 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.Get()->GetRendererSceneObject() );
1672 mRenderers->erase( mRenderers->begin()+index );
1676 bool Actor::IsOverlay() const
1678 return ( DrawMode::OVERLAY_2D == mDrawMode );
1681 void Actor::SetDrawMode( DrawMode::Type drawMode )
1683 // this flag is not animatable so keep the value
1684 mDrawMode = drawMode;
1685 if( ( NULL != mNode ) && ( drawMode != DrawMode::STENCIL ) )
1687 // mNode is being used in a separate thread; queue a message to set the value
1688 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1692 DrawMode::Type Actor::GetDrawMode() const
1697 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1699 // only valid when on-stage
1700 StagePtr stage = Stage::GetCurrent();
1701 if( stage && OnStage() )
1703 const RenderTaskList& taskList = stage->GetRenderTaskList();
1705 Vector2 converted( screenX, screenY );
1707 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1708 const int taskCount = taskList.GetTaskCount();
1709 for( int i = taskCount - 1; i >= 0; --i )
1711 Dali::RenderTask task = taskList.GetTask( i );
1712 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1714 // found a task where this conversion was ok so return
1722 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1724 bool retval = false;
1725 // only valid when on-stage
1728 CameraActor* camera = renderTask.GetCameraActor();
1732 renderTask.GetViewport( viewport );
1734 // need to translate coordinates to render tasks coordinate space
1735 Vector2 converted( screenX, screenY );
1736 if( renderTask.TranslateCoordinates( converted ) )
1738 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1745 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1747 // Early-out if mNode is NULL
1753 // Get the ModelView matrix
1755 Matrix::Multiply( modelView, mNode->GetWorldMatrix(0), viewMatrix );
1757 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1758 Matrix invertedMvp( false/*don't init*/);
1759 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1760 bool success = invertedMvp.Invert();
1762 // Convert to GL coordinates
1763 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1768 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1775 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1781 if( XyPlaneIntersect( nearPos, farPos, local ) )
1783 Vector3 size = GetCurrentSize();
1784 localX = local.x + size.x * 0.5f;
1785 localY = local.y + size.y * 0.5f;
1796 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1799 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1801 Mathematical Formulation
1803 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1805 ( p - c ) dot ( p - c ) = r^2
1807 Given a ray with a point of origin 'o', and a direction vector 'd':
1809 ray(t) = o + td, t >= 0
1811 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1813 (o + td - c ) dot ( o + td - c ) = r^2
1815 To solve for t we first expand the above into a more recognisable quadratic equation form
1817 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1826 B = 2( o - c ) dot d
1827 C = ( o - c ) dot ( o - c ) - r^2
1829 which can be solved using a standard quadratic formula.
1831 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1833 Practical Simplification
1835 In a renderer, we often differentiate between world space and object space. In the object space
1836 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1837 into object space, the mathematical solution presented above can be simplified significantly.
1839 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1843 and we can find the t at which the (transformed) ray intersects the sphere by
1845 ( o + td ) dot ( o + td ) = r^2
1847 According to the reasoning above, we expand the above quadratic equation into the general form
1851 which now has coefficients:
1858 // Early out if mNode is NULL
1864 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1866 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1867 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1868 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1870 // Compute the radius is not needed, square radius it's enough.
1871 const Vector3& size( mNode->GetSize( bufferIndex ) );
1873 // Scale the sphere.
1874 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1876 const float width = size.width * scale.width;
1877 const float height = size.height * scale.height;
1879 float squareSphereRadius = 0.5f * ( width * width + height * height );
1881 float a = rayDir.Dot( rayDir ); // a
1882 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1883 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1885 return ( b2 * b2 - a * c ) >= 0.f;
1888 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector2& hitPointLocal, float& distance ) const
1892 if( OnStage() && NULL != mNode )
1894 // Transforms the ray to the local reference system.
1895 // Calculate the inverse of Model matrix
1896 Matrix invModelMatrix( false/*don't init*/);
1898 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1899 invModelMatrix = mNode->GetWorldMatrix(0);
1900 invModelMatrix.Invert();
1902 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1903 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1905 // Test with the actor's XY plane (Normal = 0 0 1 1).
1907 float a = -rayOriginLocal.z;
1908 float b = rayDirLocal.z;
1910 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1912 // Ray travels distance * rayDirLocal to intersect with plane.
1915 const Vector3& size = mNode->GetSize( bufferIndex );
1917 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1918 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1920 // Test with the actor's geometry.
1921 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1928 void Actor::SetLeaveRequired( bool required )
1930 mLeaveRequired = required;
1933 bool Actor::GetLeaveRequired() const
1935 return mLeaveRequired;
1938 void Actor::SetKeyboardFocusable( bool focusable )
1940 mKeyboardFocusable = focusable;
1943 bool Actor::IsKeyboardFocusable() const
1945 return mKeyboardFocusable;
1948 bool Actor::GetTouchRequired() const
1950 return !mTouchedSignal.Empty() || !mTouchSignal.Empty() || mDerivedRequiresTouch;
1953 bool Actor::GetHoverRequired() const
1955 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1958 bool Actor::GetWheelEventRequired() const
1960 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1963 bool Actor::IsHittable() const
1965 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1968 ActorGestureData& Actor::GetGestureData()
1970 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1971 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1972 if( NULL == mGestureData )
1974 mGestureData = new ActorGestureData;
1976 return *mGestureData;
1979 bool Actor::IsGestureRequred( Gesture::Type type ) const
1981 return mGestureData && mGestureData->IsGestureRequred( type );
1984 bool Actor::EmitTouchEventSignal( const TouchEvent& event, const Dali::TouchData& touch )
1986 bool consumed = false;
1988 if( !mTouchSignal.Empty() )
1990 Dali::Actor handle( this );
1991 consumed = mTouchSignal.Emit( handle, touch );
1994 if( !mTouchedSignal.Empty() )
1996 Dali::Actor handle( this );
1997 consumed |= mTouchedSignal.Emit( handle, event );
2002 // Notification for derived classes
2003 consumed = OnTouchEvent( event ); // TODO
2009 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
2011 bool consumed = false;
2013 if( !mHoveredSignal.Empty() )
2015 Dali::Actor handle( this );
2016 consumed = mHoveredSignal.Emit( handle, event );
2021 // Notification for derived classes
2022 consumed = OnHoverEvent( event );
2028 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
2030 bool consumed = false;
2032 if( !mWheelEventSignal.Empty() )
2034 Dali::Actor handle( this );
2035 consumed = mWheelEventSignal.Emit( handle, event );
2040 // Notification for derived classes
2041 consumed = OnWheelEvent( event );
2047 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
2049 if( ! mVisibilityChangedSignal.Empty() )
2051 Dali::Actor handle( this );
2052 mVisibilityChangedSignal.Emit( handle, visible, type );
2056 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
2058 return mTouchedSignal;
2061 Dali::Actor::TouchDataSignalType& Actor::TouchSignal()
2063 return mTouchSignal;
2066 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
2068 return mHoveredSignal;
2071 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
2073 return mWheelEventSignal;
2076 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
2078 return mOnStageSignal;
2081 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
2083 return mOffStageSignal;
2086 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
2088 return mOnRelayoutSignal;
2091 DevelActor::VisibilityChangedSignalType& Actor::VisibilityChangedSignal()
2093 return mVisibilityChangedSignal;
2096 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
2098 bool connected( true );
2099 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
2101 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
2103 actor->TouchedSignal().Connect( tracker, functor );
2105 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
2107 actor->HoveredSignal().Connect( tracker, functor );
2109 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
2111 actor->WheelEventSignal().Connect( tracker, functor );
2113 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
2115 actor->OnStageSignal().Connect( tracker, functor );
2117 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
2119 actor->OffStageSignal().Connect( tracker, functor );
2121 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
2123 actor->OnRelayoutSignal().Connect( tracker, functor );
2125 else if( 0 == signalName.compare( SIGNAL_TOUCH ) )
2127 actor->TouchSignal().Connect( tracker, functor );
2131 // signalName does not match any signal
2138 Actor::Actor( DerivedType derivedType )
2143 mParentOrigin( NULL ),
2144 mAnchorPoint( NULL ),
2145 mRelayoutData( NULL ),
2146 mGestureData( NULL ),
2147 mTargetOrientation( Quaternion::IDENTITY ),
2148 mTargetColor( Color::WHITE ),
2149 mTargetSize( Vector3::ZERO ),
2150 mTargetPosition( Vector3::ZERO ),
2151 mTargetScale( Vector3::ONE ),
2153 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
2156 mIsRoot( ROOT_LAYER == derivedType ),
2157 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2158 mIsOnStage( false ),
2160 mLeaveRequired( false ),
2161 mKeyboardFocusable( false ),
2162 mDerivedRequiresTouch( false ),
2163 mDerivedRequiresHover( false ),
2164 mDerivedRequiresWheelEvent( false ),
2165 mOnStageSignalled( false ),
2166 mInsideOnSizeSet( false ),
2167 mInheritPosition( true ),
2168 mInheritOrientation( true ),
2169 mInheritScale( true ),
2170 mPositionUsesAnchorPoint( true ),
2172 mDrawMode( DrawMode::NORMAL ),
2173 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2174 mColorMode( Node::DEFAULT_COLOR_MODE ),
2175 mClippingMode( ClippingMode::DISABLED )
2179 void Actor::Initialize()
2182 SceneGraph::Node* node = CreateNode();
2184 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
2185 mNode = node; // Keep raw-pointer to Node
2189 GetEventThreadServices().RegisterObject( this );
2194 // Remove mParent pointers from children even if we're destroying core,
2195 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2198 ActorConstIter endIter = mChildren->end();
2199 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2201 (*iter)->SetParent( NULL );
2207 // Guard to allow handle destruction after Core has been destroyed
2208 if( EventThreadServices::IsCoreRunning() )
2212 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2213 mNode = NULL; // Node is about to be destroyed
2216 GetEventThreadServices().UnregisterObject( this );
2219 // Cleanup optional gesture data
2220 delete mGestureData;
2222 // Cleanup optional parent origin and anchor
2223 delete mParentOrigin;
2224 delete mAnchorPoint;
2226 // Delete optional relayout data
2229 delete mRelayoutData;
2233 void Actor::ConnectToStage( unsigned int parentDepth )
2235 // This container is used instead of walking the Actor hierarchy.
2236 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
2237 ActorContainer connectionList;
2239 // This stage is atomic i.e. not interrupted by user callbacks.
2240 RecursiveConnectToStage( connectionList, parentDepth + 1 );
2242 // Notify applications about the newly connected actors.
2243 const ActorIter endIter = connectionList.end();
2244 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2246 (*iter)->NotifyStageConnection();
2252 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth )
2254 DALI_ASSERT_ALWAYS( !OnStage() );
2258 SetDepthIndexMessage( GetEventThreadServices(), *mNode, GetDepthIndex( mDepth, mSiblingOrder ) );
2260 ConnectToSceneGraph();
2262 // Notification for internal derived classes
2263 OnStageConnectionInternal();
2265 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2266 connectionList.push_back( ActorPtr( this ) );
2268 // Recursively connect children
2271 ActorConstIter endIter = mChildren->end();
2272 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2274 (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
2280 * This method is called when the Actor is connected to the Stage.
2281 * The parent must have added its Node to the scene-graph.
2282 * The child must connect its Node to the parent's Node.
2283 * This is recursive; the child calls ConnectToStage() for its children.
2285 void Actor::ConnectToSceneGraph()
2287 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2291 // Reparent Node in next Update
2292 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode );
2295 // Request relayout on all actors that are added to the scenegraph
2298 // Notification for Object::Observers
2302 void Actor::NotifyStageConnection()
2304 // Actors can be removed (in a callback), before the on-stage stage is reported.
2305 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2306 if( OnStage() && !mOnStageSignalled )
2308 // Notification for external (CustomActor) derived classes
2309 OnStageConnectionExternal( mDepth );
2311 if( !mOnStageSignal.Empty() )
2313 Dali::Actor handle( this );
2314 mOnStageSignal.Emit( handle );
2317 // Guard against Remove during callbacks
2320 mOnStageSignalled = true; // signal required next time Actor is removed
2325 void Actor::DisconnectFromStage()
2327 // This container is used instead of walking the Actor hierachy.
2328 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2329 ActorContainer disconnectionList;
2331 // This stage is atomic i.e. not interrupted by user callbacks
2332 RecursiveDisconnectFromStage( disconnectionList );
2334 // Notify applications about the newly disconnected actors.
2335 const ActorIter endIter = disconnectionList.end();
2336 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2338 (*iter)->NotifyStageDisconnection();
2342 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2344 DALI_ASSERT_ALWAYS( OnStage() );
2346 // Recursively disconnect children
2349 ActorConstIter endIter = mChildren->end();
2350 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2352 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2356 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2357 disconnectionList.push_back( ActorPtr( this ) );
2359 // Notification for internal derived classes
2360 OnStageDisconnectionInternal();
2362 DisconnectFromSceneGraph();
2368 * This method is called by an actor or its parent, before a node removal message is sent.
2369 * This is recursive; the child calls DisconnectFromStage() for its children.
2371 void Actor::DisconnectFromSceneGraph()
2373 // Notification for Object::Observers
2374 OnSceneObjectRemove();
2377 void Actor::NotifyStageDisconnection()
2379 // Actors can be added (in a callback), before the off-stage state is reported.
2380 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2381 // only do this step if there is a stage, i.e. Core is not being shut down
2382 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2384 // Notification for external (CustomeActor) derived classes
2385 OnStageDisconnectionExternal();
2387 if( !mOffStageSignal.Empty() )
2389 Dali::Actor handle( this );
2390 mOffStageSignal.Emit( handle );
2393 // Guard against Add during callbacks
2396 mOnStageSignalled = false; // signal required next time Actor is added
2401 bool Actor::IsNodeConnected() const
2403 bool connected( false );
2405 if( OnStage() && ( NULL != mNode ) )
2407 if( IsRoot() || mNode->GetParent() )
2416 unsigned int Actor::GetDefaultPropertyCount() const
2418 return DEFAULT_PROPERTY_COUNT;
2421 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2423 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2425 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2427 indices.PushBack( i );
2431 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2433 if( index < DEFAULT_PROPERTY_COUNT )
2435 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2441 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2443 Property::Index index = Property::INVALID_INDEX;
2445 // Look for name in default properties
2446 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2448 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2449 if( 0 == name.compare( property->name ) )
2459 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2461 if( index < DEFAULT_PROPERTY_COUNT )
2463 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2469 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2471 if( index < DEFAULT_PROPERTY_COUNT )
2473 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2479 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2481 if( index < DEFAULT_PROPERTY_COUNT )
2483 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2489 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2491 if( index < DEFAULT_PROPERTY_COUNT )
2493 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2496 // index out of range...return Property::NONE
2497 return Property::NONE;
2500 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2504 case Dali::Actor::Property::PARENT_ORIGIN:
2506 Property::Type type = property.GetType();
2507 if( type == Property::VECTOR3 )
2509 SetParentOrigin( property.Get< Vector3 >() );
2511 else if ( type == Property::STRING )
2513 std::string parentOriginString;
2514 property.Get( parentOriginString );
2515 Vector3 parentOrigin;
2516 if( GetParentOriginConstant( parentOriginString, parentOrigin ) )
2518 SetParentOrigin( parentOrigin );
2524 case Dali::Actor::Property::PARENT_ORIGIN_X:
2526 SetParentOriginX( property.Get< float >() );
2530 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2532 SetParentOriginY( property.Get< float >() );
2536 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2538 SetParentOriginZ( property.Get< float >() );
2542 case Dali::Actor::Property::ANCHOR_POINT:
2544 Property::Type type = property.GetType();
2545 if( type == Property::VECTOR3 )
2547 SetAnchorPoint( property.Get< Vector3 >() );
2549 else if ( type == Property::STRING )
2551 std::string anchorPointString;
2552 property.Get( anchorPointString );
2554 if( GetAnchorPointConstant( anchorPointString, anchor ) )
2556 SetAnchorPoint( anchor );
2562 case Dali::Actor::Property::ANCHOR_POINT_X:
2564 SetAnchorPointX( property.Get< float >() );
2568 case Dali::Actor::Property::ANCHOR_POINT_Y:
2570 SetAnchorPointY( property.Get< float >() );
2574 case Dali::Actor::Property::ANCHOR_POINT_Z:
2576 SetAnchorPointZ( property.Get< float >() );
2580 case Dali::Actor::Property::SIZE:
2582 SetSize( property.Get< Vector3 >() );
2586 case Dali::Actor::Property::SIZE_WIDTH:
2588 SetWidth( property.Get< float >() );
2592 case Dali::Actor::Property::SIZE_HEIGHT:
2594 SetHeight( property.Get< float >() );
2598 case Dali::Actor::Property::SIZE_DEPTH:
2600 SetDepth( property.Get< float >() );
2604 case Dali::Actor::Property::POSITION:
2606 SetPosition( property.Get< Vector3 >() );
2610 case Dali::Actor::Property::POSITION_X:
2612 SetX( property.Get< float >() );
2616 case Dali::Actor::Property::POSITION_Y:
2618 SetY( property.Get< float >() );
2622 case Dali::Actor::Property::POSITION_Z:
2624 SetZ( property.Get< float >() );
2628 case Dali::Actor::Property::ORIENTATION:
2630 SetOrientation( property.Get< Quaternion >() );
2634 case Dali::Actor::Property::SCALE:
2636 SetScale( property.Get< Vector3 >() );
2640 case Dali::Actor::Property::SCALE_X:
2642 SetScaleX( property.Get< float >() );
2646 case Dali::Actor::Property::SCALE_Y:
2648 SetScaleY( property.Get< float >() );
2652 case Dali::Actor::Property::SCALE_Z:
2654 SetScaleZ( property.Get< float >() );
2658 case Dali::Actor::Property::VISIBLE:
2660 SetVisible( property.Get< bool >() );
2664 case Dali::Actor::Property::COLOR:
2666 SetColor( property.Get< Vector4 >() );
2670 case Dali::Actor::Property::COLOR_RED:
2672 SetColorRed( property.Get< float >() );
2676 case Dali::Actor::Property::COLOR_GREEN:
2678 SetColorGreen( property.Get< float >() );
2682 case Dali::Actor::Property::COLOR_BLUE:
2684 SetColorBlue( property.Get< float >() );
2688 case Dali::Actor::Property::COLOR_ALPHA:
2689 case Dali::DevelActor::Property::OPACITY:
2692 if( property.Get( value ) )
2694 SetOpacity( value );
2699 case Dali::Actor::Property::NAME:
2701 SetName( property.Get< std::string >() );
2705 case Dali::Actor::Property::SENSITIVE:
2707 SetSensitive( property.Get< bool >() );
2711 case Dali::Actor::Property::LEAVE_REQUIRED:
2713 SetLeaveRequired( property.Get< bool >() );
2717 case Dali::Actor::Property::INHERIT_POSITION:
2719 SetInheritPosition( property.Get< bool >() );
2723 case Dali::Actor::Property::INHERIT_ORIENTATION:
2725 SetInheritOrientation( property.Get< bool >() );
2729 case Dali::Actor::Property::INHERIT_SCALE:
2731 SetInheritScale( property.Get< bool >() );
2735 case Dali::Actor::Property::COLOR_MODE:
2737 ColorMode mode = mColorMode;
2738 if ( Scripting::GetEnumerationProperty< ColorMode >( property, COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT, mode ) )
2740 SetColorMode( mode );
2745 case Dali::Actor::Property::POSITION_INHERITANCE:
2747 PositionInheritanceMode mode = mPositionInheritanceMode;
2748 if( Scripting::GetEnumerationProperty< PositionInheritanceMode >( property, POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT, mode ) )
2750 SetPositionInheritanceMode( mode );
2755 case Dali::Actor::Property::DRAW_MODE:
2757 DrawMode::Type mode = mDrawMode;
2758 if( Scripting::GetEnumerationProperty< DrawMode::Type >( property, DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT, mode ) )
2760 SetDrawMode( mode );
2765 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2767 SetSizeModeFactor( property.Get< Vector3 >() );
2771 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2773 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
2774 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2776 SetResizePolicy( type, Dimension::WIDTH );
2781 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2783 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
2784 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2786 SetResizePolicy( type, Dimension::HEIGHT );
2791 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2793 SizeScalePolicy::Type type;
2794 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT, type ) )
2796 SetSizeScalePolicy( type );
2801 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2803 if( property.Get< bool >() )
2805 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2810 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2812 if( property.Get< bool >() )
2814 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2819 case Dali::Actor::Property::PADDING:
2821 Vector4 padding = property.Get< Vector4 >();
2822 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2823 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2827 case Dali::Actor::Property::MINIMUM_SIZE:
2829 Vector2 size = property.Get< Vector2 >();
2830 SetMinimumSize( size.x, Dimension::WIDTH );
2831 SetMinimumSize( size.y, Dimension::HEIGHT );
2835 case Dali::Actor::Property::MAXIMUM_SIZE:
2837 Vector2 size = property.Get< Vector2 >();
2838 SetMaximumSize( size.x, Dimension::WIDTH );
2839 SetMaximumSize( size.y, Dimension::HEIGHT );
2843 case Dali::DevelActor::Property::SIBLING_ORDER:
2847 if( property.Get( value ) )
2849 if( static_cast<unsigned int>(value) != mSiblingOrder )
2851 SetSiblingOrder( value );
2857 case Dali::Actor::Property::CLIPPING_MODE:
2859 ClippingMode::Type convertedValue = mClippingMode;
2860 if( Scripting::GetEnumerationProperty< ClippingMode::Type >( property, CLIPPING_MODE_TABLE, CLIPPING_MODE_TABLE_COUNT, convertedValue ) )
2862 mClippingMode = convertedValue;
2865 SetClippingModeMessage( GetEventThreadServices(), *mNode, mClippingMode );
2871 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
2874 if( property.Get( value ) && value != mPositionUsesAnchorPoint )
2876 mPositionUsesAnchorPoint = value;
2879 SetPositionUsesAnchorPointMessage( GetEventThreadServices(), *mNode, mPositionUsesAnchorPoint );
2887 // this can happen in the case of a non-animatable default property so just do nothing
2893 // TODO: This method needs to be removed
2894 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2896 switch( entry.GetType() )
2898 case Property::BOOLEAN:
2900 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2901 DALI_ASSERT_DEBUG( NULL != property );
2903 // property is being used in a separate thread; queue a message to set the property
2904 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2909 case Property::INTEGER:
2911 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2912 DALI_ASSERT_DEBUG( NULL != property );
2914 // property is being used in a separate thread; queue a message to set the property
2915 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2920 case Property::FLOAT:
2922 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2923 DALI_ASSERT_DEBUG( NULL != property );
2925 // property is being used in a separate thread; queue a message to set the property
2926 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2931 case Property::VECTOR2:
2933 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2934 DALI_ASSERT_DEBUG( NULL != property );
2936 // property is being used in a separate thread; queue a message to set the property
2937 if(entry.componentIndex == 0)
2939 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2941 else if(entry.componentIndex == 1)
2943 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2947 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2953 case Property::VECTOR3:
2955 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2956 DALI_ASSERT_DEBUG( NULL != property );
2958 // property is being used in a separate thread; queue a message to set the property
2959 if(entry.componentIndex == 0)
2961 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2963 else if(entry.componentIndex == 1)
2965 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2967 else if(entry.componentIndex == 2)
2969 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2973 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2979 case Property::VECTOR4:
2981 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2982 DALI_ASSERT_DEBUG( NULL != property );
2984 // property is being used in a separate thread; queue a message to set the property
2985 if(entry.componentIndex == 0)
2987 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
2989 else if(entry.componentIndex == 1)
2991 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
2993 else if(entry.componentIndex == 2)
2995 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
2997 else if(entry.componentIndex == 3)
2999 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
3003 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3009 case Property::ROTATION:
3011 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3012 DALI_ASSERT_DEBUG( NULL != property );
3014 // property is being used in a separate thread; queue a message to set the property
3015 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3020 case Property::MATRIX:
3022 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3023 DALI_ASSERT_DEBUG( NULL != property );
3025 // property is being used in a separate thread; queue a message to set the property
3026 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3031 case Property::MATRIX3:
3033 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3034 DALI_ASSERT_DEBUG( NULL != property );
3036 // property is being used in a separate thread; queue a message to set the property
3037 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3044 // nothing to do for other types
3049 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3051 Property::Value value;
3053 if( ! GetCachedPropertyValue( index, value ) )
3055 // If property value is not stored in the event-side, then it must be a scene-graph only property
3056 GetCurrentPropertyValue( index, value );
3062 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
3064 Property::Value value;
3066 if( ! GetCurrentPropertyValue( index, value ) )
3068 // If unable to retrieve scene-graph property value, then it must be an event-side only property
3069 GetCachedPropertyValue( index, value );
3075 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3080 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3082 // This method should only return an object connected to the scene-graph
3083 return OnStage() ? mNode : NULL;
3086 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3088 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3090 const PropertyBase* property( NULL );
3092 // This method should only return a property of an object connected to the scene-graph
3098 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3100 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3101 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3103 property = animatable->GetSceneGraphProperty();
3105 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3106 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3108 CustomPropertyMetadata* custom = FindCustomProperty( index );
3109 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3111 property = custom->GetSceneGraphProperty();
3113 else if( NULL != mNode )
3117 case Dali::Actor::Property::SIZE:
3118 property = &mNode->mSize;
3121 case Dali::Actor::Property::SIZE_WIDTH:
3122 property = &mNode->mSize;
3125 case Dali::Actor::Property::SIZE_HEIGHT:
3126 property = &mNode->mSize;
3129 case Dali::Actor::Property::SIZE_DEPTH:
3130 property = &mNode->mSize;
3133 case Dali::Actor::Property::POSITION:
3134 property = &mNode->mPosition;
3137 case Dali::Actor::Property::POSITION_X:
3138 property = &mNode->mPosition;
3141 case Dali::Actor::Property::POSITION_Y:
3142 property = &mNode->mPosition;
3145 case Dali::Actor::Property::POSITION_Z:
3146 property = &mNode->mPosition;
3149 case Dali::Actor::Property::ORIENTATION:
3150 property = &mNode->mOrientation;
3153 case Dali::Actor::Property::SCALE:
3154 property = &mNode->mScale;
3157 case Dali::Actor::Property::SCALE_X:
3158 property = &mNode->mScale;
3161 case Dali::Actor::Property::SCALE_Y:
3162 property = &mNode->mScale;
3165 case Dali::Actor::Property::SCALE_Z:
3166 property = &mNode->mScale;
3169 case Dali::Actor::Property::VISIBLE:
3170 property = &mNode->mVisible;
3173 case Dali::Actor::Property::COLOR:
3174 property = &mNode->mColor;
3177 case Dali::Actor::Property::COLOR_RED:
3178 property = &mNode->mColor;
3181 case Dali::Actor::Property::COLOR_GREEN:
3182 property = &mNode->mColor;
3185 case Dali::Actor::Property::COLOR_BLUE:
3186 property = &mNode->mColor;
3189 case Dali::Actor::Property::COLOR_ALPHA:
3190 case Dali::DevelActor::Property::OPACITY:
3191 property = &mNode->mColor;
3202 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3204 const PropertyInputImpl* property( NULL );
3206 // This method should only return a property of an object connected to the scene-graph
3212 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3214 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3215 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3217 property = animatable->GetSceneGraphProperty();
3219 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3220 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3222 CustomPropertyMetadata* custom = FindCustomProperty( index );
3223 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3224 property = custom->GetSceneGraphProperty();
3226 else if( NULL != mNode )
3230 case Dali::Actor::Property::PARENT_ORIGIN:
3231 property = &mNode->mParentOrigin;
3234 case Dali::Actor::Property::PARENT_ORIGIN_X:
3235 property = &mNode->mParentOrigin;
3238 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3239 property = &mNode->mParentOrigin;
3242 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3243 property = &mNode->mParentOrigin;
3246 case Dali::Actor::Property::ANCHOR_POINT:
3247 property = &mNode->mAnchorPoint;
3250 case Dali::Actor::Property::ANCHOR_POINT_X:
3251 property = &mNode->mAnchorPoint;
3254 case Dali::Actor::Property::ANCHOR_POINT_Y:
3255 property = &mNode->mAnchorPoint;
3258 case Dali::Actor::Property::ANCHOR_POINT_Z:
3259 property = &mNode->mAnchorPoint;
3262 case Dali::Actor::Property::SIZE:
3263 property = &mNode->mSize;
3266 case Dali::Actor::Property::SIZE_WIDTH:
3267 property = &mNode->mSize;
3270 case Dali::Actor::Property::SIZE_HEIGHT:
3271 property = &mNode->mSize;
3274 case Dali::Actor::Property::SIZE_DEPTH:
3275 property = &mNode->mSize;
3278 case Dali::Actor::Property::POSITION:
3279 property = &mNode->mPosition;
3282 case Dali::Actor::Property::POSITION_X:
3283 property = &mNode->mPosition;
3286 case Dali::Actor::Property::POSITION_Y:
3287 property = &mNode->mPosition;
3290 case Dali::Actor::Property::POSITION_Z:
3291 property = &mNode->mPosition;
3294 case Dali::Actor::Property::WORLD_POSITION:
3295 property = &mNode->mWorldPosition;
3298 case Dali::Actor::Property::WORLD_POSITION_X:
3299 property = &mNode->mWorldPosition;
3302 case Dali::Actor::Property::WORLD_POSITION_Y:
3303 property = &mNode->mWorldPosition;
3306 case Dali::Actor::Property::WORLD_POSITION_Z:
3307 property = &mNode->mWorldPosition;
3310 case Dali::Actor::Property::ORIENTATION:
3311 property = &mNode->mOrientation;
3314 case Dali::Actor::Property::WORLD_ORIENTATION:
3315 property = &mNode->mWorldOrientation;
3318 case Dali::Actor::Property::SCALE:
3319 property = &mNode->mScale;
3322 case Dali::Actor::Property::SCALE_X:
3323 property = &mNode->mScale;
3326 case Dali::Actor::Property::SCALE_Y:
3327 property = &mNode->mScale;
3330 case Dali::Actor::Property::SCALE_Z:
3331 property = &mNode->mScale;
3334 case Dali::Actor::Property::WORLD_SCALE:
3335 property = &mNode->mWorldScale;
3338 case Dali::Actor::Property::VISIBLE:
3339 property = &mNode->mVisible;
3342 case Dali::Actor::Property::COLOR:
3343 property = &mNode->mColor;
3346 case Dali::Actor::Property::COLOR_RED:
3347 property = &mNode->mColor;
3350 case Dali::Actor::Property::COLOR_GREEN:
3351 property = &mNode->mColor;
3354 case Dali::Actor::Property::COLOR_BLUE:
3355 property = &mNode->mColor;
3358 case Dali::Actor::Property::COLOR_ALPHA:
3359 case Dali::DevelActor::Property::OPACITY:
3361 property = &mNode->mColor;
3365 case Dali::Actor::Property::WORLD_COLOR:
3366 property = &mNode->mWorldColor;
3369 case Dali::Actor::Property::WORLD_MATRIX:
3370 property = &mNode->mWorldMatrix;
3381 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3383 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3385 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3387 // check whether the animatable property is registered already, if not then register one.
3388 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3389 if( animatableProperty )
3391 componentIndex = animatableProperty->componentIndex;
3398 case Dali::Actor::Property::PARENT_ORIGIN_X:
3399 case Dali::Actor::Property::ANCHOR_POINT_X:
3400 case Dali::Actor::Property::SIZE_WIDTH:
3401 case Dali::Actor::Property::POSITION_X:
3402 case Dali::Actor::Property::WORLD_POSITION_X:
3403 case Dali::Actor::Property::SCALE_X:
3404 case Dali::Actor::Property::COLOR_RED:
3410 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3411 case Dali::Actor::Property::ANCHOR_POINT_Y:
3412 case Dali::Actor::Property::SIZE_HEIGHT:
3413 case Dali::Actor::Property::POSITION_Y:
3414 case Dali::Actor::Property::WORLD_POSITION_Y:
3415 case Dali::Actor::Property::SCALE_Y:
3416 case Dali::Actor::Property::COLOR_GREEN:
3422 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3423 case Dali::Actor::Property::ANCHOR_POINT_Z:
3424 case Dali::Actor::Property::SIZE_DEPTH:
3425 case Dali::Actor::Property::POSITION_Z:
3426 case Dali::Actor::Property::WORLD_POSITION_Z:
3427 case Dali::Actor::Property::SCALE_Z:
3428 case Dali::Actor::Property::COLOR_BLUE:
3434 case Dali::Actor::Property::COLOR_ALPHA:
3435 case Dali::DevelActor::Property::OPACITY:
3449 return componentIndex;
3452 void Actor::SetParent( Actor* parent )
3456 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3460 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3463 // Instruct each actor to create a corresponding node in the scene graph
3464 ConnectToStage( parent->GetHierarchyDepth() );
3467 // Resolve the name and index for the child properties if any
3468 ResolveChildProperties();
3470 else // parent being set to NULL
3472 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3476 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3479 DALI_ASSERT_ALWAYS( mNode != NULL );
3483 // Disconnect the Node & its children from the scene-graph.
3484 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3487 // Instruct each actor to discard pointers to the scene-graph
3488 DisconnectFromStage();
3493 SceneGraph::Node* Actor::CreateNode() const
3498 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3501 Actor* actor = dynamic_cast< Actor* >( object );
3505 if( 0 == actionName.compare( ACTION_SHOW ) )
3507 actor->SetVisible( true );
3510 else if( 0 == actionName.compare( ACTION_HIDE ) )
3512 actor->SetVisible( false );
3520 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
3522 bool valueSet = true;
3526 case Dali::Actor::Property::PARENT_ORIGIN:
3528 value = GetCurrentParentOrigin();
3532 case Dali::Actor::Property::PARENT_ORIGIN_X:
3534 value = GetCurrentParentOrigin().x;
3538 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3540 value = GetCurrentParentOrigin().y;
3544 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3546 value = GetCurrentParentOrigin().z;
3550 case Dali::Actor::Property::ANCHOR_POINT:
3552 value = GetCurrentAnchorPoint();
3556 case Dali::Actor::Property::ANCHOR_POINT_X:
3558 value = GetCurrentAnchorPoint().x;
3562 case Dali::Actor::Property::ANCHOR_POINT_Y:
3564 value = GetCurrentAnchorPoint().y;
3568 case Dali::Actor::Property::ANCHOR_POINT_Z:
3570 value = GetCurrentAnchorPoint().z;
3574 case Dali::Actor::Property::SIZE:
3576 value = GetTargetSize();
3580 case Dali::Actor::Property::SIZE_WIDTH:
3582 value = GetTargetSize().width;
3586 case Dali::Actor::Property::SIZE_HEIGHT:
3588 value = GetTargetSize().height;
3592 case Dali::Actor::Property::SIZE_DEPTH:
3594 value = GetTargetSize().depth;
3598 case Dali::Actor::Property::POSITION:
3600 value = GetTargetPosition();
3604 case Dali::Actor::Property::POSITION_X:
3606 value = GetTargetPosition().x;
3610 case Dali::Actor::Property::POSITION_Y:
3612 value = GetTargetPosition().y;
3616 case Dali::Actor::Property::POSITION_Z:
3618 value = GetTargetPosition().z;
3622 case Dali::Actor::Property::ORIENTATION:
3624 value = mTargetOrientation;
3628 case Dali::Actor::Property::SCALE:
3630 value = mTargetScale;
3634 case Dali::Actor::Property::SCALE_X:
3636 value = mTargetScale.x;
3640 case Dali::Actor::Property::SCALE_Y:
3642 value = mTargetScale.y;
3646 case Dali::Actor::Property::SCALE_Z:
3648 value = mTargetScale.z;
3652 case Dali::Actor::Property::VISIBLE:
3658 case Dali::Actor::Property::COLOR:
3660 value = mTargetColor;
3664 case Dali::Actor::Property::COLOR_RED:
3666 value = mTargetColor.r;
3670 case Dali::Actor::Property::COLOR_GREEN:
3672 value = mTargetColor.g;
3676 case Dali::Actor::Property::COLOR_BLUE:
3678 value = mTargetColor.b;
3682 case Dali::Actor::Property::COLOR_ALPHA:
3683 case Dali::DevelActor::Property::OPACITY:
3685 value = mTargetColor.a;
3689 case Dali::Actor::Property::NAME:
3695 case Dali::Actor::Property::SENSITIVE:
3697 value = IsSensitive();
3701 case Dali::Actor::Property::LEAVE_REQUIRED:
3703 value = GetLeaveRequired();
3707 case Dali::Actor::Property::INHERIT_POSITION:
3709 value = IsPositionInherited();
3713 case Dali::Actor::Property::INHERIT_ORIENTATION:
3715 value = IsOrientationInherited();
3719 case Dali::Actor::Property::INHERIT_SCALE:
3721 value = IsScaleInherited();
3725 case Dali::Actor::Property::COLOR_MODE:
3727 value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
3731 case Dali::Actor::Property::POSITION_INHERITANCE:
3733 value = Scripting::GetLinearEnumerationName< PositionInheritanceMode >( GetPositionInheritanceMode(), POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT );
3737 case Dali::Actor::Property::DRAW_MODE:
3739 value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
3743 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3745 value = GetSizeModeFactor();
3749 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3751 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3755 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3757 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3761 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3763 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT );
3767 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3769 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3773 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3775 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3779 case Dali::Actor::Property::PADDING:
3781 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3782 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3783 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3787 case Dali::Actor::Property::MINIMUM_SIZE:
3789 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3793 case Dali::Actor::Property::MAXIMUM_SIZE:
3795 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3799 case Dali::Actor::Property::CLIPPING_MODE:
3801 value = mClippingMode;
3805 case Dali::DevelActor::Property::SIBLING_ORDER:
3807 value = static_cast<int>(mSiblingOrder);
3811 case Dali::DevelActor::Property::SCREEN_POSITION:
3813 value = GetCurrentScreenPosition();
3817 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
3819 value = mPositionUsesAnchorPoint;
3825 // Must be a scene-graph only property
3834 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
3836 bool valueSet = true;
3840 case Dali::Actor::Property::SIZE:
3842 value = GetCurrentSize();
3846 case Dali::Actor::Property::SIZE_WIDTH:
3848 value = GetCurrentSize().width;
3852 case Dali::Actor::Property::SIZE_HEIGHT:
3854 value = GetCurrentSize().height;
3858 case Dali::Actor::Property::SIZE_DEPTH:
3860 value = GetCurrentSize().depth;
3864 case Dali::Actor::Property::POSITION:
3866 value = GetCurrentPosition();
3870 case Dali::Actor::Property::POSITION_X:
3872 value = GetCurrentPosition().x;
3876 case Dali::Actor::Property::POSITION_Y:
3878 value = GetCurrentPosition().y;
3882 case Dali::Actor::Property::POSITION_Z:
3884 value = GetCurrentPosition().z;
3888 case Dali::Actor::Property::WORLD_POSITION:
3890 value = GetCurrentWorldPosition();
3894 case Dali::Actor::Property::WORLD_POSITION_X:
3896 value = GetCurrentWorldPosition().x;
3900 case Dali::Actor::Property::WORLD_POSITION_Y:
3902 value = GetCurrentWorldPosition().y;
3906 case Dali::Actor::Property::WORLD_POSITION_Z:
3908 value = GetCurrentWorldPosition().z;
3912 case Dali::Actor::Property::ORIENTATION:
3914 value = GetCurrentOrientation();
3918 case Dali::Actor::Property::WORLD_ORIENTATION:
3920 value = GetCurrentWorldOrientation();
3924 case Dali::Actor::Property::SCALE:
3926 value = GetCurrentScale();
3930 case Dali::Actor::Property::SCALE_X:
3932 value = GetCurrentScale().x;
3936 case Dali::Actor::Property::SCALE_Y:
3938 value = GetCurrentScale().y;
3942 case Dali::Actor::Property::SCALE_Z:
3944 value = GetCurrentScale().z;
3948 case Dali::Actor::Property::WORLD_SCALE:
3950 value = GetCurrentWorldScale();
3954 case Dali::Actor::Property::COLOR:
3956 value = GetCurrentColor();
3960 case Dali::Actor::Property::COLOR_RED:
3962 value = GetCurrentColor().r;
3966 case Dali::Actor::Property::COLOR_GREEN:
3968 value = GetCurrentColor().g;
3972 case Dali::Actor::Property::COLOR_BLUE:
3974 value = GetCurrentColor().b;
3978 case Dali::Actor::Property::COLOR_ALPHA:
3979 case Dali::DevelActor::Property::OPACITY:
3981 value = GetCurrentColor().a;
3985 case Dali::Actor::Property::WORLD_COLOR:
3987 value = GetCurrentWorldColor();
3991 case Dali::Actor::Property::WORLD_MATRIX:
3993 value = GetCurrentWorldMatrix();
3999 // Must be an event-side only property
4008 void Actor::EnsureRelayoutData()
4010 // Assign relayout data.
4011 if( !mRelayoutData )
4013 mRelayoutData = new RelayoutData();
4017 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
4019 // Check if actor is dependent on parent
4020 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4022 if( ( dimension & ( 1 << i ) ) )
4024 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4025 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
4035 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
4037 // Check if actor is dependent on children
4038 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4040 if( ( dimension & ( 1 << i ) ) )
4042 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4043 switch( resizePolicy )
4045 case ResizePolicy::FIT_TO_CHILDREN:
4046 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
4062 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
4064 return Actor::RelayoutDependentOnChildren( dimension );
4067 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
4069 // Check each possible dimension and see if it is dependent on the input one
4070 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4072 if( dimension & ( 1 << i ) )
4074 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
4081 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
4083 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4085 if( dimension & ( 1 << i ) )
4087 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
4092 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
4094 // If more than one dimension is requested, just return the first one found
4095 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4097 if( ( dimension & ( 1 << i ) ) )
4099 return mRelayoutData->negotiatedDimensions[ i ];
4103 return 0.0f; // Default
4106 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
4108 EnsureRelayoutData();
4110 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4112 if( dimension & ( 1 << i ) )
4114 mRelayoutData->dimensionPadding[ i ] = padding;
4119 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4121 if ( mRelayoutData )
4123 // If more than one dimension is requested, just return the first one found
4124 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4126 if( ( dimension & ( 1 << i ) ) )
4128 return mRelayoutData->dimensionPadding[ i ];
4133 return GetDefaultDimensionPadding();
4136 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4138 EnsureRelayoutData();
4140 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4142 if( dimension & ( 1 << i ) )
4144 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4149 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4151 if ( mRelayoutData )
4153 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4155 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4165 float Actor::GetHeightForWidthBase( float width )
4167 float height = 0.0f;
4169 const Vector3 naturalSize = GetNaturalSize();
4170 if( naturalSize.width > 0.0f )
4172 height = naturalSize.height * width / naturalSize.width;
4174 else // we treat 0 as 1:1 aspect ratio
4182 float Actor::GetWidthForHeightBase( float height )
4186 const Vector3 naturalSize = GetNaturalSize();
4187 if( naturalSize.height > 0.0f )
4189 width = naturalSize.width * height / naturalSize.height;
4191 else // we treat 0 as 1:1 aspect ratio
4199 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4201 // Fill to parent, taking size mode factor into account
4202 switch( child.GetResizePolicy( dimension ) )
4204 case ResizePolicy::FILL_TO_PARENT:
4206 return GetLatestSize( dimension );
4209 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4211 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4214 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4216 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4221 return GetLatestSize( dimension );
4226 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4228 // Can be overridden in derived class
4229 return CalculateChildSizeBase( child, dimension );
4232 float Actor::GetHeightForWidth( float width )
4234 // Can be overridden in derived class
4235 return GetHeightForWidthBase( width );
4238 float Actor::GetWidthForHeight( float height )
4240 // Can be overridden in derived class
4241 return GetWidthForHeightBase( height );
4244 float Actor::GetLatestSize( Dimension::Type dimension ) const
4246 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4249 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4251 Vector2 padding = GetPadding( dimension );
4253 return GetLatestSize( dimension ) + padding.x + padding.y;
4256 float Actor::NegotiateFromParent( Dimension::Type dimension )
4258 Actor* parent = GetParent();
4261 Vector2 padding( GetPadding( dimension ) );
4262 Vector2 parentPadding( parent->GetPadding( dimension ) );
4263 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4269 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4271 float maxDimensionPoint = 0.0f;
4273 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4275 ActorPtr child = GetChildAt( i );
4277 if( !child->RelayoutDependentOnParent( dimension ) )
4279 // Calculate the min and max points that the children range across
4280 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
4281 float dimensionSize = child->GetRelayoutSize( dimension );
4282 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4286 return maxDimensionPoint;
4289 float Actor::GetSize( Dimension::Type dimension ) const
4291 return GetDimensionValue( mTargetSize, dimension );
4294 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4296 return GetDimensionValue( GetNaturalSize(), dimension );
4299 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4301 switch( GetResizePolicy( dimension ) )
4303 case ResizePolicy::USE_NATURAL_SIZE:
4305 return GetNaturalSize( dimension );
4308 case ResizePolicy::FIXED:
4310 return GetDimensionValue( GetPreferredSize(), dimension );
4313 case ResizePolicy::USE_ASSIGNED_SIZE:
4315 return GetDimensionValue( maximumSize, dimension );
4318 case ResizePolicy::FILL_TO_PARENT:
4319 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4320 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4322 return NegotiateFromParent( dimension );
4325 case ResizePolicy::FIT_TO_CHILDREN:
4327 return NegotiateFromChildren( dimension );
4330 case ResizePolicy::DIMENSION_DEPENDENCY:
4332 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4335 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4337 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4340 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4342 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4354 return 0.0f; // Default
4357 float Actor::ClampDimension( float size, Dimension::Type dimension )
4359 const float minSize = GetMinimumSize( dimension );
4360 const float maxSize = GetMaximumSize( dimension );
4362 return std::max( minSize, std::min( size, maxSize ) );
4365 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4367 // Check if it needs to be negotiated
4368 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4370 // Check that we havn't gotten into an infinite loop
4371 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4372 bool recursionFound = false;
4373 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4375 if( *it == searchActor )
4377 recursionFound = true;
4382 if( !recursionFound )
4384 // Record the path that we have taken
4385 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4387 // Dimension dependency check
4388 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4390 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4392 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4394 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4398 // Parent dependency check
4399 Actor* parent = GetParent();
4400 if( parent && RelayoutDependentOnParent( dimension ) )
4402 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4405 // Children dependency check
4406 if( RelayoutDependentOnChildren( dimension ) )
4408 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4410 ActorPtr child = GetChildAt( i );
4412 // Only relayout child first if it is not dependent on this actor
4413 if( !child->RelayoutDependentOnParent( dimension ) )
4415 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
4420 // For deriving classes
4421 OnCalculateRelayoutSize( dimension );
4423 // All dependencies checked, calculate the size and set negotiated flag
4424 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4426 SetNegotiatedDimension( newSize, dimension );
4427 SetLayoutNegotiated( true, dimension );
4429 // For deriving classes
4430 OnLayoutNegotiated( newSize, dimension );
4432 // This actor has been successfully processed, pop it off the recursion stack
4433 recursionStack.pop_back();
4437 // TODO: Break infinite loop
4438 SetLayoutNegotiated( true, dimension );
4443 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4445 // Negotiate all dimensions that require it
4446 ActorDimensionStack recursionStack;
4448 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4450 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4453 NegotiateDimension( dimension, allocatedSize, recursionStack );
4457 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4459 switch( mRelayoutData->sizeSetPolicy )
4461 case SizeScalePolicy::USE_SIZE_SET:
4466 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4468 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4469 const Vector3 naturalSize = GetNaturalSize();
4470 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4472 const float sizeRatio = size.width / size.height;
4473 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4475 if( naturalSizeRatio < sizeRatio )
4477 return Vector2( naturalSizeRatio * size.height, size.height );
4479 else if( naturalSizeRatio > sizeRatio )
4481 return Vector2( size.width, size.width / naturalSizeRatio );
4492 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4494 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4495 const Vector3 naturalSize = GetNaturalSize();
4496 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4498 const float sizeRatio = size.width / size.height;
4499 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4501 if( naturalSizeRatio < sizeRatio )
4503 return Vector2( size.width, size.width / naturalSizeRatio );
4505 else if( naturalSizeRatio > sizeRatio )
4507 return Vector2( naturalSizeRatio * size.height, size.height );
4526 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4528 // Do the set actor size
4529 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4531 // Adjust for size set policy
4532 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4534 // Lock the flag to stop recursive relayouts on set size
4535 mRelayoutData->insideRelayout = true;
4536 SetSize( negotiatedSize );
4537 mRelayoutData->insideRelayout = false;
4539 // Clear flags for all dimensions
4540 SetLayoutDirty( false );
4542 // Give deriving classes a chance to respond
4543 OnRelayout( negotiatedSize, container );
4545 if( !mOnRelayoutSignal.Empty() )
4547 Dali::Actor handle( this );
4548 mOnRelayoutSignal.Emit( handle );
4552 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4554 // Force a size negotiation for actors that has assigned size during relayout
4555 // This is required as otherwise the flags that force a relayout will not
4556 // necessarilly be set. This will occur if the actor has already been laid out.
4557 // The dirty flags are then cleared. Then if the actor is added back into the
4558 // relayout container afterwards, the dirty flags would still be clear...
4559 // causing a relayout to be skipped. Here we force any actors added to the
4560 // container to be relayed out.
4561 if(GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE)
4563 SetLayoutNegotiated(false, Dimension::WIDTH);
4565 if(GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE)
4567 SetLayoutNegotiated(false, Dimension::HEIGHT);
4570 // Do the negotiation
4571 NegotiateDimensions( allocatedSize );
4573 // Set the actor size
4574 SetNegotiatedSize( container );
4576 // Negotiate down to children
4577 const Vector2 newBounds = mTargetSize.GetVectorXY();
4579 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4581 ActorPtr child = GetChildAt( i );
4583 // Forces children that have already been laid out to be relayed out
4584 // if they have assigned size during relayout.
4585 if(child->GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE)
4587 child->SetLayoutNegotiated(false, Dimension::WIDTH);
4588 child->SetLayoutDirty(true, Dimension::WIDTH);
4590 if(child->GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE)
4592 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
4593 child->SetLayoutDirty(true, Dimension::HEIGHT);
4596 // Only relayout if required
4597 if( child->RelayoutRequired() )
4599 container.Add( Dali::Actor( child.Get() ), newBounds );
4604 void Actor::RelayoutRequest( Dimension::Type dimension )
4606 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4607 if( relayoutController )
4609 Dali::Actor self( this );
4610 relayoutController->RequestRelayout( self, dimension );
4614 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4618 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4622 void Actor::SetPreferredSize( const Vector2& size )
4624 EnsureRelayoutData();
4626 if( size.width > 0.0f )
4628 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4631 if( size.height > 0.0f )
4633 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4636 mRelayoutData->preferredSize = size;
4641 Vector2 Actor::GetPreferredSize() const
4643 if ( mRelayoutData )
4645 return Vector2( mRelayoutData->preferredSize );
4648 return GetDefaultPreferredSize();
4651 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4653 EnsureRelayoutData();
4655 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4657 if( dimension & ( 1 << i ) )
4659 mRelayoutData->minimumSize[ i ] = size;
4666 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4668 if ( mRelayoutData )
4670 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4672 if( dimension & ( 1 << i ) )
4674 return mRelayoutData->minimumSize[ i ];
4679 return 0.0f; // Default
4682 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4684 EnsureRelayoutData();
4686 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4688 if( dimension & ( 1 << i ) )
4690 mRelayoutData->maximumSize[ i ] = size;
4697 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4699 if ( mRelayoutData )
4701 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4703 if( dimension & ( 1 << i ) )
4705 return mRelayoutData->maximumSize[ i ];
4710 return FLT_MAX; // Default
4713 Object* Actor::GetParentObject() const
4718 void Actor::SetSiblingOrder( unsigned int order )
4720 mSiblingOrder = std::min( order, static_cast<unsigned int>( DevelLayer::SIBLING_ORDER_MULTIPLIER ) );
4723 SetDepthIndexMessage( GetEventThreadServices(), *mNode, GetDepthIndex( mDepth, mSiblingOrder ) );
4727 void Actor::DefragmentSiblingIndexes( ActorContainer& siblings )
4729 // Sibling index may not be in consecutive order as the sibling range is limited ( DevelLayer::SIBLING_ORDER_MULTIPLIER )
4730 // we need to remove the gaps and ensure the number start from 0 and consecutive hence have a full range.
4732 // Start at index 0, while index <= highest order
4733 // Find next index higher than 0
4734 // if nextHigher > index+1
4735 // set all nextHigher orders to index+1
4737 // Limitation: May reach the ceiling of DevelLayer::SIBLING_ORDER_MULTIPLIER with highest sibling.
4739 ActorIter end = siblings.end();
4740 int highestOrder = 0;
4741 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
4743 ActorPtr sibling = (*iter);
4744 int siblingOrder = sibling->mSiblingOrder;
4745 highestOrder = std::max( highestOrder, siblingOrder );
4748 for ( int index = 0; index <= highestOrder; index++ )
4750 int nextHighest = -1;
4752 // Find Next highest
4753 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
4755 ActorPtr sibling = (*iter);
4756 int siblingOrder = sibling->mSiblingOrder;
4758 if ( siblingOrder > index )
4760 if ( nextHighest == -1 )
4762 nextHighest = siblingOrder;
4764 nextHighest = std::min( nextHighest, siblingOrder );
4768 // Check if a gap exists between indexes, if so set next index to consecutive number
4769 if ( ( nextHighest - index ) > 1 )
4771 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
4773 ActorPtr sibling = (*iter);
4774 int siblingOrder = sibling->mSiblingOrder;
4775 if ( siblingOrder == nextHighest )
4777 sibling->mSiblingOrder = index + 1;
4778 if ( sibling->mSiblingOrder >= Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER )
4780 DALI_LOG_WARNING( "Reached max sibling order level for raising / lowering actors\n" );
4781 sibling->mSiblingOrder = Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER;
4783 sibling->SetSiblingOrder( sibling->mSiblingOrder );
4790 bool Actor::ShiftSiblingsLevels( ActorContainer& siblings, int targetLevelToShiftFrom )
4792 // Allows exclusive levels for an actor by shifting all sibling levels at the target and above by 1
4793 bool defragmentationRequired( false );
4794 ActorIter end = siblings.end();
4795 for( ActorIter iter = siblings.begin(); ( iter != end ) ; ++iter )
4797 // Move actors at nearest order and above up by 1
4798 ActorPtr sibling = (*iter);
4799 if ( sibling != this )
4801 // Iterate through container of actors, any actor with a sibling order of the target or greater should
4802 // be incremented by 1.
4803 if ( sibling->mSiblingOrder >= targetLevelToShiftFrom )
4805 sibling->mSiblingOrder++;
4806 if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
4808 // If a sibling order raises so that it is only 1 from the maximum allowed then set flag so
4809 // can re-order all sibling orders.
4810 defragmentationRequired = true;
4812 sibling->SetSiblingOrder( sibling->mSiblingOrder );
4816 return defragmentationRequired;
4822 1) Check if already at top and nothing to be done.
4823 This Actor can have highest sibling order but if not exclusive then another actor at same sibling
4824 order can be positioned above it due to insertion order of actors.
4825 2) Find nearest sibling level above, these are the siblings this actor needs to be above
4826 3) a) There may be other levels above this target level
4827 b) Increment all sibling levels at the level above nearest(target)
4828 c) Now have a vacant sibling level
4829 4) Set this actor's sibling level to nearest +1 as now vacated.
4831 Note May not just be sibling level + 1 as could be empty levels in-between
4836 ActorC ( sibling level 4 )
4837 ActorB ( sibling level 3 )
4838 ActorA ( sibling level 1 )
4840 2 ) ACTION: Raise A above B
4841 a) Find nearest level above A = Level 3
4842 b) Increment levels above Level 3
4844 ActorC ( sibling level 5 )
4845 ActorB ( sibling level 3 ) NEAREST
4846 ActorA ( sibling level 1 )
4848 3 ) Set Actor A sibling level to nearest +1 as vacant
4850 ActorC ( sibling level 5 )
4851 ActorA ( sibling level 4 )
4852 ActorB ( sibling level 3 )
4854 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4855 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4856 remove any empty sibling order gaps and start from sibling level 0 again.
4857 If the number of actors reaches this maximum and all using exclusive sibling order values then
4858 defragmention will stop and new sibling orders will be set to same max value.
4862 int nearestLevel = mSiblingOrder;
4863 int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
4864 bool defragmentationRequired( false );
4866 ActorContainer* siblings = mParent->mChildren;
4868 // Find Nearest sibling level above this actor
4869 ActorIter end = siblings->end();
4870 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
4872 ActorPtr sibling = (*iter);
4873 if ( sibling != this )
4875 int order = GetSiblingOrder( sibling );
4877 if ( ( order >= mSiblingOrder ) )
4879 int distanceToNextLevel = order - mSiblingOrder;
4880 if ( distanceToNextLevel < shortestDistanceToNextLevel )
4882 nearestLevel = order;
4883 shortestDistanceToNextLevel = distanceToNextLevel;
4889 if ( nearestLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at top
4891 mSiblingOrder = nearestLevel + 1; // Set sibling level to that above the nearest level
4892 defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
4893 // Move current actor to newly vacated order level
4894 SetSiblingOrder( mSiblingOrder );
4895 if ( defragmentationRequired )
4897 DefragmentSiblingIndexes( *siblings );
4900 SetSiblingOrder( mSiblingOrder );
4904 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4911 1) Check if actor already at bottom and if nothing needs to be done
4912 This Actor can have lowest sibling order but if not exclusive then another actor at same sibling
4913 order can be positioned above it due to insertion order of actors so need to move this actor below it.
4914 2) Find nearest sibling level below, this Actor needs to be below it
4915 3) a) Need to vacate a sibling level below nearest for this actor to occupy
4916 b) Shift up all sibling order values of actor at the nearest level and levels above it to vacate a level.
4917 c) Set this actor's sibling level to this newly vacated level.
4918 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4919 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4920 remove any empty sibling order gaps and start from sibling level 0 again.
4921 If the number of actors reaches this maximum and all using exclusive sibling order values then
4922 defragmention will stop and new sibling orders will be set to same max value.
4927 // 1) Find nearest level below
4928 int nearestLevel = mSiblingOrder;
4929 int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
4931 ActorContainer* siblings = mParent->mChildren;
4933 ActorIter end = siblings->end();
4934 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
4936 ActorPtr sibling = (*iter);
4937 if ( sibling != this )
4939 int order = GetSiblingOrder( sibling );
4941 if ( order <= mSiblingOrder )
4943 int distanceToNextLevel = mSiblingOrder - order;
4944 if ( distanceToNextLevel < shortestDistanceToNextLevel )
4946 nearestLevel = order;
4947 shortestDistanceToNextLevel = distanceToNextLevel;
4953 bool defragmentationRequired ( false );
4955 // 2) If actor already not at bottom, raise all actors at required level and above
4956 if ( shortestDistanceToNextLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at bottom
4958 mSiblingOrder = nearestLevel;
4959 defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
4960 // Move current actor to newly vacated order
4961 SetSiblingOrder( mSiblingOrder );
4962 if ( defragmentationRequired )
4964 DefragmentSiblingIndexes( *siblings );
4970 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4974 void Actor::RaiseToTop()
4977 1 ) Find highest sibling order actor
4978 2 ) If highest sibling level not itself then set sibling order to that + 1
4979 3 ) highest sibling order can be same as itself so need to increment over that
4980 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
4981 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
4982 remove any empty sibling order gaps and start from sibling level 0 again.
4983 If the number of actors reaches this maximum and all using exclusive sibling order values then
4984 defragmention will stop and new sibling orders will be set to same max value.
4991 ActorContainer* siblings = mParent->mChildren;
4993 ActorIter end = siblings->end();
4994 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
4996 ActorPtr sibling = (*iter);
4997 if ( sibling != this )
4999 maxOrder = std::max( GetSiblingOrder( sibling ), maxOrder );
5003 bool defragmentationRequired( false );
5005 if ( maxOrder >= mSiblingOrder )
5007 mSiblingOrder = maxOrder + 1;
5008 if ( mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
5010 defragmentationRequired = true;
5014 SetSiblingOrder( mSiblingOrder );
5016 if ( defragmentationRequired )
5018 DefragmentSiblingIndexes( *siblings );
5023 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5027 void Actor::LowerToBottom()
5030 See Actor::LowerToBottom()
5032 1 ) Check if this actor already at exclusively at the bottom, if so then no more to be done.
5033 2 ) a ) Check if the bottom position 0 is vacant.
5034 b ) If 0 position is not vacant then shift up all sibling order values from 0 and above
5035 c ) 0 sibling position is vacant.
5036 3 ) Set this actor to vacant sibling order 0;
5037 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5038 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5039 remove any empty sibling order gaps and start from sibling level 0 again.
5040 If the number of actors reaches this maximum and all using exclusive sibling order values then
5041 defragmention will stop and new sibling orders will be set to same max value.
5046 bool defragmentationRequired( false );
5047 bool orderZeroFree ( true );
5049 ActorContainer* siblings = mParent->mChildren;
5051 bool actorAtLowestOrder = true;
5052 ActorIter end = siblings->end();
5053 for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
5055 ActorPtr sibling = (*iter);
5056 if ( sibling != this )
5058 int siblingOrder = GetSiblingOrder( sibling );
5059 if ( siblingOrder <= mSiblingOrder )
5061 actorAtLowestOrder = false;
5064 if ( siblingOrder == 0 )
5066 orderZeroFree = false;
5071 if ( ! actorAtLowestOrder )
5073 if ( ! orderZeroFree )
5075 defragmentationRequired = ShiftSiblingsLevels( *siblings, 0 );
5078 SetSiblingOrder( mSiblingOrder );
5080 if ( defragmentationRequired )
5082 DefragmentSiblingIndexes( *siblings );
5088 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5092 void Actor::RaiseAbove( Internal::Actor& target )
5095 1 ) a) Find target actor's sibling order
5096 b) If sibling order of target is the same as this actor then need to this Actor's sibling order
5097 needs to be above it or the insertion order will determine which is drawn on top.
5098 2 ) Shift up by 1 all sibling order greater than target sibling order
5099 3 ) Set this actor to the sibling order to target +1 as will be a newly vacated gap above
5100 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5101 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5102 remove any empty sibling order gaps and start from sibling level 0 again.
5103 If the number of actors reaches this maximum and all using exclusive sibling order values then
5104 defragmention will stop and new sibling orders will be set to same max value.
5109 if ( ValidateActors( *this, target ) )
5111 // Find target's sibling order
5112 // Set actor sibling order to this number +1
5113 int targetSiblingOrder = GetSiblingOrder( &target );
5114 ActorContainer* siblings = mParent->mChildren;
5115 mSiblingOrder = targetSiblingOrder + 1;
5116 bool defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
5118 SetSiblingOrder( mSiblingOrder );
5120 if ( defragmentationRequired )
5122 DefragmentSiblingIndexes( *(mParent->mChildren) );
5128 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5132 void Actor::LowerBelow( Internal::Actor& target )
5135 1 ) a) Find target actor's sibling order
5136 b) If sibling order of target is the same as this actor then need to this Actor's sibling order
5137 needs to be below it or the insertion order will determine which is drawn on top.
5138 2 ) Shift the target sibling order and all sibling orders at that level or above by 1
5139 3 ) Set this actor to the sibling order of the target before it changed.
5140 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5141 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5142 remove any empty sibling order gaps and start from sibling level 0 again.
5143 If the number of actors reaches this maximum and all using exclusive sibling order values then
5144 defragmention will stop and new sibling orders will be set to same max value.
5149 if ( ValidateActors( *this, target ) )
5151 bool defragmentationRequired ( false );
5152 // Find target's sibling order
5153 // Set actor sibling order to target sibling order - 1
5154 int targetSiblingOrder = GetSiblingOrder( &target);
5155 ActorContainer* siblings = mParent->mChildren;
5156 if ( targetSiblingOrder == 0 )
5159 ActorIter end = siblings->end();
5160 for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
5162 ActorPtr sibling = (*iter);
5163 if ( sibling != this )
5165 sibling->mSiblingOrder++;
5166 if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
5168 defragmentationRequired = true;
5170 sibling->SetSiblingOrder( sibling->mSiblingOrder );
5177 defragmentationRequired = ShiftSiblingsLevels( *siblings, targetSiblingOrder );
5179 mSiblingOrder = targetSiblingOrder;
5181 SetSiblingOrder( mSiblingOrder );
5183 if ( defragmentationRequired )
5185 DefragmentSiblingIndexes( *(mParent->mChildren) );
5191 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5195 } // namespace Internal