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 negotiatedDimensions[ i ] = 0.0f;
137 dimensionNegotiated[ i ] = false;
138 dimensionDirty[ i ] = false;
139 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
140 dimensionPadding[ i ] = GetDefaultDimensionPadding();
141 minimumSize[ i ] = 0.0f;
142 maximumSize[ i ] = FLT_MAX;
146 ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies
148 Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies
150 Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
152 float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
154 float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be
155 float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be
157 bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated
158 bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
160 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
162 Vector2 preferredSize; ///< The preferred size of the actor
164 SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
166 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
167 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
170 namespace // unnamed namespace
176 * We want to discourage the use of property strings (minimize string comparisons),
177 * particularly for the default properties.
178 * Name Type writable animatable constraint-input enum for index-checking
180 DALI_PROPERTY_TABLE_BEGIN
181 DALI_PROPERTY( "parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
182 DALI_PROPERTY( "parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
183 DALI_PROPERTY( "parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
184 DALI_PROPERTY( "parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
185 DALI_PROPERTY( "anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
186 DALI_PROPERTY( "anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
187 DALI_PROPERTY( "anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
188 DALI_PROPERTY( "anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
189 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
190 DALI_PROPERTY( "sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
191 DALI_PROPERTY( "sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
192 DALI_PROPERTY( "sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
193 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
194 DALI_PROPERTY( "positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
195 DALI_PROPERTY( "positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
196 DALI_PROPERTY( "positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
197 DALI_PROPERTY( "worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
198 DALI_PROPERTY( "worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
199 DALI_PROPERTY( "worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
200 DALI_PROPERTY( "worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
201 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
202 DALI_PROPERTY( "worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
203 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
204 DALI_PROPERTY( "scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
205 DALI_PROPERTY( "scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
206 DALI_PROPERTY( "scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
207 DALI_PROPERTY( "worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
208 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
209 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
210 DALI_PROPERTY( "colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
211 DALI_PROPERTY( "colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
212 DALI_PROPERTY( "colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
213 DALI_PROPERTY( "colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
214 DALI_PROPERTY( "worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
215 DALI_PROPERTY( "worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
216 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
217 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
218 DALI_PROPERTY( "leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
219 DALI_PROPERTY( "inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
220 DALI_PROPERTY( "inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
221 DALI_PROPERTY( "colorMode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
222 DALI_PROPERTY( "positionInheritance", STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE )
223 DALI_PROPERTY( "drawMode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
224 DALI_PROPERTY( "sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
225 DALI_PROPERTY( "widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
226 DALI_PROPERTY( "heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
227 DALI_PROPERTY( "sizeScalePolicy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
228 DALI_PROPERTY( "widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
229 DALI_PROPERTY( "heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
230 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
231 DALI_PROPERTY( "minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
232 DALI_PROPERTY( "maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
233 DALI_PROPERTY( "inheritPosition", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_POSITION )
234 DALI_PROPERTY( "clippingMode", STRING, true, false, false, Dali::Actor::Property::CLIPPING_MODE )
235 DALI_PROPERTY( "siblingOrder", INTEGER, true, false, false, Dali::DevelActor::Property::SIBLING_ORDER )
236 DALI_PROPERTY( "opacity", FLOAT, true, true, true, Dali::DevelActor::Property::OPACITY )
237 DALI_PROPERTY( "screenPosition", VECTOR2, false, false, false, Dali::DevelActor::Property::SCREEN_POSITION )
238 DALI_PROPERTY( "positionUsesAnchorPoint", BOOLEAN, true, false, false, Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT )
239 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
243 const char* const SIGNAL_TOUCHED = "touched";
244 const char* const SIGNAL_HOVERED = "hovered";
245 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
246 const char* const SIGNAL_ON_STAGE = "onStage";
247 const char* const SIGNAL_OFF_STAGE = "offStage";
248 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
249 const char* const SIGNAL_TOUCH = "touch";
253 const char* const ACTION_SHOW = "show";
254 const char* const ACTION_HIDE = "hide";
256 BaseHandle CreateActor()
258 return Dali::Actor::New();
261 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
263 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
264 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
265 SignalConnectorType signalConnector3( mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal );
266 SignalConnectorType signalConnector4( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
267 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
268 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
269 SignalConnectorType signalConnector7( mType, SIGNAL_TOUCH, &Actor::DoConnectSignal );
271 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
272 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
277 const Vector3& value;
280 DALI_ENUM_TO_STRING_TABLE_BEGIN_WITH_TYPE( AnchorValue, ANCHOR_CONSTANT )
281 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_LEFT )
282 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_CENTER )
283 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_RIGHT )
284 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_LEFT )
285 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER )
286 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_RIGHT )
287 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_LEFT )
288 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_CENTER )
289 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_RIGHT )
290 DALI_ENUM_TO_STRING_TABLE_END( ANCHOR_CONSTANT )
292 DALI_ENUM_TO_STRING_TABLE_BEGIN( COLOR_MODE )
293 DALI_ENUM_TO_STRING( USE_OWN_COLOR )
294 DALI_ENUM_TO_STRING( USE_PARENT_COLOR )
295 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_COLOR )
296 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_ALPHA )
297 DALI_ENUM_TO_STRING_TABLE_END( COLOR_MODE )
299 DALI_ENUM_TO_STRING_TABLE_BEGIN( POSITION_INHERITANCE_MODE )
300 DALI_ENUM_TO_STRING( INHERIT_PARENT_POSITION )
301 DALI_ENUM_TO_STRING( USE_PARENT_POSITION )
302 DALI_ENUM_TO_STRING( USE_PARENT_POSITION_PLUS_LOCAL_POSITION )
303 DALI_ENUM_TO_STRING( DONT_INHERIT_POSITION )
304 DALI_ENUM_TO_STRING_TABLE_END( POSITION_INHERITANCE_MODE )
306 DALI_ENUM_TO_STRING_TABLE_BEGIN( DRAW_MODE )
307 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, NORMAL )
308 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, OVERLAY_2D )
309 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, STENCIL )
310 DALI_ENUM_TO_STRING_TABLE_END( DRAW_MODE )
312 DALI_ENUM_TO_STRING_TABLE_BEGIN( RESIZE_POLICY )
313 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIXED )
314 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_NATURAL_SIZE )
315 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FILL_TO_PARENT )
316 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_RELATIVE_TO_PARENT )
317 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_FIXED_OFFSET_FROM_PARENT )
318 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIT_TO_CHILDREN )
319 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, DIMENSION_DEPENDENCY )
320 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_ASSIGNED_SIZE )
321 DALI_ENUM_TO_STRING_TABLE_END( RESIZE_POLICY )
323 DALI_ENUM_TO_STRING_TABLE_BEGIN( SIZE_SCALE_POLICY )
324 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, USE_SIZE_SET )
325 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FIT_WITH_ASPECT_RATIO )
326 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FILL_WITH_ASPECT_RATIO )
327 DALI_ENUM_TO_STRING_TABLE_END( SIZE_SCALE_POLICY )
329 DALI_ENUM_TO_STRING_TABLE_BEGIN( CLIPPING_MODE )
330 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, DISABLED )
331 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, CLIP_CHILDREN )
332 DALI_ENUM_TO_STRING_TABLE_END( CLIPPING_MODE )
335 bool GetAnchorPointConstant( const std::string& value, Vector3& anchor )
337 for( unsigned int i = 0; i < ANCHOR_CONSTANT_TABLE_COUNT; ++i )
339 size_t sizeIgnored = 0;
340 if( CompareTokens( value.c_str(), ANCHOR_CONSTANT_TABLE[ i ].name, sizeIgnored ) )
342 anchor = ANCHOR_CONSTANT_TABLE[ i ].value;
349 inline bool GetParentOriginConstant( const std::string& value, Vector3& parentOrigin )
351 // Values are the same so just use the same table as anchor-point
352 return GetAnchorPointConstant( value, parentOrigin );
356 * @brief Extract a given dimension from a Vector2
358 * @param[in] values The values to extract from
359 * @param[in] dimension The dimension to extract
360 * @return Return the value for the dimension
362 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
366 case Dimension::WIDTH:
370 case Dimension::HEIGHT:
372 return values.height;
383 * @brief Extract a given dimension from a Vector3
385 * @param[in] values The values to extract from
386 * @param[in] dimension The dimension to extract
387 * @return Return the value for the dimension
389 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
391 return GetDimensionValue( values.GetVectorXY(), dimension );
395 * @brief Recursively emits the visibility-changed-signal on the actor tree.
396 * @param[in] actor The actor to emit the signal on
397 * @param[in] visible The new visibility of the actor
398 * @param[in] type Whether the actor's visible property has changed or a parent's
400 void EmitVisibilityChangedSignalRecursively( ActorPtr actor, bool visible, DevelActor::VisibilityChange::Type type )
404 actor->EmitVisibilityChangedSignal( visible, type );
406 if( actor->GetChildCount() > 0 )
408 ActorContainer& children = actor->GetChildrenInternal();
409 for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter )
411 EmitVisibilityChangedSignalRecursively( *iter, visible, DevelActor::VisibilityChange::PARENT );
417 } // unnamed namespace
419 ActorPtr Actor::New()
421 ActorPtr actor( new Actor( BASIC ) );
423 // Second-phase construction
429 const std::string& Actor::GetName() const
434 void Actor::SetName( const std::string& name )
440 // ATTENTION: string for debug purposes is not thread safe.
441 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
445 unsigned int Actor::GetId() const
450 bool Actor::OnStage() const
455 Dali::Layer Actor::GetLayer()
459 // Short-circuit for Layer derived actors
462 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
465 // Find the immediate Layer parent
466 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
468 if( parent->IsLayer() )
470 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
477 void Actor::Add( Actor& child )
479 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
480 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
484 mChildren = new ActorContainer;
487 Actor* const oldParent( child.mParent );
489 // child might already be ours
490 if( this != oldParent )
492 // if we already have parent, unparent us first
495 oldParent->Remove( child ); // This causes OnChildRemove callback
497 // Old parent may need to readjust to missing child
498 if( oldParent->RelayoutDependentOnChildren() )
500 oldParent->RelayoutRequest();
504 // Guard against Add() during previous OnChildRemove callback
507 // Do this first, since user callbacks from within SetParent() may need to remove child
508 mChildren->push_back( ActorPtr( &child ) );
510 // SetParent asserts that child can be added
511 child.SetParent( this );
513 // Notification for derived classes
516 // Only put in a relayout request if there is a suitable dependency
517 if( RelayoutDependentOnChildren() )
525 void Actor::Remove( Actor& child )
527 if( (this == &child) || (!mChildren) )
529 // no children or removing itself
535 // Find the child in mChildren, and unparent it
536 ActorIter end = mChildren->end();
537 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
539 ActorPtr actor = (*iter);
541 if( actor.Get() == &child )
543 // Keep handle for OnChildRemove notification
546 // Do this first, since user callbacks from within SetParent() may need to add the child
547 mChildren->erase( iter );
549 DALI_ASSERT_DEBUG( actor->GetParent() == this );
550 actor->SetParent( NULL );
558 // Only put in a relayout request if there is a suitable dependency
559 if( RelayoutDependentOnChildren() )
565 // Notification for derived classes
566 OnChildRemove( child );
569 void Actor::Unparent()
573 // Remove this actor from the parent. The remove will put a relayout request in for
574 // the parent if required
575 mParent->Remove( *this );
576 // mParent is now NULL!
580 unsigned int Actor::GetChildCount() const
582 return ( NULL != mChildren ) ? mChildren->size() : 0;
585 ActorPtr Actor::GetChildAt( unsigned int index ) const
587 DALI_ASSERT_ALWAYS( index < GetChildCount() );
589 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
592 ActorPtr Actor::FindChildByName( const std::string& actorName )
595 if( actorName == mName )
601 ActorIter end = mChildren->end();
602 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
604 child = (*iter)->FindChildByName( actorName );
615 ActorPtr Actor::FindChildById( const unsigned int id )
624 ActorIter end = mChildren->end();
625 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
627 child = (*iter)->FindChildById( id );
638 void Actor::SetParentOrigin( const Vector3& origin )
642 // mNode is being used in a separate thread; queue a message to set the value & base value
643 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
646 // Cache for event-thread access
649 // not allocated, check if different from default
650 if( ParentOrigin::DEFAULT != origin )
652 mParentOrigin = new Vector3( origin );
657 // check if different from current costs more than just set
658 *mParentOrigin = origin;
662 void Actor::SetParentOriginX( float x )
664 const Vector3& current = GetCurrentParentOrigin();
666 SetParentOrigin( Vector3( x, current.y, current.z ) );
669 void Actor::SetParentOriginY( float y )
671 const Vector3& current = GetCurrentParentOrigin();
673 SetParentOrigin( Vector3( current.x, y, current.z ) );
676 void Actor::SetParentOriginZ( float z )
678 const Vector3& current = GetCurrentParentOrigin();
680 SetParentOrigin( Vector3( current.x, current.y, z ) );
683 const Vector3& Actor::GetCurrentParentOrigin() const
685 // Cached for event-thread access
686 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
689 void Actor::SetAnchorPoint( const Vector3& anchor )
693 // mNode is being used in a separate thread; queue a message to set the value & base value
694 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
697 // Cache for event-thread access
700 // not allocated, check if different from default
701 if( AnchorPoint::DEFAULT != anchor )
703 mAnchorPoint = new Vector3( anchor );
708 // check if different from current costs more than just set
709 *mAnchorPoint = anchor;
713 void Actor::SetAnchorPointX( float x )
715 const Vector3& current = GetCurrentAnchorPoint();
717 SetAnchorPoint( Vector3( x, current.y, current.z ) );
720 void Actor::SetAnchorPointY( float y )
722 const Vector3& current = GetCurrentAnchorPoint();
724 SetAnchorPoint( Vector3( current.x, y, current.z ) );
727 void Actor::SetAnchorPointZ( float z )
729 const Vector3& current = GetCurrentAnchorPoint();
731 SetAnchorPoint( Vector3( current.x, current.y, z ) );
734 const Vector3& Actor::GetCurrentAnchorPoint() const
736 // Cached for event-thread access
737 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
740 void Actor::SetPosition( float x, float y )
742 SetPosition( Vector3( x, y, 0.0f ) );
745 void Actor::SetPosition( float x, float y, float z )
747 SetPosition( Vector3( x, y, z ) );
750 void Actor::SetPosition( const Vector3& position )
752 mTargetPosition = position;
756 // mNode is being used in a separate thread; queue a message to set the value & base value
757 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
761 void Actor::SetX( float x )
763 mTargetPosition.x = x;
767 // mNode is being used in a separate thread; queue a message to set the value & base value
768 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
772 void Actor::SetY( float y )
774 mTargetPosition.y = y;
778 // mNode is being used in a separate thread; queue a message to set the value & base value
779 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
783 void Actor::SetZ( float z )
785 mTargetPosition.z = z;
789 // mNode is being used in a separate thread; queue a message to set the value & base value
790 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
794 void Actor::TranslateBy( const Vector3& distance )
796 mTargetPosition += distance;
800 // mNode is being used in a separate thread; queue a message to set the value & base value
801 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
805 const Vector3& Actor::GetCurrentPosition() const
809 // mNode is being used in a separate thread; copy the value from the previous update
810 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
813 return Vector3::ZERO;
816 const Vector3& Actor::GetTargetPosition() const
818 return mTargetPosition;
821 const Vector3& Actor::GetCurrentWorldPosition() const
825 // mNode is being used in a separate thread; copy the value from the previous update
826 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
829 return Vector3::ZERO;
832 const Vector2 Actor::GetCurrentScreenPosition() const
834 if( OnStage() && NULL != mNode )
836 StagePtr stage = Stage::GetCurrent();
837 Vector3 worldPosition = mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
838 Vector3 actorSize = GetCurrentSize() * GetCurrentScale();
839 Vector2 halfStageSize( stage->GetSize() * 0.5f ); // World position origin is center of stage
840 Vector3 halfActorSize( actorSize * 0.5f );
841 Vector3 anchorPointOffSet = halfActorSize - actorSize * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
843 return Vector2( halfStageSize.width + worldPosition.x - anchorPointOffSet.x,
844 halfStageSize.height + worldPosition.y - anchorPointOffSet.y );
847 return Vector2::ZERO;
850 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
852 // this flag is not animatable so keep the value
853 mPositionInheritanceMode = mode;
856 // mNode is being used in a separate thread; queue a message to set the value
857 SetInheritPositionMessage( GetEventThreadServices(), *mNode, mode == INHERIT_PARENT_POSITION );
861 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
863 // Cached for event-thread access
864 return mPositionInheritanceMode;
867 void Actor::SetInheritPosition( bool inherit )
869 if( mInheritPosition != inherit && NULL != mNode )
871 // non animateable so keep local copy
872 mInheritPosition = inherit;
873 SetInheritPositionMessage( GetEventThreadServices(), *mNode, inherit );
877 bool Actor::IsPositionInherited() const
879 return mInheritPosition;
882 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
884 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
885 normalizedAxis.Normalize();
887 Quaternion orientation( angle, normalizedAxis );
889 SetOrientation( orientation );
892 void Actor::SetOrientation( const Quaternion& orientation )
894 mTargetOrientation = orientation;
898 // mNode is being used in a separate thread; queue a message to set the value & base value
899 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation );
903 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
905 RotateBy( Quaternion(angle, axis) );
908 void Actor::RotateBy( const Quaternion& relativeRotation )
910 mTargetOrientation *= Quaternion( relativeRotation );
914 // mNode is being used in a separate thread; queue a message to set the value & base value
915 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
919 const Quaternion& Actor::GetCurrentOrientation() const
923 // mNode is being used in a separate thread; copy the value from the previous update
924 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
927 return Quaternion::IDENTITY;
930 const Quaternion& Actor::GetCurrentWorldOrientation() const
934 // mNode is being used in a separate thread; copy the value from the previous update
935 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
938 return Quaternion::IDENTITY;
941 void Actor::SetScale( float scale )
943 SetScale( Vector3( scale, scale, scale ) );
946 void Actor::SetScale( float x, float y, float z )
948 SetScale( Vector3( x, y, z ) );
951 void Actor::SetScale( const Vector3& scale )
953 mTargetScale = scale;
957 // mNode is being used in a separate thread; queue a message to set the value & base value
958 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
962 void Actor::SetScaleX( float x )
968 // mNode is being used in a separate thread; queue a message to set the value & base value
969 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
973 void Actor::SetScaleY( float y )
979 // mNode is being used in a separate thread; queue a message to set the value & base value
980 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
984 void Actor::SetScaleZ( float z )
990 // mNode is being used in a separate thread; queue a message to set the value & base value
991 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
995 void Actor::ScaleBy(const Vector3& relativeScale)
997 mTargetScale *= relativeScale;
1001 // mNode is being used in a separate thread; queue a message to set the value & base value
1002 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
1006 const Vector3& Actor::GetCurrentScale() const
1010 // mNode is being used in a separate thread; copy the value from the previous update
1011 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
1014 return Vector3::ONE;
1017 const Vector3& Actor::GetCurrentWorldScale() const
1021 // mNode is being used in a separate thread; copy the value from the previous update
1022 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
1025 return Vector3::ONE;
1028 void Actor::SetInheritScale( bool inherit )
1031 if( mInheritScale != inherit && NULL != mNode )
1033 // non animateable so keep local copy
1034 mInheritScale = inherit;
1035 // mNode is being used in a separate thread; queue a message to set the value
1036 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
1040 bool Actor::IsScaleInherited() const
1042 return mInheritScale;
1045 Matrix Actor::GetCurrentWorldMatrix() const
1049 return mNode->GetWorldMatrix(0);
1052 return Matrix::IDENTITY;
1055 void Actor::SetVisible( bool visible )
1057 if( mVisible != visible )
1061 // mNode is being used in a separate thread; queue a message to set the value & base value
1062 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
1067 // Emit the signal on this actor and all its children
1068 EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
1072 bool Actor::IsVisible() const
1076 // mNode is being used in a separate thread; copy the value from the previous update
1077 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
1083 void Actor::SetOpacity( float opacity )
1085 mTargetColor.a = opacity;
1089 // mNode is being used in a separate thread; queue a message to set the value & base value
1090 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
1094 float Actor::GetCurrentOpacity() const
1098 // mNode is being used in a separate thread; copy the value from the previous update
1099 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1105 ClippingMode::Type Actor::GetClippingMode() const
1107 return mClippingMode;
1110 unsigned int Actor::GetSortingDepth()
1112 return mSortedDepth;
1115 const Vector4& Actor::GetCurrentWorldColor() const
1119 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1122 return Color::WHITE;
1125 void Actor::SetColor( const Vector4& color )
1127 mTargetColor = color;
1131 // mNode is being used in a separate thread; queue a message to set the value & base value
1132 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1136 void Actor::SetColorRed( float red )
1138 mTargetColor.r = red;
1142 // mNode is being used in a separate thread; queue a message to set the value & base value
1143 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1147 void Actor::SetColorGreen( float green )
1149 mTargetColor.g = green;
1153 // mNode is being used in a separate thread; queue a message to set the value & base value
1154 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1158 void Actor::SetColorBlue( float blue )
1160 mTargetColor.b = blue;
1164 // mNode is being used in a separate thread; queue a message to set the value & base value
1165 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1169 const Vector4& Actor::GetCurrentColor() const
1173 // mNode is being used in a separate thread; copy the value from the previous update
1174 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1177 return Color::WHITE;
1180 void Actor::SetInheritOrientation( bool inherit )
1182 if( mInheritOrientation != inherit && NULL != mNode)
1184 // non animateable so keep local copy
1185 mInheritOrientation = inherit;
1186 // mNode is being used in a separate thread; queue a message to set the value
1187 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1191 bool Actor::IsOrientationInherited() const
1193 return mInheritOrientation;
1196 void Actor::SetSizeModeFactor( const Vector3& factor )
1198 EnsureRelayoutData();
1200 mRelayoutData->sizeModeFactor = factor;
1203 const Vector3& Actor::GetSizeModeFactor() const
1205 if ( mRelayoutData )
1207 return mRelayoutData->sizeModeFactor;
1210 return GetDefaultSizeModeFactor();
1213 void Actor::SetColorMode( ColorMode colorMode )
1215 // non animateable so keep local copy
1216 mColorMode = colorMode;
1219 // mNode is being used in a separate thread; queue a message to set the value
1220 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1224 ColorMode Actor::GetColorMode() const
1226 // we have cached copy
1230 void Actor::SetSize( float width, float height )
1232 SetSize( Vector2( width, height ) );
1235 void Actor::SetSize( float width, float height, float depth )
1237 SetSize( Vector3( width, height, depth ) );
1240 void Actor::SetSize( const Vector2& size )
1242 SetSize( Vector3( size.width, size.height, 0.f ) );
1245 void Actor::SetSizeInternal( const Vector2& size )
1247 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1250 void Actor::SetSize( const Vector3& size )
1252 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1254 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1255 SetPreferredSize( size.GetVectorXY() );
1259 SetSizeInternal( size );
1263 void Actor::SetSizeInternal( const Vector3& size )
1265 // dont allow recursive loop
1266 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1267 // 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
1268 if( ( NULL != mNode )&&
1269 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1270 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1271 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1275 // mNode is being used in a separate thread; queue a message to set the value & base value
1276 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
1278 // Notification for derived classes
1279 mInsideOnSizeSet = true;
1280 OnSizeSet( mTargetSize );
1281 mInsideOnSizeSet = false;
1283 // Raise a relayout request if the flag is not locked
1284 if( mRelayoutData && !mRelayoutData->insideRelayout )
1291 void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
1293 mTargetSize = targetSize;
1295 // Notify deriving classes
1296 OnSizeAnimation( animation, mTargetSize );
1299 void Actor::NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property )
1301 if ( Dali::Actor::Property::SIZE_WIDTH == property )
1303 mTargetSize.width = targetSize;
1305 else if ( Dali::Actor::Property::SIZE_HEIGHT == property )
1307 mTargetSize.height = targetSize;
1309 else if ( Dali::Actor::Property::SIZE_DEPTH == property )
1311 mTargetSize.depth = targetSize;
1313 // Notify deriving classes
1314 OnSizeAnimation( animation, mTargetSize );
1317 void Actor::NotifyPositionAnimation( Animation& animation, const Vector3& targetPosition )
1319 mTargetPosition = targetPosition;
1322 void Actor::NotifyPositionAnimation( Animation& animation, float targetPosition, Property::Index property )
1324 if ( Dali::Actor::Property::POSITION_X == property )
1326 mTargetPosition.x = targetPosition;
1328 else if ( Dali::Actor::Property::POSITION_Y == property )
1330 mTargetPosition.y = targetPosition;
1332 else if ( Dali::Actor::Property::POSITION_Z == property )
1334 mTargetPosition.z = targetPosition;
1338 void Actor::SetWidth( float width )
1340 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1342 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
1343 mRelayoutData->preferredSize.width = width;
1347 mTargetSize.width = width;
1351 // mNode is being used in a separate thread; queue a message to set the value & base value
1352 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1359 void Actor::SetHeight( float height )
1361 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1363 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
1364 mRelayoutData->preferredSize.height = height;
1368 mTargetSize.height = height;
1372 // mNode is being used in a separate thread; queue a message to set the value & base value
1373 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1380 void Actor::SetDepth( float depth )
1382 mTargetSize.depth = depth;
1386 // mNode is being used in a separate thread; queue a message to set the value & base value
1387 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1391 Vector3 Actor::GetTargetSize() const
1393 Vector3 size = mTargetSize;
1395 // Should return preferred size if size is fixed as set by SetSize
1396 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
1398 size.width = GetPreferredSize().width;
1400 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
1402 size.height = GetPreferredSize().height;
1408 const Vector3& Actor::GetCurrentSize() const
1412 // mNode is being used in a separate thread; copy the value from the previous update
1413 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1416 return Vector3::ZERO;
1419 Vector3 Actor::GetNaturalSize() const
1421 // It is up to deriving classes to return the appropriate natural size
1422 return Vector3( 0.0f, 0.0f, 0.0f );
1425 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1427 EnsureRelayoutData();
1429 ResizePolicy::Type originalWidthPolicy = GetResizePolicy(Dimension::WIDTH);
1430 ResizePolicy::Type originalHeightPolicy = GetResizePolicy(Dimension::HEIGHT);
1432 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1434 if( dimension & ( 1 << i ) )
1436 mRelayoutData->resizePolicies[ i ] = policy;
1440 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1442 if( dimension & Dimension::WIDTH )
1444 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1447 if( dimension & Dimension::HEIGHT )
1449 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1453 // If calling SetResizePolicy, assume we want relayout enabled
1454 SetRelayoutEnabled( true );
1456 // If the resize policy is set to be FIXED, the preferred size
1457 // should be overrided by the target size. Otherwise the target
1458 // size should be overrided by the preferred size.
1460 if( dimension & Dimension::WIDTH )
1462 if( originalWidthPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1464 mRelayoutData->preferredSize.width = mTargetSize.width;
1466 else if( originalWidthPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1468 mTargetSize.width = mRelayoutData->preferredSize.width;
1472 if( dimension & Dimension::HEIGHT )
1474 if( originalHeightPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1476 mRelayoutData->preferredSize.height = mTargetSize.height;
1478 else if( originalHeightPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1480 mTargetSize.height = mRelayoutData->preferredSize.height;
1484 OnSetResizePolicy( policy, dimension );
1486 // Trigger relayout on this control
1490 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1492 if ( mRelayoutData )
1494 // If more than one dimension is requested, just return the first one found
1495 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1497 if( ( dimension & ( 1 << i ) ) )
1499 return mRelayoutData->resizePolicies[ i ];
1504 return ResizePolicy::DEFAULT;
1507 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1509 EnsureRelayoutData();
1511 mRelayoutData->sizeSetPolicy = policy;
1514 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1516 if ( mRelayoutData )
1518 return mRelayoutData->sizeSetPolicy;
1521 return DEFAULT_SIZE_SCALE_POLICY;
1524 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1526 EnsureRelayoutData();
1528 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1530 if( dimension & ( 1 << i ) )
1532 mRelayoutData->dimensionDependencies[ i ] = dependency;
1537 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1539 if ( mRelayoutData )
1541 // If more than one dimension is requested, just return the first one found
1542 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1544 if( ( dimension & ( 1 << i ) ) )
1546 return mRelayoutData->dimensionDependencies[ i ];
1551 return Dimension::ALL_DIMENSIONS; // Default
1554 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1556 // If relayout data has not been allocated yet and the client is requesting
1557 // to disable it, do nothing
1558 if( mRelayoutData || relayoutEnabled )
1560 EnsureRelayoutData();
1562 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1564 mRelayoutData->relayoutEnabled = relayoutEnabled;
1568 bool Actor::IsRelayoutEnabled() const
1570 // Assume that if relayout data has not been allocated yet then
1571 // relayout is disabled
1572 return mRelayoutData && mRelayoutData->relayoutEnabled;
1575 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1577 EnsureRelayoutData();
1579 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1581 if( dimension & ( 1 << i ) )
1583 mRelayoutData->dimensionDirty[ i ] = dirty;
1588 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1590 if ( mRelayoutData )
1592 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1594 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1604 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1606 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1609 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1611 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1614 unsigned int Actor::AddRenderer( Renderer& renderer )
1618 mRenderers = new RendererContainer;
1621 unsigned int index = mRenderers->size();
1622 RendererPtr rendererPtr = RendererPtr( &renderer );
1623 mRenderers->push_back( rendererPtr );
1624 AddRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1628 unsigned int Actor::GetRendererCount() const
1630 unsigned int rendererCount(0);
1633 rendererCount = mRenderers->size();
1636 return rendererCount;
1639 RendererPtr Actor::GetRendererAt( unsigned int index )
1641 RendererPtr renderer;
1642 if( index < GetRendererCount() )
1644 renderer = ( *mRenderers )[ index ];
1650 void Actor::RemoveRenderer( Renderer& renderer )
1654 RendererIter end = mRenderers->end();
1655 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1657 if( (*iter).Get() == &renderer )
1659 mRenderers->erase( iter );
1660 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1667 void Actor::RemoveRenderer( unsigned int index )
1669 if( index < GetRendererCount() )
1671 RendererPtr renderer = ( *mRenderers )[ index ];
1672 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.Get()->GetRendererSceneObject() );
1673 mRenderers->erase( mRenderers->begin()+index );
1677 bool Actor::IsOverlay() const
1679 return ( DrawMode::OVERLAY_2D == mDrawMode );
1682 void Actor::SetDrawMode( DrawMode::Type drawMode )
1684 // this flag is not animatable so keep the value
1685 mDrawMode = drawMode;
1686 if( ( NULL != mNode ) && ( drawMode != DrawMode::STENCIL ) )
1688 // mNode is being used in a separate thread; queue a message to set the value
1689 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1693 DrawMode::Type Actor::GetDrawMode() const
1698 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1700 // only valid when on-stage
1701 StagePtr stage = Stage::GetCurrent();
1702 if( stage && OnStage() )
1704 const RenderTaskList& taskList = stage->GetRenderTaskList();
1706 Vector2 converted( screenX, screenY );
1708 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1709 const int taskCount = taskList.GetTaskCount();
1710 for( int i = taskCount - 1; i >= 0; --i )
1712 Dali::RenderTask task = taskList.GetTask( i );
1713 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1715 // found a task where this conversion was ok so return
1723 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1725 bool retval = false;
1726 // only valid when on-stage
1729 CameraActor* camera = renderTask.GetCameraActor();
1733 renderTask.GetViewport( viewport );
1735 // need to translate coordinates to render tasks coordinate space
1736 Vector2 converted( screenX, screenY );
1737 if( renderTask.TranslateCoordinates( converted ) )
1739 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1746 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1748 // Early-out if mNode is NULL
1754 // Get the ModelView matrix
1756 Matrix::Multiply( modelView, mNode->GetWorldMatrix(0), viewMatrix );
1758 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1759 Matrix invertedMvp( false/*don't init*/);
1760 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1761 bool success = invertedMvp.Invert();
1763 // Convert to GL coordinates
1764 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1769 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1776 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1782 if( XyPlaneIntersect( nearPos, farPos, local ) )
1784 Vector3 size = GetCurrentSize();
1785 localX = local.x + size.x * 0.5f;
1786 localY = local.y + size.y * 0.5f;
1797 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1800 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1802 Mathematical Formulation
1804 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1806 ( p - c ) dot ( p - c ) = r^2
1808 Given a ray with a point of origin 'o', and a direction vector 'd':
1810 ray(t) = o + td, t >= 0
1812 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1814 (o + td - c ) dot ( o + td - c ) = r^2
1816 To solve for t we first expand the above into a more recognisable quadratic equation form
1818 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1827 B = 2( o - c ) dot d
1828 C = ( o - c ) dot ( o - c ) - r^2
1830 which can be solved using a standard quadratic formula.
1832 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1834 Practical Simplification
1836 In a renderer, we often differentiate between world space and object space. In the object space
1837 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1838 into object space, the mathematical solution presented above can be simplified significantly.
1840 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1844 and we can find the t at which the (transformed) ray intersects the sphere by
1846 ( o + td ) dot ( o + td ) = r^2
1848 According to the reasoning above, we expand the above quadratic equation into the general form
1852 which now has coefficients:
1859 // Early out if mNode is NULL
1865 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1867 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1868 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1869 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1871 // Compute the radius is not needed, square radius it's enough.
1872 const Vector3& size( mNode->GetSize( bufferIndex ) );
1874 // Scale the sphere.
1875 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1877 const float width = size.width * scale.width;
1878 const float height = size.height * scale.height;
1880 float squareSphereRadius = 0.5f * ( width * width + height * height );
1882 float a = rayDir.Dot( rayDir ); // a
1883 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1884 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1886 return ( b2 * b2 - a * c ) >= 0.f;
1889 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector2& hitPointLocal, float& distance ) const
1893 if( OnStage() && NULL != mNode )
1895 // Transforms the ray to the local reference system.
1896 // Calculate the inverse of Model matrix
1897 Matrix invModelMatrix( false/*don't init*/);
1899 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1900 invModelMatrix = mNode->GetWorldMatrix(0);
1901 invModelMatrix.Invert();
1903 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1904 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1906 // Test with the actor's XY plane (Normal = 0 0 1 1).
1908 float a = -rayOriginLocal.z;
1909 float b = rayDirLocal.z;
1911 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1913 // Ray travels distance * rayDirLocal to intersect with plane.
1916 const Vector3& size = mNode->GetSize( bufferIndex );
1918 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1919 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1921 // Test with the actor's geometry.
1922 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1929 void Actor::SetLeaveRequired( bool required )
1931 mLeaveRequired = required;
1934 bool Actor::GetLeaveRequired() const
1936 return mLeaveRequired;
1939 void Actor::SetKeyboardFocusable( bool focusable )
1941 mKeyboardFocusable = focusable;
1944 bool Actor::IsKeyboardFocusable() const
1946 return mKeyboardFocusable;
1949 bool Actor::GetTouchRequired() const
1951 return !mTouchedSignal.Empty() || !mTouchSignal.Empty() || mDerivedRequiresTouch;
1954 bool Actor::GetHoverRequired() const
1956 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1959 bool Actor::GetWheelEventRequired() const
1961 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1964 bool Actor::IsHittable() const
1966 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1969 ActorGestureData& Actor::GetGestureData()
1971 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1972 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1973 if( NULL == mGestureData )
1975 mGestureData = new ActorGestureData;
1977 return *mGestureData;
1980 bool Actor::IsGestureRequred( Gesture::Type type ) const
1982 return mGestureData && mGestureData->IsGestureRequred( type );
1985 bool Actor::EmitTouchEventSignal( const TouchEvent& event, const Dali::TouchData& touch )
1987 bool consumed = false;
1989 if( !mTouchSignal.Empty() )
1991 Dali::Actor handle( this );
1992 consumed = mTouchSignal.Emit( handle, touch );
1995 if( !mTouchedSignal.Empty() )
1997 Dali::Actor handle( this );
1998 consumed |= mTouchedSignal.Emit( handle, event );
2003 // Notification for derived classes
2004 consumed = OnTouchEvent( event ); // TODO
2010 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
2012 bool consumed = false;
2014 if( !mHoveredSignal.Empty() )
2016 Dali::Actor handle( this );
2017 consumed = mHoveredSignal.Emit( handle, event );
2022 // Notification for derived classes
2023 consumed = OnHoverEvent( event );
2029 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
2031 bool consumed = false;
2033 if( !mWheelEventSignal.Empty() )
2035 Dali::Actor handle( this );
2036 consumed = mWheelEventSignal.Emit( handle, event );
2041 // Notification for derived classes
2042 consumed = OnWheelEvent( event );
2048 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
2050 if( ! mVisibilityChangedSignal.Empty() )
2052 Dali::Actor handle( this );
2053 mVisibilityChangedSignal.Emit( handle, visible, type );
2057 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
2059 return mTouchedSignal;
2062 Dali::Actor::TouchDataSignalType& Actor::TouchSignal()
2064 return mTouchSignal;
2067 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
2069 return mHoveredSignal;
2072 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
2074 return mWheelEventSignal;
2077 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
2079 return mOnStageSignal;
2082 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
2084 return mOffStageSignal;
2087 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
2089 return mOnRelayoutSignal;
2092 DevelActor::VisibilityChangedSignalType& Actor::VisibilityChangedSignal()
2094 return mVisibilityChangedSignal;
2097 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
2099 bool connected( true );
2100 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
2102 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
2104 actor->TouchedSignal().Connect( tracker, functor );
2106 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
2108 actor->HoveredSignal().Connect( tracker, functor );
2110 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
2112 actor->WheelEventSignal().Connect( tracker, functor );
2114 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
2116 actor->OnStageSignal().Connect( tracker, functor );
2118 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
2120 actor->OffStageSignal().Connect( tracker, functor );
2122 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
2124 actor->OnRelayoutSignal().Connect( tracker, functor );
2126 else if( 0 == signalName.compare( SIGNAL_TOUCH ) )
2128 actor->TouchSignal().Connect( tracker, functor );
2132 // signalName does not match any signal
2139 Actor::Actor( DerivedType derivedType )
2144 mParentOrigin( NULL ),
2145 mAnchorPoint( NULL ),
2146 mRelayoutData( NULL ),
2147 mGestureData( NULL ),
2148 mTargetOrientation( Quaternion::IDENTITY ),
2149 mTargetColor( Color::WHITE ),
2150 mTargetSize( Vector3::ZERO ),
2151 mTargetPosition( Vector3::ZERO ),
2152 mTargetScale( Vector3::ONE ),
2154 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
2158 mIsRoot( ROOT_LAYER == derivedType ),
2159 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2160 mIsOnStage( false ),
2162 mLeaveRequired( false ),
2163 mKeyboardFocusable( false ),
2164 mDerivedRequiresTouch( false ),
2165 mDerivedRequiresHover( false ),
2166 mDerivedRequiresWheelEvent( false ),
2167 mOnStageSignalled( false ),
2168 mInsideOnSizeSet( false ),
2169 mInheritPosition( true ),
2170 mInheritOrientation( true ),
2171 mInheritScale( true ),
2172 mPositionUsesAnchorPoint( true ),
2174 mDrawMode( DrawMode::NORMAL ),
2175 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2176 mColorMode( Node::DEFAULT_COLOR_MODE ),
2177 mClippingMode( ClippingMode::DISABLED )
2181 void Actor::Initialize()
2184 SceneGraph::Node* node = CreateNode();
2186 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
2187 mNode = node; // Keep raw-pointer to Node
2191 GetEventThreadServices().RegisterObject( this );
2196 // Remove mParent pointers from children even if we're destroying core,
2197 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2200 ActorConstIter endIter = mChildren->end();
2201 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2203 (*iter)->SetParent( NULL );
2209 // Guard to allow handle destruction after Core has been destroyed
2210 if( EventThreadServices::IsCoreRunning() )
2214 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2215 mNode = NULL; // Node is about to be destroyed
2218 GetEventThreadServices().UnregisterObject( this );
2221 // Cleanup optional gesture data
2222 delete mGestureData;
2224 // Cleanup optional parent origin and anchor
2225 delete mParentOrigin;
2226 delete mAnchorPoint;
2228 // Delete optional relayout data
2231 delete mRelayoutData;
2235 void Actor::ConnectToStage( unsigned int parentDepth )
2237 // This container is used instead of walking the Actor hierarchy.
2238 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
2239 ActorContainer connectionList;
2241 StagePtr stage = Stage::GetCurrent();
2244 stage->RequestRebuildDepthTree();
2247 // This stage is atomic i.e. not interrupted by user callbacks.
2248 RecursiveConnectToStage( connectionList, parentDepth + 1 );
2250 // Notify applications about the newly connected actors.
2251 const ActorIter endIter = connectionList.end();
2252 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2254 (*iter)->NotifyStageConnection();
2260 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth )
2262 DALI_ASSERT_ALWAYS( !OnStage() );
2267 ConnectToSceneGraph();
2269 // Notification for internal derived classes
2270 OnStageConnectionInternal();
2272 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2273 connectionList.push_back( ActorPtr( this ) );
2275 // Recursively connect children
2278 ActorConstIter endIter = mChildren->end();
2279 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2281 (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
2287 * This method is called when the Actor is connected to the Stage.
2288 * The parent must have added its Node to the scene-graph.
2289 * The child must connect its Node to the parent's Node.
2290 * This is recursive; the child calls ConnectToStage() for its children.
2292 void Actor::ConnectToSceneGraph()
2294 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2298 // Reparent Node in next Update
2299 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode );
2302 // Request relayout on all actors that are added to the scenegraph
2305 // Notification for Object::Observers
2309 void Actor::NotifyStageConnection()
2311 // Actors can be removed (in a callback), before the on-stage stage is reported.
2312 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2313 if( OnStage() && !mOnStageSignalled )
2315 // Notification for external (CustomActor) derived classes
2316 OnStageConnectionExternal( mDepth );
2318 if( !mOnStageSignal.Empty() )
2320 Dali::Actor handle( this );
2321 mOnStageSignal.Emit( handle );
2324 // Guard against Remove during callbacks
2327 mOnStageSignalled = true; // signal required next time Actor is removed
2332 void Actor::DisconnectFromStage()
2334 // This container is used instead of walking the Actor hierachy.
2335 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2336 ActorContainer disconnectionList;
2338 StagePtr stage = Stage::GetCurrent();
2341 stage->RequestRebuildDepthTree();
2344 // This stage is atomic i.e. not interrupted by user callbacks
2345 RecursiveDisconnectFromStage( disconnectionList );
2347 // Notify applications about the newly disconnected actors.
2348 const ActorIter endIter = disconnectionList.end();
2349 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2351 (*iter)->NotifyStageDisconnection();
2355 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2357 DALI_ASSERT_ALWAYS( OnStage() );
2359 // Recursively disconnect children
2362 ActorConstIter endIter = mChildren->end();
2363 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2365 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2369 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2370 disconnectionList.push_back( ActorPtr( this ) );
2372 // Notification for internal derived classes
2373 OnStageDisconnectionInternal();
2375 DisconnectFromSceneGraph();
2381 * This method is called by an actor or its parent, before a node removal message is sent.
2382 * This is recursive; the child calls DisconnectFromStage() for its children.
2384 void Actor::DisconnectFromSceneGraph()
2386 // Notification for Object::Observers
2387 OnSceneObjectRemove();
2390 void Actor::NotifyStageDisconnection()
2392 // Actors can be added (in a callback), before the off-stage state is reported.
2393 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2394 // only do this step if there is a stage, i.e. Core is not being shut down
2395 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2397 // Notification for external (CustomeActor) derived classes
2398 OnStageDisconnectionExternal();
2400 if( !mOffStageSignal.Empty() )
2402 Dali::Actor handle( this );
2403 mOffStageSignal.Emit( handle );
2406 // Guard against Add during callbacks
2409 mOnStageSignalled = false; // signal required next time Actor is added
2414 bool Actor::IsNodeConnected() const
2416 bool connected( false );
2418 if( OnStage() && ( NULL != mNode ) )
2420 if( IsRoot() || mNode->GetParent() )
2429 // This method generates the depth tree using the recursive function below,
2430 // then walks the tree and sets a depth index based on traversal order. It
2431 // sends a single message to update manager to update all the actor's nodes in this
2432 // tree with the depth index. The sceneGraphNodeDepths vector's elements are ordered
2433 // by depth, and could be used to reduce sorting in the update thread.
2434 void Actor::RebuildDepthTree()
2436 DALI_LOG_TIMER_START(depthTimer);
2438 DepthNodeMemoryPool nodeMemoryPool;
2439 ActorDepthTreeNode* rootNode = new (nodeMemoryPool.AllocateRaw()) ActorDepthTreeNode( this, mSiblingOrder );
2441 int actorCount = BuildDepthTree( nodeMemoryPool, rootNode );
2443 // Vector of scene-graph nodes and their depths to send to UpdateManager
2444 // in a single message
2445 SceneGraph::NodeDepths* sceneGraphNodeDepths = new SceneGraph::NodeDepths(actorCount);
2447 // Traverse depth tree and set mSortedDepth on each actor and scenegraph node
2448 uint32_t sortOrder = 1u; // Don't start at zero, as visual depth can be negative
2449 ActorDepthTreeNode* currentNode = rootNode;
2450 bool firstVisit = true;
2451 while( currentNode != rootNode || firstVisit)
2455 // Visit node, performing action
2456 for( std::vector<Actor*>::iterator iter = currentNode->mActors.begin(); iter != currentNode->mActors.end(); ++iter )
2458 (*iter)->mSortedDepth = sortOrder * DevelLayer::SIBLING_ORDER_MULTIPLIER;
2459 sceneGraphNodeDepths->Add( const_cast<SceneGraph::Node*>((*iter)->mNode), (*iter)->mSortedDepth );
2464 if( currentNode->mFirstChildNode )
2466 currentNode = currentNode->mFirstChildNode;
2468 else // leaf node, goto next sibling, or return up tree.
2470 bool breakout=false;
2471 while( ! currentNode->mNextSiblingNode )
2473 if( currentNode == rootNode ) // If we get to root of tree, stop
2478 currentNode = currentNode->mParentNode;
2485 currentNode = currentNode->mNextSiblingNode;
2489 SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths );
2490 DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree create time: ");
2494 * Structure to store the actor's associated node in the depth tree for child
2497 struct ActorNodePair
2500 ActorDepthTreeNode* node;
2501 ActorNodePair( Actor* actor, ActorDepthTreeNode* node )
2509 * Descend actor tree, building a depth tree based on actor's sibling order.
2510 * Actors with the same sibling order share the same depth tree. Siblings
2511 * in the depth tree are ordered by actor's sibling order.
2513 * An actor tree like this:
2520 * A(SO:1) B(SO:2) C(SO:1)
2523 * D(SO:0) E(SO:0) F(SO:0) G(SO:1) H(SO:0)
2525 * will end up as a depth tree like this:
2527 * RootNode [ Root ] -> NULL
2530 * Node [ A, C ] ------------------------> Node [ B ] -> NULL
2533 * Node [ D, E, H ] -> Node [ G ] -> NULL Node [ F ] -> NULL
2538 * (All nodes also point to their parents to enable storage free traversal)
2540 int Actor::BuildDepthTree( DepthNodeMemoryPool& nodeMemoryPool, ActorDepthTreeNode* node )
2542 int treeCount=1; // Count self and children
2544 // Create/add to children of this node
2547 std::vector<ActorNodePair> storedChildren;
2548 storedChildren.reserve( mChildren->size() );
2550 for( ActorContainer::iterator it = mChildren->begin(); it != mChildren->end(); ++it )
2552 Actor* childActor = (*it).Get();
2553 if( childActor->IsLayer() )
2555 Layer* layer = static_cast<Layer*>(childActor);
2556 if( layer->GetBehavior() == Dali::Layer::LAYER_3D )
2558 // Ignore this actor and children.
2563 // If no existing depth node children
2564 if( node->mFirstChildNode == NULL )
2566 node->mFirstChildNode = new (nodeMemoryPool.AllocateRaw()) ActorDepthTreeNode( childActor, childActor->mSiblingOrder );
2567 node->mFirstChildNode->mParentNode = node;
2568 storedChildren.push_back(ActorNodePair( childActor, node->mFirstChildNode ));
2570 else // find child node with matching sibling order (insertion sort)
2572 bool addedChildActor = false;
2574 // depth tree child nodes ordered by sibling order
2575 ActorDepthTreeNode* lastNode = NULL;
2576 for( ActorDepthTreeNode* childNode = node->mFirstChildNode; childNode != NULL; childNode = childNode->mNextSiblingNode )
2578 uint16_t actorSiblingOrder = childActor->mSiblingOrder;
2579 uint16_t currentSiblingOrder = childNode->GetSiblingOrder();
2581 if( actorSiblingOrder == currentSiblingOrder )
2583 // Don't need a new depth node, add to existing node
2584 childNode->AddActor( childActor );
2585 storedChildren.push_back(ActorNodePair( childActor, childNode ));
2586 addedChildActor = true;
2589 else if( actorSiblingOrder < currentSiblingOrder )
2593 lastNode = childNode;
2596 // No matching sibling order - create new node and insert into sibling list
2597 if( !addedChildActor )
2599 ActorDepthTreeNode* newNode = new (nodeMemoryPool.AllocateRaw()) ActorDepthTreeNode( childActor, childActor->mSiblingOrder );
2601 newNode->mParentNode = node;
2602 storedChildren.push_back(ActorNodePair( childActor, newNode ));
2604 if( lastNode == NULL ) // Insert at start of siblings
2606 ActorDepthTreeNode* nextNode = node->mFirstChildNode;
2607 node->mFirstChildNode = newNode;
2608 newNode->mNextSiblingNode = nextNode;
2610 else // insert into siblings after last node
2612 newNode->mNextSiblingNode = lastNode->mNextSiblingNode;
2613 lastNode->mNextSiblingNode = newNode;
2619 // Order of descent doesn't matter; we're using insertion to sort.
2620 for( std::vector<ActorNodePair>::iterator iter = storedChildren.begin(); iter != storedChildren.end(); ++iter )
2622 treeCount += iter->actor->BuildDepthTree( nodeMemoryPool, iter->node );
2628 unsigned int Actor::GetDefaultPropertyCount() const
2630 return DEFAULT_PROPERTY_COUNT;
2633 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2635 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2637 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2639 indices.PushBack( i );
2643 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2645 if( index < DEFAULT_PROPERTY_COUNT )
2647 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2653 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2655 Property::Index index = Property::INVALID_INDEX;
2657 // Look for name in default properties
2658 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2660 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2661 if( 0 == name.compare( property->name ) )
2671 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2673 if( index < DEFAULT_PROPERTY_COUNT )
2675 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2681 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2683 if( index < DEFAULT_PROPERTY_COUNT )
2685 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2691 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2693 if( index < DEFAULT_PROPERTY_COUNT )
2695 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2701 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2703 if( index < DEFAULT_PROPERTY_COUNT )
2705 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2708 // index out of range...return Property::NONE
2709 return Property::NONE;
2712 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2716 case Dali::Actor::Property::PARENT_ORIGIN:
2718 Property::Type type = property.GetType();
2719 if( type == Property::VECTOR3 )
2721 SetParentOrigin( property.Get< Vector3 >() );
2723 else if ( type == Property::STRING )
2725 std::string parentOriginString;
2726 property.Get( parentOriginString );
2727 Vector3 parentOrigin;
2728 if( GetParentOriginConstant( parentOriginString, parentOrigin ) )
2730 SetParentOrigin( parentOrigin );
2736 case Dali::Actor::Property::PARENT_ORIGIN_X:
2738 SetParentOriginX( property.Get< float >() );
2742 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2744 SetParentOriginY( property.Get< float >() );
2748 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2750 SetParentOriginZ( property.Get< float >() );
2754 case Dali::Actor::Property::ANCHOR_POINT:
2756 Property::Type type = property.GetType();
2757 if( type == Property::VECTOR3 )
2759 SetAnchorPoint( property.Get< Vector3 >() );
2761 else if ( type == Property::STRING )
2763 std::string anchorPointString;
2764 property.Get( anchorPointString );
2766 if( GetAnchorPointConstant( anchorPointString, anchor ) )
2768 SetAnchorPoint( anchor );
2774 case Dali::Actor::Property::ANCHOR_POINT_X:
2776 SetAnchorPointX( property.Get< float >() );
2780 case Dali::Actor::Property::ANCHOR_POINT_Y:
2782 SetAnchorPointY( property.Get< float >() );
2786 case Dali::Actor::Property::ANCHOR_POINT_Z:
2788 SetAnchorPointZ( property.Get< float >() );
2792 case Dali::Actor::Property::SIZE:
2794 SetSize( property.Get< Vector3 >() );
2798 case Dali::Actor::Property::SIZE_WIDTH:
2800 SetWidth( property.Get< float >() );
2804 case Dali::Actor::Property::SIZE_HEIGHT:
2806 SetHeight( property.Get< float >() );
2810 case Dali::Actor::Property::SIZE_DEPTH:
2812 SetDepth( property.Get< float >() );
2816 case Dali::Actor::Property::POSITION:
2818 SetPosition( property.Get< Vector3 >() );
2822 case Dali::Actor::Property::POSITION_X:
2824 SetX( property.Get< float >() );
2828 case Dali::Actor::Property::POSITION_Y:
2830 SetY( property.Get< float >() );
2834 case Dali::Actor::Property::POSITION_Z:
2836 SetZ( property.Get< float >() );
2840 case Dali::Actor::Property::ORIENTATION:
2842 SetOrientation( property.Get< Quaternion >() );
2846 case Dali::Actor::Property::SCALE:
2848 SetScale( property.Get< Vector3 >() );
2852 case Dali::Actor::Property::SCALE_X:
2854 SetScaleX( property.Get< float >() );
2858 case Dali::Actor::Property::SCALE_Y:
2860 SetScaleY( property.Get< float >() );
2864 case Dali::Actor::Property::SCALE_Z:
2866 SetScaleZ( property.Get< float >() );
2870 case Dali::Actor::Property::VISIBLE:
2872 SetVisible( property.Get< bool >() );
2876 case Dali::Actor::Property::COLOR:
2878 SetColor( property.Get< Vector4 >() );
2882 case Dali::Actor::Property::COLOR_RED:
2884 SetColorRed( property.Get< float >() );
2888 case Dali::Actor::Property::COLOR_GREEN:
2890 SetColorGreen( property.Get< float >() );
2894 case Dali::Actor::Property::COLOR_BLUE:
2896 SetColorBlue( property.Get< float >() );
2900 case Dali::Actor::Property::COLOR_ALPHA:
2901 case Dali::DevelActor::Property::OPACITY:
2904 if( property.Get( value ) )
2906 SetOpacity( value );
2911 case Dali::Actor::Property::NAME:
2913 SetName( property.Get< std::string >() );
2917 case Dali::Actor::Property::SENSITIVE:
2919 SetSensitive( property.Get< bool >() );
2923 case Dali::Actor::Property::LEAVE_REQUIRED:
2925 SetLeaveRequired( property.Get< bool >() );
2929 case Dali::Actor::Property::INHERIT_POSITION:
2931 SetInheritPosition( property.Get< bool >() );
2935 case Dali::Actor::Property::INHERIT_ORIENTATION:
2937 SetInheritOrientation( property.Get< bool >() );
2941 case Dali::Actor::Property::INHERIT_SCALE:
2943 SetInheritScale( property.Get< bool >() );
2947 case Dali::Actor::Property::COLOR_MODE:
2949 ColorMode mode = mColorMode;
2950 if ( Scripting::GetEnumerationProperty< ColorMode >( property, COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT, mode ) )
2952 SetColorMode( mode );
2957 case Dali::Actor::Property::POSITION_INHERITANCE:
2959 PositionInheritanceMode mode = mPositionInheritanceMode;
2960 if( Scripting::GetEnumerationProperty< PositionInheritanceMode >( property, POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT, mode ) )
2962 SetPositionInheritanceMode( mode );
2967 case Dali::Actor::Property::DRAW_MODE:
2969 DrawMode::Type mode = mDrawMode;
2970 if( Scripting::GetEnumerationProperty< DrawMode::Type >( property, DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT, mode ) )
2972 SetDrawMode( mode );
2977 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2979 SetSizeModeFactor( property.Get< Vector3 >() );
2983 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2985 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
2986 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2988 SetResizePolicy( type, Dimension::WIDTH );
2993 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2995 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
2996 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2998 SetResizePolicy( type, Dimension::HEIGHT );
3003 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3005 SizeScalePolicy::Type type;
3006 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT, type ) )
3008 SetSizeScalePolicy( type );
3013 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3015 if( property.Get< bool >() )
3017 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
3022 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3024 if( property.Get< bool >() )
3026 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
3031 case Dali::Actor::Property::PADDING:
3033 Vector4 padding = property.Get< Vector4 >();
3034 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
3035 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
3039 case Dali::Actor::Property::MINIMUM_SIZE:
3041 Vector2 size = property.Get< Vector2 >();
3042 SetMinimumSize( size.x, Dimension::WIDTH );
3043 SetMinimumSize( size.y, Dimension::HEIGHT );
3047 case Dali::Actor::Property::MAXIMUM_SIZE:
3049 Vector2 size = property.Get< Vector2 >();
3050 SetMaximumSize( size.x, Dimension::WIDTH );
3051 SetMaximumSize( size.y, Dimension::HEIGHT );
3055 case Dali::DevelActor::Property::SIBLING_ORDER:
3059 if( property.Get( value ) )
3061 if( static_cast<unsigned int>(value) != mSiblingOrder )
3063 SetSiblingOrder( value );
3069 case Dali::Actor::Property::CLIPPING_MODE:
3071 ClippingMode::Type convertedValue = mClippingMode;
3072 if( Scripting::GetEnumerationProperty< ClippingMode::Type >( property, CLIPPING_MODE_TABLE, CLIPPING_MODE_TABLE_COUNT, convertedValue ) )
3074 mClippingMode = convertedValue;
3077 SetClippingModeMessage( GetEventThreadServices(), *mNode, mClippingMode );
3083 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
3086 if( property.Get( value ) && value != mPositionUsesAnchorPoint )
3088 mPositionUsesAnchorPoint = value;
3091 SetPositionUsesAnchorPointMessage( GetEventThreadServices(), *mNode, mPositionUsesAnchorPoint );
3099 // this can happen in the case of a non-animatable default property so just do nothing
3105 // TODO: This method needs to be removed
3106 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
3108 switch( entry.GetType() )
3110 case Property::BOOLEAN:
3112 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
3113 DALI_ASSERT_DEBUG( NULL != property );
3115 // property is being used in a separate thread; queue a message to set the property
3116 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
3121 case Property::INTEGER:
3123 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
3124 DALI_ASSERT_DEBUG( NULL != property );
3126 // property is being used in a separate thread; queue a message to set the property
3127 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
3132 case Property::FLOAT:
3134 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
3135 DALI_ASSERT_DEBUG( NULL != property );
3137 // property is being used in a separate thread; queue a message to set the property
3138 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
3143 case Property::VECTOR2:
3145 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
3146 DALI_ASSERT_DEBUG( NULL != property );
3148 // property is being used in a separate thread; queue a message to set the property
3149 if(entry.componentIndex == 0)
3151 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
3153 else if(entry.componentIndex == 1)
3155 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
3159 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
3165 case Property::VECTOR3:
3167 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
3168 DALI_ASSERT_DEBUG( NULL != property );
3170 // property is being used in a separate thread; queue a message to set the property
3171 if(entry.componentIndex == 0)
3173 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
3175 else if(entry.componentIndex == 1)
3177 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
3179 else if(entry.componentIndex == 2)
3181 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
3185 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
3191 case Property::VECTOR4:
3193 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
3194 DALI_ASSERT_DEBUG( NULL != property );
3196 // property is being used in a separate thread; queue a message to set the property
3197 if(entry.componentIndex == 0)
3199 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
3201 else if(entry.componentIndex == 1)
3203 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
3205 else if(entry.componentIndex == 2)
3207 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
3209 else if(entry.componentIndex == 3)
3211 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
3215 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3221 case Property::ROTATION:
3223 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3224 DALI_ASSERT_DEBUG( NULL != property );
3226 // property is being used in a separate thread; queue a message to set the property
3227 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3232 case Property::MATRIX:
3234 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3235 DALI_ASSERT_DEBUG( NULL != property );
3237 // property is being used in a separate thread; queue a message to set the property
3238 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3243 case Property::MATRIX3:
3245 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3246 DALI_ASSERT_DEBUG( NULL != property );
3248 // property is being used in a separate thread; queue a message to set the property
3249 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3256 // nothing to do for other types
3261 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3263 Property::Value value;
3265 if( ! GetCachedPropertyValue( index, value ) )
3267 // If property value is not stored in the event-side, then it must be a scene-graph only property
3268 GetCurrentPropertyValue( index, value );
3274 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
3276 Property::Value value;
3278 if( ! GetCurrentPropertyValue( index, value ) )
3280 // If unable to retrieve scene-graph property value, then it must be an event-side only property
3281 GetCachedPropertyValue( index, value );
3287 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3292 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3294 // This method should only return an object connected to the scene-graph
3295 return OnStage() ? mNode : NULL;
3298 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3300 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3302 const PropertyBase* property( NULL );
3304 // This method should only return a property of an object connected to the scene-graph
3310 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3312 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3313 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3315 property = animatable->GetSceneGraphProperty();
3317 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3318 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3320 CustomPropertyMetadata* custom = FindCustomProperty( index );
3321 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3323 property = custom->GetSceneGraphProperty();
3325 else if( NULL != mNode )
3329 case Dali::Actor::Property::SIZE:
3330 property = &mNode->mSize;
3333 case Dali::Actor::Property::SIZE_WIDTH:
3334 property = &mNode->mSize;
3337 case Dali::Actor::Property::SIZE_HEIGHT:
3338 property = &mNode->mSize;
3341 case Dali::Actor::Property::SIZE_DEPTH:
3342 property = &mNode->mSize;
3345 case Dali::Actor::Property::POSITION:
3346 property = &mNode->mPosition;
3349 case Dali::Actor::Property::POSITION_X:
3350 property = &mNode->mPosition;
3353 case Dali::Actor::Property::POSITION_Y:
3354 property = &mNode->mPosition;
3357 case Dali::Actor::Property::POSITION_Z:
3358 property = &mNode->mPosition;
3361 case Dali::Actor::Property::ORIENTATION:
3362 property = &mNode->mOrientation;
3365 case Dali::Actor::Property::SCALE:
3366 property = &mNode->mScale;
3369 case Dali::Actor::Property::SCALE_X:
3370 property = &mNode->mScale;
3373 case Dali::Actor::Property::SCALE_Y:
3374 property = &mNode->mScale;
3377 case Dali::Actor::Property::SCALE_Z:
3378 property = &mNode->mScale;
3381 case Dali::Actor::Property::VISIBLE:
3382 property = &mNode->mVisible;
3385 case Dali::Actor::Property::COLOR:
3386 property = &mNode->mColor;
3389 case Dali::Actor::Property::COLOR_RED:
3390 property = &mNode->mColor;
3393 case Dali::Actor::Property::COLOR_GREEN:
3394 property = &mNode->mColor;
3397 case Dali::Actor::Property::COLOR_BLUE:
3398 property = &mNode->mColor;
3401 case Dali::Actor::Property::COLOR_ALPHA:
3402 case Dali::DevelActor::Property::OPACITY:
3403 property = &mNode->mColor;
3414 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3416 const PropertyInputImpl* property( NULL );
3418 // This method should only return a property of an object connected to the scene-graph
3424 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3426 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3427 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3429 property = animatable->GetSceneGraphProperty();
3431 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3432 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3434 CustomPropertyMetadata* custom = FindCustomProperty( index );
3435 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3436 property = custom->GetSceneGraphProperty();
3438 else if( NULL != mNode )
3442 case Dali::Actor::Property::PARENT_ORIGIN:
3443 property = &mNode->mParentOrigin;
3446 case Dali::Actor::Property::PARENT_ORIGIN_X:
3447 property = &mNode->mParentOrigin;
3450 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3451 property = &mNode->mParentOrigin;
3454 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3455 property = &mNode->mParentOrigin;
3458 case Dali::Actor::Property::ANCHOR_POINT:
3459 property = &mNode->mAnchorPoint;
3462 case Dali::Actor::Property::ANCHOR_POINT_X:
3463 property = &mNode->mAnchorPoint;
3466 case Dali::Actor::Property::ANCHOR_POINT_Y:
3467 property = &mNode->mAnchorPoint;
3470 case Dali::Actor::Property::ANCHOR_POINT_Z:
3471 property = &mNode->mAnchorPoint;
3474 case Dali::Actor::Property::SIZE:
3475 property = &mNode->mSize;
3478 case Dali::Actor::Property::SIZE_WIDTH:
3479 property = &mNode->mSize;
3482 case Dali::Actor::Property::SIZE_HEIGHT:
3483 property = &mNode->mSize;
3486 case Dali::Actor::Property::SIZE_DEPTH:
3487 property = &mNode->mSize;
3490 case Dali::Actor::Property::POSITION:
3491 property = &mNode->mPosition;
3494 case Dali::Actor::Property::POSITION_X:
3495 property = &mNode->mPosition;
3498 case Dali::Actor::Property::POSITION_Y:
3499 property = &mNode->mPosition;
3502 case Dali::Actor::Property::POSITION_Z:
3503 property = &mNode->mPosition;
3506 case Dali::Actor::Property::WORLD_POSITION:
3507 property = &mNode->mWorldPosition;
3510 case Dali::Actor::Property::WORLD_POSITION_X:
3511 property = &mNode->mWorldPosition;
3514 case Dali::Actor::Property::WORLD_POSITION_Y:
3515 property = &mNode->mWorldPosition;
3518 case Dali::Actor::Property::WORLD_POSITION_Z:
3519 property = &mNode->mWorldPosition;
3522 case Dali::Actor::Property::ORIENTATION:
3523 property = &mNode->mOrientation;
3526 case Dali::Actor::Property::WORLD_ORIENTATION:
3527 property = &mNode->mWorldOrientation;
3530 case Dali::Actor::Property::SCALE:
3531 property = &mNode->mScale;
3534 case Dali::Actor::Property::SCALE_X:
3535 property = &mNode->mScale;
3538 case Dali::Actor::Property::SCALE_Y:
3539 property = &mNode->mScale;
3542 case Dali::Actor::Property::SCALE_Z:
3543 property = &mNode->mScale;
3546 case Dali::Actor::Property::WORLD_SCALE:
3547 property = &mNode->mWorldScale;
3550 case Dali::Actor::Property::VISIBLE:
3551 property = &mNode->mVisible;
3554 case Dali::Actor::Property::COLOR:
3555 property = &mNode->mColor;
3558 case Dali::Actor::Property::COLOR_RED:
3559 property = &mNode->mColor;
3562 case Dali::Actor::Property::COLOR_GREEN:
3563 property = &mNode->mColor;
3566 case Dali::Actor::Property::COLOR_BLUE:
3567 property = &mNode->mColor;
3570 case Dali::Actor::Property::COLOR_ALPHA:
3571 case Dali::DevelActor::Property::OPACITY:
3573 property = &mNode->mColor;
3577 case Dali::Actor::Property::WORLD_COLOR:
3578 property = &mNode->mWorldColor;
3581 case Dali::Actor::Property::WORLD_MATRIX:
3582 property = &mNode->mWorldMatrix;
3593 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3595 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3597 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3599 // check whether the animatable property is registered already, if not then register one.
3600 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3601 if( animatableProperty )
3603 componentIndex = animatableProperty->componentIndex;
3610 case Dali::Actor::Property::PARENT_ORIGIN_X:
3611 case Dali::Actor::Property::ANCHOR_POINT_X:
3612 case Dali::Actor::Property::SIZE_WIDTH:
3613 case Dali::Actor::Property::POSITION_X:
3614 case Dali::Actor::Property::WORLD_POSITION_X:
3615 case Dali::Actor::Property::SCALE_X:
3616 case Dali::Actor::Property::COLOR_RED:
3622 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3623 case Dali::Actor::Property::ANCHOR_POINT_Y:
3624 case Dali::Actor::Property::SIZE_HEIGHT:
3625 case Dali::Actor::Property::POSITION_Y:
3626 case Dali::Actor::Property::WORLD_POSITION_Y:
3627 case Dali::Actor::Property::SCALE_Y:
3628 case Dali::Actor::Property::COLOR_GREEN:
3634 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3635 case Dali::Actor::Property::ANCHOR_POINT_Z:
3636 case Dali::Actor::Property::SIZE_DEPTH:
3637 case Dali::Actor::Property::POSITION_Z:
3638 case Dali::Actor::Property::WORLD_POSITION_Z:
3639 case Dali::Actor::Property::SCALE_Z:
3640 case Dali::Actor::Property::COLOR_BLUE:
3646 case Dali::Actor::Property::COLOR_ALPHA:
3647 case Dali::DevelActor::Property::OPACITY:
3661 return componentIndex;
3664 void Actor::SetParent( Actor* parent )
3668 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3672 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3675 // Instruct each actor to create a corresponding node in the scene graph
3676 ConnectToStage( parent->GetHierarchyDepth() );
3679 // Resolve the name and index for the child properties if any
3680 ResolveChildProperties();
3682 else // parent being set to NULL
3684 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3688 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3691 DALI_ASSERT_ALWAYS( mNode != NULL );
3695 // Disconnect the Node & its children from the scene-graph.
3696 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3699 // Instruct each actor to discard pointers to the scene-graph
3700 DisconnectFromStage();
3705 SceneGraph::Node* Actor::CreateNode() const
3710 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3713 Actor* actor = dynamic_cast< Actor* >( object );
3717 if( 0 == actionName.compare( ACTION_SHOW ) )
3719 actor->SetVisible( true );
3722 else if( 0 == actionName.compare( ACTION_HIDE ) )
3724 actor->SetVisible( false );
3732 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
3734 bool valueSet = true;
3738 case Dali::Actor::Property::PARENT_ORIGIN:
3740 value = GetCurrentParentOrigin();
3744 case Dali::Actor::Property::PARENT_ORIGIN_X:
3746 value = GetCurrentParentOrigin().x;
3750 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3752 value = GetCurrentParentOrigin().y;
3756 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3758 value = GetCurrentParentOrigin().z;
3762 case Dali::Actor::Property::ANCHOR_POINT:
3764 value = GetCurrentAnchorPoint();
3768 case Dali::Actor::Property::ANCHOR_POINT_X:
3770 value = GetCurrentAnchorPoint().x;
3774 case Dali::Actor::Property::ANCHOR_POINT_Y:
3776 value = GetCurrentAnchorPoint().y;
3780 case Dali::Actor::Property::ANCHOR_POINT_Z:
3782 value = GetCurrentAnchorPoint().z;
3786 case Dali::Actor::Property::SIZE:
3788 value = GetTargetSize();
3792 case Dali::Actor::Property::SIZE_WIDTH:
3794 value = GetTargetSize().width;
3798 case Dali::Actor::Property::SIZE_HEIGHT:
3800 value = GetTargetSize().height;
3804 case Dali::Actor::Property::SIZE_DEPTH:
3806 value = GetTargetSize().depth;
3810 case Dali::Actor::Property::POSITION:
3812 value = GetTargetPosition();
3816 case Dali::Actor::Property::POSITION_X:
3818 value = GetTargetPosition().x;
3822 case Dali::Actor::Property::POSITION_Y:
3824 value = GetTargetPosition().y;
3828 case Dali::Actor::Property::POSITION_Z:
3830 value = GetTargetPosition().z;
3834 case Dali::Actor::Property::ORIENTATION:
3836 value = mTargetOrientation;
3840 case Dali::Actor::Property::SCALE:
3842 value = mTargetScale;
3846 case Dali::Actor::Property::SCALE_X:
3848 value = mTargetScale.x;
3852 case Dali::Actor::Property::SCALE_Y:
3854 value = mTargetScale.y;
3858 case Dali::Actor::Property::SCALE_Z:
3860 value = mTargetScale.z;
3864 case Dali::Actor::Property::VISIBLE:
3870 case Dali::Actor::Property::COLOR:
3872 value = mTargetColor;
3876 case Dali::Actor::Property::COLOR_RED:
3878 value = mTargetColor.r;
3882 case Dali::Actor::Property::COLOR_GREEN:
3884 value = mTargetColor.g;
3888 case Dali::Actor::Property::COLOR_BLUE:
3890 value = mTargetColor.b;
3894 case Dali::Actor::Property::COLOR_ALPHA:
3895 case Dali::DevelActor::Property::OPACITY:
3897 value = mTargetColor.a;
3901 case Dali::Actor::Property::NAME:
3907 case Dali::Actor::Property::SENSITIVE:
3909 value = IsSensitive();
3913 case Dali::Actor::Property::LEAVE_REQUIRED:
3915 value = GetLeaveRequired();
3919 case Dali::Actor::Property::INHERIT_POSITION:
3921 value = IsPositionInherited();
3925 case Dali::Actor::Property::INHERIT_ORIENTATION:
3927 value = IsOrientationInherited();
3931 case Dali::Actor::Property::INHERIT_SCALE:
3933 value = IsScaleInherited();
3937 case Dali::Actor::Property::COLOR_MODE:
3939 value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
3943 case Dali::Actor::Property::POSITION_INHERITANCE:
3945 value = Scripting::GetLinearEnumerationName< PositionInheritanceMode >( GetPositionInheritanceMode(), POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT );
3949 case Dali::Actor::Property::DRAW_MODE:
3951 value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
3955 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3957 value = GetSizeModeFactor();
3961 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3963 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3967 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3969 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3973 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3975 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT );
3979 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3981 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3985 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3987 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3991 case Dali::Actor::Property::PADDING:
3993 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3994 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3995 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3999 case Dali::Actor::Property::MINIMUM_SIZE:
4001 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
4005 case Dali::Actor::Property::MAXIMUM_SIZE:
4007 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
4011 case Dali::Actor::Property::CLIPPING_MODE:
4013 value = mClippingMode;
4017 case Dali::DevelActor::Property::SIBLING_ORDER:
4019 value = static_cast<int>(mSiblingOrder);
4023 case Dali::DevelActor::Property::SCREEN_POSITION:
4025 value = GetCurrentScreenPosition();
4029 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
4031 value = mPositionUsesAnchorPoint;
4037 // Must be a scene-graph only property
4046 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
4048 bool valueSet = true;
4052 case Dali::Actor::Property::SIZE:
4054 value = GetCurrentSize();
4058 case Dali::Actor::Property::SIZE_WIDTH:
4060 value = GetCurrentSize().width;
4064 case Dali::Actor::Property::SIZE_HEIGHT:
4066 value = GetCurrentSize().height;
4070 case Dali::Actor::Property::SIZE_DEPTH:
4072 value = GetCurrentSize().depth;
4076 case Dali::Actor::Property::POSITION:
4078 value = GetCurrentPosition();
4082 case Dali::Actor::Property::POSITION_X:
4084 value = GetCurrentPosition().x;
4088 case Dali::Actor::Property::POSITION_Y:
4090 value = GetCurrentPosition().y;
4094 case Dali::Actor::Property::POSITION_Z:
4096 value = GetCurrentPosition().z;
4100 case Dali::Actor::Property::WORLD_POSITION:
4102 value = GetCurrentWorldPosition();
4106 case Dali::Actor::Property::WORLD_POSITION_X:
4108 value = GetCurrentWorldPosition().x;
4112 case Dali::Actor::Property::WORLD_POSITION_Y:
4114 value = GetCurrentWorldPosition().y;
4118 case Dali::Actor::Property::WORLD_POSITION_Z:
4120 value = GetCurrentWorldPosition().z;
4124 case Dali::Actor::Property::ORIENTATION:
4126 value = GetCurrentOrientation();
4130 case Dali::Actor::Property::WORLD_ORIENTATION:
4132 value = GetCurrentWorldOrientation();
4136 case Dali::Actor::Property::SCALE:
4138 value = GetCurrentScale();
4142 case Dali::Actor::Property::SCALE_X:
4144 value = GetCurrentScale().x;
4148 case Dali::Actor::Property::SCALE_Y:
4150 value = GetCurrentScale().y;
4154 case Dali::Actor::Property::SCALE_Z:
4156 value = GetCurrentScale().z;
4160 case Dali::Actor::Property::WORLD_SCALE:
4162 value = GetCurrentWorldScale();
4166 case Dali::Actor::Property::COLOR:
4168 value = GetCurrentColor();
4172 case Dali::Actor::Property::COLOR_RED:
4174 value = GetCurrentColor().r;
4178 case Dali::Actor::Property::COLOR_GREEN:
4180 value = GetCurrentColor().g;
4184 case Dali::Actor::Property::COLOR_BLUE:
4186 value = GetCurrentColor().b;
4190 case Dali::Actor::Property::COLOR_ALPHA:
4191 case Dali::DevelActor::Property::OPACITY:
4193 value = GetCurrentColor().a;
4197 case Dali::Actor::Property::WORLD_COLOR:
4199 value = GetCurrentWorldColor();
4203 case Dali::Actor::Property::WORLD_MATRIX:
4205 value = GetCurrentWorldMatrix();
4211 // Must be an event-side only property
4220 void Actor::EnsureRelayoutData()
4222 // Assign relayout data.
4223 if( !mRelayoutData )
4225 mRelayoutData = new RelayoutData();
4229 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
4231 // Check if actor is dependent on parent
4232 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4234 if( ( dimension & ( 1 << i ) ) )
4236 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4237 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
4247 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
4249 // Check if actor is dependent on children
4250 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4252 if( ( dimension & ( 1 << i ) ) )
4254 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4255 switch( resizePolicy )
4257 case ResizePolicy::FIT_TO_CHILDREN:
4258 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
4274 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
4276 return Actor::RelayoutDependentOnChildren( dimension );
4279 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
4281 // Check each possible dimension and see if it is dependent on the input one
4282 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4284 if( dimension & ( 1 << i ) )
4286 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
4293 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
4295 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4297 if( dimension & ( 1 << i ) )
4299 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
4304 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
4306 // If more than one dimension is requested, just return the first one found
4307 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4309 if( ( dimension & ( 1 << i ) ) )
4311 return mRelayoutData->negotiatedDimensions[ i ];
4315 return 0.0f; // Default
4318 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
4320 EnsureRelayoutData();
4322 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4324 if( dimension & ( 1 << i ) )
4326 mRelayoutData->dimensionPadding[ i ] = padding;
4331 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4333 if ( mRelayoutData )
4335 // If more than one dimension is requested, just return the first one found
4336 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4338 if( ( dimension & ( 1 << i ) ) )
4340 return mRelayoutData->dimensionPadding[ i ];
4345 return GetDefaultDimensionPadding();
4348 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4350 EnsureRelayoutData();
4352 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4354 if( dimension & ( 1 << i ) )
4356 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4361 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4363 if ( mRelayoutData )
4365 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4367 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4377 float Actor::GetHeightForWidthBase( float width )
4379 float height = 0.0f;
4381 const Vector3 naturalSize = GetNaturalSize();
4382 if( naturalSize.width > 0.0f )
4384 height = naturalSize.height * width / naturalSize.width;
4386 else // we treat 0 as 1:1 aspect ratio
4394 float Actor::GetWidthForHeightBase( float height )
4398 const Vector3 naturalSize = GetNaturalSize();
4399 if( naturalSize.height > 0.0f )
4401 width = naturalSize.width * height / naturalSize.height;
4403 else // we treat 0 as 1:1 aspect ratio
4411 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4413 // Fill to parent, taking size mode factor into account
4414 switch( child.GetResizePolicy( dimension ) )
4416 case ResizePolicy::FILL_TO_PARENT:
4418 return GetLatestSize( dimension );
4421 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4423 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4426 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4428 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4433 return GetLatestSize( dimension );
4438 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4440 // Can be overridden in derived class
4441 return CalculateChildSizeBase( child, dimension );
4444 float Actor::GetHeightForWidth( float width )
4446 // Can be overridden in derived class
4447 return GetHeightForWidthBase( width );
4450 float Actor::GetWidthForHeight( float height )
4452 // Can be overridden in derived class
4453 return GetWidthForHeightBase( height );
4456 float Actor::GetLatestSize( Dimension::Type dimension ) const
4458 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4461 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4463 Vector2 padding = GetPadding( dimension );
4465 return GetLatestSize( dimension ) + padding.x + padding.y;
4468 float Actor::NegotiateFromParent( Dimension::Type dimension )
4470 Actor* parent = GetParent();
4473 Vector2 padding( GetPadding( dimension ) );
4474 Vector2 parentPadding( parent->GetPadding( dimension ) );
4475 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4481 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4483 float maxDimensionPoint = 0.0f;
4485 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4487 ActorPtr child = GetChildAt( i );
4489 if( !child->RelayoutDependentOnParent( dimension ) )
4491 // Calculate the min and max points that the children range across
4492 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
4493 float dimensionSize = child->GetRelayoutSize( dimension );
4494 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4498 return maxDimensionPoint;
4501 float Actor::GetSize( Dimension::Type dimension ) const
4503 return GetDimensionValue( mTargetSize, dimension );
4506 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4508 return GetDimensionValue( GetNaturalSize(), dimension );
4511 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4513 switch( GetResizePolicy( dimension ) )
4515 case ResizePolicy::USE_NATURAL_SIZE:
4517 return GetNaturalSize( dimension );
4520 case ResizePolicy::FIXED:
4522 return GetDimensionValue( GetPreferredSize(), dimension );
4525 case ResizePolicy::USE_ASSIGNED_SIZE:
4527 return GetDimensionValue( maximumSize, dimension );
4530 case ResizePolicy::FILL_TO_PARENT:
4531 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4532 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4534 return NegotiateFromParent( dimension );
4537 case ResizePolicy::FIT_TO_CHILDREN:
4539 return NegotiateFromChildren( dimension );
4542 case ResizePolicy::DIMENSION_DEPENDENCY:
4544 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4547 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4549 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4552 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4554 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4566 return 0.0f; // Default
4569 float Actor::ClampDimension( float size, Dimension::Type dimension )
4571 const float minSize = GetMinimumSize( dimension );
4572 const float maxSize = GetMaximumSize( dimension );
4574 return std::max( minSize, std::min( size, maxSize ) );
4577 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4579 // Check if it needs to be negotiated
4580 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4582 // Check that we havn't gotten into an infinite loop
4583 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4584 bool recursionFound = false;
4585 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4587 if( *it == searchActor )
4589 recursionFound = true;
4594 if( !recursionFound )
4596 // Record the path that we have taken
4597 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4599 // Dimension dependency check
4600 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4602 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4604 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4606 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4610 // Parent dependency check
4611 Actor* parent = GetParent();
4612 if( parent && RelayoutDependentOnParent( dimension ) )
4614 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4617 // Children dependency check
4618 if( RelayoutDependentOnChildren( dimension ) )
4620 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4622 ActorPtr child = GetChildAt( i );
4624 // Only relayout child first if it is not dependent on this actor
4625 if( !child->RelayoutDependentOnParent( dimension ) )
4627 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
4632 // For deriving classes
4633 OnCalculateRelayoutSize( dimension );
4635 // All dependencies checked, calculate the size and set negotiated flag
4636 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4638 SetNegotiatedDimension( newSize, dimension );
4639 SetLayoutNegotiated( true, dimension );
4641 // For deriving classes
4642 OnLayoutNegotiated( newSize, dimension );
4644 // This actor has been successfully processed, pop it off the recursion stack
4645 recursionStack.pop_back();
4649 // TODO: Break infinite loop
4650 SetLayoutNegotiated( true, dimension );
4655 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4657 // Negotiate all dimensions that require it
4658 ActorDimensionStack recursionStack;
4660 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4662 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4665 NegotiateDimension( dimension, allocatedSize, recursionStack );
4669 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4671 switch( mRelayoutData->sizeSetPolicy )
4673 case SizeScalePolicy::USE_SIZE_SET:
4678 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4680 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4681 const Vector3 naturalSize = GetNaturalSize();
4682 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4684 const float sizeRatio = size.width / size.height;
4685 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4687 if( naturalSizeRatio < sizeRatio )
4689 return Vector2( naturalSizeRatio * size.height, size.height );
4691 else if( naturalSizeRatio > sizeRatio )
4693 return Vector2( size.width, size.width / naturalSizeRatio );
4704 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4706 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4707 const Vector3 naturalSize = GetNaturalSize();
4708 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4710 const float sizeRatio = size.width / size.height;
4711 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4713 if( naturalSizeRatio < sizeRatio )
4715 return Vector2( size.width, size.width / naturalSizeRatio );
4717 else if( naturalSizeRatio > sizeRatio )
4719 return Vector2( naturalSizeRatio * size.height, size.height );
4738 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4740 // Do the set actor size
4741 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4743 // Adjust for size set policy
4744 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4746 // Lock the flag to stop recursive relayouts on set size
4747 mRelayoutData->insideRelayout = true;
4748 SetSize( negotiatedSize );
4749 mRelayoutData->insideRelayout = false;
4751 // Clear flags for all dimensions
4752 SetLayoutDirty( false );
4754 // Give deriving classes a chance to respond
4755 OnRelayout( negotiatedSize, container );
4757 if( !mOnRelayoutSignal.Empty() )
4759 Dali::Actor handle( this );
4760 mOnRelayoutSignal.Emit( handle );
4764 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4766 // Force a size negotiation for actors that has assigned size during relayout
4767 // This is required as otherwise the flags that force a relayout will not
4768 // necessarilly be set. This will occur if the actor has already been laid out.
4769 // The dirty flags are then cleared. Then if the actor is added back into the
4770 // relayout container afterwards, the dirty flags would still be clear...
4771 // causing a relayout to be skipped. Here we force any actors added to the
4772 // container to be relayed out.
4773 DALI_LOG_TIMER_START( NegSizeTimer1 );
4775 if(GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE)
4777 SetLayoutNegotiated(false, Dimension::WIDTH);
4779 if(GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE)
4781 SetLayoutNegotiated(false, Dimension::HEIGHT);
4784 // Do the negotiation
4785 NegotiateDimensions( allocatedSize );
4787 // Set the actor size
4788 SetNegotiatedSize( container );
4790 // Negotiate down to children
4791 const Vector2 newBounds = mTargetSize.GetVectorXY();
4793 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4795 ActorPtr child = GetChildAt( i );
4797 // Forces children that have already been laid out to be relayed out
4798 // if they have assigned size during relayout.
4799 if(child->GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE)
4801 child->SetLayoutNegotiated(false, Dimension::WIDTH);
4802 child->SetLayoutDirty(true, Dimension::WIDTH);
4804 if(child->GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE)
4806 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
4807 child->SetLayoutDirty(true, Dimension::HEIGHT);
4810 // Only relayout if required
4811 if( child->RelayoutRequired() )
4813 container.Add( Dali::Actor( child.Get() ), newBounds );
4816 DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
4819 void Actor::RelayoutRequest( Dimension::Type dimension )
4821 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4822 if( relayoutController )
4824 Dali::Actor self( this );
4825 relayoutController->RequestRelayout( self, dimension );
4829 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4833 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4837 void Actor::SetPreferredSize( const Vector2& size )
4839 EnsureRelayoutData();
4841 if( size.width > 0.0f )
4843 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4846 if( size.height > 0.0f )
4848 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4851 mRelayoutData->preferredSize = size;
4856 Vector2 Actor::GetPreferredSize() const
4858 if ( mRelayoutData )
4860 return Vector2( mRelayoutData->preferredSize );
4863 return GetDefaultPreferredSize();
4866 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4868 EnsureRelayoutData();
4870 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4872 if( dimension & ( 1 << i ) )
4874 mRelayoutData->minimumSize[ i ] = size;
4881 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4883 if ( mRelayoutData )
4885 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4887 if( dimension & ( 1 << i ) )
4889 return mRelayoutData->minimumSize[ i ];
4894 return 0.0f; // Default
4897 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4899 EnsureRelayoutData();
4901 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4903 if( dimension & ( 1 << i ) )
4905 mRelayoutData->maximumSize[ i ] = size;
4912 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4914 if ( mRelayoutData )
4916 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4918 if( dimension & ( 1 << i ) )
4920 return mRelayoutData->maximumSize[ i ];
4925 return FLT_MAX; // Default
4928 Object* Actor::GetParentObject() const
4933 void Actor::SetSiblingOrder( unsigned int order )
4935 mSiblingOrder = std::min( order, static_cast<unsigned int>( DevelLayer::SIBLING_ORDER_MULTIPLIER ) );
4939 StagePtr stage = Stage::GetCurrent();
4942 stage->RequestRebuildDepthTree();
4947 void Actor::DefragmentSiblingIndexes( ActorContainer& siblings )
4949 // Sibling index may not be in consecutive order as the sibling range is limited ( DevelLayer::SIBLING_ORDER_MULTIPLIER )
4950 // we need to remove the gaps and ensure the number start from 0 and consecutive hence have a full range.
4952 // Start at index 0, while index <= highest order
4953 // Find next index higher than 0
4954 // if nextHigher > index+1
4955 // set all nextHigher orders to index+1
4957 // Limitation: May reach the ceiling of DevelLayer::SIBLING_ORDER_MULTIPLIER with highest sibling.
4959 ActorIter end = siblings.end();
4960 int highestOrder = 0;
4961 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
4963 ActorPtr sibling = (*iter);
4964 int siblingOrder = sibling->mSiblingOrder;
4965 highestOrder = std::max( highestOrder, siblingOrder );
4968 for ( int index = 0; index <= highestOrder; index++ )
4970 int nextHighest = -1;
4972 // Find Next highest
4973 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
4975 ActorPtr sibling = (*iter);
4976 int siblingOrder = sibling->mSiblingOrder;
4978 if ( siblingOrder > index )
4980 if ( nextHighest == -1 )
4982 nextHighest = siblingOrder;
4984 nextHighest = std::min( nextHighest, siblingOrder );
4988 // Check if a gap exists between indexes, if so set next index to consecutive number
4989 if ( ( nextHighest - index ) > 1 )
4991 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
4993 ActorPtr sibling = (*iter);
4994 int siblingOrder = sibling->mSiblingOrder;
4995 if ( siblingOrder == nextHighest )
4997 sibling->mSiblingOrder = index + 1;
4998 if ( sibling->mSiblingOrder >= Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER )
5000 DALI_LOG_WARNING( "Reached max sibling order level for raising / lowering actors\n" );
5001 sibling->mSiblingOrder = Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER;
5003 sibling->SetSiblingOrder( sibling->mSiblingOrder );
5010 bool Actor::ShiftSiblingsLevels( ActorContainer& siblings, int targetLevelToShiftFrom )
5012 // Allows exclusive levels for an actor by shifting all sibling levels at the target and above by 1
5013 bool defragmentationRequired( false );
5014 ActorIter end = siblings.end();
5015 for( ActorIter iter = siblings.begin(); ( iter != end ) ; ++iter )
5017 // Move actors at nearest order and above up by 1
5018 ActorPtr sibling = (*iter);
5019 if ( sibling != this )
5021 // Iterate through container of actors, any actor with a sibling order of the target or greater should
5022 // be incremented by 1.
5023 if ( sibling->mSiblingOrder >= targetLevelToShiftFrom )
5025 sibling->mSiblingOrder++;
5026 if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
5028 // If a sibling order raises so that it is only 1 from the maximum allowed then set flag so
5029 // can re-order all sibling orders.
5030 defragmentationRequired = true;
5032 sibling->SetSiblingOrder( sibling->mSiblingOrder );
5036 return defragmentationRequired;
5042 1) Check if already at top and nothing to be done.
5043 This Actor can have highest sibling order but if not exclusive then another actor at same sibling
5044 order can be positioned above it due to insertion order of actors.
5045 2) Find nearest sibling level above, these are the siblings this actor needs to be above
5046 3) a) There may be other levels above this target level
5047 b) Increment all sibling levels at the level above nearest(target)
5048 c) Now have a vacant sibling level
5049 4) Set this actor's sibling level to nearest +1 as now vacated.
5051 Note May not just be sibling level + 1 as could be empty levels in-between
5056 ActorC ( sibling level 4 )
5057 ActorB ( sibling level 3 )
5058 ActorA ( sibling level 1 )
5060 2 ) ACTION: Raise A above B
5061 a) Find nearest level above A = Level 3
5062 b) Increment levels above Level 3
5064 ActorC ( sibling level 5 )
5065 ActorB ( sibling level 3 ) NEAREST
5066 ActorA ( sibling level 1 )
5068 3 ) Set Actor A sibling level to nearest +1 as vacant
5070 ActorC ( sibling level 5 )
5071 ActorA ( sibling level 4 )
5072 ActorB ( sibling level 3 )
5074 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5075 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5076 remove any empty sibling order gaps and start from sibling level 0 again.
5077 If the number of actors reaches this maximum and all using exclusive sibling order values then
5078 defragmention will stop and new sibling orders will be set to same max value.
5082 int nearestLevel = mSiblingOrder;
5083 int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
5084 bool defragmentationRequired( false );
5086 ActorContainer* siblings = mParent->mChildren;
5088 // Find Nearest sibling level above this actor
5089 ActorIter end = siblings->end();
5090 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
5092 ActorPtr sibling = (*iter);
5093 if ( sibling != this )
5095 int order = GetSiblingOrder( sibling );
5097 if ( ( order >= mSiblingOrder ) )
5099 int distanceToNextLevel = order - mSiblingOrder;
5100 if ( distanceToNextLevel < shortestDistanceToNextLevel )
5102 nearestLevel = order;
5103 shortestDistanceToNextLevel = distanceToNextLevel;
5109 if ( nearestLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at top
5111 mSiblingOrder = nearestLevel + 1; // Set sibling level to that above the nearest level
5112 defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
5113 // Move current actor to newly vacated order level
5114 SetSiblingOrder( mSiblingOrder );
5115 if ( defragmentationRequired )
5117 DefragmentSiblingIndexes( *siblings );
5120 SetSiblingOrder( mSiblingOrder );
5124 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5131 1) Check if actor already at bottom and if nothing needs to be done
5132 This Actor can have lowest sibling order but if not exclusive then another actor at same sibling
5133 order can be positioned above it due to insertion order of actors so need to move this actor below it.
5134 2) Find nearest sibling level below, this Actor needs to be below it
5135 3) a) Need to vacate a sibling level below nearest for this actor to occupy
5136 b) Shift up all sibling order values of actor at the nearest level and levels above it to vacate a level.
5137 c) Set this actor's sibling level to this newly vacated level.
5138 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5139 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5140 remove any empty sibling order gaps and start from sibling level 0 again.
5141 If the number of actors reaches this maximum and all using exclusive sibling order values then
5142 defragmention will stop and new sibling orders will be set to same max value.
5147 // 1) Find nearest level below
5148 int nearestLevel = mSiblingOrder;
5149 int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
5151 ActorContainer* siblings = mParent->mChildren;
5153 ActorIter end = siblings->end();
5154 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
5156 ActorPtr sibling = (*iter);
5157 if ( sibling != this )
5159 int order = GetSiblingOrder( sibling );
5161 if ( order <= mSiblingOrder )
5163 int distanceToNextLevel = mSiblingOrder - order;
5164 if ( distanceToNextLevel < shortestDistanceToNextLevel )
5166 nearestLevel = order;
5167 shortestDistanceToNextLevel = distanceToNextLevel;
5173 bool defragmentationRequired ( false );
5175 // 2) If actor already not at bottom, raise all actors at required level and above
5176 if ( shortestDistanceToNextLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at bottom
5178 mSiblingOrder = nearestLevel;
5179 defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
5180 // Move current actor to newly vacated order
5181 SetSiblingOrder( mSiblingOrder );
5182 if ( defragmentationRequired )
5184 DefragmentSiblingIndexes( *siblings );
5190 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5194 void Actor::RaiseToTop()
5197 1 ) Find highest sibling order actor
5198 2 ) If highest sibling level not itself then set sibling order to that + 1
5199 3 ) highest sibling order can be same as itself so need to increment over that
5200 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5201 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5202 remove any empty sibling order gaps and start from sibling level 0 again.
5203 If the number of actors reaches this maximum and all using exclusive sibling order values then
5204 defragmention will stop and new sibling orders will be set to same max value.
5211 ActorContainer* siblings = mParent->mChildren;
5213 ActorIter end = siblings->end();
5214 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
5216 ActorPtr sibling = (*iter);
5217 if ( sibling != this )
5219 maxOrder = std::max( GetSiblingOrder( sibling ), maxOrder );
5223 bool defragmentationRequired( false );
5225 if ( maxOrder >= mSiblingOrder )
5227 mSiblingOrder = maxOrder + 1;
5228 if ( mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
5230 defragmentationRequired = true;
5234 SetSiblingOrder( mSiblingOrder );
5236 if ( defragmentationRequired )
5238 DefragmentSiblingIndexes( *siblings );
5243 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5247 void Actor::LowerToBottom()
5250 See Actor::LowerToBottom()
5252 1 ) Check if this actor already at exclusively at the bottom, if so then no more to be done.
5253 2 ) a ) Check if the bottom position 0 is vacant.
5254 b ) If 0 position is not vacant then shift up all sibling order values from 0 and above
5255 c ) 0 sibling position is vacant.
5256 3 ) Set this actor to vacant sibling order 0;
5257 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5258 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5259 remove any empty sibling order gaps and start from sibling level 0 again.
5260 If the number of actors reaches this maximum and all using exclusive sibling order values then
5261 defragmention will stop and new sibling orders will be set to same max value.
5266 bool defragmentationRequired( false );
5267 bool orderZeroFree ( true );
5269 ActorContainer* siblings = mParent->mChildren;
5271 bool actorAtLowestOrder = true;
5272 ActorIter end = siblings->end();
5273 for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
5275 ActorPtr sibling = (*iter);
5276 if ( sibling != this )
5278 int siblingOrder = GetSiblingOrder( sibling );
5279 if ( siblingOrder <= mSiblingOrder )
5281 actorAtLowestOrder = false;
5284 if ( siblingOrder == 0 )
5286 orderZeroFree = false;
5291 if ( ! actorAtLowestOrder )
5293 if ( ! orderZeroFree )
5295 defragmentationRequired = ShiftSiblingsLevels( *siblings, 0 );
5298 SetSiblingOrder( mSiblingOrder );
5300 if ( defragmentationRequired )
5302 DefragmentSiblingIndexes( *siblings );
5308 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5312 void Actor::RaiseAbove( Internal::Actor& target )
5315 1 ) a) Find target actor's sibling order
5316 b) If sibling order of target is the same as this actor then need to this Actor's sibling order
5317 needs to be above it or the insertion order will determine which is drawn on top.
5318 2 ) Shift up by 1 all sibling order greater than target sibling order
5319 3 ) Set this actor to the sibling order to target +1 as will be a newly vacated gap above
5320 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5321 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5322 remove any empty sibling order gaps and start from sibling level 0 again.
5323 If the number of actors reaches this maximum and all using exclusive sibling order values then
5324 defragmention will stop and new sibling orders will be set to same max value.
5329 if ( ValidateActors( *this, target ) )
5331 // Find target's sibling order
5332 // Set actor sibling order to this number +1
5333 int targetSiblingOrder = GetSiblingOrder( &target );
5334 ActorContainer* siblings = mParent->mChildren;
5335 mSiblingOrder = targetSiblingOrder + 1;
5336 bool defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
5338 SetSiblingOrder( mSiblingOrder );
5340 if ( defragmentationRequired )
5342 DefragmentSiblingIndexes( *(mParent->mChildren) );
5348 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5352 void Actor::LowerBelow( Internal::Actor& target )
5355 1 ) a) Find target actor's sibling order
5356 b) If sibling order of target is the same as this actor then need to this Actor's sibling order
5357 needs to be below it or the insertion order will determine which is drawn on top.
5358 2 ) Shift the target sibling order and all sibling orders at that level or above by 1
5359 3 ) Set this actor to the sibling order of the target before it changed.
5360 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5361 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5362 remove any empty sibling order gaps and start from sibling level 0 again.
5363 If the number of actors reaches this maximum and all using exclusive sibling order values then
5364 defragmention will stop and new sibling orders will be set to same max value.
5369 if ( ValidateActors( *this, target ) )
5371 bool defragmentationRequired ( false );
5372 // Find target's sibling order
5373 // Set actor sibling order to target sibling order - 1
5374 int targetSiblingOrder = GetSiblingOrder( &target);
5375 ActorContainer* siblings = mParent->mChildren;
5376 if ( targetSiblingOrder == 0 )
5379 ActorIter end = siblings->end();
5380 for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
5382 ActorPtr sibling = (*iter);
5383 if ( sibling != this )
5385 sibling->mSiblingOrder++;
5386 if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
5388 defragmentationRequired = true;
5390 sibling->SetSiblingOrder( sibling->mSiblingOrder );
5397 defragmentationRequired = ShiftSiblingsLevels( *siblings, targetSiblingOrder );
5399 mSiblingOrder = targetSiblingOrder;
5401 SetSiblingOrder( mSiblingOrder );
5403 if ( defragmentationRequired )
5405 DefragmentSiblingIndexes( *(mParent->mChildren) );
5411 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5415 } // namespace Internal