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/object/weak-handle.h>
37 #include <dali/devel-api/scripting/scripting.h>
38 #include <dali/internal/common/internal-constants.h>
39 #include <dali/internal/event/common/event-thread-services.h>
40 #include <dali/internal/event/render-tasks/render-task-impl.h>
41 #include <dali/internal/event/actors/camera-actor-impl.h>
42 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
43 #include <dali/internal/event/common/property-helper.h>
44 #include <dali/internal/event/common/stage-impl.h>
45 #include <dali/internal/event/common/type-info-impl.h>
46 #include <dali/internal/event/animation/constraint-impl.h>
47 #include <dali/internal/event/common/projection.h>
48 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
49 #include <dali/internal/update/common/animatable-property.h>
50 #include <dali/internal/update/nodes/node-messages.h>
51 #include <dali/internal/update/nodes/node-declarations.h>
52 #include <dali/internal/update/animation/scene-graph-constraint.h>
53 #include <dali/internal/event/events/actor-gesture-data.h>
54 #include <dali/internal/common/message.h>
55 #include <dali/integration-api/debug.h>
57 using Dali::Internal::SceneGraph::Node;
58 using Dali::Internal::SceneGraph::AnimatableProperty;
59 using Dali::Internal::SceneGraph::PropertyBase;
61 #if defined(DEBUG_ENABLED)
62 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_DEPTH_TIMER" );
63 Debug::Filter* gLogRelayoutFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_TIMER" );
72 unsigned int Actor::mActorCounter = 0;
76 /// Using a function because of library initialisation order. Vector3::ONE may not have been initialised yet.
77 inline const Vector3& GetDefaultSizeModeFactor()
82 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
83 inline const Vector2& GetDefaultPreferredSize()
88 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
89 inline const Vector2& GetDefaultDimensionPadding()
94 const SizeScalePolicy::Type DEFAULT_SIZE_SCALE_POLICY = SizeScalePolicy::USE_SIZE_SET;
96 int GetSiblingOrder( ActorPtr actor )
98 Property::Value value = actor->GetProperty(Dali::DevelActor::Property::SIBLING_ORDER );
104 bool ValidateActors( const Internal::Actor& actor, const Internal::Actor& target )
106 bool validTarget = true;
108 if( &actor == &target )
110 DALI_LOG_WARNING( "Source actor and target actor can not be the same, Sibling order not changed.\n" );
113 else if( actor.GetParent() != target.GetParent() )
115 DALI_LOG_WARNING( "Source actor and target actor need to have common parent, Sibling order not changed.\n" );
122 } // unnamed namespace
125 * Struct to collect relayout variables
127 struct Actor::RelayoutData
130 : sizeModeFactor( GetDefaultSizeModeFactor() ), preferredSize( GetDefaultPreferredSize() ), sizeSetPolicy( DEFAULT_SIZE_SCALE_POLICY ), relayoutEnabled( false ), insideRelayout( false )
132 // Set size negotiation defaults
133 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
135 resizePolicies[ i ] = ResizePolicy::DEFAULT;
136 useAssignedSize[ i ] = false;
137 negotiatedDimensions[ i ] = 0.0f;
138 dimensionNegotiated[ i ] = false;
139 dimensionDirty[ i ] = false;
140 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
141 dimensionPadding[ i ] = GetDefaultDimensionPadding();
142 minimumSize[ i ] = 0.0f;
143 maximumSize[ i ] = FLT_MAX;
147 ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies
148 bool useAssignedSize[ Dimension::DIMENSION_COUNT ]; ///< The flag to specify whether the size should be assigned to the actor
150 Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies
152 Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
154 float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
156 float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be
157 float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be
159 bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated
160 bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
162 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
164 Vector2 preferredSize; ///< The preferred size of the actor
166 SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
168 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
169 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
172 namespace // unnamed namespace
178 * We want to discourage the use of property strings (minimize string comparisons),
179 * particularly for the default properties.
180 * Name Type writable animatable constraint-input enum for index-checking
182 DALI_PROPERTY_TABLE_BEGIN
183 DALI_PROPERTY( "parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
184 DALI_PROPERTY( "parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
185 DALI_PROPERTY( "parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
186 DALI_PROPERTY( "parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
187 DALI_PROPERTY( "anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
188 DALI_PROPERTY( "anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
189 DALI_PROPERTY( "anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
190 DALI_PROPERTY( "anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
191 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
192 DALI_PROPERTY( "sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
193 DALI_PROPERTY( "sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
194 DALI_PROPERTY( "sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
195 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
196 DALI_PROPERTY( "positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
197 DALI_PROPERTY( "positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
198 DALI_PROPERTY( "positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
199 DALI_PROPERTY( "worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
200 DALI_PROPERTY( "worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
201 DALI_PROPERTY( "worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
202 DALI_PROPERTY( "worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
203 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
204 DALI_PROPERTY( "worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
205 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
206 DALI_PROPERTY( "scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
207 DALI_PROPERTY( "scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
208 DALI_PROPERTY( "scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
209 DALI_PROPERTY( "worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
210 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
211 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
212 DALI_PROPERTY( "colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
213 DALI_PROPERTY( "colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
214 DALI_PROPERTY( "colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
215 DALI_PROPERTY( "colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
216 DALI_PROPERTY( "worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
217 DALI_PROPERTY( "worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
218 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
219 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
220 DALI_PROPERTY( "leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
221 DALI_PROPERTY( "inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
222 DALI_PROPERTY( "inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
223 DALI_PROPERTY( "colorMode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
224 DALI_PROPERTY( "positionInheritance", STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE )
225 DALI_PROPERTY( "drawMode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
226 DALI_PROPERTY( "sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
227 DALI_PROPERTY( "widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
228 DALI_PROPERTY( "heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
229 DALI_PROPERTY( "sizeScalePolicy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
230 DALI_PROPERTY( "widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
231 DALI_PROPERTY( "heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
232 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
233 DALI_PROPERTY( "minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
234 DALI_PROPERTY( "maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
235 DALI_PROPERTY( "inheritPosition", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_POSITION )
236 DALI_PROPERTY( "clippingMode", STRING, true, false, false, Dali::Actor::Property::CLIPPING_MODE )
237 DALI_PROPERTY( "siblingOrder", INTEGER, true, false, false, Dali::DevelActor::Property::SIBLING_ORDER )
238 DALI_PROPERTY( "opacity", FLOAT, true, true, true, Dali::DevelActor::Property::OPACITY )
239 DALI_PROPERTY( "screenPosition", VECTOR2, false, false, false, Dali::DevelActor::Property::SCREEN_POSITION )
240 DALI_PROPERTY( "positionUsesAnchorPoint", BOOLEAN, true, false, false, Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT )
241 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
245 const char* const SIGNAL_TOUCHED = "touched";
246 const char* const SIGNAL_HOVERED = "hovered";
247 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
248 const char* const SIGNAL_ON_STAGE = "onStage";
249 const char* const SIGNAL_OFF_STAGE = "offStage";
250 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
251 const char* const SIGNAL_TOUCH = "touch";
255 const char* const ACTION_SHOW = "show";
256 const char* const ACTION_HIDE = "hide";
258 BaseHandle CreateActor()
260 return Dali::Actor::New();
263 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
265 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
266 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
267 SignalConnectorType signalConnector3( mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal );
268 SignalConnectorType signalConnector4( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
269 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
270 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
271 SignalConnectorType signalConnector7( mType, SIGNAL_TOUCH, &Actor::DoConnectSignal );
273 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
274 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
279 const Vector3& value;
282 DALI_ENUM_TO_STRING_TABLE_BEGIN_WITH_TYPE( AnchorValue, ANCHOR_CONSTANT )
283 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_LEFT )
284 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_CENTER )
285 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_RIGHT )
286 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_LEFT )
287 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER )
288 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_RIGHT )
289 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_LEFT )
290 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_CENTER )
291 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_RIGHT )
292 DALI_ENUM_TO_STRING_TABLE_END( ANCHOR_CONSTANT )
294 DALI_ENUM_TO_STRING_TABLE_BEGIN( COLOR_MODE )
295 DALI_ENUM_TO_STRING( USE_OWN_COLOR )
296 DALI_ENUM_TO_STRING( USE_PARENT_COLOR )
297 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_COLOR )
298 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_ALPHA )
299 DALI_ENUM_TO_STRING_TABLE_END( COLOR_MODE )
301 DALI_ENUM_TO_STRING_TABLE_BEGIN( POSITION_INHERITANCE_MODE )
302 DALI_ENUM_TO_STRING( INHERIT_PARENT_POSITION )
303 DALI_ENUM_TO_STRING( USE_PARENT_POSITION )
304 DALI_ENUM_TO_STRING( USE_PARENT_POSITION_PLUS_LOCAL_POSITION )
305 DALI_ENUM_TO_STRING( DONT_INHERIT_POSITION )
306 DALI_ENUM_TO_STRING_TABLE_END( POSITION_INHERITANCE_MODE )
308 DALI_ENUM_TO_STRING_TABLE_BEGIN( DRAW_MODE )
309 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, NORMAL )
310 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, OVERLAY_2D )
311 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, STENCIL )
312 DALI_ENUM_TO_STRING_TABLE_END( DRAW_MODE )
314 DALI_ENUM_TO_STRING_TABLE_BEGIN( RESIZE_POLICY )
315 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIXED )
316 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_NATURAL_SIZE )
317 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FILL_TO_PARENT )
318 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_RELATIVE_TO_PARENT )
319 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_FIXED_OFFSET_FROM_PARENT )
320 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIT_TO_CHILDREN )
321 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, DIMENSION_DEPENDENCY )
322 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_ASSIGNED_SIZE )
323 DALI_ENUM_TO_STRING_TABLE_END( RESIZE_POLICY )
325 DALI_ENUM_TO_STRING_TABLE_BEGIN( SIZE_SCALE_POLICY )
326 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, USE_SIZE_SET )
327 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FIT_WITH_ASPECT_RATIO )
328 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FILL_WITH_ASPECT_RATIO )
329 DALI_ENUM_TO_STRING_TABLE_END( SIZE_SCALE_POLICY )
331 DALI_ENUM_TO_STRING_TABLE_BEGIN( CLIPPING_MODE )
332 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, DISABLED )
333 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, CLIP_CHILDREN )
334 DALI_ENUM_TO_STRING_TABLE_END( CLIPPING_MODE )
337 bool GetAnchorPointConstant( const std::string& value, Vector3& anchor )
339 for( unsigned int i = 0; i < ANCHOR_CONSTANT_TABLE_COUNT; ++i )
341 size_t sizeIgnored = 0;
342 if( CompareTokens( value.c_str(), ANCHOR_CONSTANT_TABLE[ i ].name, sizeIgnored ) )
344 anchor = ANCHOR_CONSTANT_TABLE[ i ].value;
351 inline bool GetParentOriginConstant( const std::string& value, Vector3& parentOrigin )
353 // Values are the same so just use the same table as anchor-point
354 return GetAnchorPointConstant( value, parentOrigin );
358 * @brief Extract a given dimension from a Vector2
360 * @param[in] values The values to extract from
361 * @param[in] dimension The dimension to extract
362 * @return Return the value for the dimension
364 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
368 case Dimension::WIDTH:
372 case Dimension::HEIGHT:
374 return values.height;
385 * @brief Extract a given dimension from a Vector3
387 * @param[in] values The values to extract from
388 * @param[in] dimension The dimension to extract
389 * @return Return the value for the dimension
391 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
393 return GetDimensionValue( values.GetVectorXY(), dimension );
397 * @brief Recursively emits the visibility-changed-signal on the actor tree.
398 * @param[in] actor The actor to emit the signal on
399 * @param[in] visible The new visibility of the actor
400 * @param[in] type Whether the actor's visible property has changed or a parent's
402 void EmitVisibilityChangedSignalRecursively( ActorPtr actor, bool visible, DevelActor::VisibilityChange::Type type )
406 actor->EmitVisibilityChangedSignal( visible, type );
408 if( actor->GetChildCount() > 0 )
410 ActorContainer& children = actor->GetChildrenInternal();
411 for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter )
413 EmitVisibilityChangedSignalRecursively( *iter, visible, DevelActor::VisibilityChange::PARENT );
419 } // unnamed namespace
421 ActorPtr Actor::New()
423 ActorPtr actor( new Actor( BASIC ) );
425 // Second-phase construction
431 const std::string& Actor::GetName() const
436 void Actor::SetName( const std::string& name )
442 // ATTENTION: string for debug purposes is not thread safe.
443 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
447 unsigned int Actor::GetId() const
452 bool Actor::OnStage() const
457 Dali::Layer Actor::GetLayer()
461 // Short-circuit for Layer derived actors
464 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
467 // Find the immediate Layer parent
468 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
470 if( parent->IsLayer() )
472 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
479 void Actor::Add( Actor& child )
481 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
482 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
486 mChildren = new ActorContainer;
489 Actor* const oldParent( child.mParent );
491 // child might already be ours
492 if( this != oldParent )
494 // if we already have parent, unparent us first
497 oldParent->Remove( child ); // This causes OnChildRemove callback
499 // Old parent may need to readjust to missing child
500 if( oldParent->RelayoutDependentOnChildren() )
502 oldParent->RelayoutRequest();
506 // Guard against Add() during previous OnChildRemove callback
509 // Do this first, since user callbacks from within SetParent() may need to remove child
510 mChildren->push_back( ActorPtr( &child ) );
512 // SetParent asserts that child can be added
513 child.SetParent( this );
515 // Notification for derived classes
518 // Only put in a relayout request if there is a suitable dependency
519 if( RelayoutDependentOnChildren() )
527 void Actor::Remove( Actor& child )
529 if( (this == &child) || (!mChildren) )
531 // no children or removing itself
537 // Find the child in mChildren, and unparent it
538 ActorIter end = mChildren->end();
539 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
541 ActorPtr actor = (*iter);
543 if( actor.Get() == &child )
545 // Keep handle for OnChildRemove notification
548 // Do this first, since user callbacks from within SetParent() may need to add the child
549 mChildren->erase( iter );
551 DALI_ASSERT_DEBUG( actor->GetParent() == this );
552 actor->SetParent( NULL );
560 // Only put in a relayout request if there is a suitable dependency
561 if( RelayoutDependentOnChildren() )
567 // Notification for derived classes
568 OnChildRemove( child );
571 void Actor::Unparent()
575 // Remove this actor from the parent. The remove will put a relayout request in for
576 // the parent if required
577 mParent->Remove( *this );
578 // mParent is now NULL!
582 unsigned int Actor::GetChildCount() const
584 return ( NULL != mChildren ) ? mChildren->size() : 0;
587 ActorPtr Actor::GetChildAt( unsigned int index ) const
589 DALI_ASSERT_ALWAYS( index < GetChildCount() );
591 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
594 ActorPtr Actor::FindChildByName( const std::string& actorName )
597 if( actorName == mName )
603 ActorIter end = mChildren->end();
604 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
606 child = (*iter)->FindChildByName( actorName );
617 ActorPtr Actor::FindChildById( const unsigned int id )
626 ActorIter end = mChildren->end();
627 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
629 child = (*iter)->FindChildById( id );
640 void Actor::SetParentOrigin( const Vector3& origin )
644 // mNode is being used in a separate thread; queue a message to set the value & base value
645 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
648 // Cache for event-thread access
651 // not allocated, check if different from default
652 if( ParentOrigin::DEFAULT != origin )
654 mParentOrigin = new Vector3( origin );
659 // check if different from current costs more than just set
660 *mParentOrigin = origin;
664 void Actor::SetParentOriginX( float x )
666 const Vector3& current = GetCurrentParentOrigin();
668 SetParentOrigin( Vector3( x, current.y, current.z ) );
671 void Actor::SetParentOriginY( float y )
673 const Vector3& current = GetCurrentParentOrigin();
675 SetParentOrigin( Vector3( current.x, y, current.z ) );
678 void Actor::SetParentOriginZ( float z )
680 const Vector3& current = GetCurrentParentOrigin();
682 SetParentOrigin( Vector3( current.x, current.y, z ) );
685 const Vector3& Actor::GetCurrentParentOrigin() const
687 // Cached for event-thread access
688 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
691 void Actor::SetAnchorPoint( const Vector3& anchor )
695 // mNode is being used in a separate thread; queue a message to set the value & base value
696 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
699 // Cache for event-thread access
702 // not allocated, check if different from default
703 if( AnchorPoint::DEFAULT != anchor )
705 mAnchorPoint = new Vector3( anchor );
710 // check if different from current costs more than just set
711 *mAnchorPoint = anchor;
715 void Actor::SetAnchorPointX( float x )
717 const Vector3& current = GetCurrentAnchorPoint();
719 SetAnchorPoint( Vector3( x, current.y, current.z ) );
722 void Actor::SetAnchorPointY( float y )
724 const Vector3& current = GetCurrentAnchorPoint();
726 SetAnchorPoint( Vector3( current.x, y, current.z ) );
729 void Actor::SetAnchorPointZ( float z )
731 const Vector3& current = GetCurrentAnchorPoint();
733 SetAnchorPoint( Vector3( current.x, current.y, z ) );
736 const Vector3& Actor::GetCurrentAnchorPoint() const
738 // Cached for event-thread access
739 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
742 void Actor::SetPosition( float x, float y )
744 SetPosition( Vector3( x, y, 0.0f ) );
747 void Actor::SetPosition( float x, float y, float z )
749 SetPosition( Vector3( x, y, z ) );
752 void Actor::SetPosition( const Vector3& position )
754 mTargetPosition = position;
758 // mNode is being used in a separate thread; queue a message to set the value & base value
759 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
763 void Actor::SetX( float x )
765 mTargetPosition.x = x;
769 // mNode is being used in a separate thread; queue a message to set the value & base value
770 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
774 void Actor::SetY( float y )
776 mTargetPosition.y = y;
780 // mNode is being used in a separate thread; queue a message to set the value & base value
781 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
785 void Actor::SetZ( float z )
787 mTargetPosition.z = z;
791 // mNode is being used in a separate thread; queue a message to set the value & base value
792 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
796 void Actor::TranslateBy( const Vector3& distance )
798 mTargetPosition += distance;
802 // mNode is being used in a separate thread; queue a message to set the value & base value
803 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
807 const Vector3& Actor::GetCurrentPosition() const
811 // mNode is being used in a separate thread; copy the value from the previous update
812 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
815 return Vector3::ZERO;
818 const Vector3& Actor::GetTargetPosition() const
820 return mTargetPosition;
823 const Vector3& Actor::GetCurrentWorldPosition() const
827 // mNode is being used in a separate thread; copy the value from the previous update
828 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
831 return Vector3::ZERO;
834 const Vector2 Actor::GetCurrentScreenPosition() const
836 if( OnStage() && NULL != mNode )
838 StagePtr stage = Stage::GetCurrent();
839 Vector3 worldPosition = mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
840 Vector3 actorSize = GetCurrentSize() * GetCurrentScale();
841 Vector2 halfStageSize( stage->GetSize() * 0.5f ); // World position origin is center of stage
842 Vector3 halfActorSize( actorSize * 0.5f );
843 Vector3 anchorPointOffSet = halfActorSize - actorSize * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
845 return Vector2( halfStageSize.width + worldPosition.x - anchorPointOffSet.x,
846 halfStageSize.height + worldPosition.y - anchorPointOffSet.y );
849 return Vector2::ZERO;
852 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
854 // this flag is not animatable so keep the value
855 mPositionInheritanceMode = mode;
858 // mNode is being used in a separate thread; queue a message to set the value
859 SetInheritPositionMessage( GetEventThreadServices(), *mNode, mode == INHERIT_PARENT_POSITION );
863 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
865 // Cached for event-thread access
866 return mPositionInheritanceMode;
869 void Actor::SetInheritPosition( bool inherit )
871 if( mInheritPosition != inherit && NULL != mNode )
873 // non animateable so keep local copy
874 mInheritPosition = inherit;
875 SetInheritPositionMessage( GetEventThreadServices(), *mNode, inherit );
879 bool Actor::IsPositionInherited() const
881 return mInheritPosition;
884 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
886 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
887 normalizedAxis.Normalize();
889 Quaternion orientation( angle, normalizedAxis );
891 SetOrientation( orientation );
894 void Actor::SetOrientation( const Quaternion& orientation )
896 mTargetOrientation = orientation;
900 // mNode is being used in a separate thread; queue a message to set the value & base value
901 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation );
905 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
907 RotateBy( Quaternion(angle, axis) );
910 void Actor::RotateBy( const Quaternion& relativeRotation )
912 mTargetOrientation *= Quaternion( relativeRotation );
916 // mNode is being used in a separate thread; queue a message to set the value & base value
917 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
921 const Quaternion& Actor::GetCurrentOrientation() const
925 // mNode is being used in a separate thread; copy the value from the previous update
926 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
929 return Quaternion::IDENTITY;
932 const Quaternion& Actor::GetCurrentWorldOrientation() const
936 // mNode is being used in a separate thread; copy the value from the previous update
937 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
940 return Quaternion::IDENTITY;
943 void Actor::SetScale( float scale )
945 SetScale( Vector3( scale, scale, scale ) );
948 void Actor::SetScale( float x, float y, float z )
950 SetScale( Vector3( x, y, z ) );
953 void Actor::SetScale( const Vector3& scale )
955 mTargetScale = scale;
959 // mNode is being used in a separate thread; queue a message to set the value & base value
960 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
964 void Actor::SetScaleX( float x )
970 // mNode is being used in a separate thread; queue a message to set the value & base value
971 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
975 void Actor::SetScaleY( float y )
981 // mNode is being used in a separate thread; queue a message to set the value & base value
982 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
986 void Actor::SetScaleZ( float z )
992 // mNode is being used in a separate thread; queue a message to set the value & base value
993 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
997 void Actor::ScaleBy(const Vector3& relativeScale)
999 mTargetScale *= relativeScale;
1003 // mNode is being used in a separate thread; queue a message to set the value & base value
1004 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
1008 const Vector3& Actor::GetCurrentScale() const
1012 // mNode is being used in a separate thread; copy the value from the previous update
1013 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
1016 return Vector3::ONE;
1019 const Vector3& Actor::GetCurrentWorldScale() const
1023 // mNode is being used in a separate thread; copy the value from the previous update
1024 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
1027 return Vector3::ONE;
1030 void Actor::SetInheritScale( bool inherit )
1033 if( mInheritScale != inherit && NULL != mNode )
1035 // non animateable so keep local copy
1036 mInheritScale = inherit;
1037 // mNode is being used in a separate thread; queue a message to set the value
1038 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
1042 bool Actor::IsScaleInherited() const
1044 return mInheritScale;
1047 Matrix Actor::GetCurrentWorldMatrix() const
1051 return mNode->GetWorldMatrix(0);
1054 return Matrix::IDENTITY;
1057 void Actor::SetVisible( bool visible )
1059 SetVisibleInternal( visible, SendMessage::TRUE );
1062 bool Actor::IsVisible() const
1066 // mNode is being used in a separate thread; copy the value from the previous update
1067 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
1073 void Actor::SetOpacity( float opacity )
1075 mTargetColor.a = opacity;
1079 // mNode is being used in a separate thread; queue a message to set the value & base value
1080 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
1084 float Actor::GetCurrentOpacity() const
1088 // mNode is being used in a separate thread; copy the value from the previous update
1089 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1095 ClippingMode::Type Actor::GetClippingMode() const
1097 return mClippingMode;
1100 unsigned int Actor::GetSortingDepth()
1102 return mSortedDepth;
1105 const Vector4& Actor::GetCurrentWorldColor() const
1109 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1112 return Color::WHITE;
1115 void Actor::SetColor( const Vector4& color )
1117 mTargetColor = color;
1121 // mNode is being used in a separate thread; queue a message to set the value & base value
1122 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1126 void Actor::SetColorRed( float red )
1128 mTargetColor.r = red;
1132 // mNode is being used in a separate thread; queue a message to set the value & base value
1133 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1137 void Actor::SetColorGreen( float green )
1139 mTargetColor.g = green;
1143 // mNode is being used in a separate thread; queue a message to set the value & base value
1144 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1148 void Actor::SetColorBlue( float blue )
1150 mTargetColor.b = blue;
1154 // mNode is being used in a separate thread; queue a message to set the value & base value
1155 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1159 const Vector4& Actor::GetCurrentColor() const
1163 // mNode is being used in a separate thread; copy the value from the previous update
1164 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1167 return Color::WHITE;
1170 void Actor::SetInheritOrientation( bool inherit )
1172 if( mInheritOrientation != inherit && NULL != mNode)
1174 // non animateable so keep local copy
1175 mInheritOrientation = inherit;
1176 // mNode is being used in a separate thread; queue a message to set the value
1177 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1181 bool Actor::IsOrientationInherited() const
1183 return mInheritOrientation;
1186 void Actor::SetSizeModeFactor( const Vector3& factor )
1188 EnsureRelayoutData();
1190 mRelayoutData->sizeModeFactor = factor;
1193 const Vector3& Actor::GetSizeModeFactor() const
1195 if ( mRelayoutData )
1197 return mRelayoutData->sizeModeFactor;
1200 return GetDefaultSizeModeFactor();
1203 void Actor::SetColorMode( ColorMode colorMode )
1205 // non animateable so keep local copy
1206 mColorMode = colorMode;
1209 // mNode is being used in a separate thread; queue a message to set the value
1210 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1214 ColorMode Actor::GetColorMode() const
1216 // we have cached copy
1220 void Actor::SetSize( float width, float height )
1222 SetSize( Vector2( width, height ) );
1225 void Actor::SetSize( float width, float height, float depth )
1227 SetSize( Vector3( width, height, depth ) );
1230 void Actor::SetSize( const Vector2& size )
1232 SetSize( Vector3( size.width, size.height, 0.f ) );
1235 void Actor::SetSizeInternal( const Vector2& size )
1237 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1240 void Actor::SetSize( const Vector3& size )
1242 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1244 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1245 SetPreferredSize( size.GetVectorXY() );
1249 SetSizeInternal( size );
1253 void Actor::SetSizeInternal( const Vector3& size )
1255 // dont allow recursive loop
1256 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1257 // 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
1258 if( ( NULL != mNode )&&
1259 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1260 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1261 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1265 // mNode is being used in a separate thread; queue a message to set the value & base value
1266 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
1268 // Notification for derived classes
1269 mInsideOnSizeSet = true;
1270 OnSizeSet( mTargetSize );
1271 mInsideOnSizeSet = false;
1273 // Raise a relayout request if the flag is not locked
1274 if( mRelayoutData && !mRelayoutData->insideRelayout )
1281 void Actor::SetWidth( float width )
1283 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1285 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
1286 mRelayoutData->preferredSize.width = width;
1290 mTargetSize.width = width;
1294 // mNode is being used in a separate thread; queue a message to set the value & base value
1295 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1302 void Actor::SetHeight( float height )
1304 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1306 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
1307 mRelayoutData->preferredSize.height = height;
1311 mTargetSize.height = height;
1315 // mNode is being used in a separate thread; queue a message to set the value & base value
1316 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1323 void Actor::SetDepth( float depth )
1325 mTargetSize.depth = depth;
1329 // mNode is being used in a separate thread; queue a message to set the value & base value
1330 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1334 Vector3 Actor::GetTargetSize() const
1336 Vector3 size = mTargetSize;
1338 // Should return preferred size if size is fixed as set by SetSize
1339 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
1341 size.width = GetPreferredSize().width;
1343 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
1345 size.height = GetPreferredSize().height;
1351 const Vector3& Actor::GetCurrentSize() const
1355 // mNode is being used in a separate thread; copy the value from the previous update
1356 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1359 return Vector3::ZERO;
1362 Vector3 Actor::GetNaturalSize() const
1364 // It is up to deriving classes to return the appropriate natural size
1365 return Vector3( 0.0f, 0.0f, 0.0f );
1368 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1370 EnsureRelayoutData();
1372 ResizePolicy::Type originalWidthPolicy = GetResizePolicy(Dimension::WIDTH);
1373 ResizePolicy::Type originalHeightPolicy = GetResizePolicy(Dimension::HEIGHT);
1375 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1377 if( dimension & ( 1 << i ) )
1379 if ( policy == ResizePolicy::USE_ASSIGNED_SIZE )
1381 mRelayoutData->useAssignedSize[ i ] = true;
1385 mRelayoutData->resizePolicies[ i ] = policy;
1386 mRelayoutData->useAssignedSize[ i ] = false;
1391 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1393 if( dimension & Dimension::WIDTH )
1395 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1398 if( dimension & Dimension::HEIGHT )
1400 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1404 // If calling SetResizePolicy, assume we want relayout enabled
1405 SetRelayoutEnabled( true );
1407 // If the resize policy is set to be FIXED, the preferred size
1408 // should be overrided by the target size. Otherwise the target
1409 // size should be overrided by the preferred size.
1411 if( dimension & Dimension::WIDTH )
1413 if( originalWidthPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1415 mRelayoutData->preferredSize.width = mTargetSize.width;
1417 else if( originalWidthPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1419 mTargetSize.width = mRelayoutData->preferredSize.width;
1423 if( dimension & Dimension::HEIGHT )
1425 if( originalHeightPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1427 mRelayoutData->preferredSize.height = mTargetSize.height;
1429 else if( originalHeightPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1431 mTargetSize.height = mRelayoutData->preferredSize.height;
1435 OnSetResizePolicy( policy, dimension );
1437 // Trigger relayout on this control
1441 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1443 if ( mRelayoutData )
1445 // If more than one dimension is requested, just return the first one found
1446 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1448 if( ( dimension & ( 1 << i ) ) )
1450 if( mRelayoutData->useAssignedSize[ i ] )
1452 return ResizePolicy::USE_ASSIGNED_SIZE;
1456 return mRelayoutData->resizePolicies[ i ];
1462 return ResizePolicy::DEFAULT;
1465 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1467 EnsureRelayoutData();
1469 mRelayoutData->sizeSetPolicy = policy;
1472 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1474 if ( mRelayoutData )
1476 return mRelayoutData->sizeSetPolicy;
1479 return DEFAULT_SIZE_SCALE_POLICY;
1482 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1484 EnsureRelayoutData();
1486 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1488 if( dimension & ( 1 << i ) )
1490 mRelayoutData->dimensionDependencies[ i ] = dependency;
1495 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1497 if ( mRelayoutData )
1499 // If more than one dimension is requested, just return the first one found
1500 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1502 if( ( dimension & ( 1 << i ) ) )
1504 return mRelayoutData->dimensionDependencies[ i ];
1509 return Dimension::ALL_DIMENSIONS; // Default
1512 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1514 // If relayout data has not been allocated yet and the client is requesting
1515 // to disable it, do nothing
1516 if( mRelayoutData || relayoutEnabled )
1518 EnsureRelayoutData();
1520 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1522 mRelayoutData->relayoutEnabled = relayoutEnabled;
1526 bool Actor::IsRelayoutEnabled() const
1528 // Assume that if relayout data has not been allocated yet then
1529 // relayout is disabled
1530 return mRelayoutData && mRelayoutData->relayoutEnabled;
1533 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1535 EnsureRelayoutData();
1537 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1539 if( dimension & ( 1 << i ) )
1541 mRelayoutData->dimensionDirty[ i ] = dirty;
1546 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1548 if ( mRelayoutData )
1550 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1552 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1562 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1564 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1567 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1569 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1572 unsigned int Actor::AddRenderer( Renderer& renderer )
1576 mRenderers = new RendererContainer;
1579 unsigned int index = mRenderers->size();
1580 RendererPtr rendererPtr = RendererPtr( &renderer );
1581 mRenderers->push_back( rendererPtr );
1582 AddRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1586 unsigned int Actor::GetRendererCount() const
1588 unsigned int rendererCount(0);
1591 rendererCount = mRenderers->size();
1594 return rendererCount;
1597 RendererPtr Actor::GetRendererAt( unsigned int index )
1599 RendererPtr renderer;
1600 if( index < GetRendererCount() )
1602 renderer = ( *mRenderers )[ index ];
1608 void Actor::RemoveRenderer( Renderer& renderer )
1612 RendererIter end = mRenderers->end();
1613 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1615 if( (*iter).Get() == &renderer )
1617 mRenderers->erase( iter );
1618 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1625 void Actor::RemoveRenderer( unsigned int index )
1627 if( index < GetRendererCount() )
1629 RendererPtr renderer = ( *mRenderers )[ index ];
1630 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.Get()->GetRendererSceneObject() );
1631 mRenderers->erase( mRenderers->begin()+index );
1635 bool Actor::IsOverlay() const
1637 return ( DrawMode::OVERLAY_2D == mDrawMode );
1640 void Actor::SetDrawMode( DrawMode::Type drawMode )
1642 // this flag is not animatable so keep the value
1643 mDrawMode = drawMode;
1644 if( ( NULL != mNode ) && ( drawMode != DrawMode::STENCIL ) )
1646 // mNode is being used in a separate thread; queue a message to set the value
1647 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1651 DrawMode::Type Actor::GetDrawMode() const
1656 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1658 // only valid when on-stage
1659 StagePtr stage = Stage::GetCurrent();
1660 if( stage && OnStage() )
1662 const RenderTaskList& taskList = stage->GetRenderTaskList();
1664 Vector2 converted( screenX, screenY );
1666 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1667 const int taskCount = taskList.GetTaskCount();
1668 for( int i = taskCount - 1; i >= 0; --i )
1670 Dali::RenderTask task = taskList.GetTask( i );
1671 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1673 // found a task where this conversion was ok so return
1681 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1683 bool retval = false;
1684 // only valid when on-stage
1687 CameraActor* camera = renderTask.GetCameraActor();
1691 renderTask.GetViewport( viewport );
1693 // need to translate coordinates to render tasks coordinate space
1694 Vector2 converted( screenX, screenY );
1695 if( renderTask.TranslateCoordinates( converted ) )
1697 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1704 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1706 // Early-out if mNode is NULL
1712 // Get the ModelView matrix
1714 Matrix::Multiply( modelView, mNode->GetWorldMatrix(0), viewMatrix );
1716 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1717 Matrix invertedMvp( false/*don't init*/);
1718 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1719 bool success = invertedMvp.Invert();
1721 // Convert to GL coordinates
1722 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1727 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1734 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1740 if( XyPlaneIntersect( nearPos, farPos, local ) )
1742 Vector3 size = GetCurrentSize();
1743 localX = local.x + size.x * 0.5f;
1744 localY = local.y + size.y * 0.5f;
1755 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1758 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1760 Mathematical Formulation
1762 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1764 ( p - c ) dot ( p - c ) = r^2
1766 Given a ray with a point of origin 'o', and a direction vector 'd':
1768 ray(t) = o + td, t >= 0
1770 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1772 (o + td - c ) dot ( o + td - c ) = r^2
1774 To solve for t we first expand the above into a more recognisable quadratic equation form
1776 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1785 B = 2( o - c ) dot d
1786 C = ( o - c ) dot ( o - c ) - r^2
1788 which can be solved using a standard quadratic formula.
1790 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1792 Practical Simplification
1794 In a renderer, we often differentiate between world space and object space. In the object space
1795 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1796 into object space, the mathematical solution presented above can be simplified significantly.
1798 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1802 and we can find the t at which the (transformed) ray intersects the sphere by
1804 ( o + td ) dot ( o + td ) = r^2
1806 According to the reasoning above, we expand the above quadratic equation into the general form
1810 which now has coefficients:
1817 // Early out if mNode is NULL
1823 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1825 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1826 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1827 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1829 // Compute the radius is not needed, square radius it's enough.
1830 const Vector3& size( mNode->GetSize( bufferIndex ) );
1832 // Scale the sphere.
1833 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1835 const float width = size.width * scale.width;
1836 const float height = size.height * scale.height;
1838 float squareSphereRadius = 0.5f * ( width * width + height * height );
1840 float a = rayDir.Dot( rayDir ); // a
1841 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1842 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1844 return ( b2 * b2 - a * c ) >= 0.f;
1847 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector2& hitPointLocal, float& distance ) const
1851 if( OnStage() && NULL != mNode )
1853 // Transforms the ray to the local reference system.
1854 // Calculate the inverse of Model matrix
1855 Matrix invModelMatrix( false/*don't init*/);
1857 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1858 invModelMatrix = mNode->GetWorldMatrix(0);
1859 invModelMatrix.Invert();
1861 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1862 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1864 // Test with the actor's XY plane (Normal = 0 0 1 1).
1866 float a = -rayOriginLocal.z;
1867 float b = rayDirLocal.z;
1869 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1871 // Ray travels distance * rayDirLocal to intersect with plane.
1874 const Vector3& size = mNode->GetSize( bufferIndex );
1876 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1877 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1879 // Test with the actor's geometry.
1880 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1887 void Actor::SetLeaveRequired( bool required )
1889 mLeaveRequired = required;
1892 bool Actor::GetLeaveRequired() const
1894 return mLeaveRequired;
1897 void Actor::SetKeyboardFocusable( bool focusable )
1899 mKeyboardFocusable = focusable;
1902 bool Actor::IsKeyboardFocusable() const
1904 return mKeyboardFocusable;
1907 bool Actor::GetTouchRequired() const
1909 return !mTouchedSignal.Empty() || !mTouchSignal.Empty() || mDerivedRequiresTouch;
1912 bool Actor::GetHoverRequired() const
1914 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1917 bool Actor::GetWheelEventRequired() const
1919 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1922 bool Actor::IsHittable() const
1924 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1927 ActorGestureData& Actor::GetGestureData()
1929 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1930 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1931 if( NULL == mGestureData )
1933 mGestureData = new ActorGestureData;
1935 return *mGestureData;
1938 bool Actor::IsGestureRequred( Gesture::Type type ) const
1940 return mGestureData && mGestureData->IsGestureRequred( type );
1943 bool Actor::EmitTouchEventSignal( const TouchEvent& event, const Dali::TouchData& touch )
1945 bool consumed = false;
1947 if( !mTouchSignal.Empty() )
1949 Dali::Actor handle( this );
1950 consumed = mTouchSignal.Emit( handle, touch );
1953 if( !mTouchedSignal.Empty() )
1955 Dali::Actor handle( this );
1956 consumed |= mTouchedSignal.Emit( handle, event );
1961 // Notification for derived classes
1962 consumed = OnTouchEvent( event ); // TODO
1968 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1970 bool consumed = false;
1972 if( !mHoveredSignal.Empty() )
1974 Dali::Actor handle( this );
1975 consumed = mHoveredSignal.Emit( handle, event );
1980 // Notification for derived classes
1981 consumed = OnHoverEvent( event );
1987 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1989 bool consumed = false;
1991 if( !mWheelEventSignal.Empty() )
1993 Dali::Actor handle( this );
1994 consumed = mWheelEventSignal.Emit( handle, event );
1999 // Notification for derived classes
2000 consumed = OnWheelEvent( event );
2006 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
2008 if( ! mVisibilityChangedSignal.Empty() )
2010 Dali::Actor handle( this );
2011 mVisibilityChangedSignal.Emit( handle, visible, type );
2015 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
2017 return mTouchedSignal;
2020 Dali::Actor::TouchDataSignalType& Actor::TouchSignal()
2022 return mTouchSignal;
2025 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
2027 return mHoveredSignal;
2030 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
2032 return mWheelEventSignal;
2035 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
2037 return mOnStageSignal;
2040 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
2042 return mOffStageSignal;
2045 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
2047 return mOnRelayoutSignal;
2050 DevelActor::VisibilityChangedSignalType& Actor::VisibilityChangedSignal()
2052 return mVisibilityChangedSignal;
2055 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
2057 bool connected( true );
2058 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
2060 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
2062 actor->TouchedSignal().Connect( tracker, functor );
2064 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
2066 actor->HoveredSignal().Connect( tracker, functor );
2068 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
2070 actor->WheelEventSignal().Connect( tracker, functor );
2072 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
2074 actor->OnStageSignal().Connect( tracker, functor );
2076 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
2078 actor->OffStageSignal().Connect( tracker, functor );
2080 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
2082 actor->OnRelayoutSignal().Connect( tracker, functor );
2084 else if( 0 == signalName.compare( SIGNAL_TOUCH ) )
2086 actor->TouchSignal().Connect( tracker, functor );
2090 // signalName does not match any signal
2097 Actor::Actor( DerivedType derivedType )
2102 mParentOrigin( NULL ),
2103 mAnchorPoint( NULL ),
2104 mRelayoutData( NULL ),
2105 mGestureData( NULL ),
2106 mTargetOrientation( Quaternion::IDENTITY ),
2107 mTargetColor( Color::WHITE ),
2108 mTargetSize( Vector3::ZERO ),
2109 mTargetPosition( Vector3::ZERO ),
2110 mTargetScale( Vector3::ONE ),
2112 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
2116 mIsRoot( ROOT_LAYER == derivedType ),
2117 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2118 mIsOnStage( false ),
2120 mLeaveRequired( false ),
2121 mKeyboardFocusable( false ),
2122 mDerivedRequiresTouch( false ),
2123 mDerivedRequiresHover( false ),
2124 mDerivedRequiresWheelEvent( false ),
2125 mOnStageSignalled( false ),
2126 mInsideOnSizeSet( false ),
2127 mInheritPosition( true ),
2128 mInheritOrientation( true ),
2129 mInheritScale( true ),
2130 mPositionUsesAnchorPoint( true ),
2132 mDrawMode( DrawMode::NORMAL ),
2133 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2134 mColorMode( Node::DEFAULT_COLOR_MODE ),
2135 mClippingMode( ClippingMode::DISABLED )
2139 void Actor::Initialize()
2142 SceneGraph::Node* node = CreateNode();
2144 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
2145 mNode = node; // Keep raw-pointer to Node
2149 GetEventThreadServices().RegisterObject( this );
2154 // Remove mParent pointers from children even if we're destroying core,
2155 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2158 ActorConstIter endIter = mChildren->end();
2159 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2161 (*iter)->SetParent( NULL );
2167 // Guard to allow handle destruction after Core has been destroyed
2168 if( EventThreadServices::IsCoreRunning() )
2172 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2173 mNode = NULL; // Node is about to be destroyed
2176 GetEventThreadServices().UnregisterObject( this );
2179 // Cleanup optional gesture data
2180 delete mGestureData;
2182 // Cleanup optional parent origin and anchor
2183 delete mParentOrigin;
2184 delete mAnchorPoint;
2186 // Delete optional relayout data
2189 delete mRelayoutData;
2193 void Actor::ConnectToStage( unsigned int parentDepth )
2195 // This container is used instead of walking the Actor hierarchy.
2196 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
2197 ActorContainer connectionList;
2199 StagePtr stage = Stage::GetCurrent();
2202 stage->RequestRebuildDepthTree();
2205 // This stage is atomic i.e. not interrupted by user callbacks.
2206 RecursiveConnectToStage( connectionList, parentDepth + 1 );
2208 // Notify applications about the newly connected actors.
2209 const ActorIter endIter = connectionList.end();
2210 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2212 (*iter)->NotifyStageConnection();
2218 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth )
2220 DALI_ASSERT_ALWAYS( !OnStage() );
2225 ConnectToSceneGraph();
2227 // Notification for internal derived classes
2228 OnStageConnectionInternal();
2230 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2231 connectionList.push_back( ActorPtr( this ) );
2233 // Recursively connect children
2236 ActorConstIter endIter = mChildren->end();
2237 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2239 (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
2245 * This method is called when the Actor is connected to the Stage.
2246 * The parent must have added its Node to the scene-graph.
2247 * The child must connect its Node to the parent's Node.
2248 * This is recursive; the child calls ConnectToStage() for its children.
2250 void Actor::ConnectToSceneGraph()
2252 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2256 // Reparent Node in next Update
2257 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode );
2260 // Request relayout on all actors that are added to the scenegraph
2263 // Notification for Object::Observers
2267 void Actor::NotifyStageConnection()
2269 // Actors can be removed (in a callback), before the on-stage stage is reported.
2270 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2271 if( OnStage() && !mOnStageSignalled )
2273 // Notification for external (CustomActor) derived classes
2274 OnStageConnectionExternal( mDepth );
2276 if( !mOnStageSignal.Empty() )
2278 Dali::Actor handle( this );
2279 mOnStageSignal.Emit( handle );
2282 // Guard against Remove during callbacks
2285 mOnStageSignalled = true; // signal required next time Actor is removed
2290 void Actor::DisconnectFromStage()
2292 // This container is used instead of walking the Actor hierachy.
2293 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2294 ActorContainer disconnectionList;
2296 StagePtr stage = Stage::GetCurrent();
2299 stage->RequestRebuildDepthTree();
2302 // This stage is atomic i.e. not interrupted by user callbacks
2303 RecursiveDisconnectFromStage( disconnectionList );
2305 // Notify applications about the newly disconnected actors.
2306 const ActorIter endIter = disconnectionList.end();
2307 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2309 (*iter)->NotifyStageDisconnection();
2313 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2315 DALI_ASSERT_ALWAYS( OnStage() );
2317 // Recursively disconnect children
2320 ActorConstIter endIter = mChildren->end();
2321 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2323 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2327 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2328 disconnectionList.push_back( ActorPtr( this ) );
2330 // Notification for internal derived classes
2331 OnStageDisconnectionInternal();
2333 DisconnectFromSceneGraph();
2339 * This method is called by an actor or its parent, before a node removal message is sent.
2340 * This is recursive; the child calls DisconnectFromStage() for its children.
2342 void Actor::DisconnectFromSceneGraph()
2344 // Notification for Object::Observers
2345 OnSceneObjectRemove();
2348 void Actor::NotifyStageDisconnection()
2350 // Actors can be added (in a callback), before the off-stage state is reported.
2351 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2352 // only do this step if there is a stage, i.e. Core is not being shut down
2353 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2355 // Notification for external (CustomeActor) derived classes
2356 OnStageDisconnectionExternal();
2358 if( !mOffStageSignal.Empty() )
2360 Dali::Actor handle( this );
2361 mOffStageSignal.Emit( handle );
2364 // Guard against Add during callbacks
2367 mOnStageSignalled = false; // signal required next time Actor is added
2372 bool Actor::IsNodeConnected() const
2374 bool connected( false );
2376 if( OnStage() && ( NULL != mNode ) )
2378 if( IsRoot() || mNode->GetParent() )
2387 // This method generates the depth tree using the recursive function below,
2388 // then walks the tree and sets a depth index based on traversal order. It
2389 // sends a single message to update manager to update all the actor's nodes in this
2390 // tree with the depth index. The sceneGraphNodeDepths vector's elements are ordered
2391 // by depth, and could be used to reduce sorting in the update thread.
2392 void Actor::RebuildDepthTree()
2394 DALI_LOG_TIMER_START(depthTimer);
2396 DepthNodeMemoryPool nodeMemoryPool;
2397 ActorDepthTreeNode* rootNode = new (nodeMemoryPool.AllocateRaw()) ActorDepthTreeNode( this, mSiblingOrder );
2399 int actorCount = BuildDepthTree( nodeMemoryPool, rootNode );
2401 // Vector of scene-graph nodes and their depths to send to UpdateManager
2402 // in a single message
2403 SceneGraph::NodeDepths* sceneGraphNodeDepths = new SceneGraph::NodeDepths(actorCount);
2405 // Traverse depth tree and set mSortedDepth on each actor and scenegraph node
2406 uint32_t sortOrder = 1u; // Don't start at zero, as visual depth can be negative
2407 ActorDepthTreeNode* currentNode = rootNode;
2408 bool firstVisit = true;
2409 while( currentNode != rootNode || firstVisit)
2413 // Visit node, performing action
2414 for( std::vector<Actor*>::iterator iter = currentNode->mActors.begin(); iter != currentNode->mActors.end(); ++iter )
2416 (*iter)->mSortedDepth = sortOrder * DevelLayer::SIBLING_ORDER_MULTIPLIER;
2417 sceneGraphNodeDepths->Add( const_cast<SceneGraph::Node*>((*iter)->mNode), (*iter)->mSortedDepth );
2422 if( currentNode->mFirstChildNode )
2424 currentNode = currentNode->mFirstChildNode;
2426 else // leaf node, goto next sibling, or return up tree.
2428 bool breakout=false;
2429 while( ! currentNode->mNextSiblingNode )
2431 if( currentNode == rootNode ) // If we get to root of tree, stop
2436 currentNode = currentNode->mParentNode;
2443 currentNode = currentNode->mNextSiblingNode;
2447 SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths );
2448 DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree create time: ");
2452 * Structure to store the actor's associated node in the depth tree for child
2455 struct ActorNodePair
2458 ActorDepthTreeNode* node;
2459 ActorNodePair( Actor* actor, ActorDepthTreeNode* node )
2467 * Descend actor tree, building a depth tree based on actor's sibling order.
2468 * Actors with the same sibling order share the same depth tree. Siblings
2469 * in the depth tree are ordered by actor's sibling order.
2471 * An actor tree like this:
2478 * A(SO:1) B(SO:2) C(SO:1)
2481 * D(SO:0) E(SO:0) F(SO:0) G(SO:1) H(SO:0)
2483 * will end up as a depth tree like this:
2485 * RootNode [ Root ] -> NULL
2488 * Node [ A, C ] ------------------------> Node [ B ] -> NULL
2491 * Node [ D, E, H ] -> Node [ G ] -> NULL Node [ F ] -> NULL
2496 * (All nodes also point to their parents to enable storage free traversal)
2498 int Actor::BuildDepthTree( DepthNodeMemoryPool& nodeMemoryPool, ActorDepthTreeNode* node )
2500 int treeCount=1; // Count self and children
2502 // Create/add to children of this node
2505 std::vector<ActorNodePair> storedChildren;
2506 storedChildren.reserve( mChildren->size() );
2508 for( ActorContainer::iterator it = mChildren->begin(); it != mChildren->end(); ++it )
2510 Actor* childActor = (*it).Get();
2511 if( childActor->IsLayer() )
2513 Layer* layer = static_cast<Layer*>(childActor);
2514 if( layer->GetBehavior() == Dali::Layer::LAYER_3D )
2516 // Ignore this actor and children.
2521 // If no existing depth node children
2522 if( node->mFirstChildNode == NULL )
2524 node->mFirstChildNode = new (nodeMemoryPool.AllocateRaw()) ActorDepthTreeNode( childActor, childActor->mSiblingOrder );
2525 node->mFirstChildNode->mParentNode = node;
2526 storedChildren.push_back(ActorNodePair( childActor, node->mFirstChildNode ));
2528 else // find child node with matching sibling order (insertion sort)
2530 bool addedChildActor = false;
2532 // depth tree child nodes ordered by sibling order
2533 ActorDepthTreeNode* lastNode = NULL;
2534 for( ActorDepthTreeNode* childNode = node->mFirstChildNode; childNode != NULL; childNode = childNode->mNextSiblingNode )
2536 uint16_t actorSiblingOrder = childActor->mSiblingOrder;
2537 uint16_t currentSiblingOrder = childNode->GetSiblingOrder();
2539 if( actorSiblingOrder == currentSiblingOrder )
2541 // Don't need a new depth node, add to existing node
2542 childNode->AddActor( childActor );
2543 storedChildren.push_back(ActorNodePair( childActor, childNode ));
2544 addedChildActor = true;
2547 else if( actorSiblingOrder < currentSiblingOrder )
2551 lastNode = childNode;
2554 // No matching sibling order - create new node and insert into sibling list
2555 if( !addedChildActor )
2557 ActorDepthTreeNode* newNode = new (nodeMemoryPool.AllocateRaw()) ActorDepthTreeNode( childActor, childActor->mSiblingOrder );
2559 newNode->mParentNode = node;
2560 storedChildren.push_back(ActorNodePair( childActor, newNode ));
2562 if( lastNode == NULL ) // Insert at start of siblings
2564 ActorDepthTreeNode* nextNode = node->mFirstChildNode;
2565 node->mFirstChildNode = newNode;
2566 newNode->mNextSiblingNode = nextNode;
2568 else // insert into siblings after last node
2570 newNode->mNextSiblingNode = lastNode->mNextSiblingNode;
2571 lastNode->mNextSiblingNode = newNode;
2577 // Order of descent doesn't matter; we're using insertion to sort.
2578 for( std::vector<ActorNodePair>::iterator iter = storedChildren.begin(); iter != storedChildren.end(); ++iter )
2580 treeCount += iter->actor->BuildDepthTree( nodeMemoryPool, iter->node );
2586 unsigned int Actor::GetDefaultPropertyCount() const
2588 return DEFAULT_PROPERTY_COUNT;
2591 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2593 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2595 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2597 indices.PushBack( i );
2601 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2603 if( index < DEFAULT_PROPERTY_COUNT )
2605 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2611 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2613 Property::Index index = Property::INVALID_INDEX;
2615 // Look for name in default properties
2616 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2618 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2619 if( 0 == name.compare( property->name ) )
2629 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2631 if( index < DEFAULT_PROPERTY_COUNT )
2633 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2639 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2641 if( index < DEFAULT_PROPERTY_COUNT )
2643 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2649 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2651 if( index < DEFAULT_PROPERTY_COUNT )
2653 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2659 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2661 if( index < DEFAULT_PROPERTY_COUNT )
2663 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2666 // index out of range...return Property::NONE
2667 return Property::NONE;
2670 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2674 case Dali::Actor::Property::PARENT_ORIGIN:
2676 Property::Type type = property.GetType();
2677 if( type == Property::VECTOR3 )
2679 SetParentOrigin( property.Get< Vector3 >() );
2681 else if ( type == Property::STRING )
2683 std::string parentOriginString;
2684 property.Get( parentOriginString );
2685 Vector3 parentOrigin;
2686 if( GetParentOriginConstant( parentOriginString, parentOrigin ) )
2688 SetParentOrigin( parentOrigin );
2694 case Dali::Actor::Property::PARENT_ORIGIN_X:
2696 SetParentOriginX( property.Get< float >() );
2700 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2702 SetParentOriginY( property.Get< float >() );
2706 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2708 SetParentOriginZ( property.Get< float >() );
2712 case Dali::Actor::Property::ANCHOR_POINT:
2714 Property::Type type = property.GetType();
2715 if( type == Property::VECTOR3 )
2717 SetAnchorPoint( property.Get< Vector3 >() );
2719 else if ( type == Property::STRING )
2721 std::string anchorPointString;
2722 property.Get( anchorPointString );
2724 if( GetAnchorPointConstant( anchorPointString, anchor ) )
2726 SetAnchorPoint( anchor );
2732 case Dali::Actor::Property::ANCHOR_POINT_X:
2734 SetAnchorPointX( property.Get< float >() );
2738 case Dali::Actor::Property::ANCHOR_POINT_Y:
2740 SetAnchorPointY( property.Get< float >() );
2744 case Dali::Actor::Property::ANCHOR_POINT_Z:
2746 SetAnchorPointZ( property.Get< float >() );
2750 case Dali::Actor::Property::SIZE:
2752 SetSize( property.Get< Vector3 >() );
2756 case Dali::Actor::Property::SIZE_WIDTH:
2758 SetWidth( property.Get< float >() );
2762 case Dali::Actor::Property::SIZE_HEIGHT:
2764 SetHeight( property.Get< float >() );
2768 case Dali::Actor::Property::SIZE_DEPTH:
2770 SetDepth( property.Get< float >() );
2774 case Dali::Actor::Property::POSITION:
2776 SetPosition( property.Get< Vector3 >() );
2780 case Dali::Actor::Property::POSITION_X:
2782 SetX( property.Get< float >() );
2786 case Dali::Actor::Property::POSITION_Y:
2788 SetY( property.Get< float >() );
2792 case Dali::Actor::Property::POSITION_Z:
2794 SetZ( property.Get< float >() );
2798 case Dali::Actor::Property::ORIENTATION:
2800 SetOrientation( property.Get< Quaternion >() );
2804 case Dali::Actor::Property::SCALE:
2806 SetScale( property.Get< Vector3 >() );
2810 case Dali::Actor::Property::SCALE_X:
2812 SetScaleX( property.Get< float >() );
2816 case Dali::Actor::Property::SCALE_Y:
2818 SetScaleY( property.Get< float >() );
2822 case Dali::Actor::Property::SCALE_Z:
2824 SetScaleZ( property.Get< float >() );
2828 case Dali::Actor::Property::VISIBLE:
2830 SetVisible( property.Get< bool >() );
2834 case Dali::Actor::Property::COLOR:
2836 SetColor( property.Get< Vector4 >() );
2840 case Dali::Actor::Property::COLOR_RED:
2842 SetColorRed( property.Get< float >() );
2846 case Dali::Actor::Property::COLOR_GREEN:
2848 SetColorGreen( property.Get< float >() );
2852 case Dali::Actor::Property::COLOR_BLUE:
2854 SetColorBlue( property.Get< float >() );
2858 case Dali::Actor::Property::COLOR_ALPHA:
2859 case Dali::DevelActor::Property::OPACITY:
2862 if( property.Get( value ) )
2864 SetOpacity( value );
2869 case Dali::Actor::Property::NAME:
2871 SetName( property.Get< std::string >() );
2875 case Dali::Actor::Property::SENSITIVE:
2877 SetSensitive( property.Get< bool >() );
2881 case Dali::Actor::Property::LEAVE_REQUIRED:
2883 SetLeaveRequired( property.Get< bool >() );
2887 case Dali::Actor::Property::INHERIT_POSITION:
2889 SetInheritPosition( property.Get< bool >() );
2893 case Dali::Actor::Property::INHERIT_ORIENTATION:
2895 SetInheritOrientation( property.Get< bool >() );
2899 case Dali::Actor::Property::INHERIT_SCALE:
2901 SetInheritScale( property.Get< bool >() );
2905 case Dali::Actor::Property::COLOR_MODE:
2907 ColorMode mode = mColorMode;
2908 if ( Scripting::GetEnumerationProperty< ColorMode >( property, COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT, mode ) )
2910 SetColorMode( mode );
2915 case Dali::Actor::Property::POSITION_INHERITANCE:
2917 PositionInheritanceMode mode = mPositionInheritanceMode;
2918 if( Scripting::GetEnumerationProperty< PositionInheritanceMode >( property, POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT, mode ) )
2920 SetPositionInheritanceMode( mode );
2925 case Dali::Actor::Property::DRAW_MODE:
2927 DrawMode::Type mode = mDrawMode;
2928 if( Scripting::GetEnumerationProperty< DrawMode::Type >( property, DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT, mode ) )
2930 SetDrawMode( mode );
2935 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2937 SetSizeModeFactor( property.Get< Vector3 >() );
2941 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2943 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
2944 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2946 SetResizePolicy( type, Dimension::WIDTH );
2951 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2953 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
2954 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2956 SetResizePolicy( type, Dimension::HEIGHT );
2961 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2963 SizeScalePolicy::Type type;
2964 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT, type ) )
2966 SetSizeScalePolicy( type );
2971 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2973 if( property.Get< bool >() )
2975 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2980 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2982 if( property.Get< bool >() )
2984 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2989 case Dali::Actor::Property::PADDING:
2991 Vector4 padding = property.Get< Vector4 >();
2992 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2993 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2997 case Dali::Actor::Property::MINIMUM_SIZE:
2999 Vector2 size = property.Get< Vector2 >();
3000 SetMinimumSize( size.x, Dimension::WIDTH );
3001 SetMinimumSize( size.y, Dimension::HEIGHT );
3005 case Dali::Actor::Property::MAXIMUM_SIZE:
3007 Vector2 size = property.Get< Vector2 >();
3008 SetMaximumSize( size.x, Dimension::WIDTH );
3009 SetMaximumSize( size.y, Dimension::HEIGHT );
3013 case Dali::DevelActor::Property::SIBLING_ORDER:
3017 if( property.Get( value ) )
3019 if( static_cast<unsigned int>(value) != mSiblingOrder )
3021 SetSiblingOrder( value );
3027 case Dali::Actor::Property::CLIPPING_MODE:
3029 ClippingMode::Type convertedValue = mClippingMode;
3030 if( Scripting::GetEnumerationProperty< ClippingMode::Type >( property, CLIPPING_MODE_TABLE, CLIPPING_MODE_TABLE_COUNT, convertedValue ) )
3032 mClippingMode = convertedValue;
3035 SetClippingModeMessage( GetEventThreadServices(), *mNode, mClippingMode );
3041 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
3044 if( property.Get( value ) && value != mPositionUsesAnchorPoint )
3046 mPositionUsesAnchorPoint = value;
3049 SetPositionUsesAnchorPointMessage( GetEventThreadServices(), *mNode, mPositionUsesAnchorPoint );
3057 // this can happen in the case of a non-animatable default property so just do nothing
3063 // TODO: This method needs to be removed
3064 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
3066 switch( entry.GetType() )
3068 case Property::BOOLEAN:
3070 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
3071 DALI_ASSERT_DEBUG( NULL != property );
3073 // property is being used in a separate thread; queue a message to set the property
3074 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
3079 case Property::INTEGER:
3081 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
3082 DALI_ASSERT_DEBUG( NULL != property );
3084 // property is being used in a separate thread; queue a message to set the property
3085 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
3090 case Property::FLOAT:
3092 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
3093 DALI_ASSERT_DEBUG( NULL != property );
3095 // property is being used in a separate thread; queue a message to set the property
3096 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
3101 case Property::VECTOR2:
3103 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
3104 DALI_ASSERT_DEBUG( NULL != property );
3106 // property is being used in a separate thread; queue a message to set the property
3107 if(entry.componentIndex == 0)
3109 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
3111 else if(entry.componentIndex == 1)
3113 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
3117 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
3123 case Property::VECTOR3:
3125 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
3126 DALI_ASSERT_DEBUG( NULL != property );
3128 // property is being used in a separate thread; queue a message to set the property
3129 if(entry.componentIndex == 0)
3131 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
3133 else if(entry.componentIndex == 1)
3135 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
3137 else if(entry.componentIndex == 2)
3139 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
3143 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
3149 case Property::VECTOR4:
3151 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
3152 DALI_ASSERT_DEBUG( NULL != property );
3154 // property is being used in a separate thread; queue a message to set the property
3155 if(entry.componentIndex == 0)
3157 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
3159 else if(entry.componentIndex == 1)
3161 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
3163 else if(entry.componentIndex == 2)
3165 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
3167 else if(entry.componentIndex == 3)
3169 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
3173 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3179 case Property::ROTATION:
3181 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3182 DALI_ASSERT_DEBUG( NULL != property );
3184 // property is being used in a separate thread; queue a message to set the property
3185 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3190 case Property::MATRIX:
3192 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3193 DALI_ASSERT_DEBUG( NULL != property );
3195 // property is being used in a separate thread; queue a message to set the property
3196 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3201 case Property::MATRIX3:
3203 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3204 DALI_ASSERT_DEBUG( NULL != property );
3206 // property is being used in a separate thread; queue a message to set the property
3207 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3214 // nothing to do for other types
3219 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3221 Property::Value value;
3223 if( ! GetCachedPropertyValue( index, value ) )
3225 // If property value is not stored in the event-side, then it must be a scene-graph only property
3226 GetCurrentPropertyValue( index, value );
3232 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
3234 Property::Value value;
3236 if( ! GetCurrentPropertyValue( index, value ) )
3238 // If unable to retrieve scene-graph property value, then it must be an event-side only property
3239 GetCachedPropertyValue( index, value );
3245 void Actor::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value )
3249 case Dali::Actor::Property::SIZE:
3251 if( value.Get( mTargetSize ) )
3253 // Notify deriving classes
3254 OnSizeAnimation( animation, mTargetSize );
3259 case Dali::Actor::Property::SIZE_WIDTH:
3261 if( value.Get( mTargetSize.width ) )
3263 // Notify deriving classes
3264 OnSizeAnimation( animation, mTargetSize );
3269 case Dali::Actor::Property::SIZE_HEIGHT:
3271 if( value.Get( mTargetSize.height ) )
3273 // Notify deriving classes
3274 OnSizeAnimation( animation, mTargetSize );
3279 case Dali::Actor::Property::SIZE_DEPTH:
3281 if( value.Get( mTargetSize.depth ) )
3283 // Notify deriving classes
3284 OnSizeAnimation( animation, mTargetSize );
3289 case Dali::Actor::Property::POSITION:
3291 value.Get( mTargetPosition );
3295 case Dali::Actor::Property::POSITION_X:
3297 value.Get( mTargetPosition.x );
3301 case Dali::Actor::Property::POSITION_Y:
3303 value.Get( mTargetPosition.y );
3307 case Dali::Actor::Property::POSITION_Z:
3309 value.Get( mTargetPosition.z );
3313 case Dali::Actor::Property::ORIENTATION:
3315 value.Get( mTargetOrientation );
3319 case Dali::Actor::Property::SCALE:
3321 value.Get( mTargetScale );
3325 case Dali::Actor::Property::SCALE_X:
3327 value.Get( mTargetScale.x );
3331 case Dali::Actor::Property::SCALE_Y:
3333 value.Get( mTargetScale.y );
3337 case Dali::Actor::Property::SCALE_Z:
3339 value.Get( mTargetScale.z );
3343 case Dali::Actor::Property::VISIBLE:
3345 SetVisibleInternal( value.Get< bool >(), SendMessage::FALSE );
3349 case Dali::Actor::Property::COLOR:
3351 value.Get( mTargetColor );
3355 case Dali::Actor::Property::COLOR_RED:
3357 value.Get( mTargetColor.r );
3361 case Dali::Actor::Property::COLOR_GREEN:
3363 value.Get( mTargetColor.g );
3367 case Dali::Actor::Property::COLOR_BLUE:
3369 value.Get( mTargetColor.b );
3373 case Dali::Actor::Property::COLOR_ALPHA:
3374 case Dali::DevelActor::Property::OPACITY:
3376 value.Get( mTargetColor.a );
3382 // Not an animatable property. Do nothing.
3388 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3393 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3395 // This method should only return an object connected to the scene-graph
3396 return OnStage() ? mNode : NULL;
3399 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3401 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3403 const PropertyBase* property( NULL );
3405 // This method should only return a property of an object connected to the scene-graph
3411 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3413 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3414 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3416 property = animatable->GetSceneGraphProperty();
3418 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3419 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3421 CustomPropertyMetadata* custom = FindCustomProperty( index );
3422 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3424 property = custom->GetSceneGraphProperty();
3426 else if( NULL != mNode )
3430 case Dali::Actor::Property::SIZE:
3431 property = &mNode->mSize;
3434 case Dali::Actor::Property::SIZE_WIDTH:
3435 property = &mNode->mSize;
3438 case Dali::Actor::Property::SIZE_HEIGHT:
3439 property = &mNode->mSize;
3442 case Dali::Actor::Property::SIZE_DEPTH:
3443 property = &mNode->mSize;
3446 case Dali::Actor::Property::POSITION:
3447 property = &mNode->mPosition;
3450 case Dali::Actor::Property::POSITION_X:
3451 property = &mNode->mPosition;
3454 case Dali::Actor::Property::POSITION_Y:
3455 property = &mNode->mPosition;
3458 case Dali::Actor::Property::POSITION_Z:
3459 property = &mNode->mPosition;
3462 case Dali::Actor::Property::ORIENTATION:
3463 property = &mNode->mOrientation;
3466 case Dali::Actor::Property::SCALE:
3467 property = &mNode->mScale;
3470 case Dali::Actor::Property::SCALE_X:
3471 property = &mNode->mScale;
3474 case Dali::Actor::Property::SCALE_Y:
3475 property = &mNode->mScale;
3478 case Dali::Actor::Property::SCALE_Z:
3479 property = &mNode->mScale;
3482 case Dali::Actor::Property::VISIBLE:
3483 property = &mNode->mVisible;
3486 case Dali::Actor::Property::COLOR:
3487 property = &mNode->mColor;
3490 case Dali::Actor::Property::COLOR_RED:
3491 property = &mNode->mColor;
3494 case Dali::Actor::Property::COLOR_GREEN:
3495 property = &mNode->mColor;
3498 case Dali::Actor::Property::COLOR_BLUE:
3499 property = &mNode->mColor;
3502 case Dali::Actor::Property::COLOR_ALPHA:
3503 case Dali::DevelActor::Property::OPACITY:
3504 property = &mNode->mColor;
3515 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3517 const PropertyInputImpl* property( NULL );
3519 // This method should only return a property of an object connected to the scene-graph
3525 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3527 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3528 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3530 property = animatable->GetSceneGraphProperty();
3532 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3533 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3535 CustomPropertyMetadata* custom = FindCustomProperty( index );
3536 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3537 property = custom->GetSceneGraphProperty();
3539 else if( NULL != mNode )
3543 case Dali::Actor::Property::PARENT_ORIGIN:
3544 property = &mNode->mParentOrigin;
3547 case Dali::Actor::Property::PARENT_ORIGIN_X:
3548 property = &mNode->mParentOrigin;
3551 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3552 property = &mNode->mParentOrigin;
3555 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3556 property = &mNode->mParentOrigin;
3559 case Dali::Actor::Property::ANCHOR_POINT:
3560 property = &mNode->mAnchorPoint;
3563 case Dali::Actor::Property::ANCHOR_POINT_X:
3564 property = &mNode->mAnchorPoint;
3567 case Dali::Actor::Property::ANCHOR_POINT_Y:
3568 property = &mNode->mAnchorPoint;
3571 case Dali::Actor::Property::ANCHOR_POINT_Z:
3572 property = &mNode->mAnchorPoint;
3575 case Dali::Actor::Property::SIZE:
3576 property = &mNode->mSize;
3579 case Dali::Actor::Property::SIZE_WIDTH:
3580 property = &mNode->mSize;
3583 case Dali::Actor::Property::SIZE_HEIGHT:
3584 property = &mNode->mSize;
3587 case Dali::Actor::Property::SIZE_DEPTH:
3588 property = &mNode->mSize;
3591 case Dali::Actor::Property::POSITION:
3592 property = &mNode->mPosition;
3595 case Dali::Actor::Property::POSITION_X:
3596 property = &mNode->mPosition;
3599 case Dali::Actor::Property::POSITION_Y:
3600 property = &mNode->mPosition;
3603 case Dali::Actor::Property::POSITION_Z:
3604 property = &mNode->mPosition;
3607 case Dali::Actor::Property::WORLD_POSITION:
3608 property = &mNode->mWorldPosition;
3611 case Dali::Actor::Property::WORLD_POSITION_X:
3612 property = &mNode->mWorldPosition;
3615 case Dali::Actor::Property::WORLD_POSITION_Y:
3616 property = &mNode->mWorldPosition;
3619 case Dali::Actor::Property::WORLD_POSITION_Z:
3620 property = &mNode->mWorldPosition;
3623 case Dali::Actor::Property::ORIENTATION:
3624 property = &mNode->mOrientation;
3627 case Dali::Actor::Property::WORLD_ORIENTATION:
3628 property = &mNode->mWorldOrientation;
3631 case Dali::Actor::Property::SCALE:
3632 property = &mNode->mScale;
3635 case Dali::Actor::Property::SCALE_X:
3636 property = &mNode->mScale;
3639 case Dali::Actor::Property::SCALE_Y:
3640 property = &mNode->mScale;
3643 case Dali::Actor::Property::SCALE_Z:
3644 property = &mNode->mScale;
3647 case Dali::Actor::Property::WORLD_SCALE:
3648 property = &mNode->mWorldScale;
3651 case Dali::Actor::Property::VISIBLE:
3652 property = &mNode->mVisible;
3655 case Dali::Actor::Property::COLOR:
3656 property = &mNode->mColor;
3659 case Dali::Actor::Property::COLOR_RED:
3660 property = &mNode->mColor;
3663 case Dali::Actor::Property::COLOR_GREEN:
3664 property = &mNode->mColor;
3667 case Dali::Actor::Property::COLOR_BLUE:
3668 property = &mNode->mColor;
3671 case Dali::Actor::Property::COLOR_ALPHA:
3672 case Dali::DevelActor::Property::OPACITY:
3674 property = &mNode->mColor;
3678 case Dali::Actor::Property::WORLD_COLOR:
3679 property = &mNode->mWorldColor;
3682 case Dali::Actor::Property::WORLD_MATRIX:
3683 property = &mNode->mWorldMatrix;
3694 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3696 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3698 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3700 // check whether the animatable property is registered already, if not then register one.
3701 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3702 if( animatableProperty )
3704 componentIndex = animatableProperty->componentIndex;
3711 case Dali::Actor::Property::PARENT_ORIGIN_X:
3712 case Dali::Actor::Property::ANCHOR_POINT_X:
3713 case Dali::Actor::Property::SIZE_WIDTH:
3714 case Dali::Actor::Property::POSITION_X:
3715 case Dali::Actor::Property::WORLD_POSITION_X:
3716 case Dali::Actor::Property::SCALE_X:
3717 case Dali::Actor::Property::COLOR_RED:
3723 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3724 case Dali::Actor::Property::ANCHOR_POINT_Y:
3725 case Dali::Actor::Property::SIZE_HEIGHT:
3726 case Dali::Actor::Property::POSITION_Y:
3727 case Dali::Actor::Property::WORLD_POSITION_Y:
3728 case Dali::Actor::Property::SCALE_Y:
3729 case Dali::Actor::Property::COLOR_GREEN:
3735 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3736 case Dali::Actor::Property::ANCHOR_POINT_Z:
3737 case Dali::Actor::Property::SIZE_DEPTH:
3738 case Dali::Actor::Property::POSITION_Z:
3739 case Dali::Actor::Property::WORLD_POSITION_Z:
3740 case Dali::Actor::Property::SCALE_Z:
3741 case Dali::Actor::Property::COLOR_BLUE:
3747 case Dali::Actor::Property::COLOR_ALPHA:
3748 case Dali::DevelActor::Property::OPACITY:
3762 return componentIndex;
3765 void Actor::SetParent( Actor* parent )
3769 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3773 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3776 // Instruct each actor to create a corresponding node in the scene graph
3777 ConnectToStage( parent->GetHierarchyDepth() );
3780 // Resolve the name and index for the child properties if any
3781 ResolveChildProperties();
3783 else // parent being set to NULL
3785 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3789 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3792 DALI_ASSERT_ALWAYS( mNode != NULL );
3796 // Disconnect the Node & its children from the scene-graph.
3797 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3800 // Instruct each actor to discard pointers to the scene-graph
3801 DisconnectFromStage();
3806 SceneGraph::Node* Actor::CreateNode() const
3811 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3814 Actor* actor = dynamic_cast< Actor* >( object );
3818 if( 0 == actionName.compare( ACTION_SHOW ) )
3820 actor->SetVisible( true );
3823 else if( 0 == actionName.compare( ACTION_HIDE ) )
3825 actor->SetVisible( false );
3833 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
3835 bool valueSet = true;
3839 case Dali::Actor::Property::PARENT_ORIGIN:
3841 value = GetCurrentParentOrigin();
3845 case Dali::Actor::Property::PARENT_ORIGIN_X:
3847 value = GetCurrentParentOrigin().x;
3851 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3853 value = GetCurrentParentOrigin().y;
3857 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3859 value = GetCurrentParentOrigin().z;
3863 case Dali::Actor::Property::ANCHOR_POINT:
3865 value = GetCurrentAnchorPoint();
3869 case Dali::Actor::Property::ANCHOR_POINT_X:
3871 value = GetCurrentAnchorPoint().x;
3875 case Dali::Actor::Property::ANCHOR_POINT_Y:
3877 value = GetCurrentAnchorPoint().y;
3881 case Dali::Actor::Property::ANCHOR_POINT_Z:
3883 value = GetCurrentAnchorPoint().z;
3887 case Dali::Actor::Property::SIZE:
3889 value = GetTargetSize();
3893 case Dali::Actor::Property::SIZE_WIDTH:
3895 value = GetTargetSize().width;
3899 case Dali::Actor::Property::SIZE_HEIGHT:
3901 value = GetTargetSize().height;
3905 case Dali::Actor::Property::SIZE_DEPTH:
3907 value = GetTargetSize().depth;
3911 case Dali::Actor::Property::POSITION:
3913 value = GetTargetPosition();
3917 case Dali::Actor::Property::POSITION_X:
3919 value = GetTargetPosition().x;
3923 case Dali::Actor::Property::POSITION_Y:
3925 value = GetTargetPosition().y;
3929 case Dali::Actor::Property::POSITION_Z:
3931 value = GetTargetPosition().z;
3935 case Dali::Actor::Property::ORIENTATION:
3937 value = mTargetOrientation;
3941 case Dali::Actor::Property::SCALE:
3943 value = mTargetScale;
3947 case Dali::Actor::Property::SCALE_X:
3949 value = mTargetScale.x;
3953 case Dali::Actor::Property::SCALE_Y:
3955 value = mTargetScale.y;
3959 case Dali::Actor::Property::SCALE_Z:
3961 value = mTargetScale.z;
3965 case Dali::Actor::Property::VISIBLE:
3971 case Dali::Actor::Property::COLOR:
3973 value = mTargetColor;
3977 case Dali::Actor::Property::COLOR_RED:
3979 value = mTargetColor.r;
3983 case Dali::Actor::Property::COLOR_GREEN:
3985 value = mTargetColor.g;
3989 case Dali::Actor::Property::COLOR_BLUE:
3991 value = mTargetColor.b;
3995 case Dali::Actor::Property::COLOR_ALPHA:
3996 case Dali::DevelActor::Property::OPACITY:
3998 value = mTargetColor.a;
4002 case Dali::Actor::Property::NAME:
4008 case Dali::Actor::Property::SENSITIVE:
4010 value = IsSensitive();
4014 case Dali::Actor::Property::LEAVE_REQUIRED:
4016 value = GetLeaveRequired();
4020 case Dali::Actor::Property::INHERIT_POSITION:
4022 value = IsPositionInherited();
4026 case Dali::Actor::Property::INHERIT_ORIENTATION:
4028 value = IsOrientationInherited();
4032 case Dali::Actor::Property::INHERIT_SCALE:
4034 value = IsScaleInherited();
4038 case Dali::Actor::Property::COLOR_MODE:
4040 value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
4044 case Dali::Actor::Property::POSITION_INHERITANCE:
4046 value = Scripting::GetLinearEnumerationName< PositionInheritanceMode >( GetPositionInheritanceMode(), POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT );
4050 case Dali::Actor::Property::DRAW_MODE:
4052 value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
4056 case Dali::Actor::Property::SIZE_MODE_FACTOR:
4058 value = GetSizeModeFactor();
4062 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
4064 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
4068 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
4070 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
4074 case Dali::Actor::Property::SIZE_SCALE_POLICY:
4076 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT );
4080 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
4082 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
4086 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
4088 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
4092 case Dali::Actor::Property::PADDING:
4094 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
4095 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
4096 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
4100 case Dali::Actor::Property::MINIMUM_SIZE:
4102 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
4106 case Dali::Actor::Property::MAXIMUM_SIZE:
4108 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
4112 case Dali::Actor::Property::CLIPPING_MODE:
4114 value = mClippingMode;
4118 case Dali::DevelActor::Property::SIBLING_ORDER:
4120 value = static_cast<int>(mSiblingOrder);
4124 case Dali::DevelActor::Property::SCREEN_POSITION:
4126 value = GetCurrentScreenPosition();
4130 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
4132 value = mPositionUsesAnchorPoint;
4138 // Must be a scene-graph only property
4147 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
4149 bool valueSet = true;
4153 case Dali::Actor::Property::SIZE:
4155 value = GetCurrentSize();
4159 case Dali::Actor::Property::SIZE_WIDTH:
4161 value = GetCurrentSize().width;
4165 case Dali::Actor::Property::SIZE_HEIGHT:
4167 value = GetCurrentSize().height;
4171 case Dali::Actor::Property::SIZE_DEPTH:
4173 value = GetCurrentSize().depth;
4177 case Dali::Actor::Property::POSITION:
4179 value = GetCurrentPosition();
4183 case Dali::Actor::Property::POSITION_X:
4185 value = GetCurrentPosition().x;
4189 case Dali::Actor::Property::POSITION_Y:
4191 value = GetCurrentPosition().y;
4195 case Dali::Actor::Property::POSITION_Z:
4197 value = GetCurrentPosition().z;
4201 case Dali::Actor::Property::WORLD_POSITION:
4203 value = GetCurrentWorldPosition();
4207 case Dali::Actor::Property::WORLD_POSITION_X:
4209 value = GetCurrentWorldPosition().x;
4213 case Dali::Actor::Property::WORLD_POSITION_Y:
4215 value = GetCurrentWorldPosition().y;
4219 case Dali::Actor::Property::WORLD_POSITION_Z:
4221 value = GetCurrentWorldPosition().z;
4225 case Dali::Actor::Property::ORIENTATION:
4227 value = GetCurrentOrientation();
4231 case Dali::Actor::Property::WORLD_ORIENTATION:
4233 value = GetCurrentWorldOrientation();
4237 case Dali::Actor::Property::SCALE:
4239 value = GetCurrentScale();
4243 case Dali::Actor::Property::SCALE_X:
4245 value = GetCurrentScale().x;
4249 case Dali::Actor::Property::SCALE_Y:
4251 value = GetCurrentScale().y;
4255 case Dali::Actor::Property::SCALE_Z:
4257 value = GetCurrentScale().z;
4261 case Dali::Actor::Property::WORLD_SCALE:
4263 value = GetCurrentWorldScale();
4267 case Dali::Actor::Property::COLOR:
4269 value = GetCurrentColor();
4273 case Dali::Actor::Property::COLOR_RED:
4275 value = GetCurrentColor().r;
4279 case Dali::Actor::Property::COLOR_GREEN:
4281 value = GetCurrentColor().g;
4285 case Dali::Actor::Property::COLOR_BLUE:
4287 value = GetCurrentColor().b;
4291 case Dali::Actor::Property::COLOR_ALPHA:
4292 case Dali::DevelActor::Property::OPACITY:
4294 value = GetCurrentColor().a;
4298 case Dali::Actor::Property::WORLD_COLOR:
4300 value = GetCurrentWorldColor();
4304 case Dali::Actor::Property::WORLD_MATRIX:
4306 value = GetCurrentWorldMatrix();
4310 case Dali::Actor::Property::VISIBLE:
4312 value = IsVisible();
4318 // Must be an event-side only property
4327 void Actor::EnsureRelayoutData()
4329 // Assign relayout data.
4330 if( !mRelayoutData )
4332 mRelayoutData = new RelayoutData();
4336 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
4338 // Check if actor is dependent on parent
4339 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4341 if( ( dimension & ( 1 << i ) ) )
4343 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4344 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
4354 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
4356 // Check if actor is dependent on children
4357 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4359 if( ( dimension & ( 1 << i ) ) )
4361 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4362 switch( resizePolicy )
4364 case ResizePolicy::FIT_TO_CHILDREN:
4365 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
4381 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
4383 return Actor::RelayoutDependentOnChildren( dimension );
4386 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
4388 // Check each possible dimension and see if it is dependent on the input one
4389 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4391 if( dimension & ( 1 << i ) )
4393 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
4400 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
4402 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4404 if( dimension & ( 1 << i ) )
4406 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
4411 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
4413 // If more than one dimension is requested, just return the first one found
4414 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4416 if( ( dimension & ( 1 << i ) ) )
4418 return mRelayoutData->negotiatedDimensions[ i ];
4422 return 0.0f; // Default
4425 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
4427 EnsureRelayoutData();
4429 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4431 if( dimension & ( 1 << i ) )
4433 mRelayoutData->dimensionPadding[ i ] = padding;
4438 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4440 if ( mRelayoutData )
4442 // If more than one dimension is requested, just return the first one found
4443 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4445 if( ( dimension & ( 1 << i ) ) )
4447 return mRelayoutData->dimensionPadding[ i ];
4452 return GetDefaultDimensionPadding();
4455 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4457 EnsureRelayoutData();
4459 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4461 if( dimension & ( 1 << i ) )
4463 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4468 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4470 if ( mRelayoutData )
4472 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4474 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4484 float Actor::GetHeightForWidthBase( float width )
4486 float height = 0.0f;
4488 const Vector3 naturalSize = GetNaturalSize();
4489 if( naturalSize.width > 0.0f )
4491 height = naturalSize.height * width / naturalSize.width;
4493 else // we treat 0 as 1:1 aspect ratio
4501 float Actor::GetWidthForHeightBase( float height )
4505 const Vector3 naturalSize = GetNaturalSize();
4506 if( naturalSize.height > 0.0f )
4508 width = naturalSize.width * height / naturalSize.height;
4510 else // we treat 0 as 1:1 aspect ratio
4518 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4520 // Fill to parent, taking size mode factor into account
4521 switch( child.GetResizePolicy( dimension ) )
4523 case ResizePolicy::FILL_TO_PARENT:
4525 return GetLatestSize( dimension );
4528 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4530 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4533 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4535 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4540 return GetLatestSize( dimension );
4545 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4547 // Can be overridden in derived class
4548 return CalculateChildSizeBase( child, dimension );
4551 float Actor::GetHeightForWidth( float width )
4553 // Can be overridden in derived class
4554 return GetHeightForWidthBase( width );
4557 float Actor::GetWidthForHeight( float height )
4559 // Can be overridden in derived class
4560 return GetWidthForHeightBase( height );
4563 float Actor::GetLatestSize( Dimension::Type dimension ) const
4565 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4568 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4570 Vector2 padding = GetPadding( dimension );
4572 return GetLatestSize( dimension ) + padding.x + padding.y;
4575 float Actor::NegotiateFromParent( Dimension::Type dimension )
4577 Actor* parent = GetParent();
4580 Vector2 padding( GetPadding( dimension ) );
4581 Vector2 parentPadding( parent->GetPadding( dimension ) );
4582 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4588 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4590 float maxDimensionPoint = 0.0f;
4592 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4594 ActorPtr child = GetChildAt( i );
4596 if( !child->RelayoutDependentOnParent( dimension ) )
4598 // Calculate the min and max points that the children range across
4599 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
4600 float dimensionSize = child->GetRelayoutSize( dimension );
4601 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4605 return maxDimensionPoint;
4608 float Actor::GetSize( Dimension::Type dimension ) const
4610 return GetDimensionValue( mTargetSize, dimension );
4613 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4615 return GetDimensionValue( GetNaturalSize(), dimension );
4618 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4620 switch( GetResizePolicy( dimension ) )
4622 case ResizePolicy::USE_NATURAL_SIZE:
4624 return GetNaturalSize( dimension );
4627 case ResizePolicy::FIXED:
4629 return GetDimensionValue( GetPreferredSize(), dimension );
4632 case ResizePolicy::USE_ASSIGNED_SIZE:
4634 return GetDimensionValue( maximumSize, dimension );
4637 case ResizePolicy::FILL_TO_PARENT:
4638 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4639 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4641 return NegotiateFromParent( dimension );
4644 case ResizePolicy::FIT_TO_CHILDREN:
4646 return NegotiateFromChildren( dimension );
4649 case ResizePolicy::DIMENSION_DEPENDENCY:
4651 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4654 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4656 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4659 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4661 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4673 return 0.0f; // Default
4676 float Actor::ClampDimension( float size, Dimension::Type dimension )
4678 const float minSize = GetMinimumSize( dimension );
4679 const float maxSize = GetMaximumSize( dimension );
4681 return std::max( minSize, std::min( size, maxSize ) );
4684 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4686 // Check if it needs to be negotiated
4687 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4689 // Check that we havn't gotten into an infinite loop
4690 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4691 bool recursionFound = false;
4692 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4694 if( *it == searchActor )
4696 recursionFound = true;
4701 if( !recursionFound )
4703 // Record the path that we have taken
4704 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4706 // Dimension dependency check
4707 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4709 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4711 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4713 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4717 // Parent dependency check
4718 Actor* parent = GetParent();
4719 if( parent && RelayoutDependentOnParent( dimension ) )
4721 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4724 // Children dependency check
4725 if( RelayoutDependentOnChildren( dimension ) )
4727 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4729 ActorPtr child = GetChildAt( i );
4731 // Only relayout child first if it is not dependent on this actor
4732 if( !child->RelayoutDependentOnParent( dimension ) )
4734 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
4739 // For deriving classes
4740 OnCalculateRelayoutSize( dimension );
4742 // All dependencies checked, calculate the size and set negotiated flag
4743 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4745 SetNegotiatedDimension( newSize, dimension );
4746 SetLayoutNegotiated( true, dimension );
4748 // For deriving classes
4749 OnLayoutNegotiated( newSize, dimension );
4751 // This actor has been successfully processed, pop it off the recursion stack
4752 recursionStack.pop_back();
4756 // TODO: Break infinite loop
4757 SetLayoutNegotiated( true, dimension );
4762 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4764 // Negotiate all dimensions that require it
4765 ActorDimensionStack recursionStack;
4767 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4769 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4772 NegotiateDimension( dimension, allocatedSize, recursionStack );
4776 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4778 switch( mRelayoutData->sizeSetPolicy )
4780 case SizeScalePolicy::USE_SIZE_SET:
4785 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4787 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4788 const Vector3 naturalSize = GetNaturalSize();
4789 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4791 const float sizeRatio = size.width / size.height;
4792 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4794 if( naturalSizeRatio < sizeRatio )
4796 return Vector2( naturalSizeRatio * size.height, size.height );
4798 else if( naturalSizeRatio > sizeRatio )
4800 return Vector2( size.width, size.width / naturalSizeRatio );
4811 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4813 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4814 const Vector3 naturalSize = GetNaturalSize();
4815 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4817 const float sizeRatio = size.width / size.height;
4818 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4820 if( naturalSizeRatio < sizeRatio )
4822 return Vector2( size.width, size.width / naturalSizeRatio );
4824 else if( naturalSizeRatio > sizeRatio )
4826 return Vector2( naturalSizeRatio * size.height, size.height );
4845 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4847 // Do the set actor size
4848 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4850 // Adjust for size set policy
4851 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4853 // Lock the flag to stop recursive relayouts on set size
4854 mRelayoutData->insideRelayout = true;
4855 SetSize( negotiatedSize );
4856 mRelayoutData->insideRelayout = false;
4858 // Clear flags for all dimensions
4859 SetLayoutDirty( false );
4861 // Give deriving classes a chance to respond
4862 OnRelayout( negotiatedSize, container );
4864 if( !mOnRelayoutSignal.Empty() )
4866 Dali::Actor handle( this );
4867 mOnRelayoutSignal.Emit( handle );
4871 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4873 // Force a size negotiation for actors that has assigned size during relayout
4874 // This is required as otherwise the flags that force a relayout will not
4875 // necessarilly be set. This will occur if the actor has already been laid out.
4876 // The dirty flags are then cleared. Then if the actor is added back into the
4877 // relayout container afterwards, the dirty flags would still be clear...
4878 // causing a relayout to be skipped. Here we force any actors added to the
4879 // container to be relayed out.
4880 DALI_LOG_TIMER_START( NegSizeTimer1 );
4882 if( GetUseAssignedSize(Dimension::WIDTH ) )
4884 SetLayoutNegotiated( false, Dimension::WIDTH );
4886 if( GetUseAssignedSize( Dimension::HEIGHT ) )
4888 SetLayoutNegotiated( false, Dimension::HEIGHT );
4891 // Do the negotiation
4892 NegotiateDimensions( allocatedSize );
4894 // Set the actor size
4895 SetNegotiatedSize( container );
4897 // Negotiate down to children
4898 const Vector2 newBounds = mTargetSize.GetVectorXY();
4900 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4902 ActorPtr child = GetChildAt( i );
4904 // Forces children that have already been laid out to be relayed out
4905 // if they have assigned size during relayout.
4906 if( child->GetUseAssignedSize(Dimension::WIDTH) )
4908 child->SetLayoutNegotiated(false, Dimension::WIDTH);
4909 child->SetLayoutDirty(true, Dimension::WIDTH);
4912 if( child->GetUseAssignedSize(Dimension::HEIGHT) )
4914 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
4915 child->SetLayoutDirty(true, Dimension::HEIGHT);
4918 // Only relayout if required
4919 if( child->RelayoutRequired() )
4921 container.Add( Dali::Actor( child.Get() ), newBounds );
4924 DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
4927 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
4931 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4933 if( dimension & ( 1 << i ) )
4935 mRelayoutData->useAssignedSize[ i ] = use;
4941 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
4943 if ( mRelayoutData )
4945 // If more than one dimension is requested, just return the first one found
4946 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4948 if( dimension & ( 1 << i ) )
4950 return mRelayoutData->useAssignedSize[ i ];
4958 void Actor::RelayoutRequest( Dimension::Type dimension )
4960 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4961 if( relayoutController )
4963 Dali::Actor self( this );
4964 relayoutController->RequestRelayout( self, dimension );
4968 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4972 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4976 void Actor::SetPreferredSize( const Vector2& size )
4978 EnsureRelayoutData();
4980 if( size.width > 0.0f )
4982 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4985 if( size.height > 0.0f )
4987 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4990 mRelayoutData->preferredSize = size;
4995 Vector2 Actor::GetPreferredSize() const
4997 if ( mRelayoutData )
4999 return Vector2( mRelayoutData->preferredSize );
5002 return GetDefaultPreferredSize();
5005 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
5007 EnsureRelayoutData();
5009 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5011 if( dimension & ( 1 << i ) )
5013 mRelayoutData->minimumSize[ i ] = size;
5020 float Actor::GetMinimumSize( Dimension::Type dimension ) const
5022 if ( mRelayoutData )
5024 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5026 if( dimension & ( 1 << i ) )
5028 return mRelayoutData->minimumSize[ i ];
5033 return 0.0f; // Default
5036 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
5038 EnsureRelayoutData();
5040 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5042 if( dimension & ( 1 << i ) )
5044 mRelayoutData->maximumSize[ i ] = size;
5051 float Actor::GetMaximumSize( Dimension::Type dimension ) const
5053 if ( mRelayoutData )
5055 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5057 if( dimension & ( 1 << i ) )
5059 return mRelayoutData->maximumSize[ i ];
5064 return FLT_MAX; // Default
5067 Object* Actor::GetParentObject() const
5072 void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
5074 if( mVisible != visible )
5076 if( sendMessage == SendMessage::TRUE && NULL != mNode )
5078 // mNode is being used in a separate thread; queue a message to set the value & base value
5079 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
5084 // Emit the signal on this actor and all its children
5085 EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
5089 void Actor::SetSiblingOrder( unsigned int order )
5091 mSiblingOrder = std::min( order, static_cast<unsigned int>( DevelLayer::SIBLING_ORDER_MULTIPLIER ) );
5095 StagePtr stage = Stage::GetCurrent();
5098 stage->RequestRebuildDepthTree();
5103 void Actor::DefragmentSiblingIndexes( ActorContainer& siblings )
5105 // Sibling index may not be in consecutive order as the sibling range is limited ( DevelLayer::SIBLING_ORDER_MULTIPLIER )
5106 // we need to remove the gaps and ensure the number start from 0 and consecutive hence have a full range.
5108 // Start at index 0, while index <= highest order
5109 // Find next index higher than 0
5110 // if nextHigher > index+1
5111 // set all nextHigher orders to index+1
5113 // Limitation: May reach the ceiling of DevelLayer::SIBLING_ORDER_MULTIPLIER with highest sibling.
5115 ActorIter end = siblings.end();
5116 int highestOrder = 0;
5117 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
5119 ActorPtr sibling = (*iter);
5120 int siblingOrder = sibling->mSiblingOrder;
5121 highestOrder = std::max( highestOrder, siblingOrder );
5124 for ( int index = 0; index <= highestOrder; index++ )
5126 int nextHighest = -1;
5128 // Find Next highest
5129 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
5131 ActorPtr sibling = (*iter);
5132 int siblingOrder = sibling->mSiblingOrder;
5134 if ( siblingOrder > index )
5136 if ( nextHighest == -1 )
5138 nextHighest = siblingOrder;
5140 nextHighest = std::min( nextHighest, siblingOrder );
5144 // Check if a gap exists between indexes, if so set next index to consecutive number
5145 if ( ( nextHighest - index ) > 1 )
5147 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
5149 ActorPtr sibling = (*iter);
5150 int siblingOrder = sibling->mSiblingOrder;
5151 if ( siblingOrder == nextHighest )
5153 sibling->mSiblingOrder = index + 1;
5154 if ( sibling->mSiblingOrder >= Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER )
5156 DALI_LOG_WARNING( "Reached max sibling order level for raising / lowering actors\n" );
5157 sibling->mSiblingOrder = Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER;
5159 sibling->SetSiblingOrder( sibling->mSiblingOrder );
5166 bool Actor::ShiftSiblingsLevels( ActorContainer& siblings, int targetLevelToShiftFrom )
5168 // Allows exclusive levels for an actor by shifting all sibling levels at the target and above by 1
5169 bool defragmentationRequired( false );
5170 ActorIter end = siblings.end();
5171 for( ActorIter iter = siblings.begin(); ( iter != end ) ; ++iter )
5173 // Move actors at nearest order and above up by 1
5174 ActorPtr sibling = (*iter);
5175 if ( sibling != this )
5177 // Iterate through container of actors, any actor with a sibling order of the target or greater should
5178 // be incremented by 1.
5179 if ( sibling->mSiblingOrder >= targetLevelToShiftFrom )
5181 sibling->mSiblingOrder++;
5182 if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
5184 // If a sibling order raises so that it is only 1 from the maximum allowed then set flag so
5185 // can re-order all sibling orders.
5186 defragmentationRequired = true;
5188 sibling->SetSiblingOrder( sibling->mSiblingOrder );
5192 return defragmentationRequired;
5198 1) Check if already at top and nothing to be done.
5199 This Actor can have highest sibling order but if not exclusive then another actor at same sibling
5200 order can be positioned above it due to insertion order of actors.
5201 2) Find nearest sibling level above, these are the siblings this actor needs to be above
5202 3) a) There may be other levels above this target level
5203 b) Increment all sibling levels at the level above nearest(target)
5204 c) Now have a vacant sibling level
5205 4) Set this actor's sibling level to nearest +1 as now vacated.
5207 Note May not just be sibling level + 1 as could be empty levels in-between
5212 ActorC ( sibling level 4 )
5213 ActorB ( sibling level 3 )
5214 ActorA ( sibling level 1 )
5216 2 ) ACTION: Raise A above B
5217 a) Find nearest level above A = Level 3
5218 b) Increment levels above Level 3
5220 ActorC ( sibling level 5 )
5221 ActorB ( sibling level 3 ) NEAREST
5222 ActorA ( sibling level 1 )
5224 3 ) Set Actor A sibling level to nearest +1 as vacant
5226 ActorC ( sibling level 5 )
5227 ActorA ( sibling level 4 )
5228 ActorB ( sibling level 3 )
5230 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5231 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5232 remove any empty sibling order gaps and start from sibling level 0 again.
5233 If the number of actors reaches this maximum and all using exclusive sibling order values then
5234 defragmention will stop and new sibling orders will be set to same max value.
5238 int nearestLevel = mSiblingOrder;
5239 int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
5240 bool defragmentationRequired( false );
5242 ActorContainer* siblings = mParent->mChildren;
5244 // Find Nearest sibling level above this actor
5245 ActorIter end = siblings->end();
5246 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
5248 ActorPtr sibling = (*iter);
5249 if ( sibling != this )
5251 int order = GetSiblingOrder( sibling );
5253 if ( ( order >= mSiblingOrder ) )
5255 int distanceToNextLevel = order - mSiblingOrder;
5256 if ( distanceToNextLevel < shortestDistanceToNextLevel )
5258 nearestLevel = order;
5259 shortestDistanceToNextLevel = distanceToNextLevel;
5265 if ( nearestLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at top
5267 mSiblingOrder = nearestLevel + 1; // Set sibling level to that above the nearest level
5268 defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
5269 // Move current actor to newly vacated order level
5270 SetSiblingOrder( mSiblingOrder );
5271 if ( defragmentationRequired )
5273 DefragmentSiblingIndexes( *siblings );
5276 SetSiblingOrder( mSiblingOrder );
5280 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5287 1) Check if actor already at bottom and if nothing needs to be done
5288 This Actor can have lowest sibling order but if not exclusive then another actor at same sibling
5289 order can be positioned above it due to insertion order of actors so need to move this actor below it.
5290 2) Find nearest sibling level below, this Actor needs to be below it
5291 3) a) Need to vacate a sibling level below nearest for this actor to occupy
5292 b) Shift up all sibling order values of actor at the nearest level and levels above it to vacate a level.
5293 c) Set this actor's sibling level to this newly vacated level.
5294 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5295 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5296 remove any empty sibling order gaps and start from sibling level 0 again.
5297 If the number of actors reaches this maximum and all using exclusive sibling order values then
5298 defragmention will stop and new sibling orders will be set to same max value.
5303 // 1) Find nearest level below
5304 int nearestLevel = mSiblingOrder;
5305 int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
5307 ActorContainer* siblings = mParent->mChildren;
5309 ActorIter end = siblings->end();
5310 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
5312 ActorPtr sibling = (*iter);
5313 if ( sibling != this )
5315 int order = GetSiblingOrder( sibling );
5317 if ( order <= mSiblingOrder )
5319 int distanceToNextLevel = mSiblingOrder - order;
5320 if ( distanceToNextLevel < shortestDistanceToNextLevel )
5322 nearestLevel = order;
5323 shortestDistanceToNextLevel = distanceToNextLevel;
5329 bool defragmentationRequired ( false );
5331 // 2) If actor already not at bottom, raise all actors at required level and above
5332 if ( shortestDistanceToNextLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at bottom
5334 mSiblingOrder = nearestLevel;
5335 defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
5336 // Move current actor to newly vacated order
5337 SetSiblingOrder( mSiblingOrder );
5338 if ( defragmentationRequired )
5340 DefragmentSiblingIndexes( *siblings );
5346 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5350 void Actor::RaiseToTop()
5353 1 ) Find highest sibling order actor
5354 2 ) If highest sibling level not itself then set sibling order to that + 1
5355 3 ) highest sibling order can be same as itself so need to increment over that
5356 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5357 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5358 remove any empty sibling order gaps and start from sibling level 0 again.
5359 If the number of actors reaches this maximum and all using exclusive sibling order values then
5360 defragmention will stop and new sibling orders will be set to same max value.
5367 ActorContainer* siblings = mParent->mChildren;
5369 ActorIter end = siblings->end();
5370 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
5372 ActorPtr sibling = (*iter);
5373 if ( sibling != this )
5375 maxOrder = std::max( GetSiblingOrder( sibling ), maxOrder );
5379 bool defragmentationRequired( false );
5381 if ( maxOrder >= mSiblingOrder )
5383 mSiblingOrder = maxOrder + 1;
5384 if ( mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
5386 defragmentationRequired = true;
5390 SetSiblingOrder( mSiblingOrder );
5392 if ( defragmentationRequired )
5394 DefragmentSiblingIndexes( *siblings );
5399 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5403 void Actor::LowerToBottom()
5406 See Actor::LowerToBottom()
5408 1 ) Check if this actor already at exclusively at the bottom, if so then no more to be done.
5409 2 ) a ) Check if the bottom position 0 is vacant.
5410 b ) If 0 position is not vacant then shift up all sibling order values from 0 and above
5411 c ) 0 sibling position is vacant.
5412 3 ) Set this actor to vacant sibling order 0;
5413 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5414 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5415 remove any empty sibling order gaps and start from sibling level 0 again.
5416 If the number of actors reaches this maximum and all using exclusive sibling order values then
5417 defragmention will stop and new sibling orders will be set to same max value.
5422 bool defragmentationRequired( false );
5423 bool orderZeroFree ( true );
5425 ActorContainer* siblings = mParent->mChildren;
5427 bool actorAtLowestOrder = true;
5428 ActorIter end = siblings->end();
5429 for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
5431 ActorPtr sibling = (*iter);
5432 if ( sibling != this )
5434 int siblingOrder = GetSiblingOrder( sibling );
5435 if ( siblingOrder <= mSiblingOrder )
5437 actorAtLowestOrder = false;
5440 if ( siblingOrder == 0 )
5442 orderZeroFree = false;
5447 if ( ! actorAtLowestOrder )
5449 if ( ! orderZeroFree )
5451 defragmentationRequired = ShiftSiblingsLevels( *siblings, 0 );
5454 SetSiblingOrder( mSiblingOrder );
5456 if ( defragmentationRequired )
5458 DefragmentSiblingIndexes( *siblings );
5464 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5468 void Actor::RaiseAbove( Internal::Actor& target )
5471 1 ) a) Find target actor's sibling order
5472 b) If sibling order of target is the same as this actor then need to this Actor's sibling order
5473 needs to be above it or the insertion order will determine which is drawn on top.
5474 2 ) Shift up by 1 all sibling order greater than target sibling order
5475 3 ) Set this actor to the sibling order to target +1 as will be a newly vacated gap above
5476 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5477 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5478 remove any empty sibling order gaps and start from sibling level 0 again.
5479 If the number of actors reaches this maximum and all using exclusive sibling order values then
5480 defragmention will stop and new sibling orders will be set to same max value.
5485 if ( ValidateActors( *this, target ) )
5487 // Find target's sibling order
5488 // Set actor sibling order to this number +1
5489 int targetSiblingOrder = GetSiblingOrder( &target );
5490 ActorContainer* siblings = mParent->mChildren;
5491 mSiblingOrder = targetSiblingOrder + 1;
5492 bool defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
5494 SetSiblingOrder( mSiblingOrder );
5496 if ( defragmentationRequired )
5498 DefragmentSiblingIndexes( *(mParent->mChildren) );
5504 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5508 void Actor::LowerBelow( Internal::Actor& target )
5511 1 ) a) Find target actor's sibling order
5512 b) If sibling order of target is the same as this actor then need to this Actor's sibling order
5513 needs to be below it or the insertion order will determine which is drawn on top.
5514 2 ) Shift the target sibling order and all sibling orders at that level or above by 1
5515 3 ) Set this actor to the sibling order of the target before it changed.
5516 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5517 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5518 remove any empty sibling order gaps and start from sibling level 0 again.
5519 If the number of actors reaches this maximum and all using exclusive sibling order values then
5520 defragmention will stop and new sibling orders will be set to same max value.
5525 if ( ValidateActors( *this, target ) )
5527 bool defragmentationRequired ( false );
5528 // Find target's sibling order
5529 // Set actor sibling order to target sibling order - 1
5530 int targetSiblingOrder = GetSiblingOrder( &target);
5531 ActorContainer* siblings = mParent->mChildren;
5532 if ( targetSiblingOrder == 0 )
5535 ActorIter end = siblings->end();
5536 for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
5538 ActorPtr sibling = (*iter);
5539 if ( sibling != this )
5541 sibling->mSiblingOrder++;
5542 if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
5544 defragmentationRequired = true;
5546 sibling->SetSiblingOrder( sibling->mSiblingOrder );
5553 defragmentationRequired = ShiftSiblingsLevels( *siblings, targetSiblingOrder );
5555 mSiblingOrder = targetSiblingOrder;
5557 SetSiblingOrder( mSiblingOrder );
5559 if ( defragmentationRequired )
5561 DefragmentSiblingIndexes( *(mParent->mChildren) );
5567 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5571 } // namespace Internal