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 if( mVisible != visible )
1063 // mNode is being used in a separate thread; queue a message to set the value & base value
1064 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
1069 // Emit the signal on this actor and all its children
1070 EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
1074 bool Actor::IsVisible() const
1078 // mNode is being used in a separate thread; copy the value from the previous update
1079 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
1085 void Actor::SetOpacity( float opacity )
1087 mTargetColor.a = opacity;
1091 // mNode is being used in a separate thread; queue a message to set the value & base value
1092 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
1096 float Actor::GetCurrentOpacity() const
1100 // mNode is being used in a separate thread; copy the value from the previous update
1101 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1107 ClippingMode::Type Actor::GetClippingMode() const
1109 return mClippingMode;
1112 unsigned int Actor::GetSortingDepth()
1114 return mSortedDepth;
1117 const Vector4& Actor::GetCurrentWorldColor() const
1121 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1124 return Color::WHITE;
1127 void Actor::SetColor( const Vector4& color )
1129 mTargetColor = color;
1133 // mNode is being used in a separate thread; queue a message to set the value & base value
1134 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1138 void Actor::SetColorRed( float red )
1140 mTargetColor.r = red;
1144 // mNode is being used in a separate thread; queue a message to set the value & base value
1145 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1149 void Actor::SetColorGreen( float green )
1151 mTargetColor.g = green;
1155 // mNode is being used in a separate thread; queue a message to set the value & base value
1156 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1160 void Actor::SetColorBlue( float blue )
1162 mTargetColor.b = blue;
1166 // mNode is being used in a separate thread; queue a message to set the value & base value
1167 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1171 const Vector4& Actor::GetCurrentColor() const
1175 // mNode is being used in a separate thread; copy the value from the previous update
1176 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1179 return Color::WHITE;
1182 void Actor::SetInheritOrientation( bool inherit )
1184 if( mInheritOrientation != inherit && NULL != mNode)
1186 // non animateable so keep local copy
1187 mInheritOrientation = inherit;
1188 // mNode is being used in a separate thread; queue a message to set the value
1189 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1193 bool Actor::IsOrientationInherited() const
1195 return mInheritOrientation;
1198 void Actor::SetSizeModeFactor( const Vector3& factor )
1200 EnsureRelayoutData();
1202 mRelayoutData->sizeModeFactor = factor;
1205 const Vector3& Actor::GetSizeModeFactor() const
1207 if ( mRelayoutData )
1209 return mRelayoutData->sizeModeFactor;
1212 return GetDefaultSizeModeFactor();
1215 void Actor::SetColorMode( ColorMode colorMode )
1217 // non animateable so keep local copy
1218 mColorMode = colorMode;
1221 // mNode is being used in a separate thread; queue a message to set the value
1222 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1226 ColorMode Actor::GetColorMode() const
1228 // we have cached copy
1232 void Actor::SetSize( float width, float height )
1234 SetSize( Vector2( width, height ) );
1237 void Actor::SetSize( float width, float height, float depth )
1239 SetSize( Vector3( width, height, depth ) );
1242 void Actor::SetSize( const Vector2& size )
1244 SetSize( Vector3( size.width, size.height, 0.f ) );
1247 void Actor::SetSizeInternal( const Vector2& size )
1249 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1252 void Actor::SetSize( const Vector3& size )
1254 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1256 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1257 SetPreferredSize( size.GetVectorXY() );
1261 SetSizeInternal( size );
1265 void Actor::SetSizeInternal( const Vector3& size )
1267 // dont allow recursive loop
1268 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1269 // 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
1270 if( ( NULL != mNode )&&
1271 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1272 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1273 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1277 // mNode is being used in a separate thread; queue a message to set the value & base value
1278 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
1280 // Notification for derived classes
1281 mInsideOnSizeSet = true;
1282 OnSizeSet( mTargetSize );
1283 mInsideOnSizeSet = false;
1285 // Raise a relayout request if the flag is not locked
1286 if( mRelayoutData && !mRelayoutData->insideRelayout )
1293 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1295 mTargetSize = targetSize;
1297 // Notify deriving classes
1298 OnSizeAnimation( animation, mTargetSize );
1301 void Actor::NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property )
1303 if ( Dali::Actor::Property::SIZE_WIDTH == property )
1305 mTargetSize.width = targetSize;
1307 else if ( Dali::Actor::Property::SIZE_HEIGHT == property )
1309 mTargetSize.height = targetSize;
1311 else if ( Dali::Actor::Property::SIZE_DEPTH == property )
1313 mTargetSize.depth = targetSize;
1315 // Notify deriving classes
1316 OnSizeAnimation( animation, mTargetSize );
1319 void Actor::NotifyPositionAnimation( Animation& animation, const Vector3& targetPosition )
1321 mTargetPosition = targetPosition;
1324 void Actor::NotifyPositionAnimation( Animation& animation, float targetPosition, Property::Index property )
1326 if ( Dali::Actor::Property::POSITION_X == property )
1328 mTargetPosition.x = targetPosition;
1330 else if ( Dali::Actor::Property::POSITION_Y == property )
1332 mTargetPosition.y = targetPosition;
1334 else if ( Dali::Actor::Property::POSITION_Z == property )
1336 mTargetPosition.z = targetPosition;
1340 void Actor::SetWidth( float width )
1342 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1344 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
1345 mRelayoutData->preferredSize.width = width;
1349 mTargetSize.width = width;
1353 // mNode is being used in a separate thread; queue a message to set the value & base value
1354 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1361 void Actor::SetHeight( float height )
1363 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1365 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
1366 mRelayoutData->preferredSize.height = height;
1370 mTargetSize.height = height;
1374 // mNode is being used in a separate thread; queue a message to set the value & base value
1375 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1382 void Actor::SetDepth( float depth )
1384 mTargetSize.depth = depth;
1388 // mNode is being used in a separate thread; queue a message to set the value & base value
1389 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1393 Vector3 Actor::GetTargetSize() const
1395 Vector3 size = mTargetSize;
1397 // Should return preferred size if size is fixed as set by SetSize
1398 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
1400 size.width = GetPreferredSize().width;
1402 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
1404 size.height = GetPreferredSize().height;
1410 const Vector3& Actor::GetCurrentSize() const
1414 // mNode is being used in a separate thread; copy the value from the previous update
1415 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1418 return Vector3::ZERO;
1421 Vector3 Actor::GetNaturalSize() const
1423 // It is up to deriving classes to return the appropriate natural size
1424 return Vector3( 0.0f, 0.0f, 0.0f );
1427 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1429 EnsureRelayoutData();
1431 ResizePolicy::Type originalWidthPolicy = GetResizePolicy(Dimension::WIDTH);
1432 ResizePolicy::Type originalHeightPolicy = GetResizePolicy(Dimension::HEIGHT);
1434 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1436 if( dimension & ( 1 << i ) )
1438 if ( policy == ResizePolicy::USE_ASSIGNED_SIZE )
1440 mRelayoutData->useAssignedSize[ i ] = true;
1444 mRelayoutData->resizePolicies[ i ] = policy;
1445 mRelayoutData->useAssignedSize[ i ] = false;
1450 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1452 if( dimension & Dimension::WIDTH )
1454 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1457 if( dimension & Dimension::HEIGHT )
1459 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1463 // If calling SetResizePolicy, assume we want relayout enabled
1464 SetRelayoutEnabled( true );
1466 // If the resize policy is set to be FIXED, the preferred size
1467 // should be overrided by the target size. Otherwise the target
1468 // size should be overrided by the preferred size.
1470 if( dimension & Dimension::WIDTH )
1472 if( originalWidthPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1474 mRelayoutData->preferredSize.width = mTargetSize.width;
1476 else if( originalWidthPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1478 mTargetSize.width = mRelayoutData->preferredSize.width;
1482 if( dimension & Dimension::HEIGHT )
1484 if( originalHeightPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1486 mRelayoutData->preferredSize.height = mTargetSize.height;
1488 else if( originalHeightPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1490 mTargetSize.height = mRelayoutData->preferredSize.height;
1494 OnSetResizePolicy( policy, dimension );
1496 // Trigger relayout on this control
1500 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1502 if ( mRelayoutData )
1504 // If more than one dimension is requested, just return the first one found
1505 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1507 if( ( dimension & ( 1 << i ) ) )
1509 if( mRelayoutData->useAssignedSize[ i ] )
1511 return ResizePolicy::USE_ASSIGNED_SIZE;
1515 return mRelayoutData->resizePolicies[ i ];
1521 return ResizePolicy::DEFAULT;
1524 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1526 EnsureRelayoutData();
1528 mRelayoutData->sizeSetPolicy = policy;
1531 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1533 if ( mRelayoutData )
1535 return mRelayoutData->sizeSetPolicy;
1538 return DEFAULT_SIZE_SCALE_POLICY;
1541 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1543 EnsureRelayoutData();
1545 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1547 if( dimension & ( 1 << i ) )
1549 mRelayoutData->dimensionDependencies[ i ] = dependency;
1554 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1556 if ( mRelayoutData )
1558 // If more than one dimension is requested, just return the first one found
1559 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1561 if( ( dimension & ( 1 << i ) ) )
1563 return mRelayoutData->dimensionDependencies[ i ];
1568 return Dimension::ALL_DIMENSIONS; // Default
1571 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1573 // If relayout data has not been allocated yet and the client is requesting
1574 // to disable it, do nothing
1575 if( mRelayoutData || relayoutEnabled )
1577 EnsureRelayoutData();
1579 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1581 mRelayoutData->relayoutEnabled = relayoutEnabled;
1585 bool Actor::IsRelayoutEnabled() const
1587 // Assume that if relayout data has not been allocated yet then
1588 // relayout is disabled
1589 return mRelayoutData && mRelayoutData->relayoutEnabled;
1592 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1594 EnsureRelayoutData();
1596 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1598 if( dimension & ( 1 << i ) )
1600 mRelayoutData->dimensionDirty[ i ] = dirty;
1605 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1607 if ( mRelayoutData )
1609 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1611 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1621 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1623 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1626 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1628 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1631 unsigned int Actor::AddRenderer( Renderer& renderer )
1635 mRenderers = new RendererContainer;
1638 unsigned int index = mRenderers->size();
1639 RendererPtr rendererPtr = RendererPtr( &renderer );
1640 mRenderers->push_back( rendererPtr );
1641 AddRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1645 unsigned int Actor::GetRendererCount() const
1647 unsigned int rendererCount(0);
1650 rendererCount = mRenderers->size();
1653 return rendererCount;
1656 RendererPtr Actor::GetRendererAt( unsigned int index )
1658 RendererPtr renderer;
1659 if( index < GetRendererCount() )
1661 renderer = ( *mRenderers )[ index ];
1667 void Actor::RemoveRenderer( Renderer& renderer )
1671 RendererIter end = mRenderers->end();
1672 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1674 if( (*iter).Get() == &renderer )
1676 mRenderers->erase( iter );
1677 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1684 void Actor::RemoveRenderer( unsigned int index )
1686 if( index < GetRendererCount() )
1688 RendererPtr renderer = ( *mRenderers )[ index ];
1689 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.Get()->GetRendererSceneObject() );
1690 mRenderers->erase( mRenderers->begin()+index );
1694 bool Actor::IsOverlay() const
1696 return ( DrawMode::OVERLAY_2D == mDrawMode );
1699 void Actor::SetDrawMode( DrawMode::Type drawMode )
1701 // this flag is not animatable so keep the value
1702 mDrawMode = drawMode;
1703 if( ( NULL != mNode ) && ( drawMode != DrawMode::STENCIL ) )
1705 // mNode is being used in a separate thread; queue a message to set the value
1706 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1710 DrawMode::Type Actor::GetDrawMode() const
1715 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1717 // only valid when on-stage
1718 StagePtr stage = Stage::GetCurrent();
1719 if( stage && OnStage() )
1721 const RenderTaskList& taskList = stage->GetRenderTaskList();
1723 Vector2 converted( screenX, screenY );
1725 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1726 const int taskCount = taskList.GetTaskCount();
1727 for( int i = taskCount - 1; i >= 0; --i )
1729 Dali::RenderTask task = taskList.GetTask( i );
1730 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1732 // found a task where this conversion was ok so return
1740 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1742 bool retval = false;
1743 // only valid when on-stage
1746 CameraActor* camera = renderTask.GetCameraActor();
1750 renderTask.GetViewport( viewport );
1752 // need to translate coordinates to render tasks coordinate space
1753 Vector2 converted( screenX, screenY );
1754 if( renderTask.TranslateCoordinates( converted ) )
1756 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1763 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1765 // Early-out if mNode is NULL
1771 // Get the ModelView matrix
1773 Matrix::Multiply( modelView, mNode->GetWorldMatrix(0), viewMatrix );
1775 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1776 Matrix invertedMvp( false/*don't init*/);
1777 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1778 bool success = invertedMvp.Invert();
1780 // Convert to GL coordinates
1781 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1786 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1793 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1799 if( XyPlaneIntersect( nearPos, farPos, local ) )
1801 Vector3 size = GetCurrentSize();
1802 localX = local.x + size.x * 0.5f;
1803 localY = local.y + size.y * 0.5f;
1814 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1817 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1819 Mathematical Formulation
1821 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1823 ( p - c ) dot ( p - c ) = r^2
1825 Given a ray with a point of origin 'o', and a direction vector 'd':
1827 ray(t) = o + td, t >= 0
1829 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1831 (o + td - c ) dot ( o + td - c ) = r^2
1833 To solve for t we first expand the above into a more recognisable quadratic equation form
1835 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1844 B = 2( o - c ) dot d
1845 C = ( o - c ) dot ( o - c ) - r^2
1847 which can be solved using a standard quadratic formula.
1849 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1851 Practical Simplification
1853 In a renderer, we often differentiate between world space and object space. In the object space
1854 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1855 into object space, the mathematical solution presented above can be simplified significantly.
1857 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1861 and we can find the t at which the (transformed) ray intersects the sphere by
1863 ( o + td ) dot ( o + td ) = r^2
1865 According to the reasoning above, we expand the above quadratic equation into the general form
1869 which now has coefficients:
1876 // Early out if mNode is NULL
1882 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1884 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1885 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1886 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1888 // Compute the radius is not needed, square radius it's enough.
1889 const Vector3& size( mNode->GetSize( bufferIndex ) );
1891 // Scale the sphere.
1892 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1894 const float width = size.width * scale.width;
1895 const float height = size.height * scale.height;
1897 float squareSphereRadius = 0.5f * ( width * width + height * height );
1899 float a = rayDir.Dot( rayDir ); // a
1900 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1901 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1903 return ( b2 * b2 - a * c ) >= 0.f;
1906 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector2& hitPointLocal, float& distance ) const
1910 if( OnStage() && NULL != mNode )
1912 // Transforms the ray to the local reference system.
1913 // Calculate the inverse of Model matrix
1914 Matrix invModelMatrix( false/*don't init*/);
1916 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1917 invModelMatrix = mNode->GetWorldMatrix(0);
1918 invModelMatrix.Invert();
1920 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1921 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1923 // Test with the actor's XY plane (Normal = 0 0 1 1).
1925 float a = -rayOriginLocal.z;
1926 float b = rayDirLocal.z;
1928 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1930 // Ray travels distance * rayDirLocal to intersect with plane.
1933 const Vector3& size = mNode->GetSize( bufferIndex );
1935 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1936 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1938 // Test with the actor's geometry.
1939 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1946 void Actor::SetLeaveRequired( bool required )
1948 mLeaveRequired = required;
1951 bool Actor::GetLeaveRequired() const
1953 return mLeaveRequired;
1956 void Actor::SetKeyboardFocusable( bool focusable )
1958 mKeyboardFocusable = focusable;
1961 bool Actor::IsKeyboardFocusable() const
1963 return mKeyboardFocusable;
1966 bool Actor::GetTouchRequired() const
1968 return !mTouchedSignal.Empty() || !mTouchSignal.Empty() || mDerivedRequiresTouch;
1971 bool Actor::GetHoverRequired() const
1973 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1976 bool Actor::GetWheelEventRequired() const
1978 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1981 bool Actor::IsHittable() const
1983 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1986 ActorGestureData& Actor::GetGestureData()
1988 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1989 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1990 if( NULL == mGestureData )
1992 mGestureData = new ActorGestureData;
1994 return *mGestureData;
1997 bool Actor::IsGestureRequred( Gesture::Type type ) const
1999 return mGestureData && mGestureData->IsGestureRequred( type );
2002 bool Actor::EmitTouchEventSignal( const TouchEvent& event, const Dali::TouchData& touch )
2004 bool consumed = false;
2006 if( !mTouchSignal.Empty() )
2008 Dali::Actor handle( this );
2009 consumed = mTouchSignal.Emit( handle, touch );
2012 if( !mTouchedSignal.Empty() )
2014 Dali::Actor handle( this );
2015 consumed |= mTouchedSignal.Emit( handle, event );
2020 // Notification for derived classes
2021 consumed = OnTouchEvent( event ); // TODO
2027 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
2029 bool consumed = false;
2031 if( !mHoveredSignal.Empty() )
2033 Dali::Actor handle( this );
2034 consumed = mHoveredSignal.Emit( handle, event );
2039 // Notification for derived classes
2040 consumed = OnHoverEvent( event );
2046 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
2048 bool consumed = false;
2050 if( !mWheelEventSignal.Empty() )
2052 Dali::Actor handle( this );
2053 consumed = mWheelEventSignal.Emit( handle, event );
2058 // Notification for derived classes
2059 consumed = OnWheelEvent( event );
2065 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
2067 if( ! mVisibilityChangedSignal.Empty() )
2069 Dali::Actor handle( this );
2070 mVisibilityChangedSignal.Emit( handle, visible, type );
2074 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
2076 return mTouchedSignal;
2079 Dali::Actor::TouchDataSignalType& Actor::TouchSignal()
2081 return mTouchSignal;
2084 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
2086 return mHoveredSignal;
2089 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
2091 return mWheelEventSignal;
2094 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
2096 return mOnStageSignal;
2099 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
2101 return mOffStageSignal;
2104 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
2106 return mOnRelayoutSignal;
2109 DevelActor::VisibilityChangedSignalType& Actor::VisibilityChangedSignal()
2111 return mVisibilityChangedSignal;
2114 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
2116 bool connected( true );
2117 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
2119 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
2121 actor->TouchedSignal().Connect( tracker, functor );
2123 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
2125 actor->HoveredSignal().Connect( tracker, functor );
2127 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
2129 actor->WheelEventSignal().Connect( tracker, functor );
2131 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
2133 actor->OnStageSignal().Connect( tracker, functor );
2135 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
2137 actor->OffStageSignal().Connect( tracker, functor );
2139 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
2141 actor->OnRelayoutSignal().Connect( tracker, functor );
2143 else if( 0 == signalName.compare( SIGNAL_TOUCH ) )
2145 actor->TouchSignal().Connect( tracker, functor );
2149 // signalName does not match any signal
2156 Actor::Actor( DerivedType derivedType )
2161 mParentOrigin( NULL ),
2162 mAnchorPoint( NULL ),
2163 mRelayoutData( NULL ),
2164 mGestureData( NULL ),
2165 mTargetOrientation( Quaternion::IDENTITY ),
2166 mTargetColor( Color::WHITE ),
2167 mTargetSize( Vector3::ZERO ),
2168 mTargetPosition( Vector3::ZERO ),
2169 mTargetScale( Vector3::ONE ),
2171 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
2175 mIsRoot( ROOT_LAYER == derivedType ),
2176 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2177 mIsOnStage( false ),
2179 mLeaveRequired( false ),
2180 mKeyboardFocusable( false ),
2181 mDerivedRequiresTouch( false ),
2182 mDerivedRequiresHover( false ),
2183 mDerivedRequiresWheelEvent( false ),
2184 mOnStageSignalled( false ),
2185 mInsideOnSizeSet( false ),
2186 mInheritPosition( true ),
2187 mInheritOrientation( true ),
2188 mInheritScale( true ),
2189 mPositionUsesAnchorPoint( true ),
2191 mDrawMode( DrawMode::NORMAL ),
2192 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2193 mColorMode( Node::DEFAULT_COLOR_MODE ),
2194 mClippingMode( ClippingMode::DISABLED )
2198 void Actor::Initialize()
2201 SceneGraph::Node* node = CreateNode();
2203 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
2204 mNode = node; // Keep raw-pointer to Node
2208 GetEventThreadServices().RegisterObject( this );
2213 // Remove mParent pointers from children even if we're destroying core,
2214 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2217 ActorConstIter endIter = mChildren->end();
2218 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2220 (*iter)->SetParent( NULL );
2226 // Guard to allow handle destruction after Core has been destroyed
2227 if( EventThreadServices::IsCoreRunning() )
2231 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2232 mNode = NULL; // Node is about to be destroyed
2235 GetEventThreadServices().UnregisterObject( this );
2238 // Cleanup optional gesture data
2239 delete mGestureData;
2241 // Cleanup optional parent origin and anchor
2242 delete mParentOrigin;
2243 delete mAnchorPoint;
2245 // Delete optional relayout data
2248 delete mRelayoutData;
2252 void Actor::ConnectToStage( unsigned int parentDepth )
2254 // This container is used instead of walking the Actor hierarchy.
2255 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
2256 ActorContainer connectionList;
2258 StagePtr stage = Stage::GetCurrent();
2261 stage->RequestRebuildDepthTree();
2264 // This stage is atomic i.e. not interrupted by user callbacks.
2265 RecursiveConnectToStage( connectionList, parentDepth + 1 );
2267 // Notify applications about the newly connected actors.
2268 const ActorIter endIter = connectionList.end();
2269 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2271 (*iter)->NotifyStageConnection();
2277 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth )
2279 DALI_ASSERT_ALWAYS( !OnStage() );
2284 ConnectToSceneGraph();
2286 // Notification for internal derived classes
2287 OnStageConnectionInternal();
2289 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2290 connectionList.push_back( ActorPtr( this ) );
2292 // Recursively connect children
2295 ActorConstIter endIter = mChildren->end();
2296 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2298 (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
2304 * This method is called when the Actor is connected to the Stage.
2305 * The parent must have added its Node to the scene-graph.
2306 * The child must connect its Node to the parent's Node.
2307 * This is recursive; the child calls ConnectToStage() for its children.
2309 void Actor::ConnectToSceneGraph()
2311 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2315 // Reparent Node in next Update
2316 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode );
2319 // Request relayout on all actors that are added to the scenegraph
2322 // Notification for Object::Observers
2326 void Actor::NotifyStageConnection()
2328 // Actors can be removed (in a callback), before the on-stage stage is reported.
2329 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2330 if( OnStage() && !mOnStageSignalled )
2332 // Notification for external (CustomActor) derived classes
2333 OnStageConnectionExternal( mDepth );
2335 if( !mOnStageSignal.Empty() )
2337 Dali::Actor handle( this );
2338 mOnStageSignal.Emit( handle );
2341 // Guard against Remove during callbacks
2344 mOnStageSignalled = true; // signal required next time Actor is removed
2349 void Actor::DisconnectFromStage()
2351 // This container is used instead of walking the Actor hierachy.
2352 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2353 ActorContainer disconnectionList;
2355 StagePtr stage = Stage::GetCurrent();
2358 stage->RequestRebuildDepthTree();
2361 // This stage is atomic i.e. not interrupted by user callbacks
2362 RecursiveDisconnectFromStage( disconnectionList );
2364 // Notify applications about the newly disconnected actors.
2365 const ActorIter endIter = disconnectionList.end();
2366 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2368 (*iter)->NotifyStageDisconnection();
2372 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2374 DALI_ASSERT_ALWAYS( OnStage() );
2376 // Recursively disconnect children
2379 ActorConstIter endIter = mChildren->end();
2380 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2382 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2386 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2387 disconnectionList.push_back( ActorPtr( this ) );
2389 // Notification for internal derived classes
2390 OnStageDisconnectionInternal();
2392 DisconnectFromSceneGraph();
2398 * This method is called by an actor or its parent, before a node removal message is sent.
2399 * This is recursive; the child calls DisconnectFromStage() for its children.
2401 void Actor::DisconnectFromSceneGraph()
2403 // Notification for Object::Observers
2404 OnSceneObjectRemove();
2407 void Actor::NotifyStageDisconnection()
2409 // Actors can be added (in a callback), before the off-stage state is reported.
2410 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2411 // only do this step if there is a stage, i.e. Core is not being shut down
2412 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2414 // Notification for external (CustomeActor) derived classes
2415 OnStageDisconnectionExternal();
2417 if( !mOffStageSignal.Empty() )
2419 Dali::Actor handle( this );
2420 mOffStageSignal.Emit( handle );
2423 // Guard against Add during callbacks
2426 mOnStageSignalled = false; // signal required next time Actor is added
2431 bool Actor::IsNodeConnected() const
2433 bool connected( false );
2435 if( OnStage() && ( NULL != mNode ) )
2437 if( IsRoot() || mNode->GetParent() )
2446 // This method generates the depth tree using the recursive function below,
2447 // then walks the tree and sets a depth index based on traversal order. It
2448 // sends a single message to update manager to update all the actor's nodes in this
2449 // tree with the depth index. The sceneGraphNodeDepths vector's elements are ordered
2450 // by depth, and could be used to reduce sorting in the update thread.
2451 void Actor::RebuildDepthTree()
2453 DALI_LOG_TIMER_START(depthTimer);
2455 DepthNodeMemoryPool nodeMemoryPool;
2456 ActorDepthTreeNode* rootNode = new (nodeMemoryPool.AllocateRaw()) ActorDepthTreeNode( this, mSiblingOrder );
2458 int actorCount = BuildDepthTree( nodeMemoryPool, rootNode );
2460 // Vector of scene-graph nodes and their depths to send to UpdateManager
2461 // in a single message
2462 SceneGraph::NodeDepths* sceneGraphNodeDepths = new SceneGraph::NodeDepths(actorCount);
2464 // Traverse depth tree and set mSortedDepth on each actor and scenegraph node
2465 uint32_t sortOrder = 1u; // Don't start at zero, as visual depth can be negative
2466 ActorDepthTreeNode* currentNode = rootNode;
2467 bool firstVisit = true;
2468 while( currentNode != rootNode || firstVisit)
2472 // Visit node, performing action
2473 for( std::vector<Actor*>::iterator iter = currentNode->mActors.begin(); iter != currentNode->mActors.end(); ++iter )
2475 (*iter)->mSortedDepth = sortOrder * DevelLayer::SIBLING_ORDER_MULTIPLIER;
2476 sceneGraphNodeDepths->Add( const_cast<SceneGraph::Node*>((*iter)->mNode), (*iter)->mSortedDepth );
2481 if( currentNode->mFirstChildNode )
2483 currentNode = currentNode->mFirstChildNode;
2485 else // leaf node, goto next sibling, or return up tree.
2487 bool breakout=false;
2488 while( ! currentNode->mNextSiblingNode )
2490 if( currentNode == rootNode ) // If we get to root of tree, stop
2495 currentNode = currentNode->mParentNode;
2502 currentNode = currentNode->mNextSiblingNode;
2506 SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths );
2507 DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree create time: ");
2511 * Structure to store the actor's associated node in the depth tree for child
2514 struct ActorNodePair
2517 ActorDepthTreeNode* node;
2518 ActorNodePair( Actor* actor, ActorDepthTreeNode* node )
2526 * Descend actor tree, building a depth tree based on actor's sibling order.
2527 * Actors with the same sibling order share the same depth tree. Siblings
2528 * in the depth tree are ordered by actor's sibling order.
2530 * An actor tree like this:
2537 * A(SO:1) B(SO:2) C(SO:1)
2540 * D(SO:0) E(SO:0) F(SO:0) G(SO:1) H(SO:0)
2542 * will end up as a depth tree like this:
2544 * RootNode [ Root ] -> NULL
2547 * Node [ A, C ] ------------------------> Node [ B ] -> NULL
2550 * Node [ D, E, H ] -> Node [ G ] -> NULL Node [ F ] -> NULL
2555 * (All nodes also point to their parents to enable storage free traversal)
2557 int Actor::BuildDepthTree( DepthNodeMemoryPool& nodeMemoryPool, ActorDepthTreeNode* node )
2559 int treeCount=1; // Count self and children
2561 // Create/add to children of this node
2564 std::vector<ActorNodePair> storedChildren;
2565 storedChildren.reserve( mChildren->size() );
2567 for( ActorContainer::iterator it = mChildren->begin(); it != mChildren->end(); ++it )
2569 Actor* childActor = (*it).Get();
2570 if( childActor->IsLayer() )
2572 Layer* layer = static_cast<Layer*>(childActor);
2573 if( layer->GetBehavior() == Dali::Layer::LAYER_3D )
2575 // Ignore this actor and children.
2580 // If no existing depth node children
2581 if( node->mFirstChildNode == NULL )
2583 node->mFirstChildNode = new (nodeMemoryPool.AllocateRaw()) ActorDepthTreeNode( childActor, childActor->mSiblingOrder );
2584 node->mFirstChildNode->mParentNode = node;
2585 storedChildren.push_back(ActorNodePair( childActor, node->mFirstChildNode ));
2587 else // find child node with matching sibling order (insertion sort)
2589 bool addedChildActor = false;
2591 // depth tree child nodes ordered by sibling order
2592 ActorDepthTreeNode* lastNode = NULL;
2593 for( ActorDepthTreeNode* childNode = node->mFirstChildNode; childNode != NULL; childNode = childNode->mNextSiblingNode )
2595 uint16_t actorSiblingOrder = childActor->mSiblingOrder;
2596 uint16_t currentSiblingOrder = childNode->GetSiblingOrder();
2598 if( actorSiblingOrder == currentSiblingOrder )
2600 // Don't need a new depth node, add to existing node
2601 childNode->AddActor( childActor );
2602 storedChildren.push_back(ActorNodePair( childActor, childNode ));
2603 addedChildActor = true;
2606 else if( actorSiblingOrder < currentSiblingOrder )
2610 lastNode = childNode;
2613 // No matching sibling order - create new node and insert into sibling list
2614 if( !addedChildActor )
2616 ActorDepthTreeNode* newNode = new (nodeMemoryPool.AllocateRaw()) ActorDepthTreeNode( childActor, childActor->mSiblingOrder );
2618 newNode->mParentNode = node;
2619 storedChildren.push_back(ActorNodePair( childActor, newNode ));
2621 if( lastNode == NULL ) // Insert at start of siblings
2623 ActorDepthTreeNode* nextNode = node->mFirstChildNode;
2624 node->mFirstChildNode = newNode;
2625 newNode->mNextSiblingNode = nextNode;
2627 else // insert into siblings after last node
2629 newNode->mNextSiblingNode = lastNode->mNextSiblingNode;
2630 lastNode->mNextSiblingNode = newNode;
2636 // Order of descent doesn't matter; we're using insertion to sort.
2637 for( std::vector<ActorNodePair>::iterator iter = storedChildren.begin(); iter != storedChildren.end(); ++iter )
2639 treeCount += iter->actor->BuildDepthTree( nodeMemoryPool, iter->node );
2645 unsigned int Actor::GetDefaultPropertyCount() const
2647 return DEFAULT_PROPERTY_COUNT;
2650 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2652 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2654 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2656 indices.PushBack( i );
2660 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2662 if( index < DEFAULT_PROPERTY_COUNT )
2664 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2670 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2672 Property::Index index = Property::INVALID_INDEX;
2674 // Look for name in default properties
2675 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2677 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2678 if( 0 == name.compare( property->name ) )
2688 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2690 if( index < DEFAULT_PROPERTY_COUNT )
2692 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2698 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2700 if( index < DEFAULT_PROPERTY_COUNT )
2702 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2708 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2710 if( index < DEFAULT_PROPERTY_COUNT )
2712 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2718 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2720 if( index < DEFAULT_PROPERTY_COUNT )
2722 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2725 // index out of range...return Property::NONE
2726 return Property::NONE;
2729 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2733 case Dali::Actor::Property::PARENT_ORIGIN:
2735 Property::Type type = property.GetType();
2736 if( type == Property::VECTOR3 )
2738 SetParentOrigin( property.Get< Vector3 >() );
2740 else if ( type == Property::STRING )
2742 std::string parentOriginString;
2743 property.Get( parentOriginString );
2744 Vector3 parentOrigin;
2745 if( GetParentOriginConstant( parentOriginString, parentOrigin ) )
2747 SetParentOrigin( parentOrigin );
2753 case Dali::Actor::Property::PARENT_ORIGIN_X:
2755 SetParentOriginX( property.Get< float >() );
2759 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2761 SetParentOriginY( property.Get< float >() );
2765 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2767 SetParentOriginZ( property.Get< float >() );
2771 case Dali::Actor::Property::ANCHOR_POINT:
2773 Property::Type type = property.GetType();
2774 if( type == Property::VECTOR3 )
2776 SetAnchorPoint( property.Get< Vector3 >() );
2778 else if ( type == Property::STRING )
2780 std::string anchorPointString;
2781 property.Get( anchorPointString );
2783 if( GetAnchorPointConstant( anchorPointString, anchor ) )
2785 SetAnchorPoint( anchor );
2791 case Dali::Actor::Property::ANCHOR_POINT_X:
2793 SetAnchorPointX( property.Get< float >() );
2797 case Dali::Actor::Property::ANCHOR_POINT_Y:
2799 SetAnchorPointY( property.Get< float >() );
2803 case Dali::Actor::Property::ANCHOR_POINT_Z:
2805 SetAnchorPointZ( property.Get< float >() );
2809 case Dali::Actor::Property::SIZE:
2811 SetSize( property.Get< Vector3 >() );
2815 case Dali::Actor::Property::SIZE_WIDTH:
2817 SetWidth( property.Get< float >() );
2821 case Dali::Actor::Property::SIZE_HEIGHT:
2823 SetHeight( property.Get< float >() );
2827 case Dali::Actor::Property::SIZE_DEPTH:
2829 SetDepth( property.Get< float >() );
2833 case Dali::Actor::Property::POSITION:
2835 SetPosition( property.Get< Vector3 >() );
2839 case Dali::Actor::Property::POSITION_X:
2841 SetX( property.Get< float >() );
2845 case Dali::Actor::Property::POSITION_Y:
2847 SetY( property.Get< float >() );
2851 case Dali::Actor::Property::POSITION_Z:
2853 SetZ( property.Get< float >() );
2857 case Dali::Actor::Property::ORIENTATION:
2859 SetOrientation( property.Get< Quaternion >() );
2863 case Dali::Actor::Property::SCALE:
2865 SetScale( property.Get< Vector3 >() );
2869 case Dali::Actor::Property::SCALE_X:
2871 SetScaleX( property.Get< float >() );
2875 case Dali::Actor::Property::SCALE_Y:
2877 SetScaleY( property.Get< float >() );
2881 case Dali::Actor::Property::SCALE_Z:
2883 SetScaleZ( property.Get< float >() );
2887 case Dali::Actor::Property::VISIBLE:
2889 SetVisible( property.Get< bool >() );
2893 case Dali::Actor::Property::COLOR:
2895 SetColor( property.Get< Vector4 >() );
2899 case Dali::Actor::Property::COLOR_RED:
2901 SetColorRed( property.Get< float >() );
2905 case Dali::Actor::Property::COLOR_GREEN:
2907 SetColorGreen( property.Get< float >() );
2911 case Dali::Actor::Property::COLOR_BLUE:
2913 SetColorBlue( property.Get< float >() );
2917 case Dali::Actor::Property::COLOR_ALPHA:
2918 case Dali::DevelActor::Property::OPACITY:
2921 if( property.Get( value ) )
2923 SetOpacity( value );
2928 case Dali::Actor::Property::NAME:
2930 SetName( property.Get< std::string >() );
2934 case Dali::Actor::Property::SENSITIVE:
2936 SetSensitive( property.Get< bool >() );
2940 case Dali::Actor::Property::LEAVE_REQUIRED:
2942 SetLeaveRequired( property.Get< bool >() );
2946 case Dali::Actor::Property::INHERIT_POSITION:
2948 SetInheritPosition( property.Get< bool >() );
2952 case Dali::Actor::Property::INHERIT_ORIENTATION:
2954 SetInheritOrientation( property.Get< bool >() );
2958 case Dali::Actor::Property::INHERIT_SCALE:
2960 SetInheritScale( property.Get< bool >() );
2964 case Dali::Actor::Property::COLOR_MODE:
2966 ColorMode mode = mColorMode;
2967 if ( Scripting::GetEnumerationProperty< ColorMode >( property, COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT, mode ) )
2969 SetColorMode( mode );
2974 case Dali::Actor::Property::POSITION_INHERITANCE:
2976 PositionInheritanceMode mode = mPositionInheritanceMode;
2977 if( Scripting::GetEnumerationProperty< PositionInheritanceMode >( property, POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT, mode ) )
2979 SetPositionInheritanceMode( mode );
2984 case Dali::Actor::Property::DRAW_MODE:
2986 DrawMode::Type mode = mDrawMode;
2987 if( Scripting::GetEnumerationProperty< DrawMode::Type >( property, DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT, mode ) )
2989 SetDrawMode( mode );
2994 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2996 SetSizeModeFactor( property.Get< Vector3 >() );
3000 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3002 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
3003 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
3005 SetResizePolicy( type, Dimension::WIDTH );
3010 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3012 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
3013 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
3015 SetResizePolicy( type, Dimension::HEIGHT );
3020 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3022 SizeScalePolicy::Type type;
3023 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT, type ) )
3025 SetSizeScalePolicy( type );
3030 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3032 if( property.Get< bool >() )
3034 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
3039 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3041 if( property.Get< bool >() )
3043 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
3048 case Dali::Actor::Property::PADDING:
3050 Vector4 padding = property.Get< Vector4 >();
3051 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
3052 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
3056 case Dali::Actor::Property::MINIMUM_SIZE:
3058 Vector2 size = property.Get< Vector2 >();
3059 SetMinimumSize( size.x, Dimension::WIDTH );
3060 SetMinimumSize( size.y, Dimension::HEIGHT );
3064 case Dali::Actor::Property::MAXIMUM_SIZE:
3066 Vector2 size = property.Get< Vector2 >();
3067 SetMaximumSize( size.x, Dimension::WIDTH );
3068 SetMaximumSize( size.y, Dimension::HEIGHT );
3072 case Dali::DevelActor::Property::SIBLING_ORDER:
3076 if( property.Get( value ) )
3078 if( static_cast<unsigned int>(value) != mSiblingOrder )
3080 SetSiblingOrder( value );
3086 case Dali::Actor::Property::CLIPPING_MODE:
3088 ClippingMode::Type convertedValue = mClippingMode;
3089 if( Scripting::GetEnumerationProperty< ClippingMode::Type >( property, CLIPPING_MODE_TABLE, CLIPPING_MODE_TABLE_COUNT, convertedValue ) )
3091 mClippingMode = convertedValue;
3094 SetClippingModeMessage( GetEventThreadServices(), *mNode, mClippingMode );
3100 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
3103 if( property.Get( value ) && value != mPositionUsesAnchorPoint )
3105 mPositionUsesAnchorPoint = value;
3108 SetPositionUsesAnchorPointMessage( GetEventThreadServices(), *mNode, mPositionUsesAnchorPoint );
3116 // this can happen in the case of a non-animatable default property so just do nothing
3122 // TODO: This method needs to be removed
3123 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
3125 switch( entry.GetType() )
3127 case Property::BOOLEAN:
3129 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
3130 DALI_ASSERT_DEBUG( NULL != property );
3132 // property is being used in a separate thread; queue a message to set the property
3133 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
3138 case Property::INTEGER:
3140 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
3141 DALI_ASSERT_DEBUG( NULL != property );
3143 // property is being used in a separate thread; queue a message to set the property
3144 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
3149 case Property::FLOAT:
3151 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( 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 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
3160 case Property::VECTOR2:
3162 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
3163 DALI_ASSERT_DEBUG( NULL != property );
3165 // property is being used in a separate thread; queue a message to set the property
3166 if(entry.componentIndex == 0)
3168 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
3170 else if(entry.componentIndex == 1)
3172 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
3176 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
3182 case Property::VECTOR3:
3184 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
3185 DALI_ASSERT_DEBUG( NULL != property );
3187 // property is being used in a separate thread; queue a message to set the property
3188 if(entry.componentIndex == 0)
3190 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
3192 else if(entry.componentIndex == 1)
3194 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
3196 else if(entry.componentIndex == 2)
3198 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
3202 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
3208 case Property::VECTOR4:
3210 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
3211 DALI_ASSERT_DEBUG( NULL != property );
3213 // property is being used in a separate thread; queue a message to set the property
3214 if(entry.componentIndex == 0)
3216 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
3218 else if(entry.componentIndex == 1)
3220 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
3222 else if(entry.componentIndex == 2)
3224 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
3226 else if(entry.componentIndex == 3)
3228 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
3232 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3238 case Property::ROTATION:
3240 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3241 DALI_ASSERT_DEBUG( NULL != property );
3243 // property is being used in a separate thread; queue a message to set the property
3244 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3249 case Property::MATRIX:
3251 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3252 DALI_ASSERT_DEBUG( NULL != property );
3254 // property is being used in a separate thread; queue a message to set the property
3255 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3260 case Property::MATRIX3:
3262 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3263 DALI_ASSERT_DEBUG( NULL != property );
3265 // property is being used in a separate thread; queue a message to set the property
3266 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3273 // nothing to do for other types
3278 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3280 Property::Value value;
3282 if( ! GetCachedPropertyValue( index, value ) )
3284 // If property value is not stored in the event-side, then it must be a scene-graph only property
3285 GetCurrentPropertyValue( index, value );
3291 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
3293 Property::Value value;
3295 if( ! GetCurrentPropertyValue( index, value ) )
3297 // If unable to retrieve scene-graph property value, then it must be an event-side only property
3298 GetCachedPropertyValue( index, value );
3304 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3309 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3311 // This method should only return an object connected to the scene-graph
3312 return OnStage() ? mNode : NULL;
3315 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3317 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3319 const PropertyBase* property( NULL );
3321 // This method should only return a property of an object connected to the scene-graph
3327 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3329 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3330 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3332 property = animatable->GetSceneGraphProperty();
3334 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3335 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3337 CustomPropertyMetadata* custom = FindCustomProperty( index );
3338 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3340 property = custom->GetSceneGraphProperty();
3342 else if( NULL != mNode )
3346 case Dali::Actor::Property::SIZE:
3347 property = &mNode->mSize;
3350 case Dali::Actor::Property::SIZE_WIDTH:
3351 property = &mNode->mSize;
3354 case Dali::Actor::Property::SIZE_HEIGHT:
3355 property = &mNode->mSize;
3358 case Dali::Actor::Property::SIZE_DEPTH:
3359 property = &mNode->mSize;
3362 case Dali::Actor::Property::POSITION:
3363 property = &mNode->mPosition;
3366 case Dali::Actor::Property::POSITION_X:
3367 property = &mNode->mPosition;
3370 case Dali::Actor::Property::POSITION_Y:
3371 property = &mNode->mPosition;
3374 case Dali::Actor::Property::POSITION_Z:
3375 property = &mNode->mPosition;
3378 case Dali::Actor::Property::ORIENTATION:
3379 property = &mNode->mOrientation;
3382 case Dali::Actor::Property::SCALE:
3383 property = &mNode->mScale;
3386 case Dali::Actor::Property::SCALE_X:
3387 property = &mNode->mScale;
3390 case Dali::Actor::Property::SCALE_Y:
3391 property = &mNode->mScale;
3394 case Dali::Actor::Property::SCALE_Z:
3395 property = &mNode->mScale;
3398 case Dali::Actor::Property::VISIBLE:
3399 property = &mNode->mVisible;
3402 case Dali::Actor::Property::COLOR:
3403 property = &mNode->mColor;
3406 case Dali::Actor::Property::COLOR_RED:
3407 property = &mNode->mColor;
3410 case Dali::Actor::Property::COLOR_GREEN:
3411 property = &mNode->mColor;
3414 case Dali::Actor::Property::COLOR_BLUE:
3415 property = &mNode->mColor;
3418 case Dali::Actor::Property::COLOR_ALPHA:
3419 case Dali::DevelActor::Property::OPACITY:
3420 property = &mNode->mColor;
3431 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3433 const PropertyInputImpl* property( NULL );
3435 // This method should only return a property of an object connected to the scene-graph
3441 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3443 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3444 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3446 property = animatable->GetSceneGraphProperty();
3448 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3449 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3451 CustomPropertyMetadata* custom = FindCustomProperty( index );
3452 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3453 property = custom->GetSceneGraphProperty();
3455 else if( NULL != mNode )
3459 case Dali::Actor::Property::PARENT_ORIGIN:
3460 property = &mNode->mParentOrigin;
3463 case Dali::Actor::Property::PARENT_ORIGIN_X:
3464 property = &mNode->mParentOrigin;
3467 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3468 property = &mNode->mParentOrigin;
3471 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3472 property = &mNode->mParentOrigin;
3475 case Dali::Actor::Property::ANCHOR_POINT:
3476 property = &mNode->mAnchorPoint;
3479 case Dali::Actor::Property::ANCHOR_POINT_X:
3480 property = &mNode->mAnchorPoint;
3483 case Dali::Actor::Property::ANCHOR_POINT_Y:
3484 property = &mNode->mAnchorPoint;
3487 case Dali::Actor::Property::ANCHOR_POINT_Z:
3488 property = &mNode->mAnchorPoint;
3491 case Dali::Actor::Property::SIZE:
3492 property = &mNode->mSize;
3495 case Dali::Actor::Property::SIZE_WIDTH:
3496 property = &mNode->mSize;
3499 case Dali::Actor::Property::SIZE_HEIGHT:
3500 property = &mNode->mSize;
3503 case Dali::Actor::Property::SIZE_DEPTH:
3504 property = &mNode->mSize;
3507 case Dali::Actor::Property::POSITION:
3508 property = &mNode->mPosition;
3511 case Dali::Actor::Property::POSITION_X:
3512 property = &mNode->mPosition;
3515 case Dali::Actor::Property::POSITION_Y:
3516 property = &mNode->mPosition;
3519 case Dali::Actor::Property::POSITION_Z:
3520 property = &mNode->mPosition;
3523 case Dali::Actor::Property::WORLD_POSITION:
3524 property = &mNode->mWorldPosition;
3527 case Dali::Actor::Property::WORLD_POSITION_X:
3528 property = &mNode->mWorldPosition;
3531 case Dali::Actor::Property::WORLD_POSITION_Y:
3532 property = &mNode->mWorldPosition;
3535 case Dali::Actor::Property::WORLD_POSITION_Z:
3536 property = &mNode->mWorldPosition;
3539 case Dali::Actor::Property::ORIENTATION:
3540 property = &mNode->mOrientation;
3543 case Dali::Actor::Property::WORLD_ORIENTATION:
3544 property = &mNode->mWorldOrientation;
3547 case Dali::Actor::Property::SCALE:
3548 property = &mNode->mScale;
3551 case Dali::Actor::Property::SCALE_X:
3552 property = &mNode->mScale;
3555 case Dali::Actor::Property::SCALE_Y:
3556 property = &mNode->mScale;
3559 case Dali::Actor::Property::SCALE_Z:
3560 property = &mNode->mScale;
3563 case Dali::Actor::Property::WORLD_SCALE:
3564 property = &mNode->mWorldScale;
3567 case Dali::Actor::Property::VISIBLE:
3568 property = &mNode->mVisible;
3571 case Dali::Actor::Property::COLOR:
3572 property = &mNode->mColor;
3575 case Dali::Actor::Property::COLOR_RED:
3576 property = &mNode->mColor;
3579 case Dali::Actor::Property::COLOR_GREEN:
3580 property = &mNode->mColor;
3583 case Dali::Actor::Property::COLOR_BLUE:
3584 property = &mNode->mColor;
3587 case Dali::Actor::Property::COLOR_ALPHA:
3588 case Dali::DevelActor::Property::OPACITY:
3590 property = &mNode->mColor;
3594 case Dali::Actor::Property::WORLD_COLOR:
3595 property = &mNode->mWorldColor;
3598 case Dali::Actor::Property::WORLD_MATRIX:
3599 property = &mNode->mWorldMatrix;
3610 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3612 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3614 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3616 // check whether the animatable property is registered already, if not then register one.
3617 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3618 if( animatableProperty )
3620 componentIndex = animatableProperty->componentIndex;
3627 case Dali::Actor::Property::PARENT_ORIGIN_X:
3628 case Dali::Actor::Property::ANCHOR_POINT_X:
3629 case Dali::Actor::Property::SIZE_WIDTH:
3630 case Dali::Actor::Property::POSITION_X:
3631 case Dali::Actor::Property::WORLD_POSITION_X:
3632 case Dali::Actor::Property::SCALE_X:
3633 case Dali::Actor::Property::COLOR_RED:
3639 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3640 case Dali::Actor::Property::ANCHOR_POINT_Y:
3641 case Dali::Actor::Property::SIZE_HEIGHT:
3642 case Dali::Actor::Property::POSITION_Y:
3643 case Dali::Actor::Property::WORLD_POSITION_Y:
3644 case Dali::Actor::Property::SCALE_Y:
3645 case Dali::Actor::Property::COLOR_GREEN:
3651 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3652 case Dali::Actor::Property::ANCHOR_POINT_Z:
3653 case Dali::Actor::Property::SIZE_DEPTH:
3654 case Dali::Actor::Property::POSITION_Z:
3655 case Dali::Actor::Property::WORLD_POSITION_Z:
3656 case Dali::Actor::Property::SCALE_Z:
3657 case Dali::Actor::Property::COLOR_BLUE:
3663 case Dali::Actor::Property::COLOR_ALPHA:
3664 case Dali::DevelActor::Property::OPACITY:
3678 return componentIndex;
3681 void Actor::SetParent( Actor* parent )
3685 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3689 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3692 // Instruct each actor to create a corresponding node in the scene graph
3693 ConnectToStage( parent->GetHierarchyDepth() );
3696 // Resolve the name and index for the child properties if any
3697 ResolveChildProperties();
3699 else // parent being set to NULL
3701 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3705 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3708 DALI_ASSERT_ALWAYS( mNode != NULL );
3712 // Disconnect the Node & its children from the scene-graph.
3713 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3716 // Instruct each actor to discard pointers to the scene-graph
3717 DisconnectFromStage();
3722 SceneGraph::Node* Actor::CreateNode() const
3727 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3730 Actor* actor = dynamic_cast< Actor* >( object );
3734 if( 0 == actionName.compare( ACTION_SHOW ) )
3736 actor->SetVisible( true );
3739 else if( 0 == actionName.compare( ACTION_HIDE ) )
3741 actor->SetVisible( false );
3749 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
3751 bool valueSet = true;
3755 case Dali::Actor::Property::PARENT_ORIGIN:
3757 value = GetCurrentParentOrigin();
3761 case Dali::Actor::Property::PARENT_ORIGIN_X:
3763 value = GetCurrentParentOrigin().x;
3767 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3769 value = GetCurrentParentOrigin().y;
3773 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3775 value = GetCurrentParentOrigin().z;
3779 case Dali::Actor::Property::ANCHOR_POINT:
3781 value = GetCurrentAnchorPoint();
3785 case Dali::Actor::Property::ANCHOR_POINT_X:
3787 value = GetCurrentAnchorPoint().x;
3791 case Dali::Actor::Property::ANCHOR_POINT_Y:
3793 value = GetCurrentAnchorPoint().y;
3797 case Dali::Actor::Property::ANCHOR_POINT_Z:
3799 value = GetCurrentAnchorPoint().z;
3803 case Dali::Actor::Property::SIZE:
3805 value = GetTargetSize();
3809 case Dali::Actor::Property::SIZE_WIDTH:
3811 value = GetTargetSize().width;
3815 case Dali::Actor::Property::SIZE_HEIGHT:
3817 value = GetTargetSize().height;
3821 case Dali::Actor::Property::SIZE_DEPTH:
3823 value = GetTargetSize().depth;
3827 case Dali::Actor::Property::POSITION:
3829 value = GetTargetPosition();
3833 case Dali::Actor::Property::POSITION_X:
3835 value = GetTargetPosition().x;
3839 case Dali::Actor::Property::POSITION_Y:
3841 value = GetTargetPosition().y;
3845 case Dali::Actor::Property::POSITION_Z:
3847 value = GetTargetPosition().z;
3851 case Dali::Actor::Property::ORIENTATION:
3853 value = mTargetOrientation;
3857 case Dali::Actor::Property::SCALE:
3859 value = mTargetScale;
3863 case Dali::Actor::Property::SCALE_X:
3865 value = mTargetScale.x;
3869 case Dali::Actor::Property::SCALE_Y:
3871 value = mTargetScale.y;
3875 case Dali::Actor::Property::SCALE_Z:
3877 value = mTargetScale.z;
3881 case Dali::Actor::Property::VISIBLE:
3887 case Dali::Actor::Property::COLOR:
3889 value = mTargetColor;
3893 case Dali::Actor::Property::COLOR_RED:
3895 value = mTargetColor.r;
3899 case Dali::Actor::Property::COLOR_GREEN:
3901 value = mTargetColor.g;
3905 case Dali::Actor::Property::COLOR_BLUE:
3907 value = mTargetColor.b;
3911 case Dali::Actor::Property::COLOR_ALPHA:
3912 case Dali::DevelActor::Property::OPACITY:
3914 value = mTargetColor.a;
3918 case Dali::Actor::Property::NAME:
3924 case Dali::Actor::Property::SENSITIVE:
3926 value = IsSensitive();
3930 case Dali::Actor::Property::LEAVE_REQUIRED:
3932 value = GetLeaveRequired();
3936 case Dali::Actor::Property::INHERIT_POSITION:
3938 value = IsPositionInherited();
3942 case Dali::Actor::Property::INHERIT_ORIENTATION:
3944 value = IsOrientationInherited();
3948 case Dali::Actor::Property::INHERIT_SCALE:
3950 value = IsScaleInherited();
3954 case Dali::Actor::Property::COLOR_MODE:
3956 value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
3960 case Dali::Actor::Property::POSITION_INHERITANCE:
3962 value = Scripting::GetLinearEnumerationName< PositionInheritanceMode >( GetPositionInheritanceMode(), POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT );
3966 case Dali::Actor::Property::DRAW_MODE:
3968 value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
3972 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3974 value = GetSizeModeFactor();
3978 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3980 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3984 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3986 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3990 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3992 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT );
3996 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3998 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
4002 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
4004 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
4008 case Dali::Actor::Property::PADDING:
4010 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
4011 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
4012 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
4016 case Dali::Actor::Property::MINIMUM_SIZE:
4018 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
4022 case Dali::Actor::Property::MAXIMUM_SIZE:
4024 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
4028 case Dali::Actor::Property::CLIPPING_MODE:
4030 value = mClippingMode;
4034 case Dali::DevelActor::Property::SIBLING_ORDER:
4036 value = static_cast<int>(mSiblingOrder);
4040 case Dali::DevelActor::Property::SCREEN_POSITION:
4042 value = GetCurrentScreenPosition();
4046 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
4048 value = mPositionUsesAnchorPoint;
4054 // Must be a scene-graph only property
4063 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
4065 bool valueSet = true;
4069 case Dali::Actor::Property::SIZE:
4071 value = GetCurrentSize();
4075 case Dali::Actor::Property::SIZE_WIDTH:
4077 value = GetCurrentSize().width;
4081 case Dali::Actor::Property::SIZE_HEIGHT:
4083 value = GetCurrentSize().height;
4087 case Dali::Actor::Property::SIZE_DEPTH:
4089 value = GetCurrentSize().depth;
4093 case Dali::Actor::Property::POSITION:
4095 value = GetCurrentPosition();
4099 case Dali::Actor::Property::POSITION_X:
4101 value = GetCurrentPosition().x;
4105 case Dali::Actor::Property::POSITION_Y:
4107 value = GetCurrentPosition().y;
4111 case Dali::Actor::Property::POSITION_Z:
4113 value = GetCurrentPosition().z;
4117 case Dali::Actor::Property::WORLD_POSITION:
4119 value = GetCurrentWorldPosition();
4123 case Dali::Actor::Property::WORLD_POSITION_X:
4125 value = GetCurrentWorldPosition().x;
4129 case Dali::Actor::Property::WORLD_POSITION_Y:
4131 value = GetCurrentWorldPosition().y;
4135 case Dali::Actor::Property::WORLD_POSITION_Z:
4137 value = GetCurrentWorldPosition().z;
4141 case Dali::Actor::Property::ORIENTATION:
4143 value = GetCurrentOrientation();
4147 case Dali::Actor::Property::WORLD_ORIENTATION:
4149 value = GetCurrentWorldOrientation();
4153 case Dali::Actor::Property::SCALE:
4155 value = GetCurrentScale();
4159 case Dali::Actor::Property::SCALE_X:
4161 value = GetCurrentScale().x;
4165 case Dali::Actor::Property::SCALE_Y:
4167 value = GetCurrentScale().y;
4171 case Dali::Actor::Property::SCALE_Z:
4173 value = GetCurrentScale().z;
4177 case Dali::Actor::Property::WORLD_SCALE:
4179 value = GetCurrentWorldScale();
4183 case Dali::Actor::Property::COLOR:
4185 value = GetCurrentColor();
4189 case Dali::Actor::Property::COLOR_RED:
4191 value = GetCurrentColor().r;
4195 case Dali::Actor::Property::COLOR_GREEN:
4197 value = GetCurrentColor().g;
4201 case Dali::Actor::Property::COLOR_BLUE:
4203 value = GetCurrentColor().b;
4207 case Dali::Actor::Property::COLOR_ALPHA:
4208 case Dali::DevelActor::Property::OPACITY:
4210 value = GetCurrentColor().a;
4214 case Dali::Actor::Property::WORLD_COLOR:
4216 value = GetCurrentWorldColor();
4220 case Dali::Actor::Property::WORLD_MATRIX:
4222 value = GetCurrentWorldMatrix();
4228 // Must be an event-side only property
4237 void Actor::EnsureRelayoutData()
4239 // Assign relayout data.
4240 if( !mRelayoutData )
4242 mRelayoutData = new RelayoutData();
4246 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
4248 // Check if actor is dependent on parent
4249 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4251 if( ( dimension & ( 1 << i ) ) )
4253 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4254 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
4264 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
4266 // Check if actor is dependent on children
4267 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4269 if( ( dimension & ( 1 << i ) ) )
4271 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4272 switch( resizePolicy )
4274 case ResizePolicy::FIT_TO_CHILDREN:
4275 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
4291 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
4293 return Actor::RelayoutDependentOnChildren( dimension );
4296 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
4298 // Check each possible dimension and see if it is dependent on the input one
4299 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4301 if( dimension & ( 1 << i ) )
4303 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
4310 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
4312 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4314 if( dimension & ( 1 << i ) )
4316 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
4321 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
4323 // If more than one dimension is requested, just return the first one found
4324 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4326 if( ( dimension & ( 1 << i ) ) )
4328 return mRelayoutData->negotiatedDimensions[ i ];
4332 return 0.0f; // Default
4335 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
4337 EnsureRelayoutData();
4339 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4341 if( dimension & ( 1 << i ) )
4343 mRelayoutData->dimensionPadding[ i ] = padding;
4348 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4350 if ( mRelayoutData )
4352 // If more than one dimension is requested, just return the first one found
4353 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4355 if( ( dimension & ( 1 << i ) ) )
4357 return mRelayoutData->dimensionPadding[ i ];
4362 return GetDefaultDimensionPadding();
4365 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4367 EnsureRelayoutData();
4369 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4371 if( dimension & ( 1 << i ) )
4373 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4378 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4380 if ( mRelayoutData )
4382 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4384 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4394 float Actor::GetHeightForWidthBase( float width )
4396 float height = 0.0f;
4398 const Vector3 naturalSize = GetNaturalSize();
4399 if( naturalSize.width > 0.0f )
4401 height = naturalSize.height * width / naturalSize.width;
4403 else // we treat 0 as 1:1 aspect ratio
4411 float Actor::GetWidthForHeightBase( float height )
4415 const Vector3 naturalSize = GetNaturalSize();
4416 if( naturalSize.height > 0.0f )
4418 width = naturalSize.width * height / naturalSize.height;
4420 else // we treat 0 as 1:1 aspect ratio
4428 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4430 // Fill to parent, taking size mode factor into account
4431 switch( child.GetResizePolicy( dimension ) )
4433 case ResizePolicy::FILL_TO_PARENT:
4435 return GetLatestSize( dimension );
4438 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4440 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4443 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4445 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4450 return GetLatestSize( dimension );
4455 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4457 // Can be overridden in derived class
4458 return CalculateChildSizeBase( child, dimension );
4461 float Actor::GetHeightForWidth( float width )
4463 // Can be overridden in derived class
4464 return GetHeightForWidthBase( width );
4467 float Actor::GetWidthForHeight( float height )
4469 // Can be overridden in derived class
4470 return GetWidthForHeightBase( height );
4473 float Actor::GetLatestSize( Dimension::Type dimension ) const
4475 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4478 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4480 Vector2 padding = GetPadding( dimension );
4482 return GetLatestSize( dimension ) + padding.x + padding.y;
4485 float Actor::NegotiateFromParent( Dimension::Type dimension )
4487 Actor* parent = GetParent();
4490 Vector2 padding( GetPadding( dimension ) );
4491 Vector2 parentPadding( parent->GetPadding( dimension ) );
4492 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4498 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4500 float maxDimensionPoint = 0.0f;
4502 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4504 ActorPtr child = GetChildAt( i );
4506 if( !child->RelayoutDependentOnParent( dimension ) )
4508 // Calculate the min and max points that the children range across
4509 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
4510 float dimensionSize = child->GetRelayoutSize( dimension );
4511 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4515 return maxDimensionPoint;
4518 float Actor::GetSize( Dimension::Type dimension ) const
4520 return GetDimensionValue( mTargetSize, dimension );
4523 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4525 return GetDimensionValue( GetNaturalSize(), dimension );
4528 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4530 switch( GetResizePolicy( dimension ) )
4532 case ResizePolicy::USE_NATURAL_SIZE:
4534 return GetNaturalSize( dimension );
4537 case ResizePolicy::FIXED:
4539 return GetDimensionValue( GetPreferredSize(), dimension );
4542 case ResizePolicy::USE_ASSIGNED_SIZE:
4544 return GetDimensionValue( maximumSize, dimension );
4547 case ResizePolicy::FILL_TO_PARENT:
4548 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4549 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4551 return NegotiateFromParent( dimension );
4554 case ResizePolicy::FIT_TO_CHILDREN:
4556 return NegotiateFromChildren( dimension );
4559 case ResizePolicy::DIMENSION_DEPENDENCY:
4561 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4564 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4566 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4569 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4571 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4583 return 0.0f; // Default
4586 float Actor::ClampDimension( float size, Dimension::Type dimension )
4588 const float minSize = GetMinimumSize( dimension );
4589 const float maxSize = GetMaximumSize( dimension );
4591 return std::max( minSize, std::min( size, maxSize ) );
4594 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4596 // Check if it needs to be negotiated
4597 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4599 // Check that we havn't gotten into an infinite loop
4600 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4601 bool recursionFound = false;
4602 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4604 if( *it == searchActor )
4606 recursionFound = true;
4611 if( !recursionFound )
4613 // Record the path that we have taken
4614 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4616 // Dimension dependency check
4617 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4619 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4621 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4623 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4627 // Parent dependency check
4628 Actor* parent = GetParent();
4629 if( parent && RelayoutDependentOnParent( dimension ) )
4631 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4634 // Children dependency check
4635 if( RelayoutDependentOnChildren( dimension ) )
4637 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4639 ActorPtr child = GetChildAt( i );
4641 // Only relayout child first if it is not dependent on this actor
4642 if( !child->RelayoutDependentOnParent( dimension ) )
4644 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
4649 // For deriving classes
4650 OnCalculateRelayoutSize( dimension );
4652 // All dependencies checked, calculate the size and set negotiated flag
4653 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4655 SetNegotiatedDimension( newSize, dimension );
4656 SetLayoutNegotiated( true, dimension );
4658 // For deriving classes
4659 OnLayoutNegotiated( newSize, dimension );
4661 // This actor has been successfully processed, pop it off the recursion stack
4662 recursionStack.pop_back();
4666 // TODO: Break infinite loop
4667 SetLayoutNegotiated( true, dimension );
4672 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4674 // Negotiate all dimensions that require it
4675 ActorDimensionStack recursionStack;
4677 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4679 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4682 NegotiateDimension( dimension, allocatedSize, recursionStack );
4686 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4688 switch( mRelayoutData->sizeSetPolicy )
4690 case SizeScalePolicy::USE_SIZE_SET:
4695 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4697 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4698 const Vector3 naturalSize = GetNaturalSize();
4699 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4701 const float sizeRatio = size.width / size.height;
4702 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4704 if( naturalSizeRatio < sizeRatio )
4706 return Vector2( naturalSizeRatio * size.height, size.height );
4708 else if( naturalSizeRatio > sizeRatio )
4710 return Vector2( size.width, size.width / naturalSizeRatio );
4721 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4723 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4724 const Vector3 naturalSize = GetNaturalSize();
4725 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4727 const float sizeRatio = size.width / size.height;
4728 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4730 if( naturalSizeRatio < sizeRatio )
4732 return Vector2( size.width, size.width / naturalSizeRatio );
4734 else if( naturalSizeRatio > sizeRatio )
4736 return Vector2( naturalSizeRatio * size.height, size.height );
4755 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4757 // Do the set actor size
4758 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4760 // Adjust for size set policy
4761 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4763 // Lock the flag to stop recursive relayouts on set size
4764 mRelayoutData->insideRelayout = true;
4765 SetSize( negotiatedSize );
4766 mRelayoutData->insideRelayout = false;
4768 // Clear flags for all dimensions
4769 SetLayoutDirty( false );
4771 // Give deriving classes a chance to respond
4772 OnRelayout( negotiatedSize, container );
4774 if( !mOnRelayoutSignal.Empty() )
4776 Dali::Actor handle( this );
4777 mOnRelayoutSignal.Emit( handle );
4781 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4783 // Force a size negotiation for actors that has assigned size during relayout
4784 // This is required as otherwise the flags that force a relayout will not
4785 // necessarilly be set. This will occur if the actor has already been laid out.
4786 // The dirty flags are then cleared. Then if the actor is added back into the
4787 // relayout container afterwards, the dirty flags would still be clear...
4788 // causing a relayout to be skipped. Here we force any actors added to the
4789 // container to be relayed out.
4790 DALI_LOG_TIMER_START( NegSizeTimer1 );
4792 if( GetUseAssignedSize(Dimension::WIDTH ) )
4794 SetLayoutNegotiated( false, Dimension::WIDTH );
4796 if( GetUseAssignedSize( Dimension::HEIGHT ) )
4798 SetLayoutNegotiated( false, Dimension::HEIGHT );
4801 // Do the negotiation
4802 NegotiateDimensions( allocatedSize );
4804 // Set the actor size
4805 SetNegotiatedSize( container );
4807 // Negotiate down to children
4808 const Vector2 newBounds = mTargetSize.GetVectorXY();
4810 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4812 ActorPtr child = GetChildAt( i );
4814 // Forces children that have already been laid out to be relayed out
4815 // if they have assigned size during relayout.
4816 if( child->GetUseAssignedSize(Dimension::WIDTH) )
4818 child->SetLayoutNegotiated(false, Dimension::WIDTH);
4819 child->SetLayoutDirty(true, Dimension::WIDTH);
4822 if( child->GetUseAssignedSize(Dimension::HEIGHT) )
4824 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
4825 child->SetLayoutDirty(true, Dimension::HEIGHT);
4828 // Only relayout if required
4829 if( child->RelayoutRequired() )
4831 container.Add( Dali::Actor( child.Get() ), newBounds );
4834 DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
4837 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
4841 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4843 if( dimension & ( 1 << i ) )
4845 mRelayoutData->useAssignedSize[ i ] = use;
4851 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
4853 if ( mRelayoutData )
4855 // If more than one dimension is requested, just return the first one found
4856 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4858 if( dimension & ( 1 << i ) )
4860 return mRelayoutData->useAssignedSize[ i ];
4868 void Actor::RelayoutRequest( Dimension::Type dimension )
4870 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4871 if( relayoutController )
4873 Dali::Actor self( this );
4874 relayoutController->RequestRelayout( self, dimension );
4878 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4882 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4886 void Actor::SetPreferredSize( const Vector2& size )
4888 EnsureRelayoutData();
4890 if( size.width > 0.0f )
4892 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4895 if( size.height > 0.0f )
4897 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4900 mRelayoutData->preferredSize = size;
4905 Vector2 Actor::GetPreferredSize() const
4907 if ( mRelayoutData )
4909 return Vector2( mRelayoutData->preferredSize );
4912 return GetDefaultPreferredSize();
4915 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4917 EnsureRelayoutData();
4919 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4921 if( dimension & ( 1 << i ) )
4923 mRelayoutData->minimumSize[ i ] = size;
4930 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4932 if ( mRelayoutData )
4934 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4936 if( dimension & ( 1 << i ) )
4938 return mRelayoutData->minimumSize[ i ];
4943 return 0.0f; // Default
4946 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4948 EnsureRelayoutData();
4950 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4952 if( dimension & ( 1 << i ) )
4954 mRelayoutData->maximumSize[ i ] = size;
4961 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4963 if ( mRelayoutData )
4965 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4967 if( dimension & ( 1 << i ) )
4969 return mRelayoutData->maximumSize[ i ];
4974 return FLT_MAX; // Default
4977 Object* Actor::GetParentObject() const
4982 void Actor::SetSiblingOrder( unsigned int order )
4984 mSiblingOrder = std::min( order, static_cast<unsigned int>( DevelLayer::SIBLING_ORDER_MULTIPLIER ) );
4988 StagePtr stage = Stage::GetCurrent();
4991 stage->RequestRebuildDepthTree();
4996 void Actor::DefragmentSiblingIndexes( ActorContainer& siblings )
4998 // Sibling index may not be in consecutive order as the sibling range is limited ( DevelLayer::SIBLING_ORDER_MULTIPLIER )
4999 // we need to remove the gaps and ensure the number start from 0 and consecutive hence have a full range.
5001 // Start at index 0, while index <= highest order
5002 // Find next index higher than 0
5003 // if nextHigher > index+1
5004 // set all nextHigher orders to index+1
5006 // Limitation: May reach the ceiling of DevelLayer::SIBLING_ORDER_MULTIPLIER with highest sibling.
5008 ActorIter end = siblings.end();
5009 int highestOrder = 0;
5010 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
5012 ActorPtr sibling = (*iter);
5013 int siblingOrder = sibling->mSiblingOrder;
5014 highestOrder = std::max( highestOrder, siblingOrder );
5017 for ( int index = 0; index <= highestOrder; index++ )
5019 int nextHighest = -1;
5021 // Find Next highest
5022 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
5024 ActorPtr sibling = (*iter);
5025 int siblingOrder = sibling->mSiblingOrder;
5027 if ( siblingOrder > index )
5029 if ( nextHighest == -1 )
5031 nextHighest = siblingOrder;
5033 nextHighest = std::min( nextHighest, siblingOrder );
5037 // Check if a gap exists between indexes, if so set next index to consecutive number
5038 if ( ( nextHighest - index ) > 1 )
5040 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
5042 ActorPtr sibling = (*iter);
5043 int siblingOrder = sibling->mSiblingOrder;
5044 if ( siblingOrder == nextHighest )
5046 sibling->mSiblingOrder = index + 1;
5047 if ( sibling->mSiblingOrder >= Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER )
5049 DALI_LOG_WARNING( "Reached max sibling order level for raising / lowering actors\n" );
5050 sibling->mSiblingOrder = Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER;
5052 sibling->SetSiblingOrder( sibling->mSiblingOrder );
5059 bool Actor::ShiftSiblingsLevels( ActorContainer& siblings, int targetLevelToShiftFrom )
5061 // Allows exclusive levels for an actor by shifting all sibling levels at the target and above by 1
5062 bool defragmentationRequired( false );
5063 ActorIter end = siblings.end();
5064 for( ActorIter iter = siblings.begin(); ( iter != end ) ; ++iter )
5066 // Move actors at nearest order and above up by 1
5067 ActorPtr sibling = (*iter);
5068 if ( sibling != this )
5070 // Iterate through container of actors, any actor with a sibling order of the target or greater should
5071 // be incremented by 1.
5072 if ( sibling->mSiblingOrder >= targetLevelToShiftFrom )
5074 sibling->mSiblingOrder++;
5075 if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
5077 // If a sibling order raises so that it is only 1 from the maximum allowed then set flag so
5078 // can re-order all sibling orders.
5079 defragmentationRequired = true;
5081 sibling->SetSiblingOrder( sibling->mSiblingOrder );
5085 return defragmentationRequired;
5091 1) Check if already at top and nothing to be done.
5092 This Actor can have highest sibling order but if not exclusive then another actor at same sibling
5093 order can be positioned above it due to insertion order of actors.
5094 2) Find nearest sibling level above, these are the siblings this actor needs to be above
5095 3) a) There may be other levels above this target level
5096 b) Increment all sibling levels at the level above nearest(target)
5097 c) Now have a vacant sibling level
5098 4) Set this actor's sibling level to nearest +1 as now vacated.
5100 Note May not just be sibling level + 1 as could be empty levels in-between
5105 ActorC ( sibling level 4 )
5106 ActorB ( sibling level 3 )
5107 ActorA ( sibling level 1 )
5109 2 ) ACTION: Raise A above B
5110 a) Find nearest level above A = Level 3
5111 b) Increment levels above Level 3
5113 ActorC ( sibling level 5 )
5114 ActorB ( sibling level 3 ) NEAREST
5115 ActorA ( sibling level 1 )
5117 3 ) Set Actor A sibling level to nearest +1 as vacant
5119 ActorC ( sibling level 5 )
5120 ActorA ( sibling level 4 )
5121 ActorB ( sibling level 3 )
5123 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5124 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5125 remove any empty sibling order gaps and start from sibling level 0 again.
5126 If the number of actors reaches this maximum and all using exclusive sibling order values then
5127 defragmention will stop and new sibling orders will be set to same max value.
5131 int nearestLevel = mSiblingOrder;
5132 int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
5133 bool defragmentationRequired( false );
5135 ActorContainer* siblings = mParent->mChildren;
5137 // Find Nearest sibling level above this actor
5138 ActorIter end = siblings->end();
5139 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
5141 ActorPtr sibling = (*iter);
5142 if ( sibling != this )
5144 int order = GetSiblingOrder( sibling );
5146 if ( ( order >= mSiblingOrder ) )
5148 int distanceToNextLevel = order - mSiblingOrder;
5149 if ( distanceToNextLevel < shortestDistanceToNextLevel )
5151 nearestLevel = order;
5152 shortestDistanceToNextLevel = distanceToNextLevel;
5158 if ( nearestLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at top
5160 mSiblingOrder = nearestLevel + 1; // Set sibling level to that above the nearest level
5161 defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
5162 // Move current actor to newly vacated order level
5163 SetSiblingOrder( mSiblingOrder );
5164 if ( defragmentationRequired )
5166 DefragmentSiblingIndexes( *siblings );
5169 SetSiblingOrder( mSiblingOrder );
5173 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5180 1) Check if actor already at bottom and if nothing needs to be done
5181 This Actor can have lowest sibling order but if not exclusive then another actor at same sibling
5182 order can be positioned above it due to insertion order of actors so need to move this actor below it.
5183 2) Find nearest sibling level below, this Actor needs to be below it
5184 3) a) Need to vacate a sibling level below nearest for this actor to occupy
5185 b) Shift up all sibling order values of actor at the nearest level and levels above it to vacate a level.
5186 c) Set this actor's sibling level to this newly vacated level.
5187 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5188 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5189 remove any empty sibling order gaps and start from sibling level 0 again.
5190 If the number of actors reaches this maximum and all using exclusive sibling order values then
5191 defragmention will stop and new sibling orders will be set to same max value.
5196 // 1) Find nearest level below
5197 int nearestLevel = mSiblingOrder;
5198 int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
5200 ActorContainer* siblings = mParent->mChildren;
5202 ActorIter end = siblings->end();
5203 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
5205 ActorPtr sibling = (*iter);
5206 if ( sibling != this )
5208 int order = GetSiblingOrder( sibling );
5210 if ( order <= mSiblingOrder )
5212 int distanceToNextLevel = mSiblingOrder - order;
5213 if ( distanceToNextLevel < shortestDistanceToNextLevel )
5215 nearestLevel = order;
5216 shortestDistanceToNextLevel = distanceToNextLevel;
5222 bool defragmentationRequired ( false );
5224 // 2) If actor already not at bottom, raise all actors at required level and above
5225 if ( shortestDistanceToNextLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at bottom
5227 mSiblingOrder = nearestLevel;
5228 defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
5229 // Move current actor to newly vacated order
5230 SetSiblingOrder( mSiblingOrder );
5231 if ( defragmentationRequired )
5233 DefragmentSiblingIndexes( *siblings );
5239 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5243 void Actor::RaiseToTop()
5246 1 ) Find highest sibling order actor
5247 2 ) If highest sibling level not itself then set sibling order to that + 1
5248 3 ) highest sibling order can be same as itself so need to increment over that
5249 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5250 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5251 remove any empty sibling order gaps and start from sibling level 0 again.
5252 If the number of actors reaches this maximum and all using exclusive sibling order values then
5253 defragmention will stop and new sibling orders will be set to same max value.
5260 ActorContainer* siblings = mParent->mChildren;
5262 ActorIter end = siblings->end();
5263 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
5265 ActorPtr sibling = (*iter);
5266 if ( sibling != this )
5268 maxOrder = std::max( GetSiblingOrder( sibling ), maxOrder );
5272 bool defragmentationRequired( false );
5274 if ( maxOrder >= mSiblingOrder )
5276 mSiblingOrder = maxOrder + 1;
5277 if ( mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
5279 defragmentationRequired = true;
5283 SetSiblingOrder( mSiblingOrder );
5285 if ( defragmentationRequired )
5287 DefragmentSiblingIndexes( *siblings );
5292 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5296 void Actor::LowerToBottom()
5299 See Actor::LowerToBottom()
5301 1 ) Check if this actor already at exclusively at the bottom, if so then no more to be done.
5302 2 ) a ) Check if the bottom position 0 is vacant.
5303 b ) If 0 position is not vacant then shift up all sibling order values from 0 and above
5304 c ) 0 sibling position is vacant.
5305 3 ) Set this actor to vacant sibling order 0;
5306 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5307 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5308 remove any empty sibling order gaps and start from sibling level 0 again.
5309 If the number of actors reaches this maximum and all using exclusive sibling order values then
5310 defragmention will stop and new sibling orders will be set to same max value.
5315 bool defragmentationRequired( false );
5316 bool orderZeroFree ( true );
5318 ActorContainer* siblings = mParent->mChildren;
5320 bool actorAtLowestOrder = true;
5321 ActorIter end = siblings->end();
5322 for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
5324 ActorPtr sibling = (*iter);
5325 if ( sibling != this )
5327 int siblingOrder = GetSiblingOrder( sibling );
5328 if ( siblingOrder <= mSiblingOrder )
5330 actorAtLowestOrder = false;
5333 if ( siblingOrder == 0 )
5335 orderZeroFree = false;
5340 if ( ! actorAtLowestOrder )
5342 if ( ! orderZeroFree )
5344 defragmentationRequired = ShiftSiblingsLevels( *siblings, 0 );
5347 SetSiblingOrder( mSiblingOrder );
5349 if ( defragmentationRequired )
5351 DefragmentSiblingIndexes( *siblings );
5357 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5361 void Actor::RaiseAbove( Internal::Actor& target )
5364 1 ) a) Find target actor's sibling order
5365 b) If sibling order of target is the same as this actor then need to this Actor's sibling order
5366 needs to be above it or the insertion order will determine which is drawn on top.
5367 2 ) Shift up by 1 all sibling order greater than target sibling order
5368 3 ) Set this actor to the sibling order to target +1 as will be a newly vacated gap above
5369 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5370 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5371 remove any empty sibling order gaps and start from sibling level 0 again.
5372 If the number of actors reaches this maximum and all using exclusive sibling order values then
5373 defragmention will stop and new sibling orders will be set to same max value.
5378 if ( ValidateActors( *this, target ) )
5380 // Find target's sibling order
5381 // Set actor sibling order to this number +1
5382 int targetSiblingOrder = GetSiblingOrder( &target );
5383 ActorContainer* siblings = mParent->mChildren;
5384 mSiblingOrder = targetSiblingOrder + 1;
5385 bool defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
5387 SetSiblingOrder( mSiblingOrder );
5389 if ( defragmentationRequired )
5391 DefragmentSiblingIndexes( *(mParent->mChildren) );
5397 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5401 void Actor::LowerBelow( Internal::Actor& target )
5404 1 ) a) Find target actor's sibling order
5405 b) If sibling order of target is the same as this actor then need to this Actor's sibling order
5406 needs to be below it or the insertion order will determine which is drawn on top.
5407 2 ) Shift the target sibling order and all sibling orders at that level or above by 1
5408 3 ) Set this actor to the sibling order of the target before it changed.
5409 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5410 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5411 remove any empty sibling order gaps and start from sibling level 0 again.
5412 If the number of actors reaches this maximum and all using exclusive sibling order values then
5413 defragmention will stop and new sibling orders will be set to same max value.
5418 if ( ValidateActors( *this, target ) )
5420 bool defragmentationRequired ( false );
5421 // Find target's sibling order
5422 // Set actor sibling order to target sibling order - 1
5423 int targetSiblingOrder = GetSiblingOrder( &target);
5424 ActorContainer* siblings = mParent->mChildren;
5425 if ( targetSiblingOrder == 0 )
5428 ActorIter end = siblings->end();
5429 for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
5431 ActorPtr sibling = (*iter);
5432 if ( sibling != this )
5434 sibling->mSiblingOrder++;
5435 if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
5437 defragmentationRequired = true;
5439 sibling->SetSiblingOrder( sibling->mSiblingOrder );
5446 defragmentationRequired = ShiftSiblingsLevels( *siblings, targetSiblingOrder );
5448 mSiblingOrder = targetSiblingOrder;
5450 SetSiblingOrder( mSiblingOrder );
5452 if ( defragmentationRequired )
5454 DefragmentSiblingIndexes( *(mParent->mChildren) );
5460 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5464 } // namespace Internal