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 const Vector3& Actor::GetTargetSize() const
1396 const Vector3& Actor::GetCurrentSize() const
1400 // mNode is being used in a separate thread; copy the value from the previous update
1401 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1404 return Vector3::ZERO;
1407 Vector3 Actor::GetNaturalSize() const
1409 // It is up to deriving classes to return the appropriate natural size
1410 return Vector3( 0.0f, 0.0f, 0.0f );
1413 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1415 EnsureRelayoutData();
1417 ResizePolicy::Type originalWidthPolicy = GetResizePolicy(Dimension::WIDTH);
1418 ResizePolicy::Type originalHeightPolicy = GetResizePolicy(Dimension::HEIGHT);
1420 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1422 if( dimension & ( 1 << i ) )
1424 mRelayoutData->resizePolicies[ i ] = policy;
1428 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1430 if( dimension & Dimension::WIDTH )
1432 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1435 if( dimension & Dimension::HEIGHT )
1437 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1441 // If calling SetResizePolicy, assume we want relayout enabled
1442 SetRelayoutEnabled( true );
1444 // If the resize policy is set to be FIXED, the preferred size
1445 // should be overrided by the target size. Otherwise the target
1446 // size should be overrided by the preferred size.
1448 if( dimension & Dimension::WIDTH )
1450 if( originalWidthPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1452 mRelayoutData->preferredSize.width = mTargetSize.width;
1454 else if( originalWidthPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1456 mTargetSize.width = mRelayoutData->preferredSize.width;
1460 if( dimension & Dimension::HEIGHT )
1462 if( originalHeightPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1464 mRelayoutData->preferredSize.height = mTargetSize.height;
1466 else if( originalHeightPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1468 mTargetSize.height = mRelayoutData->preferredSize.height;
1472 OnSetResizePolicy( policy, dimension );
1474 // Trigger relayout on this control
1478 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1480 if ( mRelayoutData )
1482 // If more than one dimension is requested, just return the first one found
1483 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1485 if( ( dimension & ( 1 << i ) ) )
1487 return mRelayoutData->resizePolicies[ i ];
1492 return ResizePolicy::DEFAULT;
1495 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1497 EnsureRelayoutData();
1499 mRelayoutData->sizeSetPolicy = policy;
1502 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1504 if ( mRelayoutData )
1506 return mRelayoutData->sizeSetPolicy;
1509 return DEFAULT_SIZE_SCALE_POLICY;
1512 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1514 EnsureRelayoutData();
1516 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1518 if( dimension & ( 1 << i ) )
1520 mRelayoutData->dimensionDependencies[ i ] = dependency;
1525 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1527 if ( mRelayoutData )
1529 // If more than one dimension is requested, just return the first one found
1530 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1532 if( ( dimension & ( 1 << i ) ) )
1534 return mRelayoutData->dimensionDependencies[ i ];
1539 return Dimension::ALL_DIMENSIONS; // Default
1542 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1544 // If relayout data has not been allocated yet and the client is requesting
1545 // to disable it, do nothing
1546 if( mRelayoutData || relayoutEnabled )
1548 EnsureRelayoutData();
1550 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1552 mRelayoutData->relayoutEnabled = relayoutEnabled;
1556 bool Actor::IsRelayoutEnabled() const
1558 // Assume that if relayout data has not been allocated yet then
1559 // relayout is disabled
1560 return mRelayoutData && mRelayoutData->relayoutEnabled;
1563 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1565 EnsureRelayoutData();
1567 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1569 if( dimension & ( 1 << i ) )
1571 mRelayoutData->dimensionDirty[ i ] = dirty;
1576 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1578 if ( mRelayoutData )
1580 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1582 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1592 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1594 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1597 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1599 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1602 unsigned int Actor::AddRenderer( Renderer& renderer )
1606 mRenderers = new RendererContainer;
1609 unsigned int index = mRenderers->size();
1610 RendererPtr rendererPtr = RendererPtr( &renderer );
1611 mRenderers->push_back( rendererPtr );
1612 AddRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1616 unsigned int Actor::GetRendererCount() const
1618 unsigned int rendererCount(0);
1621 rendererCount = mRenderers->size();
1624 return rendererCount;
1627 RendererPtr Actor::GetRendererAt( unsigned int index )
1629 RendererPtr renderer;
1630 if( index < GetRendererCount() )
1632 renderer = ( *mRenderers )[ index ];
1638 void Actor::RemoveRenderer( Renderer& renderer )
1642 RendererIter end = mRenderers->end();
1643 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1645 if( (*iter).Get() == &renderer )
1647 mRenderers->erase( iter );
1648 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1655 void Actor::RemoveRenderer( unsigned int index )
1657 if( index < GetRendererCount() )
1659 RendererPtr renderer = ( *mRenderers )[ index ];
1660 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.Get()->GetRendererSceneObject() );
1661 mRenderers->erase( mRenderers->begin()+index );
1665 bool Actor::IsOverlay() const
1667 return ( DrawMode::OVERLAY_2D == mDrawMode );
1670 void Actor::SetDrawMode( DrawMode::Type drawMode )
1672 // this flag is not animatable so keep the value
1673 mDrawMode = drawMode;
1674 if( ( NULL != mNode ) && ( drawMode != DrawMode::STENCIL ) )
1676 // mNode is being used in a separate thread; queue a message to set the value
1677 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1681 DrawMode::Type Actor::GetDrawMode() const
1686 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1688 // only valid when on-stage
1689 StagePtr stage = Stage::GetCurrent();
1690 if( stage && OnStage() )
1692 const RenderTaskList& taskList = stage->GetRenderTaskList();
1694 Vector2 converted( screenX, screenY );
1696 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1697 const int taskCount = taskList.GetTaskCount();
1698 for( int i = taskCount - 1; i >= 0; --i )
1700 Dali::RenderTask task = taskList.GetTask( i );
1701 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1703 // found a task where this conversion was ok so return
1711 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1713 bool retval = false;
1714 // only valid when on-stage
1717 CameraActor* camera = renderTask.GetCameraActor();
1721 renderTask.GetViewport( viewport );
1723 // need to translate coordinates to render tasks coordinate space
1724 Vector2 converted( screenX, screenY );
1725 if( renderTask.TranslateCoordinates( converted ) )
1727 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1734 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1736 // Early-out if mNode is NULL
1742 // Get the ModelView matrix
1744 Matrix::Multiply( modelView, mNode->GetWorldMatrix(0), viewMatrix );
1746 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1747 Matrix invertedMvp( false/*don't init*/);
1748 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1749 bool success = invertedMvp.Invert();
1751 // Convert to GL coordinates
1752 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1757 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1764 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1770 if( XyPlaneIntersect( nearPos, farPos, local ) )
1772 Vector3 size = GetCurrentSize();
1773 localX = local.x + size.x * 0.5f;
1774 localY = local.y + size.y * 0.5f;
1785 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1788 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1790 Mathematical Formulation
1792 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1794 ( p - c ) dot ( p - c ) = r^2
1796 Given a ray with a point of origin 'o', and a direction vector 'd':
1798 ray(t) = o + td, t >= 0
1800 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1802 (o + td - c ) dot ( o + td - c ) = r^2
1804 To solve for t we first expand the above into a more recognisable quadratic equation form
1806 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1815 B = 2( o - c ) dot d
1816 C = ( o - c ) dot ( o - c ) - r^2
1818 which can be solved using a standard quadratic formula.
1820 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1822 Practical Simplification
1824 In a renderer, we often differentiate between world space and object space. In the object space
1825 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1826 into object space, the mathematical solution presented above can be simplified significantly.
1828 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1832 and we can find the t at which the (transformed) ray intersects the sphere by
1834 ( o + td ) dot ( o + td ) = r^2
1836 According to the reasoning above, we expand the above quadratic equation into the general form
1840 which now has coefficients:
1847 // Early out if mNode is NULL
1853 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1855 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1856 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1857 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1859 // Compute the radius is not needed, square radius it's enough.
1860 const Vector3& size( mNode->GetSize( bufferIndex ) );
1862 // Scale the sphere.
1863 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1865 const float width = size.width * scale.width;
1866 const float height = size.height * scale.height;
1868 float squareSphereRadius = 0.5f * ( width * width + height * height );
1870 float a = rayDir.Dot( rayDir ); // a
1871 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1872 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1874 return ( b2 * b2 - a * c ) >= 0.f;
1877 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector2& hitPointLocal, float& distance ) const
1881 if( OnStage() && NULL != mNode )
1883 // Transforms the ray to the local reference system.
1884 // Calculate the inverse of Model matrix
1885 Matrix invModelMatrix( false/*don't init*/);
1887 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1888 invModelMatrix = mNode->GetWorldMatrix(0);
1889 invModelMatrix.Invert();
1891 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1892 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1894 // Test with the actor's XY plane (Normal = 0 0 1 1).
1896 float a = -rayOriginLocal.z;
1897 float b = rayDirLocal.z;
1899 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1901 // Ray travels distance * rayDirLocal to intersect with plane.
1904 const Vector3& size = mNode->GetSize( bufferIndex );
1906 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1907 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1909 // Test with the actor's geometry.
1910 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1917 void Actor::SetLeaveRequired( bool required )
1919 mLeaveRequired = required;
1922 bool Actor::GetLeaveRequired() const
1924 return mLeaveRequired;
1927 void Actor::SetKeyboardFocusable( bool focusable )
1929 mKeyboardFocusable = focusable;
1932 bool Actor::IsKeyboardFocusable() const
1934 return mKeyboardFocusable;
1937 bool Actor::GetTouchRequired() const
1939 return !mTouchedSignal.Empty() || !mTouchSignal.Empty() || mDerivedRequiresTouch;
1942 bool Actor::GetHoverRequired() const
1944 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1947 bool Actor::GetWheelEventRequired() const
1949 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1952 bool Actor::IsHittable() const
1954 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1957 ActorGestureData& Actor::GetGestureData()
1959 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1960 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1961 if( NULL == mGestureData )
1963 mGestureData = new ActorGestureData;
1965 return *mGestureData;
1968 bool Actor::IsGestureRequred( Gesture::Type type ) const
1970 return mGestureData && mGestureData->IsGestureRequred( type );
1973 bool Actor::EmitTouchEventSignal( const TouchEvent& event, const Dali::TouchData& touch )
1975 bool consumed = false;
1977 if( !mTouchSignal.Empty() )
1979 Dali::Actor handle( this );
1980 consumed = mTouchSignal.Emit( handle, touch );
1983 if( !mTouchedSignal.Empty() )
1985 Dali::Actor handle( this );
1986 consumed |= mTouchedSignal.Emit( handle, event );
1991 // Notification for derived classes
1992 consumed = OnTouchEvent( event ); // TODO
1998 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
2000 bool consumed = false;
2002 if( !mHoveredSignal.Empty() )
2004 Dali::Actor handle( this );
2005 consumed = mHoveredSignal.Emit( handle, event );
2010 // Notification for derived classes
2011 consumed = OnHoverEvent( event );
2017 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
2019 bool consumed = false;
2021 if( !mWheelEventSignal.Empty() )
2023 Dali::Actor handle( this );
2024 consumed = mWheelEventSignal.Emit( handle, event );
2029 // Notification for derived classes
2030 consumed = OnWheelEvent( event );
2036 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
2038 if( ! mVisibilityChangedSignal.Empty() )
2040 Dali::Actor handle( this );
2041 mVisibilityChangedSignal.Emit( handle, visible, type );
2045 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
2047 return mTouchedSignal;
2050 Dali::Actor::TouchDataSignalType& Actor::TouchSignal()
2052 return mTouchSignal;
2055 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
2057 return mHoveredSignal;
2060 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
2062 return mWheelEventSignal;
2065 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
2067 return mOnStageSignal;
2070 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
2072 return mOffStageSignal;
2075 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
2077 return mOnRelayoutSignal;
2080 DevelActor::VisibilityChangedSignalType& Actor::VisibilityChangedSignal()
2082 return mVisibilityChangedSignal;
2085 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
2087 bool connected( true );
2088 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
2090 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
2092 actor->TouchedSignal().Connect( tracker, functor );
2094 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
2096 actor->HoveredSignal().Connect( tracker, functor );
2098 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
2100 actor->WheelEventSignal().Connect( tracker, functor );
2102 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
2104 actor->OnStageSignal().Connect( tracker, functor );
2106 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
2108 actor->OffStageSignal().Connect( tracker, functor );
2110 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
2112 actor->OnRelayoutSignal().Connect( tracker, functor );
2114 else if( 0 == signalName.compare( SIGNAL_TOUCH ) )
2116 actor->TouchSignal().Connect( tracker, functor );
2120 // signalName does not match any signal
2127 Actor::Actor( DerivedType derivedType )
2132 mParentOrigin( NULL ),
2133 mAnchorPoint( NULL ),
2134 mRelayoutData( NULL ),
2135 mGestureData( NULL ),
2136 mTargetOrientation( Quaternion::IDENTITY ),
2137 mTargetColor( Color::WHITE ),
2138 mTargetSize( Vector3::ZERO ),
2139 mTargetPosition( Vector3::ZERO ),
2140 mTargetScale( Vector3::ONE ),
2142 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
2146 mIsRoot( ROOT_LAYER == derivedType ),
2147 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2148 mIsOnStage( false ),
2150 mLeaveRequired( false ),
2151 mKeyboardFocusable( false ),
2152 mDerivedRequiresTouch( false ),
2153 mDerivedRequiresHover( false ),
2154 mDerivedRequiresWheelEvent( false ),
2155 mOnStageSignalled( false ),
2156 mInsideOnSizeSet( false ),
2157 mInheritPosition( true ),
2158 mInheritOrientation( true ),
2159 mInheritScale( true ),
2160 mPositionUsesAnchorPoint( true ),
2162 mDrawMode( DrawMode::NORMAL ),
2163 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2164 mColorMode( Node::DEFAULT_COLOR_MODE ),
2165 mClippingMode( ClippingMode::DISABLED )
2169 void Actor::Initialize()
2172 SceneGraph::Node* node = CreateNode();
2174 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
2175 mNode = node; // Keep raw-pointer to Node
2179 GetEventThreadServices().RegisterObject( this );
2184 // Remove mParent pointers from children even if we're destroying core,
2185 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2188 ActorConstIter endIter = mChildren->end();
2189 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2191 (*iter)->SetParent( NULL );
2197 // Guard to allow handle destruction after Core has been destroyed
2198 if( EventThreadServices::IsCoreRunning() )
2202 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2203 mNode = NULL; // Node is about to be destroyed
2206 GetEventThreadServices().UnregisterObject( this );
2209 // Cleanup optional gesture data
2210 delete mGestureData;
2212 // Cleanup optional parent origin and anchor
2213 delete mParentOrigin;
2214 delete mAnchorPoint;
2216 // Delete optional relayout data
2219 delete mRelayoutData;
2223 void Actor::ConnectToStage( unsigned int parentDepth )
2225 // This container is used instead of walking the Actor hierarchy.
2226 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
2227 ActorContainer connectionList;
2229 StagePtr stage = Stage::GetCurrent();
2232 stage->RequestRebuildDepthTree();
2235 // This stage is atomic i.e. not interrupted by user callbacks.
2236 RecursiveConnectToStage( connectionList, parentDepth + 1 );
2238 // Notify applications about the newly connected actors.
2239 const ActorIter endIter = connectionList.end();
2240 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2242 (*iter)->NotifyStageConnection();
2248 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth )
2250 DALI_ASSERT_ALWAYS( !OnStage() );
2255 ConnectToSceneGraph();
2257 // Notification for internal derived classes
2258 OnStageConnectionInternal();
2260 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2261 connectionList.push_back( ActorPtr( this ) );
2263 // Recursively connect children
2266 ActorConstIter endIter = mChildren->end();
2267 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2269 (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
2275 * This method is called when the Actor is connected to the Stage.
2276 * The parent must have added its Node to the scene-graph.
2277 * The child must connect its Node to the parent's Node.
2278 * This is recursive; the child calls ConnectToStage() for its children.
2280 void Actor::ConnectToSceneGraph()
2282 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2286 // Reparent Node in next Update
2287 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode );
2290 // Request relayout on all actors that are added to the scenegraph
2293 // Notification for Object::Observers
2297 void Actor::NotifyStageConnection()
2299 // Actors can be removed (in a callback), before the on-stage stage is reported.
2300 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2301 if( OnStage() && !mOnStageSignalled )
2303 // Notification for external (CustomActor) derived classes
2304 OnStageConnectionExternal( mDepth );
2306 if( !mOnStageSignal.Empty() )
2308 Dali::Actor handle( this );
2309 mOnStageSignal.Emit( handle );
2312 // Guard against Remove during callbacks
2315 mOnStageSignalled = true; // signal required next time Actor is removed
2320 void Actor::DisconnectFromStage()
2322 // This container is used instead of walking the Actor hierachy.
2323 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2324 ActorContainer disconnectionList;
2326 StagePtr stage = Stage::GetCurrent();
2329 stage->RequestRebuildDepthTree();
2332 // This stage is atomic i.e. not interrupted by user callbacks
2333 RecursiveDisconnectFromStage( disconnectionList );
2335 // Notify applications about the newly disconnected actors.
2336 const ActorIter endIter = disconnectionList.end();
2337 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2339 (*iter)->NotifyStageDisconnection();
2343 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2345 DALI_ASSERT_ALWAYS( OnStage() );
2347 // Recursively disconnect children
2350 ActorConstIter endIter = mChildren->end();
2351 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2353 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2357 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2358 disconnectionList.push_back( ActorPtr( this ) );
2360 // Notification for internal derived classes
2361 OnStageDisconnectionInternal();
2363 DisconnectFromSceneGraph();
2369 * This method is called by an actor or its parent, before a node removal message is sent.
2370 * This is recursive; the child calls DisconnectFromStage() for its children.
2372 void Actor::DisconnectFromSceneGraph()
2374 // Notification for Object::Observers
2375 OnSceneObjectRemove();
2378 void Actor::NotifyStageDisconnection()
2380 // Actors can be added (in a callback), before the off-stage state is reported.
2381 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2382 // only do this step if there is a stage, i.e. Core is not being shut down
2383 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2385 // Notification for external (CustomeActor) derived classes
2386 OnStageDisconnectionExternal();
2388 if( !mOffStageSignal.Empty() )
2390 Dali::Actor handle( this );
2391 mOffStageSignal.Emit( handle );
2394 // Guard against Add during callbacks
2397 mOnStageSignalled = false; // signal required next time Actor is added
2402 bool Actor::IsNodeConnected() const
2404 bool connected( false );
2406 if( OnStage() && ( NULL != mNode ) )
2408 if( IsRoot() || mNode->GetParent() )
2417 // This method generates the depth tree using the recursive function below,
2418 // then walks the tree and sets a depth index based on traversal order. It
2419 // sends a single message to update manager to update all the actor's nodes in this
2420 // tree with the depth index. The sceneGraphNodeDepths vector's elements are ordered
2421 // by depth, and could be used to reduce sorting in the update thread.
2422 void Actor::RebuildDepthTree()
2424 DALI_LOG_TIMER_START(depthTimer);
2426 DepthNodeMemoryPool nodeMemoryPool;
2427 ActorDepthTreeNode* rootNode = new (nodeMemoryPool.AllocateRaw()) ActorDepthTreeNode( this, mSiblingOrder );
2429 int actorCount = BuildDepthTree( nodeMemoryPool, rootNode );
2431 // Vector of scene-graph nodes and their depths to send to UpdateManager
2432 // in a single message
2433 SceneGraph::NodeDepths* sceneGraphNodeDepths = new SceneGraph::NodeDepths(actorCount);
2435 // Traverse depth tree and set mSortedDepth on each actor and scenegraph node
2436 uint32_t sortOrder = 1u; // Don't start at zero, as visual depth can be negative
2437 ActorDepthTreeNode* currentNode = rootNode;
2438 bool firstVisit = true;
2439 while( currentNode != rootNode || firstVisit)
2443 // Visit node, performing action
2444 for( std::vector<Actor*>::iterator iter = currentNode->mActors.begin(); iter != currentNode->mActors.end(); ++iter )
2446 (*iter)->mSortedDepth = sortOrder * DevelLayer::SIBLING_ORDER_MULTIPLIER;
2447 sceneGraphNodeDepths->Add( const_cast<SceneGraph::Node*>((*iter)->mNode), (*iter)->mSortedDepth );
2452 if( currentNode->mFirstChildNode )
2454 currentNode = currentNode->mFirstChildNode;
2456 else // leaf node, goto next sibling, or return up tree.
2458 bool breakout=false;
2459 while( ! currentNode->mNextSiblingNode )
2461 if( currentNode == rootNode ) // If we get to root of tree, stop
2466 currentNode = currentNode->mParentNode;
2473 currentNode = currentNode->mNextSiblingNode;
2477 SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths );
2478 DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree create time: ");
2482 * Structure to store the actor's associated node in the depth tree for child
2485 struct ActorNodePair
2488 ActorDepthTreeNode* node;
2489 ActorNodePair( Actor* actor, ActorDepthTreeNode* node )
2497 * Descend actor tree, building a depth tree based on actor's sibling order.
2498 * Actors with the same sibling order share the same depth tree. Siblings
2499 * in the depth tree are ordered by actor's sibling order.
2501 * An actor tree like this:
2508 * A(SO:1) B(SO:2) C(SO:1)
2511 * D(SO:0) E(SO:0) F(SO:0) G(SO:1) H(SO:0)
2513 * will end up as a depth tree like this:
2515 * RootNode [ Root ] -> NULL
2518 * Node [ A, C ] ------------------------> Node [ B ] -> NULL
2521 * Node [ D, E, H ] -> Node [ G ] -> NULL Node [ F ] -> NULL
2526 * (All nodes also point to their parents to enable storage free traversal)
2528 int Actor::BuildDepthTree( DepthNodeMemoryPool& nodeMemoryPool, ActorDepthTreeNode* node )
2530 int treeCount=1; // Count self and children
2532 // Create/add to children of this node
2535 std::vector<ActorNodePair> storedChildren;
2536 storedChildren.reserve( mChildren->size() );
2538 for( ActorContainer::iterator it = mChildren->begin(); it != mChildren->end(); ++it )
2540 Actor* childActor = (*it).Get();
2541 if( childActor->IsLayer() )
2543 Layer* layer = static_cast<Layer*>(childActor);
2544 if( layer->GetBehavior() == Dali::Layer::LAYER_3D )
2546 // Ignore this actor and children.
2551 // If no existing depth node children
2552 if( node->mFirstChildNode == NULL )
2554 node->mFirstChildNode = new (nodeMemoryPool.AllocateRaw()) ActorDepthTreeNode( childActor, childActor->mSiblingOrder );
2555 node->mFirstChildNode->mParentNode = node;
2556 storedChildren.push_back(ActorNodePair( childActor, node->mFirstChildNode ));
2558 else // find child node with matching sibling order (insertion sort)
2560 bool addedChildActor = false;
2562 // depth tree child nodes ordered by sibling order
2563 ActorDepthTreeNode* lastNode = NULL;
2564 for( ActorDepthTreeNode* childNode = node->mFirstChildNode; childNode != NULL; childNode = childNode->mNextSiblingNode )
2566 uint16_t actorSiblingOrder = childActor->mSiblingOrder;
2567 uint16_t currentSiblingOrder = childNode->GetSiblingOrder();
2569 if( actorSiblingOrder == currentSiblingOrder )
2571 // Don't need a new depth node, add to existing node
2572 childNode->AddActor( childActor );
2573 storedChildren.push_back(ActorNodePair( childActor, childNode ));
2574 addedChildActor = true;
2577 else if( actorSiblingOrder < currentSiblingOrder )
2581 lastNode = childNode;
2584 // No matching sibling order - create new node and insert into sibling list
2585 if( !addedChildActor )
2587 ActorDepthTreeNode* newNode = new (nodeMemoryPool.AllocateRaw()) ActorDepthTreeNode( childActor, childActor->mSiblingOrder );
2589 newNode->mParentNode = node;
2590 storedChildren.push_back(ActorNodePair( childActor, newNode ));
2592 if( lastNode == NULL ) // Insert at start of siblings
2594 ActorDepthTreeNode* nextNode = node->mFirstChildNode;
2595 node->mFirstChildNode = newNode;
2596 newNode->mNextSiblingNode = nextNode;
2598 else // insert into siblings after last node
2600 newNode->mNextSiblingNode = lastNode->mNextSiblingNode;
2601 lastNode->mNextSiblingNode = newNode;
2607 // Order of descent doesn't matter; we're using insertion to sort.
2608 for( std::vector<ActorNodePair>::iterator iter = storedChildren.begin(); iter != storedChildren.end(); ++iter )
2610 treeCount += iter->actor->BuildDepthTree( nodeMemoryPool, iter->node );
2616 unsigned int Actor::GetDefaultPropertyCount() const
2618 return DEFAULT_PROPERTY_COUNT;
2621 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2623 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2625 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2627 indices.PushBack( i );
2631 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2633 if( index < DEFAULT_PROPERTY_COUNT )
2635 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2641 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2643 Property::Index index = Property::INVALID_INDEX;
2645 // Look for name in default properties
2646 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2648 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2649 if( 0 == name.compare( property->name ) )
2659 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2661 if( index < DEFAULT_PROPERTY_COUNT )
2663 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2669 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2671 if( index < DEFAULT_PROPERTY_COUNT )
2673 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2679 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2681 if( index < DEFAULT_PROPERTY_COUNT )
2683 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2689 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2691 if( index < DEFAULT_PROPERTY_COUNT )
2693 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2696 // index out of range...return Property::NONE
2697 return Property::NONE;
2700 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2704 case Dali::Actor::Property::PARENT_ORIGIN:
2706 Property::Type type = property.GetType();
2707 if( type == Property::VECTOR3 )
2709 SetParentOrigin( property.Get< Vector3 >() );
2711 else if ( type == Property::STRING )
2713 std::string parentOriginString;
2714 property.Get( parentOriginString );
2715 Vector3 parentOrigin;
2716 if( GetParentOriginConstant( parentOriginString, parentOrigin ) )
2718 SetParentOrigin( parentOrigin );
2724 case Dali::Actor::Property::PARENT_ORIGIN_X:
2726 SetParentOriginX( property.Get< float >() );
2730 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2732 SetParentOriginY( property.Get< float >() );
2736 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2738 SetParentOriginZ( property.Get< float >() );
2742 case Dali::Actor::Property::ANCHOR_POINT:
2744 Property::Type type = property.GetType();
2745 if( type == Property::VECTOR3 )
2747 SetAnchorPoint( property.Get< Vector3 >() );
2749 else if ( type == Property::STRING )
2751 std::string anchorPointString;
2752 property.Get( anchorPointString );
2754 if( GetAnchorPointConstant( anchorPointString, anchor ) )
2756 SetAnchorPoint( anchor );
2762 case Dali::Actor::Property::ANCHOR_POINT_X:
2764 SetAnchorPointX( property.Get< float >() );
2768 case Dali::Actor::Property::ANCHOR_POINT_Y:
2770 SetAnchorPointY( property.Get< float >() );
2774 case Dali::Actor::Property::ANCHOR_POINT_Z:
2776 SetAnchorPointZ( property.Get< float >() );
2780 case Dali::Actor::Property::SIZE:
2782 SetSize( property.Get< Vector3 >() );
2786 case Dali::Actor::Property::SIZE_WIDTH:
2788 SetWidth( property.Get< float >() );
2792 case Dali::Actor::Property::SIZE_HEIGHT:
2794 SetHeight( property.Get< float >() );
2798 case Dali::Actor::Property::SIZE_DEPTH:
2800 SetDepth( property.Get< float >() );
2804 case Dali::Actor::Property::POSITION:
2806 SetPosition( property.Get< Vector3 >() );
2810 case Dali::Actor::Property::POSITION_X:
2812 SetX( property.Get< float >() );
2816 case Dali::Actor::Property::POSITION_Y:
2818 SetY( property.Get< float >() );
2822 case Dali::Actor::Property::POSITION_Z:
2824 SetZ( property.Get< float >() );
2828 case Dali::Actor::Property::ORIENTATION:
2830 SetOrientation( property.Get< Quaternion >() );
2834 case Dali::Actor::Property::SCALE:
2836 SetScale( property.Get< Vector3 >() );
2840 case Dali::Actor::Property::SCALE_X:
2842 SetScaleX( property.Get< float >() );
2846 case Dali::Actor::Property::SCALE_Y:
2848 SetScaleY( property.Get< float >() );
2852 case Dali::Actor::Property::SCALE_Z:
2854 SetScaleZ( property.Get< float >() );
2858 case Dali::Actor::Property::VISIBLE:
2860 SetVisible( property.Get< bool >() );
2864 case Dali::Actor::Property::COLOR:
2866 SetColor( property.Get< Vector4 >() );
2870 case Dali::Actor::Property::COLOR_RED:
2872 SetColorRed( property.Get< float >() );
2876 case Dali::Actor::Property::COLOR_GREEN:
2878 SetColorGreen( property.Get< float >() );
2882 case Dali::Actor::Property::COLOR_BLUE:
2884 SetColorBlue( property.Get< float >() );
2888 case Dali::Actor::Property::COLOR_ALPHA:
2889 case Dali::DevelActor::Property::OPACITY:
2892 if( property.Get( value ) )
2894 SetOpacity( value );
2899 case Dali::Actor::Property::NAME:
2901 SetName( property.Get< std::string >() );
2905 case Dali::Actor::Property::SENSITIVE:
2907 SetSensitive( property.Get< bool >() );
2911 case Dali::Actor::Property::LEAVE_REQUIRED:
2913 SetLeaveRequired( property.Get< bool >() );
2917 case Dali::Actor::Property::INHERIT_POSITION:
2919 SetInheritPosition( property.Get< bool >() );
2923 case Dali::Actor::Property::INHERIT_ORIENTATION:
2925 SetInheritOrientation( property.Get< bool >() );
2929 case Dali::Actor::Property::INHERIT_SCALE:
2931 SetInheritScale( property.Get< bool >() );
2935 case Dali::Actor::Property::COLOR_MODE:
2937 ColorMode mode = mColorMode;
2938 if ( Scripting::GetEnumerationProperty< ColorMode >( property, COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT, mode ) )
2940 SetColorMode( mode );
2945 case Dali::Actor::Property::POSITION_INHERITANCE:
2947 PositionInheritanceMode mode = mPositionInheritanceMode;
2948 if( Scripting::GetEnumerationProperty< PositionInheritanceMode >( property, POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT, mode ) )
2950 SetPositionInheritanceMode( mode );
2955 case Dali::Actor::Property::DRAW_MODE:
2957 DrawMode::Type mode = mDrawMode;
2958 if( Scripting::GetEnumerationProperty< DrawMode::Type >( property, DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT, mode ) )
2960 SetDrawMode( mode );
2965 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2967 SetSizeModeFactor( property.Get< Vector3 >() );
2971 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2973 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
2974 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2976 SetResizePolicy( type, Dimension::WIDTH );
2981 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2983 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
2984 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2986 SetResizePolicy( type, Dimension::HEIGHT );
2991 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2993 SizeScalePolicy::Type type;
2994 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT, type ) )
2996 SetSizeScalePolicy( type );
3001 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3003 if( property.Get< bool >() )
3005 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
3010 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3012 if( property.Get< bool >() )
3014 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
3019 case Dali::Actor::Property::PADDING:
3021 Vector4 padding = property.Get< Vector4 >();
3022 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
3023 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
3027 case Dali::Actor::Property::MINIMUM_SIZE:
3029 Vector2 size = property.Get< Vector2 >();
3030 SetMinimumSize( size.x, Dimension::WIDTH );
3031 SetMinimumSize( size.y, Dimension::HEIGHT );
3035 case Dali::Actor::Property::MAXIMUM_SIZE:
3037 Vector2 size = property.Get< Vector2 >();
3038 SetMaximumSize( size.x, Dimension::WIDTH );
3039 SetMaximumSize( size.y, Dimension::HEIGHT );
3043 case Dali::DevelActor::Property::SIBLING_ORDER:
3047 if( property.Get( value ) )
3049 if( static_cast<unsigned int>(value) != mSiblingOrder )
3051 SetSiblingOrder( value );
3057 case Dali::Actor::Property::CLIPPING_MODE:
3059 ClippingMode::Type convertedValue = mClippingMode;
3060 if( Scripting::GetEnumerationProperty< ClippingMode::Type >( property, CLIPPING_MODE_TABLE, CLIPPING_MODE_TABLE_COUNT, convertedValue ) )
3062 mClippingMode = convertedValue;
3065 SetClippingModeMessage( GetEventThreadServices(), *mNode, mClippingMode );
3071 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
3074 if( property.Get( value ) && value != mPositionUsesAnchorPoint )
3076 mPositionUsesAnchorPoint = value;
3079 SetPositionUsesAnchorPointMessage( GetEventThreadServices(), *mNode, mPositionUsesAnchorPoint );
3087 // this can happen in the case of a non-animatable default property so just do nothing
3093 // TODO: This method needs to be removed
3094 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
3096 switch( entry.GetType() )
3098 case Property::BOOLEAN:
3100 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
3101 DALI_ASSERT_DEBUG( NULL != property );
3103 // property is being used in a separate thread; queue a message to set the property
3104 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
3109 case Property::INTEGER:
3111 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
3112 DALI_ASSERT_DEBUG( NULL != property );
3114 // property is being used in a separate thread; queue a message to set the property
3115 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
3120 case Property::FLOAT:
3122 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
3123 DALI_ASSERT_DEBUG( NULL != property );
3125 // property is being used in a separate thread; queue a message to set the property
3126 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
3131 case Property::VECTOR2:
3133 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
3134 DALI_ASSERT_DEBUG( NULL != property );
3136 // property is being used in a separate thread; queue a message to set the property
3137 if(entry.componentIndex == 0)
3139 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
3141 else if(entry.componentIndex == 1)
3143 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
3147 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
3153 case Property::VECTOR3:
3155 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
3156 DALI_ASSERT_DEBUG( NULL != property );
3158 // property is being used in a separate thread; queue a message to set the property
3159 if(entry.componentIndex == 0)
3161 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
3163 else if(entry.componentIndex == 1)
3165 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
3167 else if(entry.componentIndex == 2)
3169 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
3173 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
3179 case Property::VECTOR4:
3181 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
3182 DALI_ASSERT_DEBUG( NULL != property );
3184 // property is being used in a separate thread; queue a message to set the property
3185 if(entry.componentIndex == 0)
3187 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
3189 else if(entry.componentIndex == 1)
3191 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
3193 else if(entry.componentIndex == 2)
3195 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
3197 else if(entry.componentIndex == 3)
3199 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
3203 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3209 case Property::ROTATION:
3211 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3212 DALI_ASSERT_DEBUG( NULL != property );
3214 // property is being used in a separate thread; queue a message to set the property
3215 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3220 case Property::MATRIX:
3222 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3223 DALI_ASSERT_DEBUG( NULL != property );
3225 // property is being used in a separate thread; queue a message to set the property
3226 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3231 case Property::MATRIX3:
3233 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3234 DALI_ASSERT_DEBUG( NULL != property );
3236 // property is being used in a separate thread; queue a message to set the property
3237 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3244 // nothing to do for other types
3249 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3251 Property::Value value;
3253 if( ! GetCachedPropertyValue( index, value ) )
3255 // If property value is not stored in the event-side, then it must be a scene-graph only property
3256 GetCurrentPropertyValue( index, value );
3262 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
3264 Property::Value value;
3266 if( ! GetCurrentPropertyValue( index, value ) )
3268 // If unable to retrieve scene-graph property value, then it must be an event-side only property
3269 GetCachedPropertyValue( index, value );
3275 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3280 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3282 // This method should only return an object connected to the scene-graph
3283 return OnStage() ? mNode : NULL;
3286 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3288 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3290 const PropertyBase* property( NULL );
3292 // This method should only return a property of an object connected to the scene-graph
3298 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3300 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3301 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3303 property = animatable->GetSceneGraphProperty();
3305 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3306 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3308 CustomPropertyMetadata* custom = FindCustomProperty( index );
3309 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3311 property = custom->GetSceneGraphProperty();
3313 else if( NULL != mNode )
3317 case Dali::Actor::Property::SIZE:
3318 property = &mNode->mSize;
3321 case Dali::Actor::Property::SIZE_WIDTH:
3322 property = &mNode->mSize;
3325 case Dali::Actor::Property::SIZE_HEIGHT:
3326 property = &mNode->mSize;
3329 case Dali::Actor::Property::SIZE_DEPTH:
3330 property = &mNode->mSize;
3333 case Dali::Actor::Property::POSITION:
3334 property = &mNode->mPosition;
3337 case Dali::Actor::Property::POSITION_X:
3338 property = &mNode->mPosition;
3341 case Dali::Actor::Property::POSITION_Y:
3342 property = &mNode->mPosition;
3345 case Dali::Actor::Property::POSITION_Z:
3346 property = &mNode->mPosition;
3349 case Dali::Actor::Property::ORIENTATION:
3350 property = &mNode->mOrientation;
3353 case Dali::Actor::Property::SCALE:
3354 property = &mNode->mScale;
3357 case Dali::Actor::Property::SCALE_X:
3358 property = &mNode->mScale;
3361 case Dali::Actor::Property::SCALE_Y:
3362 property = &mNode->mScale;
3365 case Dali::Actor::Property::SCALE_Z:
3366 property = &mNode->mScale;
3369 case Dali::Actor::Property::VISIBLE:
3370 property = &mNode->mVisible;
3373 case Dali::Actor::Property::COLOR:
3374 property = &mNode->mColor;
3377 case Dali::Actor::Property::COLOR_RED:
3378 property = &mNode->mColor;
3381 case Dali::Actor::Property::COLOR_GREEN:
3382 property = &mNode->mColor;
3385 case Dali::Actor::Property::COLOR_BLUE:
3386 property = &mNode->mColor;
3389 case Dali::Actor::Property::COLOR_ALPHA:
3390 case Dali::DevelActor::Property::OPACITY:
3391 property = &mNode->mColor;
3402 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3404 const PropertyInputImpl* property( NULL );
3406 // This method should only return a property of an object connected to the scene-graph
3412 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3414 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3415 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3417 property = animatable->GetSceneGraphProperty();
3419 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3420 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3422 CustomPropertyMetadata* custom = FindCustomProperty( index );
3423 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3424 property = custom->GetSceneGraphProperty();
3426 else if( NULL != mNode )
3430 case Dali::Actor::Property::PARENT_ORIGIN:
3431 property = &mNode->mParentOrigin;
3434 case Dali::Actor::Property::PARENT_ORIGIN_X:
3435 property = &mNode->mParentOrigin;
3438 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3439 property = &mNode->mParentOrigin;
3442 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3443 property = &mNode->mParentOrigin;
3446 case Dali::Actor::Property::ANCHOR_POINT:
3447 property = &mNode->mAnchorPoint;
3450 case Dali::Actor::Property::ANCHOR_POINT_X:
3451 property = &mNode->mAnchorPoint;
3454 case Dali::Actor::Property::ANCHOR_POINT_Y:
3455 property = &mNode->mAnchorPoint;
3458 case Dali::Actor::Property::ANCHOR_POINT_Z:
3459 property = &mNode->mAnchorPoint;
3462 case Dali::Actor::Property::SIZE:
3463 property = &mNode->mSize;
3466 case Dali::Actor::Property::SIZE_WIDTH:
3467 property = &mNode->mSize;
3470 case Dali::Actor::Property::SIZE_HEIGHT:
3471 property = &mNode->mSize;
3474 case Dali::Actor::Property::SIZE_DEPTH:
3475 property = &mNode->mSize;
3478 case Dali::Actor::Property::POSITION:
3479 property = &mNode->mPosition;
3482 case Dali::Actor::Property::POSITION_X:
3483 property = &mNode->mPosition;
3486 case Dali::Actor::Property::POSITION_Y:
3487 property = &mNode->mPosition;
3490 case Dali::Actor::Property::POSITION_Z:
3491 property = &mNode->mPosition;
3494 case Dali::Actor::Property::WORLD_POSITION:
3495 property = &mNode->mWorldPosition;
3498 case Dali::Actor::Property::WORLD_POSITION_X:
3499 property = &mNode->mWorldPosition;
3502 case Dali::Actor::Property::WORLD_POSITION_Y:
3503 property = &mNode->mWorldPosition;
3506 case Dali::Actor::Property::WORLD_POSITION_Z:
3507 property = &mNode->mWorldPosition;
3510 case Dali::Actor::Property::ORIENTATION:
3511 property = &mNode->mOrientation;
3514 case Dali::Actor::Property::WORLD_ORIENTATION:
3515 property = &mNode->mWorldOrientation;
3518 case Dali::Actor::Property::SCALE:
3519 property = &mNode->mScale;
3522 case Dali::Actor::Property::SCALE_X:
3523 property = &mNode->mScale;
3526 case Dali::Actor::Property::SCALE_Y:
3527 property = &mNode->mScale;
3530 case Dali::Actor::Property::SCALE_Z:
3531 property = &mNode->mScale;
3534 case Dali::Actor::Property::WORLD_SCALE:
3535 property = &mNode->mWorldScale;
3538 case Dali::Actor::Property::VISIBLE:
3539 property = &mNode->mVisible;
3542 case Dali::Actor::Property::COLOR:
3543 property = &mNode->mColor;
3546 case Dali::Actor::Property::COLOR_RED:
3547 property = &mNode->mColor;
3550 case Dali::Actor::Property::COLOR_GREEN:
3551 property = &mNode->mColor;
3554 case Dali::Actor::Property::COLOR_BLUE:
3555 property = &mNode->mColor;
3558 case Dali::Actor::Property::COLOR_ALPHA:
3559 case Dali::DevelActor::Property::OPACITY:
3561 property = &mNode->mColor;
3565 case Dali::Actor::Property::WORLD_COLOR:
3566 property = &mNode->mWorldColor;
3569 case Dali::Actor::Property::WORLD_MATRIX:
3570 property = &mNode->mWorldMatrix;
3581 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3583 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3585 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3587 // check whether the animatable property is registered already, if not then register one.
3588 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3589 if( animatableProperty )
3591 componentIndex = animatableProperty->componentIndex;
3598 case Dali::Actor::Property::PARENT_ORIGIN_X:
3599 case Dali::Actor::Property::ANCHOR_POINT_X:
3600 case Dali::Actor::Property::SIZE_WIDTH:
3601 case Dali::Actor::Property::POSITION_X:
3602 case Dali::Actor::Property::WORLD_POSITION_X:
3603 case Dali::Actor::Property::SCALE_X:
3604 case Dali::Actor::Property::COLOR_RED:
3610 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3611 case Dali::Actor::Property::ANCHOR_POINT_Y:
3612 case Dali::Actor::Property::SIZE_HEIGHT:
3613 case Dali::Actor::Property::POSITION_Y:
3614 case Dali::Actor::Property::WORLD_POSITION_Y:
3615 case Dali::Actor::Property::SCALE_Y:
3616 case Dali::Actor::Property::COLOR_GREEN:
3622 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3623 case Dali::Actor::Property::ANCHOR_POINT_Z:
3624 case Dali::Actor::Property::SIZE_DEPTH:
3625 case Dali::Actor::Property::POSITION_Z:
3626 case Dali::Actor::Property::WORLD_POSITION_Z:
3627 case Dali::Actor::Property::SCALE_Z:
3628 case Dali::Actor::Property::COLOR_BLUE:
3634 case Dali::Actor::Property::COLOR_ALPHA:
3635 case Dali::DevelActor::Property::OPACITY:
3649 return componentIndex;
3652 void Actor::SetParent( Actor* parent )
3656 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3660 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3663 // Instruct each actor to create a corresponding node in the scene graph
3664 ConnectToStage( parent->GetHierarchyDepth() );
3667 // Resolve the name and index for the child properties if any
3668 ResolveChildProperties();
3670 else // parent being set to NULL
3672 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3676 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3679 DALI_ASSERT_ALWAYS( mNode != NULL );
3683 // Disconnect the Node & its children from the scene-graph.
3684 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3687 // Instruct each actor to discard pointers to the scene-graph
3688 DisconnectFromStage();
3693 SceneGraph::Node* Actor::CreateNode() const
3698 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3701 Actor* actor = dynamic_cast< Actor* >( object );
3705 if( 0 == actionName.compare( ACTION_SHOW ) )
3707 actor->SetVisible( true );
3710 else if( 0 == actionName.compare( ACTION_HIDE ) )
3712 actor->SetVisible( false );
3720 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
3722 bool valueSet = true;
3726 case Dali::Actor::Property::PARENT_ORIGIN:
3728 value = GetCurrentParentOrigin();
3732 case Dali::Actor::Property::PARENT_ORIGIN_X:
3734 value = GetCurrentParentOrigin().x;
3738 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3740 value = GetCurrentParentOrigin().y;
3744 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3746 value = GetCurrentParentOrigin().z;
3750 case Dali::Actor::Property::ANCHOR_POINT:
3752 value = GetCurrentAnchorPoint();
3756 case Dali::Actor::Property::ANCHOR_POINT_X:
3758 value = GetCurrentAnchorPoint().x;
3762 case Dali::Actor::Property::ANCHOR_POINT_Y:
3764 value = GetCurrentAnchorPoint().y;
3768 case Dali::Actor::Property::ANCHOR_POINT_Z:
3770 value = GetCurrentAnchorPoint().z;
3774 case Dali::Actor::Property::SIZE:
3776 Vector3 size = GetTargetSize();
3778 // Should return preferred size if size is fixed as set by SetSize
3779 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
3781 size.width = GetPreferredSize().width;
3783 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
3785 size.height = GetPreferredSize().height;
3793 case Dali::Actor::Property::SIZE_WIDTH:
3795 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
3797 // Should return preferred size if size is fixed as set by SetSize
3798 value = GetPreferredSize().width;
3802 value = GetTargetSize().width;
3807 case Dali::Actor::Property::SIZE_HEIGHT:
3809 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
3811 // Should return preferred size if size is fixed as set by SetSize
3812 value = GetPreferredSize().height;
3816 value = GetTargetSize().height;
3821 case Dali::Actor::Property::SIZE_DEPTH:
3823 value = GetTargetSize().depth;
3827 case Dali::Actor::Property::POSITION:
3829 value = GetTargetPosition();
3833 case Dali::Actor::Property::POSITION_X:
3835 value = GetTargetPosition().x;
3839 case Dali::Actor::Property::POSITION_Y:
3841 value = GetTargetPosition().y;
3845 case Dali::Actor::Property::POSITION_Z:
3847 value = GetTargetPosition().z;
3851 case Dali::Actor::Property::ORIENTATION:
3853 value = mTargetOrientation;
3857 case Dali::Actor::Property::SCALE:
3859 value = mTargetScale;
3863 case Dali::Actor::Property::SCALE_X:
3865 value = mTargetScale.x;
3869 case Dali::Actor::Property::SCALE_Y:
3871 value = mTargetScale.y;
3875 case Dali::Actor::Property::SCALE_Z:
3877 value = mTargetScale.z;
3881 case Dali::Actor::Property::VISIBLE:
3887 case Dali::Actor::Property::COLOR:
3889 value = mTargetColor;
3893 case Dali::Actor::Property::COLOR_RED:
3895 value = mTargetColor.r;
3899 case Dali::Actor::Property::COLOR_GREEN:
3901 value = mTargetColor.g;
3905 case Dali::Actor::Property::COLOR_BLUE:
3907 value = mTargetColor.b;
3911 case Dali::Actor::Property::COLOR_ALPHA:
3912 case Dali::DevelActor::Property::OPACITY:
3914 value = mTargetColor.a;
3918 case Dali::Actor::Property::NAME:
3924 case Dali::Actor::Property::SENSITIVE:
3926 value = IsSensitive();
3930 case Dali::Actor::Property::LEAVE_REQUIRED:
3932 value = GetLeaveRequired();
3936 case Dali::Actor::Property::INHERIT_POSITION:
3938 value = IsPositionInherited();
3942 case Dali::Actor::Property::INHERIT_ORIENTATION:
3944 value = IsOrientationInherited();
3948 case Dali::Actor::Property::INHERIT_SCALE:
3950 value = IsScaleInherited();
3954 case Dali::Actor::Property::COLOR_MODE:
3956 value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
3960 case Dali::Actor::Property::POSITION_INHERITANCE:
3962 value = Scripting::GetLinearEnumerationName< PositionInheritanceMode >( GetPositionInheritanceMode(), POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT );
3966 case Dali::Actor::Property::DRAW_MODE:
3968 value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
3972 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3974 value = GetSizeModeFactor();
3978 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3980 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3984 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3986 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3990 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3992 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT );
3996 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3998 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
4002 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
4004 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
4008 case Dali::Actor::Property::PADDING:
4010 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
4011 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
4012 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
4016 case Dali::Actor::Property::MINIMUM_SIZE:
4018 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
4022 case Dali::Actor::Property::MAXIMUM_SIZE:
4024 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
4028 case Dali::Actor::Property::CLIPPING_MODE:
4030 value = mClippingMode;
4034 case Dali::DevelActor::Property::SIBLING_ORDER:
4036 value = static_cast<int>(mSiblingOrder);
4040 case Dali::DevelActor::Property::SCREEN_POSITION:
4042 value = GetCurrentScreenPosition();
4046 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
4048 value = mPositionUsesAnchorPoint;
4054 // Must be a scene-graph only property
4063 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
4065 bool valueSet = true;
4069 case Dali::Actor::Property::SIZE:
4071 value = GetCurrentSize();
4075 case Dali::Actor::Property::SIZE_WIDTH:
4077 value = GetCurrentSize().width;
4081 case Dali::Actor::Property::SIZE_HEIGHT:
4083 value = GetCurrentSize().height;
4087 case Dali::Actor::Property::SIZE_DEPTH:
4089 value = GetCurrentSize().depth;
4093 case Dali::Actor::Property::POSITION:
4095 value = GetCurrentPosition();
4099 case Dali::Actor::Property::POSITION_X:
4101 value = GetCurrentPosition().x;
4105 case Dali::Actor::Property::POSITION_Y:
4107 value = GetCurrentPosition().y;
4111 case Dali::Actor::Property::POSITION_Z:
4113 value = GetCurrentPosition().z;
4117 case Dali::Actor::Property::WORLD_POSITION:
4119 value = GetCurrentWorldPosition();
4123 case Dali::Actor::Property::WORLD_POSITION_X:
4125 value = GetCurrentWorldPosition().x;
4129 case Dali::Actor::Property::WORLD_POSITION_Y:
4131 value = GetCurrentWorldPosition().y;
4135 case Dali::Actor::Property::WORLD_POSITION_Z:
4137 value = GetCurrentWorldPosition().z;
4141 case Dali::Actor::Property::ORIENTATION:
4143 value = GetCurrentOrientation();
4147 case Dali::Actor::Property::WORLD_ORIENTATION:
4149 value = GetCurrentWorldOrientation();
4153 case Dali::Actor::Property::SCALE:
4155 value = GetCurrentScale();
4159 case Dali::Actor::Property::SCALE_X:
4161 value = GetCurrentScale().x;
4165 case Dali::Actor::Property::SCALE_Y:
4167 value = GetCurrentScale().y;
4171 case Dali::Actor::Property::SCALE_Z:
4173 value = GetCurrentScale().z;
4177 case Dali::Actor::Property::WORLD_SCALE:
4179 value = GetCurrentWorldScale();
4183 case Dali::Actor::Property::COLOR:
4185 value = GetCurrentColor();
4189 case Dali::Actor::Property::COLOR_RED:
4191 value = GetCurrentColor().r;
4195 case Dali::Actor::Property::COLOR_GREEN:
4197 value = GetCurrentColor().g;
4201 case Dali::Actor::Property::COLOR_BLUE:
4203 value = GetCurrentColor().b;
4207 case Dali::Actor::Property::COLOR_ALPHA:
4208 case Dali::DevelActor::Property::OPACITY:
4210 value = GetCurrentColor().a;
4214 case Dali::Actor::Property::WORLD_COLOR:
4216 value = GetCurrentWorldColor();
4220 case Dali::Actor::Property::WORLD_MATRIX:
4222 value = GetCurrentWorldMatrix();
4228 // Must be an event-side only property
4237 void Actor::EnsureRelayoutData()
4239 // Assign relayout data.
4240 if( !mRelayoutData )
4242 mRelayoutData = new RelayoutData();
4246 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
4248 // Check if actor is dependent on parent
4249 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4251 if( ( dimension & ( 1 << i ) ) )
4253 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4254 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
4264 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
4266 // Check if actor is dependent on children
4267 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4269 if( ( dimension & ( 1 << i ) ) )
4271 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4272 switch( resizePolicy )
4274 case ResizePolicy::FIT_TO_CHILDREN:
4275 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
4291 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
4293 return Actor::RelayoutDependentOnChildren( dimension );
4296 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
4298 // Check each possible dimension and see if it is dependent on the input one
4299 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4301 if( dimension & ( 1 << i ) )
4303 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
4310 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
4312 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4314 if( dimension & ( 1 << i ) )
4316 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
4321 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
4323 // If more than one dimension is requested, just return the first one found
4324 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4326 if( ( dimension & ( 1 << i ) ) )
4328 return mRelayoutData->negotiatedDimensions[ i ];
4332 return 0.0f; // Default
4335 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
4337 EnsureRelayoutData();
4339 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4341 if( dimension & ( 1 << i ) )
4343 mRelayoutData->dimensionPadding[ i ] = padding;
4348 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4350 if ( mRelayoutData )
4352 // If more than one dimension is requested, just return the first one found
4353 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4355 if( ( dimension & ( 1 << i ) ) )
4357 return mRelayoutData->dimensionPadding[ i ];
4362 return GetDefaultDimensionPadding();
4365 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4367 EnsureRelayoutData();
4369 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4371 if( dimension & ( 1 << i ) )
4373 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4378 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4380 if ( mRelayoutData )
4382 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4384 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4394 float Actor::GetHeightForWidthBase( float width )
4396 float height = 0.0f;
4398 const Vector3 naturalSize = GetNaturalSize();
4399 if( naturalSize.width > 0.0f )
4401 height = naturalSize.height * width / naturalSize.width;
4403 else // we treat 0 as 1:1 aspect ratio
4411 float Actor::GetWidthForHeightBase( float height )
4415 const Vector3 naturalSize = GetNaturalSize();
4416 if( naturalSize.height > 0.0f )
4418 width = naturalSize.width * height / naturalSize.height;
4420 else // we treat 0 as 1:1 aspect ratio
4428 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4430 // Fill to parent, taking size mode factor into account
4431 switch( child.GetResizePolicy( dimension ) )
4433 case ResizePolicy::FILL_TO_PARENT:
4435 return GetLatestSize( dimension );
4438 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4440 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4443 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4445 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4450 return GetLatestSize( dimension );
4455 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4457 // Can be overridden in derived class
4458 return CalculateChildSizeBase( child, dimension );
4461 float Actor::GetHeightForWidth( float width )
4463 // Can be overridden in derived class
4464 return GetHeightForWidthBase( width );
4467 float Actor::GetWidthForHeight( float height )
4469 // Can be overridden in derived class
4470 return GetWidthForHeightBase( height );
4473 float Actor::GetLatestSize( Dimension::Type dimension ) const
4475 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4478 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4480 Vector2 padding = GetPadding( dimension );
4482 return GetLatestSize( dimension ) + padding.x + padding.y;
4485 float Actor::NegotiateFromParent( Dimension::Type dimension )
4487 Actor* parent = GetParent();
4490 Vector2 padding( GetPadding( dimension ) );
4491 Vector2 parentPadding( parent->GetPadding( dimension ) );
4492 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4498 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4500 float maxDimensionPoint = 0.0f;
4502 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4504 ActorPtr child = GetChildAt( i );
4506 if( !child->RelayoutDependentOnParent( dimension ) )
4508 // Calculate the min and max points that the children range across
4509 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
4510 float dimensionSize = child->GetRelayoutSize( dimension );
4511 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4515 return maxDimensionPoint;
4518 float Actor::GetSize( Dimension::Type dimension ) const
4520 return GetDimensionValue( GetTargetSize(), dimension );
4523 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4525 return GetDimensionValue( GetNaturalSize(), dimension );
4528 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4530 switch( GetResizePolicy( dimension ) )
4532 case ResizePolicy::USE_NATURAL_SIZE:
4534 return GetNaturalSize( dimension );
4537 case ResizePolicy::FIXED:
4539 return GetDimensionValue( GetPreferredSize(), dimension );
4542 case ResizePolicy::USE_ASSIGNED_SIZE:
4544 return GetDimensionValue( maximumSize, dimension );
4547 case ResizePolicy::FILL_TO_PARENT:
4548 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4549 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4551 return NegotiateFromParent( dimension );
4554 case ResizePolicy::FIT_TO_CHILDREN:
4556 return NegotiateFromChildren( dimension );
4559 case ResizePolicy::DIMENSION_DEPENDENCY:
4561 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4564 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4566 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4569 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4571 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4583 return 0.0f; // Default
4586 float Actor::ClampDimension( float size, Dimension::Type dimension )
4588 const float minSize = GetMinimumSize( dimension );
4589 const float maxSize = GetMaximumSize( dimension );
4591 return std::max( minSize, std::min( size, maxSize ) );
4594 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4596 // Check if it needs to be negotiated
4597 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4599 // Check that we havn't gotten into an infinite loop
4600 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4601 bool recursionFound = false;
4602 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4604 if( *it == searchActor )
4606 recursionFound = true;
4611 if( !recursionFound )
4613 // Record the path that we have taken
4614 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4616 // Dimension dependency check
4617 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4619 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4621 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4623 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4627 // Parent dependency check
4628 Actor* parent = GetParent();
4629 if( parent && RelayoutDependentOnParent( dimension ) )
4631 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4634 // Children dependency check
4635 if( RelayoutDependentOnChildren( dimension ) )
4637 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4639 ActorPtr child = GetChildAt( i );
4641 // Only relayout child first if it is not dependent on this actor
4642 if( !child->RelayoutDependentOnParent( dimension ) )
4644 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
4649 // For deriving classes
4650 OnCalculateRelayoutSize( dimension );
4652 // All dependencies checked, calculate the size and set negotiated flag
4653 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4655 SetNegotiatedDimension( newSize, dimension );
4656 SetLayoutNegotiated( true, dimension );
4658 // For deriving classes
4659 OnLayoutNegotiated( newSize, dimension );
4661 // This actor has been successfully processed, pop it off the recursion stack
4662 recursionStack.pop_back();
4666 // TODO: Break infinite loop
4667 SetLayoutNegotiated( true, dimension );
4672 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4674 // Negotiate all dimensions that require it
4675 ActorDimensionStack recursionStack;
4677 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4679 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4682 NegotiateDimension( dimension, allocatedSize, recursionStack );
4686 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4688 switch( mRelayoutData->sizeSetPolicy )
4690 case SizeScalePolicy::USE_SIZE_SET:
4695 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4697 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4698 const Vector3 naturalSize = GetNaturalSize();
4699 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4701 const float sizeRatio = size.width / size.height;
4702 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4704 if( naturalSizeRatio < sizeRatio )
4706 return Vector2( naturalSizeRatio * size.height, size.height );
4708 else if( naturalSizeRatio > sizeRatio )
4710 return Vector2( size.width, size.width / naturalSizeRatio );
4721 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4723 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4724 const Vector3 naturalSize = GetNaturalSize();
4725 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4727 const float sizeRatio = size.width / size.height;
4728 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4730 if( naturalSizeRatio < sizeRatio )
4732 return Vector2( size.width, size.width / naturalSizeRatio );
4734 else if( naturalSizeRatio > sizeRatio )
4736 return Vector2( naturalSizeRatio * size.height, size.height );
4755 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4757 // Do the set actor size
4758 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4760 // Adjust for size set policy
4761 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4763 // Lock the flag to stop recursive relayouts on set size
4764 mRelayoutData->insideRelayout = true;
4765 SetSize( negotiatedSize );
4766 mRelayoutData->insideRelayout = false;
4768 // Clear flags for all dimensions
4769 SetLayoutDirty( false );
4771 // Give deriving classes a chance to respond
4772 OnRelayout( negotiatedSize, container );
4774 if( !mOnRelayoutSignal.Empty() )
4776 Dali::Actor handle( this );
4777 mOnRelayoutSignal.Emit( handle );
4781 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4783 // Force a size negotiation for actors that has assigned size during relayout
4784 // This is required as otherwise the flags that force a relayout will not
4785 // necessarilly be set. This will occur if the actor has already been laid out.
4786 // The dirty flags are then cleared. Then if the actor is added back into the
4787 // relayout container afterwards, the dirty flags would still be clear...
4788 // causing a relayout to be skipped. Here we force any actors added to the
4789 // container to be relayed out.
4790 DALI_LOG_TIMER_START( NegSizeTimer1 );
4792 if(GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE)
4794 SetLayoutNegotiated(false, Dimension::WIDTH);
4796 if(GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE)
4798 SetLayoutNegotiated(false, Dimension::HEIGHT);
4801 // Do the negotiation
4802 NegotiateDimensions( allocatedSize );
4804 // Set the actor size
4805 SetNegotiatedSize( container );
4807 // Negotiate down to children
4808 const Vector2 newBounds = GetTargetSize().GetVectorXY();
4810 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4812 ActorPtr child = GetChildAt( i );
4814 // Forces children that have already been laid out to be relayed out
4815 // if they have assigned size during relayout.
4816 if(child->GetResizePolicy(Dimension::WIDTH) == ResizePolicy::USE_ASSIGNED_SIZE)
4818 child->SetLayoutNegotiated(false, Dimension::WIDTH);
4819 child->SetLayoutDirty(true, Dimension::WIDTH);
4821 if(child->GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::USE_ASSIGNED_SIZE)
4823 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
4824 child->SetLayoutDirty(true, Dimension::HEIGHT);
4827 // Only relayout if required
4828 if( child->RelayoutRequired() )
4830 container.Add( Dali::Actor( child.Get() ), newBounds );
4833 DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
4836 void Actor::RelayoutRequest( Dimension::Type dimension )
4838 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4839 if( relayoutController )
4841 Dali::Actor self( this );
4842 relayoutController->RequestRelayout( self, dimension );
4846 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4850 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4854 void Actor::SetPreferredSize( const Vector2& size )
4856 EnsureRelayoutData();
4858 if( size.width > 0.0f )
4860 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4863 if( size.height > 0.0f )
4865 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4868 mRelayoutData->preferredSize = size;
4873 Vector2 Actor::GetPreferredSize() const
4875 if ( mRelayoutData )
4877 return Vector2( mRelayoutData->preferredSize );
4880 return GetDefaultPreferredSize();
4883 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4885 EnsureRelayoutData();
4887 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4889 if( dimension & ( 1 << i ) )
4891 mRelayoutData->minimumSize[ i ] = size;
4898 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4900 if ( mRelayoutData )
4902 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4904 if( dimension & ( 1 << i ) )
4906 return mRelayoutData->minimumSize[ i ];
4911 return 0.0f; // Default
4914 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4916 EnsureRelayoutData();
4918 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4920 if( dimension & ( 1 << i ) )
4922 mRelayoutData->maximumSize[ i ] = size;
4929 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4931 if ( mRelayoutData )
4933 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4935 if( dimension & ( 1 << i ) )
4937 return mRelayoutData->maximumSize[ i ];
4942 return FLT_MAX; // Default
4945 Object* Actor::GetParentObject() const
4950 void Actor::SetSiblingOrder( unsigned int order )
4952 mSiblingOrder = std::min( order, static_cast<unsigned int>( DevelLayer::SIBLING_ORDER_MULTIPLIER ) );
4956 StagePtr stage = Stage::GetCurrent();
4959 stage->RequestRebuildDepthTree();
4964 void Actor::DefragmentSiblingIndexes( ActorContainer& siblings )
4966 // Sibling index may not be in consecutive order as the sibling range is limited ( DevelLayer::SIBLING_ORDER_MULTIPLIER )
4967 // we need to remove the gaps and ensure the number start from 0 and consecutive hence have a full range.
4969 // Start at index 0, while index <= highest order
4970 // Find next index higher than 0
4971 // if nextHigher > index+1
4972 // set all nextHigher orders to index+1
4974 // Limitation: May reach the ceiling of DevelLayer::SIBLING_ORDER_MULTIPLIER with highest sibling.
4976 ActorIter end = siblings.end();
4977 int highestOrder = 0;
4978 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
4980 ActorPtr sibling = (*iter);
4981 int siblingOrder = sibling->mSiblingOrder;
4982 highestOrder = std::max( highestOrder, siblingOrder );
4985 for ( int index = 0; index <= highestOrder; index++ )
4987 int nextHighest = -1;
4989 // Find Next highest
4990 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
4992 ActorPtr sibling = (*iter);
4993 int siblingOrder = sibling->mSiblingOrder;
4995 if ( siblingOrder > index )
4997 if ( nextHighest == -1 )
4999 nextHighest = siblingOrder;
5001 nextHighest = std::min( nextHighest, siblingOrder );
5005 // Check if a gap exists between indexes, if so set next index to consecutive number
5006 if ( ( nextHighest - index ) > 1 )
5008 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
5010 ActorPtr sibling = (*iter);
5011 int siblingOrder = sibling->mSiblingOrder;
5012 if ( siblingOrder == nextHighest )
5014 sibling->mSiblingOrder = index + 1;
5015 if ( sibling->mSiblingOrder >= Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER )
5017 DALI_LOG_WARNING( "Reached max sibling order level for raising / lowering actors\n" );
5018 sibling->mSiblingOrder = Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER;
5020 sibling->SetSiblingOrder( sibling->mSiblingOrder );
5027 bool Actor::ShiftSiblingsLevels( ActorContainer& siblings, int targetLevelToShiftFrom )
5029 // Allows exclusive levels for an actor by shifting all sibling levels at the target and above by 1
5030 bool defragmentationRequired( false );
5031 ActorIter end = siblings.end();
5032 for( ActorIter iter = siblings.begin(); ( iter != end ) ; ++iter )
5034 // Move actors at nearest order and above up by 1
5035 ActorPtr sibling = (*iter);
5036 if ( sibling != this )
5038 // Iterate through container of actors, any actor with a sibling order of the target or greater should
5039 // be incremented by 1.
5040 if ( sibling->mSiblingOrder >= targetLevelToShiftFrom )
5042 sibling->mSiblingOrder++;
5043 if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
5045 // If a sibling order raises so that it is only 1 from the maximum allowed then set flag so
5046 // can re-order all sibling orders.
5047 defragmentationRequired = true;
5049 sibling->SetSiblingOrder( sibling->mSiblingOrder );
5053 return defragmentationRequired;
5059 1) Check if already at top and nothing to be done.
5060 This Actor can have highest sibling order but if not exclusive then another actor at same sibling
5061 order can be positioned above it due to insertion order of actors.
5062 2) Find nearest sibling level above, these are the siblings this actor needs to be above
5063 3) a) There may be other levels above this target level
5064 b) Increment all sibling levels at the level above nearest(target)
5065 c) Now have a vacant sibling level
5066 4) Set this actor's sibling level to nearest +1 as now vacated.
5068 Note May not just be sibling level + 1 as could be empty levels in-between
5073 ActorC ( sibling level 4 )
5074 ActorB ( sibling level 3 )
5075 ActorA ( sibling level 1 )
5077 2 ) ACTION: Raise A above B
5078 a) Find nearest level above A = Level 3
5079 b) Increment levels above Level 3
5081 ActorC ( sibling level 5 )
5082 ActorB ( sibling level 3 ) NEAREST
5083 ActorA ( sibling level 1 )
5085 3 ) Set Actor A sibling level to nearest +1 as vacant
5087 ActorC ( sibling level 5 )
5088 ActorA ( sibling level 4 )
5089 ActorB ( sibling level 3 )
5091 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5092 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5093 remove any empty sibling order gaps and start from sibling level 0 again.
5094 If the number of actors reaches this maximum and all using exclusive sibling order values then
5095 defragmention will stop and new sibling orders will be set to same max value.
5099 int nearestLevel = mSiblingOrder;
5100 int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
5101 bool defragmentationRequired( false );
5103 ActorContainer* siblings = mParent->mChildren;
5105 // Find Nearest sibling level above this actor
5106 ActorIter end = siblings->end();
5107 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
5109 ActorPtr sibling = (*iter);
5110 if ( sibling != this )
5112 int order = GetSiblingOrder( sibling );
5114 if ( ( order >= mSiblingOrder ) )
5116 int distanceToNextLevel = order - mSiblingOrder;
5117 if ( distanceToNextLevel < shortestDistanceToNextLevel )
5119 nearestLevel = order;
5120 shortestDistanceToNextLevel = distanceToNextLevel;
5126 if ( nearestLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at top
5128 mSiblingOrder = nearestLevel + 1; // Set sibling level to that above the nearest level
5129 defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
5130 // Move current actor to newly vacated order level
5131 SetSiblingOrder( mSiblingOrder );
5132 if ( defragmentationRequired )
5134 DefragmentSiblingIndexes( *siblings );
5137 SetSiblingOrder( mSiblingOrder );
5141 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5148 1) Check if actor already at bottom and if nothing needs to be done
5149 This Actor can have lowest sibling order but if not exclusive then another actor at same sibling
5150 order can be positioned above it due to insertion order of actors so need to move this actor below it.
5151 2) Find nearest sibling level below, this Actor needs to be below it
5152 3) a) Need to vacate a sibling level below nearest for this actor to occupy
5153 b) Shift up all sibling order values of actor at the nearest level and levels above it to vacate a level.
5154 c) Set this actor's sibling level to this newly vacated level.
5155 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5156 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5157 remove any empty sibling order gaps and start from sibling level 0 again.
5158 If the number of actors reaches this maximum and all using exclusive sibling order values then
5159 defragmention will stop and new sibling orders will be set to same max value.
5164 // 1) Find nearest level below
5165 int nearestLevel = mSiblingOrder;
5166 int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
5168 ActorContainer* siblings = mParent->mChildren;
5170 ActorIter end = siblings->end();
5171 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
5173 ActorPtr sibling = (*iter);
5174 if ( sibling != this )
5176 int order = GetSiblingOrder( sibling );
5178 if ( order <= mSiblingOrder )
5180 int distanceToNextLevel = mSiblingOrder - order;
5181 if ( distanceToNextLevel < shortestDistanceToNextLevel )
5183 nearestLevel = order;
5184 shortestDistanceToNextLevel = distanceToNextLevel;
5190 bool defragmentationRequired ( false );
5192 // 2) If actor already not at bottom, raise all actors at required level and above
5193 if ( shortestDistanceToNextLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at bottom
5195 mSiblingOrder = nearestLevel;
5196 defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
5197 // Move current actor to newly vacated order
5198 SetSiblingOrder( mSiblingOrder );
5199 if ( defragmentationRequired )
5201 DefragmentSiblingIndexes( *siblings );
5207 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5211 void Actor::RaiseToTop()
5214 1 ) Find highest sibling order actor
5215 2 ) If highest sibling level not itself then set sibling order to that + 1
5216 3 ) highest sibling order can be same as itself so need to increment over that
5217 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5218 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5219 remove any empty sibling order gaps and start from sibling level 0 again.
5220 If the number of actors reaches this maximum and all using exclusive sibling order values then
5221 defragmention will stop and new sibling orders will be set to same max value.
5228 ActorContainer* siblings = mParent->mChildren;
5230 ActorIter end = siblings->end();
5231 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
5233 ActorPtr sibling = (*iter);
5234 if ( sibling != this )
5236 maxOrder = std::max( GetSiblingOrder( sibling ), maxOrder );
5240 bool defragmentationRequired( false );
5242 if ( maxOrder >= mSiblingOrder )
5244 mSiblingOrder = maxOrder + 1;
5245 if ( mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
5247 defragmentationRequired = true;
5251 SetSiblingOrder( mSiblingOrder );
5253 if ( defragmentationRequired )
5255 DefragmentSiblingIndexes( *siblings );
5260 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5264 void Actor::LowerToBottom()
5267 See Actor::LowerToBottom()
5269 1 ) Check if this actor already at exclusively at the bottom, if so then no more to be done.
5270 2 ) a ) Check if the bottom position 0 is vacant.
5271 b ) If 0 position is not vacant then shift up all sibling order values from 0 and above
5272 c ) 0 sibling position is vacant.
5273 3 ) Set this actor to vacant sibling order 0;
5274 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5275 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5276 remove any empty sibling order gaps and start from sibling level 0 again.
5277 If the number of actors reaches this maximum and all using exclusive sibling order values then
5278 defragmention will stop and new sibling orders will be set to same max value.
5283 bool defragmentationRequired( false );
5284 bool orderZeroFree ( true );
5286 ActorContainer* siblings = mParent->mChildren;
5288 bool actorAtLowestOrder = true;
5289 ActorIter end = siblings->end();
5290 for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
5292 ActorPtr sibling = (*iter);
5293 if ( sibling != this )
5295 int siblingOrder = GetSiblingOrder( sibling );
5296 if ( siblingOrder <= mSiblingOrder )
5298 actorAtLowestOrder = false;
5301 if ( siblingOrder == 0 )
5303 orderZeroFree = false;
5308 if ( ! actorAtLowestOrder )
5310 if ( ! orderZeroFree )
5312 defragmentationRequired = ShiftSiblingsLevels( *siblings, 0 );
5315 SetSiblingOrder( mSiblingOrder );
5317 if ( defragmentationRequired )
5319 DefragmentSiblingIndexes( *siblings );
5325 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5329 void Actor::RaiseAbove( Internal::Actor& target )
5332 1 ) a) Find target actor's sibling order
5333 b) If sibling order of target is the same as this actor then need to this Actor's sibling order
5334 needs to be above it or the insertion order will determine which is drawn on top.
5335 2 ) Shift up by 1 all sibling order greater than target sibling order
5336 3 ) Set this actor to the sibling order to target +1 as will be a newly vacated gap above
5337 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5338 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5339 remove any empty sibling order gaps and start from sibling level 0 again.
5340 If the number of actors reaches this maximum and all using exclusive sibling order values then
5341 defragmention will stop and new sibling orders will be set to same max value.
5346 if ( ValidateActors( *this, target ) )
5348 // Find target's sibling order
5349 // Set actor sibling order to this number +1
5350 int targetSiblingOrder = GetSiblingOrder( &target );
5351 ActorContainer* siblings = mParent->mChildren;
5352 mSiblingOrder = targetSiblingOrder + 1;
5353 bool defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
5355 SetSiblingOrder( mSiblingOrder );
5357 if ( defragmentationRequired )
5359 DefragmentSiblingIndexes( *(mParent->mChildren) );
5365 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5369 void Actor::LowerBelow( Internal::Actor& target )
5372 1 ) a) Find target actor's sibling order
5373 b) If sibling order of target is the same as this actor then need to this Actor's sibling order
5374 needs to be below it or the insertion order will determine which is drawn on top.
5375 2 ) Shift the target sibling order and all sibling orders at that level or above by 1
5376 3 ) Set this actor to the sibling order of the target before it changed.
5377 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5378 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5379 remove any empty sibling order gaps and start from sibling level 0 again.
5380 If the number of actors reaches this maximum and all using exclusive sibling order values then
5381 defragmention will stop and new sibling orders will be set to same max value.
5386 if ( ValidateActors( *this, target ) )
5388 bool defragmentationRequired ( false );
5389 // Find target's sibling order
5390 // Set actor sibling order to target sibling order - 1
5391 int targetSiblingOrder = GetSiblingOrder( &target);
5392 ActorContainer* siblings = mParent->mChildren;
5393 if ( targetSiblingOrder == 0 )
5396 ActorIter end = siblings->end();
5397 for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
5399 ActorPtr sibling = (*iter);
5400 if ( sibling != this )
5402 sibling->mSiblingOrder++;
5403 if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
5405 defragmentationRequired = true;
5407 sibling->SetSiblingOrder( sibling->mSiblingOrder );
5414 defragmentationRequired = ShiftSiblingsLevels( *siblings, targetSiblingOrder );
5416 mSiblingOrder = targetSiblingOrder;
5418 SetSiblingOrder( mSiblingOrder );
5420 if ( defragmentationRequired )
5422 DefragmentSiblingIndexes( *(mParent->mChildren) );
5428 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5432 } // namespace Internal