2 * Copyright (c) 2017 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/event/actors/actor-impl.h>
27 #include <dali/devel-api/actors/layer-devel.h>
28 #include <dali/public-api/common/dali-common.h>
29 #include <dali/public-api/common/constants.h>
30 #include <dali/public-api/events/touch-data.h>
31 #include <dali/public-api/math/vector2.h>
32 #include <dali/public-api/math/vector3.h>
33 #include <dali/public-api/math/radian.h>
34 #include <dali/public-api/object/type-registry.h>
35 #include <dali/devel-api/actors/actor-devel.h>
36 #include <dali/devel-api/object/weak-handle.h>
37 #include <dali/devel-api/scripting/scripting.h>
38 #include <dali/internal/common/internal-constants.h>
39 #include <dali/internal/event/common/event-thread-services.h>
40 #include <dali/internal/event/render-tasks/render-task-impl.h>
41 #include <dali/internal/event/actors/camera-actor-impl.h>
42 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
43 #include <dali/internal/event/common/property-helper.h>
44 #include <dali/internal/event/common/stage-impl.h>
45 #include <dali/internal/event/common/type-info-impl.h>
46 #include <dali/internal/event/animation/constraint-impl.h>
47 #include <dali/internal/event/common/projection.h>
48 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
49 #include <dali/internal/update/common/animatable-property.h>
50 #include <dali/internal/update/nodes/node-messages.h>
51 #include <dali/internal/update/nodes/node-declarations.h>
52 #include <dali/internal/update/animation/scene-graph-constraint.h>
53 #include <dali/internal/event/events/actor-gesture-data.h>
54 #include <dali/internal/common/message.h>
55 #include <dali/integration-api/debug.h>
57 using Dali::Internal::SceneGraph::Node;
58 using Dali::Internal::SceneGraph::AnimatableProperty;
59 using Dali::Internal::SceneGraph::PropertyBase;
61 #if defined(DEBUG_ENABLED)
62 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_DEPTH_TIMER" );
63 Debug::Filter* gLogRelayoutFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_TIMER" );
72 unsigned int Actor::mActorCounter = 0;
76 /// Using a function because of library initialisation order. Vector3::ONE may not have been initialised yet.
77 inline const Vector3& GetDefaultSizeModeFactor()
82 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
83 inline const Vector2& GetDefaultPreferredSize()
88 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
89 inline const Vector2& GetDefaultDimensionPadding()
94 const SizeScalePolicy::Type DEFAULT_SIZE_SCALE_POLICY = SizeScalePolicy::USE_SIZE_SET;
96 int GetSiblingOrder( ActorPtr actor )
98 Property::Value value = actor->GetProperty(Dali::DevelActor::Property::SIBLING_ORDER );
104 bool ValidateActors( const Internal::Actor& actor, const Internal::Actor& target )
106 bool validTarget = true;
108 if( &actor == &target )
110 DALI_LOG_WARNING( "Source actor and target actor can not be the same, Sibling order not changed.\n" );
113 else if( actor.GetParent() != target.GetParent() )
115 DALI_LOG_WARNING( "Source actor and target actor need to have common parent, Sibling order not changed.\n" );
122 } // unnamed namespace
125 * Struct to collect relayout variables
127 struct Actor::RelayoutData
130 : sizeModeFactor( GetDefaultSizeModeFactor() ), preferredSize( GetDefaultPreferredSize() ), sizeSetPolicy( DEFAULT_SIZE_SCALE_POLICY ), relayoutEnabled( false ), insideRelayout( false )
132 // Set size negotiation defaults
133 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
135 resizePolicies[ i ] = ResizePolicy::DEFAULT;
136 useAssignedSize[ i ] = false;
137 negotiatedDimensions[ i ] = 0.0f;
138 dimensionNegotiated[ i ] = false;
139 dimensionDirty[ i ] = false;
140 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
141 dimensionPadding[ i ] = GetDefaultDimensionPadding();
142 minimumSize[ i ] = 0.0f;
143 maximumSize[ i ] = FLT_MAX;
147 ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies
148 bool useAssignedSize[ Dimension::DIMENSION_COUNT ]; ///< The flag to specify whether the size should be assigned to the actor
150 Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies
152 Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
154 float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
156 float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be
157 float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be
159 bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated
160 bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
162 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
164 Vector2 preferredSize; ///< The preferred size of the actor
166 SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
168 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
169 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
172 namespace // unnamed namespace
178 * We want to discourage the use of property strings (minimize string comparisons),
179 * particularly for the default properties.
180 * Name Type writable animatable constraint-input enum for index-checking
182 DALI_PROPERTY_TABLE_BEGIN
183 DALI_PROPERTY( "parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
184 DALI_PROPERTY( "parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
185 DALI_PROPERTY( "parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
186 DALI_PROPERTY( "parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
187 DALI_PROPERTY( "anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
188 DALI_PROPERTY( "anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
189 DALI_PROPERTY( "anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
190 DALI_PROPERTY( "anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
191 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
192 DALI_PROPERTY( "sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
193 DALI_PROPERTY( "sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
194 DALI_PROPERTY( "sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
195 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
196 DALI_PROPERTY( "positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
197 DALI_PROPERTY( "positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
198 DALI_PROPERTY( "positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
199 DALI_PROPERTY( "worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
200 DALI_PROPERTY( "worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
201 DALI_PROPERTY( "worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
202 DALI_PROPERTY( "worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
203 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
204 DALI_PROPERTY( "worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
205 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
206 DALI_PROPERTY( "scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
207 DALI_PROPERTY( "scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
208 DALI_PROPERTY( "scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
209 DALI_PROPERTY( "worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
210 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
211 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
212 DALI_PROPERTY( "colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
213 DALI_PROPERTY( "colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
214 DALI_PROPERTY( "colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
215 DALI_PROPERTY( "colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
216 DALI_PROPERTY( "worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
217 DALI_PROPERTY( "worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
218 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
219 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
220 DALI_PROPERTY( "leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
221 DALI_PROPERTY( "inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
222 DALI_PROPERTY( "inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
223 DALI_PROPERTY( "colorMode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
224 DALI_PROPERTY( "positionInheritance", STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE )
225 DALI_PROPERTY( "drawMode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
226 DALI_PROPERTY( "sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
227 DALI_PROPERTY( "widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
228 DALI_PROPERTY( "heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
229 DALI_PROPERTY( "sizeScalePolicy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
230 DALI_PROPERTY( "widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
231 DALI_PROPERTY( "heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
232 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
233 DALI_PROPERTY( "minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
234 DALI_PROPERTY( "maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
235 DALI_PROPERTY( "inheritPosition", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_POSITION )
236 DALI_PROPERTY( "clippingMode", STRING, true, false, false, Dali::Actor::Property::CLIPPING_MODE )
237 DALI_PROPERTY( "siblingOrder", INTEGER, true, false, false, Dali::DevelActor::Property::SIBLING_ORDER )
238 DALI_PROPERTY( "opacity", FLOAT, true, true, true, Dali::DevelActor::Property::OPACITY )
239 DALI_PROPERTY( "screenPosition", VECTOR2, false, false, false, Dali::DevelActor::Property::SCREEN_POSITION )
240 DALI_PROPERTY( "positionUsesAnchorPoint", BOOLEAN, true, false, false, Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT )
241 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
245 const char* const SIGNAL_TOUCHED = "touched";
246 const char* const SIGNAL_HOVERED = "hovered";
247 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
248 const char* const SIGNAL_ON_STAGE = "onStage";
249 const char* const SIGNAL_OFF_STAGE = "offStage";
250 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
251 const char* const SIGNAL_TOUCH = "touch";
255 const char* const ACTION_SHOW = "show";
256 const char* const ACTION_HIDE = "hide";
258 BaseHandle CreateActor()
260 return Dali::Actor::New();
263 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
265 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
266 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
267 SignalConnectorType signalConnector3( mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal );
268 SignalConnectorType signalConnector4( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
269 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
270 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
271 SignalConnectorType signalConnector7( mType, SIGNAL_TOUCH, &Actor::DoConnectSignal );
273 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
274 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
279 const Vector3& value;
282 DALI_ENUM_TO_STRING_TABLE_BEGIN_WITH_TYPE( AnchorValue, ANCHOR_CONSTANT )
283 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_LEFT )
284 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_CENTER )
285 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_RIGHT )
286 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_LEFT )
287 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER )
288 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_RIGHT )
289 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_LEFT )
290 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_CENTER )
291 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_RIGHT )
292 DALI_ENUM_TO_STRING_TABLE_END( ANCHOR_CONSTANT )
294 DALI_ENUM_TO_STRING_TABLE_BEGIN( COLOR_MODE )
295 DALI_ENUM_TO_STRING( USE_OWN_COLOR )
296 DALI_ENUM_TO_STRING( USE_PARENT_COLOR )
297 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_COLOR )
298 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_ALPHA )
299 DALI_ENUM_TO_STRING_TABLE_END( COLOR_MODE )
301 DALI_ENUM_TO_STRING_TABLE_BEGIN( POSITION_INHERITANCE_MODE )
302 DALI_ENUM_TO_STRING( INHERIT_PARENT_POSITION )
303 DALI_ENUM_TO_STRING( USE_PARENT_POSITION )
304 DALI_ENUM_TO_STRING( USE_PARENT_POSITION_PLUS_LOCAL_POSITION )
305 DALI_ENUM_TO_STRING( DONT_INHERIT_POSITION )
306 DALI_ENUM_TO_STRING_TABLE_END( POSITION_INHERITANCE_MODE )
308 DALI_ENUM_TO_STRING_TABLE_BEGIN( DRAW_MODE )
309 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, NORMAL )
310 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, OVERLAY_2D )
311 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, STENCIL )
312 DALI_ENUM_TO_STRING_TABLE_END( DRAW_MODE )
314 DALI_ENUM_TO_STRING_TABLE_BEGIN( RESIZE_POLICY )
315 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIXED )
316 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_NATURAL_SIZE )
317 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FILL_TO_PARENT )
318 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_RELATIVE_TO_PARENT )
319 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_FIXED_OFFSET_FROM_PARENT )
320 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIT_TO_CHILDREN )
321 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, DIMENSION_DEPENDENCY )
322 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_ASSIGNED_SIZE )
323 DALI_ENUM_TO_STRING_TABLE_END( RESIZE_POLICY )
325 DALI_ENUM_TO_STRING_TABLE_BEGIN( SIZE_SCALE_POLICY )
326 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, USE_SIZE_SET )
327 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FIT_WITH_ASPECT_RATIO )
328 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FILL_WITH_ASPECT_RATIO )
329 DALI_ENUM_TO_STRING_TABLE_END( SIZE_SCALE_POLICY )
331 DALI_ENUM_TO_STRING_TABLE_BEGIN( CLIPPING_MODE )
332 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, DISABLED )
333 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, CLIP_CHILDREN )
334 DALI_ENUM_TO_STRING_TABLE_END( CLIPPING_MODE )
337 bool GetAnchorPointConstant( const std::string& value, Vector3& anchor )
339 for( unsigned int i = 0; i < ANCHOR_CONSTANT_TABLE_COUNT; ++i )
341 size_t sizeIgnored = 0;
342 if( CompareTokens( value.c_str(), ANCHOR_CONSTANT_TABLE[ i ].name, sizeIgnored ) )
344 anchor = ANCHOR_CONSTANT_TABLE[ i ].value;
351 inline bool GetParentOriginConstant( const std::string& value, Vector3& parentOrigin )
353 // Values are the same so just use the same table as anchor-point
354 return GetAnchorPointConstant( value, parentOrigin );
358 * @brief Extract a given dimension from a Vector2
360 * @param[in] values The values to extract from
361 * @param[in] dimension The dimension to extract
362 * @return Return the value for the dimension
364 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
368 case Dimension::WIDTH:
372 case Dimension::HEIGHT:
374 return values.height;
385 * @brief Extract a given dimension from a Vector3
387 * @param[in] values The values to extract from
388 * @param[in] dimension The dimension to extract
389 * @return Return the value for the dimension
391 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
393 return GetDimensionValue( values.GetVectorXY(), dimension );
397 * @brief Recursively emits the visibility-changed-signal on the actor tree.
398 * @param[in] actor The actor to emit the signal on
399 * @param[in] visible The new visibility of the actor
400 * @param[in] type Whether the actor's visible property has changed or a parent's
402 void EmitVisibilityChangedSignalRecursively( ActorPtr actor, bool visible, DevelActor::VisibilityChange::Type type )
406 actor->EmitVisibilityChangedSignal( visible, type );
408 if( actor->GetChildCount() > 0 )
410 ActorContainer& children = actor->GetChildrenInternal();
411 for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter )
413 EmitVisibilityChangedSignalRecursively( *iter, visible, DevelActor::VisibilityChange::PARENT );
419 } // unnamed namespace
421 ActorPtr Actor::New()
423 ActorPtr actor( new Actor( BASIC ) );
425 // Second-phase construction
431 const std::string& Actor::GetName() const
436 void Actor::SetName( const std::string& name )
442 // ATTENTION: string for debug purposes is not thread safe.
443 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
447 unsigned int Actor::GetId() const
452 bool Actor::OnStage() const
457 Dali::Layer Actor::GetLayer()
461 // Short-circuit for Layer derived actors
464 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
467 // Find the immediate Layer parent
468 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
470 if( parent->IsLayer() )
472 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
479 void Actor::Add( Actor& child )
481 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
482 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
486 mChildren = new ActorContainer;
489 Actor* const oldParent( child.mParent );
491 // child might already be ours
492 if( this != oldParent )
494 // if we already have parent, unparent us first
497 oldParent->Remove( child ); // This causes OnChildRemove callback
499 // Old parent may need to readjust to missing child
500 if( oldParent->RelayoutDependentOnChildren() )
502 oldParent->RelayoutRequest();
506 // Guard against Add() during previous OnChildRemove callback
509 // Do this first, since user callbacks from within SetParent() may need to remove child
510 mChildren->push_back( ActorPtr( &child ) );
512 // SetParent asserts that child can be added
513 child.SetParent( this );
515 // Notification for derived classes
518 // Only put in a relayout request if there is a suitable dependency
519 if( RelayoutDependentOnChildren() )
527 void Actor::Remove( Actor& child )
529 if( (this == &child) || (!mChildren) )
531 // no children or removing itself
537 // Find the child in mChildren, and unparent it
538 ActorIter end = mChildren->end();
539 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
541 ActorPtr actor = (*iter);
543 if( actor.Get() == &child )
545 // Keep handle for OnChildRemove notification
548 // Do this first, since user callbacks from within SetParent() may need to add the child
549 mChildren->erase( iter );
551 DALI_ASSERT_DEBUG( actor->GetParent() == this );
552 actor->SetParent( NULL );
560 // Only put in a relayout request if there is a suitable dependency
561 if( RelayoutDependentOnChildren() )
567 // Notification for derived classes
568 OnChildRemove( child );
571 void Actor::Unparent()
575 // Remove this actor from the parent. The remove will put a relayout request in for
576 // the parent if required
577 mParent->Remove( *this );
578 // mParent is now NULL!
582 unsigned int Actor::GetChildCount() const
584 return ( NULL != mChildren ) ? mChildren->size() : 0;
587 ActorPtr Actor::GetChildAt( unsigned int index ) const
589 DALI_ASSERT_ALWAYS( index < GetChildCount() );
591 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
594 ActorPtr Actor::FindChildByName( const std::string& actorName )
597 if( actorName == mName )
603 ActorIter end = mChildren->end();
604 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
606 child = (*iter)->FindChildByName( actorName );
617 ActorPtr Actor::FindChildById( const unsigned int id )
626 ActorIter end = mChildren->end();
627 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
629 child = (*iter)->FindChildById( id );
640 void Actor::SetParentOrigin( const Vector3& origin )
644 // mNode is being used in a separate thread; queue a message to set the value & base value
645 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
648 // Cache for event-thread access
651 // not allocated, check if different from default
652 if( ParentOrigin::DEFAULT != origin )
654 mParentOrigin = new Vector3( origin );
659 // check if different from current costs more than just set
660 *mParentOrigin = origin;
664 void Actor::SetParentOriginX( float x )
666 const Vector3& current = GetCurrentParentOrigin();
668 SetParentOrigin( Vector3( x, current.y, current.z ) );
671 void Actor::SetParentOriginY( float y )
673 const Vector3& current = GetCurrentParentOrigin();
675 SetParentOrigin( Vector3( current.x, y, current.z ) );
678 void Actor::SetParentOriginZ( float z )
680 const Vector3& current = GetCurrentParentOrigin();
682 SetParentOrigin( Vector3( current.x, current.y, z ) );
685 const Vector3& Actor::GetCurrentParentOrigin() const
687 // Cached for event-thread access
688 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
691 void Actor::SetAnchorPoint( const Vector3& anchor )
695 // mNode is being used in a separate thread; queue a message to set the value & base value
696 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
699 // Cache for event-thread access
702 // not allocated, check if different from default
703 if( AnchorPoint::DEFAULT != anchor )
705 mAnchorPoint = new Vector3( anchor );
710 // check if different from current costs more than just set
711 *mAnchorPoint = anchor;
715 void Actor::SetAnchorPointX( float x )
717 const Vector3& current = GetCurrentAnchorPoint();
719 SetAnchorPoint( Vector3( x, current.y, current.z ) );
722 void Actor::SetAnchorPointY( float y )
724 const Vector3& current = GetCurrentAnchorPoint();
726 SetAnchorPoint( Vector3( current.x, y, current.z ) );
729 void Actor::SetAnchorPointZ( float z )
731 const Vector3& current = GetCurrentAnchorPoint();
733 SetAnchorPoint( Vector3( current.x, current.y, z ) );
736 const Vector3& Actor::GetCurrentAnchorPoint() const
738 // Cached for event-thread access
739 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
742 void Actor::SetPosition( float x, float y )
744 SetPosition( Vector3( x, y, 0.0f ) );
747 void Actor::SetPosition( float x, float y, float z )
749 SetPosition( Vector3( x, y, z ) );
752 void Actor::SetPosition( const Vector3& position )
754 mTargetPosition = position;
758 // mNode is being used in a separate thread; queue a message to set the value & base value
759 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
763 void Actor::SetX( float x )
765 mTargetPosition.x = x;
769 // mNode is being used in a separate thread; queue a message to set the value & base value
770 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
774 void Actor::SetY( float y )
776 mTargetPosition.y = y;
780 // mNode is being used in a separate thread; queue a message to set the value & base value
781 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
785 void Actor::SetZ( float z )
787 mTargetPosition.z = z;
791 // mNode is being used in a separate thread; queue a message to set the value & base value
792 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
796 void Actor::TranslateBy( const Vector3& distance )
798 mTargetPosition += distance;
802 // mNode is being used in a separate thread; queue a message to set the value & base value
803 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
807 const Vector3& Actor::GetCurrentPosition() const
811 // mNode is being used in a separate thread; copy the value from the previous update
812 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
815 return Vector3::ZERO;
818 const Vector3& Actor::GetTargetPosition() const
820 return mTargetPosition;
823 const Vector3& Actor::GetCurrentWorldPosition() const
827 // mNode is being used in a separate thread; copy the value from the previous update
828 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
831 return Vector3::ZERO;
834 const Vector2 Actor::GetCurrentScreenPosition() const
836 if( OnStage() && NULL != mNode )
838 StagePtr stage = Stage::GetCurrent();
839 Vector3 worldPosition = mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
840 Vector3 actorSize = GetCurrentSize() * GetCurrentScale();
841 Vector2 halfStageSize( stage->GetSize() * 0.5f ); // World position origin is center of stage
842 Vector3 halfActorSize( actorSize * 0.5f );
843 Vector3 anchorPointOffSet = halfActorSize - actorSize * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
845 return Vector2( halfStageSize.width + worldPosition.x - anchorPointOffSet.x,
846 halfStageSize.height + worldPosition.y - anchorPointOffSet.y );
849 return Vector2::ZERO;
852 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
854 // this flag is not animatable so keep the value
855 mPositionInheritanceMode = mode;
858 // mNode is being used in a separate thread; queue a message to set the value
859 SetInheritPositionMessage( GetEventThreadServices(), *mNode, mode == INHERIT_PARENT_POSITION );
863 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
865 // Cached for event-thread access
866 return mPositionInheritanceMode;
869 void Actor::SetInheritPosition( bool inherit )
871 if( mInheritPosition != inherit && NULL != mNode )
873 // non animateable so keep local copy
874 mInheritPosition = inherit;
875 SetInheritPositionMessage( GetEventThreadServices(), *mNode, inherit );
879 bool Actor::IsPositionInherited() const
881 return mInheritPosition;
884 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
886 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
887 normalizedAxis.Normalize();
889 Quaternion orientation( angle, normalizedAxis );
891 SetOrientation( orientation );
894 void Actor::SetOrientation( const Quaternion& orientation )
896 mTargetOrientation = orientation;
900 // mNode is being used in a separate thread; queue a message to set the value & base value
901 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation );
905 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
907 RotateBy( Quaternion(angle, axis) );
910 void Actor::RotateBy( const Quaternion& relativeRotation )
912 mTargetOrientation *= Quaternion( relativeRotation );
916 // mNode is being used in a separate thread; queue a message to set the value & base value
917 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
921 const Quaternion& Actor::GetCurrentOrientation() const
925 // mNode is being used in a separate thread; copy the value from the previous update
926 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
929 return Quaternion::IDENTITY;
932 const Quaternion& Actor::GetCurrentWorldOrientation() const
936 // mNode is being used in a separate thread; copy the value from the previous update
937 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
940 return Quaternion::IDENTITY;
943 void Actor::SetScale( float scale )
945 SetScale( Vector3( scale, scale, scale ) );
948 void Actor::SetScale( float x, float y, float z )
950 SetScale( Vector3( x, y, z ) );
953 void Actor::SetScale( const Vector3& scale )
955 mTargetScale = scale;
959 // mNode is being used in a separate thread; queue a message to set the value & base value
960 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
964 void Actor::SetScaleX( float x )
970 // mNode is being used in a separate thread; queue a message to set the value & base value
971 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
975 void Actor::SetScaleY( float y )
981 // mNode is being used in a separate thread; queue a message to set the value & base value
982 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
986 void Actor::SetScaleZ( float z )
992 // mNode is being used in a separate thread; queue a message to set the value & base value
993 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
997 void Actor::ScaleBy(const Vector3& relativeScale)
999 mTargetScale *= relativeScale;
1003 // mNode is being used in a separate thread; queue a message to set the value & base value
1004 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
1008 const Vector3& Actor::GetCurrentScale() const
1012 // mNode is being used in a separate thread; copy the value from the previous update
1013 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
1016 return Vector3::ONE;
1019 const Vector3& Actor::GetCurrentWorldScale() const
1023 // mNode is being used in a separate thread; copy the value from the previous update
1024 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
1027 return Vector3::ONE;
1030 void Actor::SetInheritScale( bool inherit )
1033 if( mInheritScale != inherit && NULL != mNode )
1035 // non animateable so keep local copy
1036 mInheritScale = inherit;
1037 // mNode is being used in a separate thread; queue a message to set the value
1038 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
1042 bool Actor::IsScaleInherited() const
1044 return mInheritScale;
1047 Matrix Actor::GetCurrentWorldMatrix() const
1051 return mNode->GetWorldMatrix(0);
1054 return Matrix::IDENTITY;
1057 void Actor::SetVisible( bool visible )
1059 SetVisibleInternal( visible, SendMessage::TRUE );
1062 bool Actor::IsVisible() const
1066 // mNode is being used in a separate thread; copy the value from the previous update
1067 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
1073 void Actor::SetOpacity( float opacity )
1075 mTargetColor.a = opacity;
1079 // mNode is being used in a separate thread; queue a message to set the value & base value
1080 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
1084 float Actor::GetCurrentOpacity() const
1088 // mNode is being used in a separate thread; copy the value from the previous update
1089 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1095 ClippingMode::Type Actor::GetClippingMode() const
1097 return mClippingMode;
1100 unsigned int Actor::GetSortingDepth()
1102 return mSortedDepth;
1105 const Vector4& Actor::GetCurrentWorldColor() const
1109 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1112 return Color::WHITE;
1115 void Actor::SetColor( const Vector4& color )
1117 mTargetColor = color;
1121 // mNode is being used in a separate thread; queue a message to set the value & base value
1122 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1126 void Actor::SetColorRed( float red )
1128 mTargetColor.r = red;
1132 // mNode is being used in a separate thread; queue a message to set the value & base value
1133 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1137 void Actor::SetColorGreen( float green )
1139 mTargetColor.g = green;
1143 // mNode is being used in a separate thread; queue a message to set the value & base value
1144 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1148 void Actor::SetColorBlue( float blue )
1150 mTargetColor.b = blue;
1154 // mNode is being used in a separate thread; queue a message to set the value & base value
1155 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1159 const Vector4& Actor::GetCurrentColor() const
1163 // mNode is being used in a separate thread; copy the value from the previous update
1164 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1167 return Color::WHITE;
1170 void Actor::SetInheritOrientation( bool inherit )
1172 if( mInheritOrientation != inherit && NULL != mNode)
1174 // non animateable so keep local copy
1175 mInheritOrientation = inherit;
1176 // mNode is being used in a separate thread; queue a message to set the value
1177 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1181 bool Actor::IsOrientationInherited() const
1183 return mInheritOrientation;
1186 void Actor::SetSizeModeFactor( const Vector3& factor )
1188 EnsureRelayoutData();
1190 mRelayoutData->sizeModeFactor = factor;
1193 const Vector3& Actor::GetSizeModeFactor() const
1195 if ( mRelayoutData )
1197 return mRelayoutData->sizeModeFactor;
1200 return GetDefaultSizeModeFactor();
1203 void Actor::SetColorMode( ColorMode colorMode )
1205 // non animateable so keep local copy
1206 mColorMode = colorMode;
1209 // mNode is being used in a separate thread; queue a message to set the value
1210 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1214 ColorMode Actor::GetColorMode() const
1216 // we have cached copy
1220 void Actor::SetSize( float width, float height )
1222 SetSize( Vector2( width, height ) );
1225 void Actor::SetSize( float width, float height, float depth )
1227 SetSize( Vector3( width, height, depth ) );
1230 void Actor::SetSize( const Vector2& size )
1232 SetSize( Vector3( size.width, size.height, 0.f ) );
1235 void Actor::SetSizeInternal( const Vector2& size )
1237 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1240 void Actor::SetSize( const Vector3& size )
1242 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1244 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1245 SetPreferredSize( size.GetVectorXY() );
1249 SetSizeInternal( size );
1253 void Actor::SetSizeInternal( const Vector3& size )
1255 // dont allow recursive loop
1256 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1257 // check that we have a node AND the new size width, height or depth is at least a little bit different from the old one
1258 if( ( NULL != mNode )&&
1259 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1260 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1261 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1265 // mNode is being used in a separate thread; queue a message to set the value & base value
1266 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
1268 // Notification for derived classes
1269 mInsideOnSizeSet = true;
1270 OnSizeSet( mTargetSize );
1271 mInsideOnSizeSet = false;
1273 // Raise a relayout request if the flag is not locked
1274 if( mRelayoutData && !mRelayoutData->insideRelayout )
1281 void Actor::SetWidth( float width )
1283 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1285 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
1286 mRelayoutData->preferredSize.width = width;
1290 mTargetSize.width = width;
1294 // mNode is being used in a separate thread; queue a message to set the value & base value
1295 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1302 void Actor::SetHeight( float height )
1304 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1306 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
1307 mRelayoutData->preferredSize.height = height;
1311 mTargetSize.height = height;
1315 // mNode is being used in a separate thread; queue a message to set the value & base value
1316 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1323 void Actor::SetDepth( float depth )
1325 mTargetSize.depth = depth;
1329 // mNode is being used in a separate thread; queue a message to set the value & base value
1330 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1334 Vector3 Actor::GetTargetSize() const
1336 Vector3 size = mTargetSize;
1338 // Should return preferred size if size is fixed as set by SetSize
1339 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
1341 size.width = GetPreferredSize().width;
1343 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
1345 size.height = GetPreferredSize().height;
1351 const Vector3& Actor::GetCurrentSize() const
1355 // mNode is being used in a separate thread; copy the value from the previous update
1356 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1359 return Vector3::ZERO;
1362 Vector3 Actor::GetNaturalSize() const
1364 // It is up to deriving classes to return the appropriate natural size
1365 return Vector3( 0.0f, 0.0f, 0.0f );
1368 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1370 EnsureRelayoutData();
1372 ResizePolicy::Type originalWidthPolicy = GetResizePolicy(Dimension::WIDTH);
1373 ResizePolicy::Type originalHeightPolicy = GetResizePolicy(Dimension::HEIGHT);
1375 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1377 if( dimension & ( 1 << i ) )
1379 if ( policy == ResizePolicy::USE_ASSIGNED_SIZE )
1381 mRelayoutData->useAssignedSize[ i ] = true;
1385 mRelayoutData->resizePolicies[ i ] = policy;
1386 mRelayoutData->useAssignedSize[ i ] = false;
1391 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1393 if( dimension & Dimension::WIDTH )
1395 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1398 if( dimension & Dimension::HEIGHT )
1400 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1404 // If calling SetResizePolicy, assume we want relayout enabled
1405 SetRelayoutEnabled( true );
1407 // If the resize policy is set to be FIXED, the preferred size
1408 // should be overrided by the target size. Otherwise the target
1409 // size should be overrided by the preferred size.
1411 if( dimension & Dimension::WIDTH )
1413 if( originalWidthPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1415 mRelayoutData->preferredSize.width = mTargetSize.width;
1417 else if( originalWidthPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1419 mTargetSize.width = mRelayoutData->preferredSize.width;
1423 if( dimension & Dimension::HEIGHT )
1425 if( originalHeightPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1427 mRelayoutData->preferredSize.height = mTargetSize.height;
1429 else if( originalHeightPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1431 mTargetSize.height = mRelayoutData->preferredSize.height;
1435 OnSetResizePolicy( policy, dimension );
1437 // Trigger relayout on this control
1441 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1443 if ( mRelayoutData )
1445 // If more than one dimension is requested, just return the first one found
1446 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1448 if( ( dimension & ( 1 << i ) ) )
1450 if( mRelayoutData->useAssignedSize[ i ] )
1452 return ResizePolicy::USE_ASSIGNED_SIZE;
1456 return mRelayoutData->resizePolicies[ i ];
1462 return ResizePolicy::DEFAULT;
1465 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1467 EnsureRelayoutData();
1469 mRelayoutData->sizeSetPolicy = policy;
1472 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1474 if ( mRelayoutData )
1476 return mRelayoutData->sizeSetPolicy;
1479 return DEFAULT_SIZE_SCALE_POLICY;
1482 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1484 EnsureRelayoutData();
1486 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1488 if( dimension & ( 1 << i ) )
1490 mRelayoutData->dimensionDependencies[ i ] = dependency;
1495 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1497 if ( mRelayoutData )
1499 // If more than one dimension is requested, just return the first one found
1500 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1502 if( ( dimension & ( 1 << i ) ) )
1504 return mRelayoutData->dimensionDependencies[ i ];
1509 return Dimension::ALL_DIMENSIONS; // Default
1512 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1514 // If relayout data has not been allocated yet and the client is requesting
1515 // to disable it, do nothing
1516 if( mRelayoutData || relayoutEnabled )
1518 EnsureRelayoutData();
1520 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1522 mRelayoutData->relayoutEnabled = relayoutEnabled;
1526 bool Actor::IsRelayoutEnabled() const
1528 // Assume that if relayout data has not been allocated yet then
1529 // relayout is disabled
1530 return mRelayoutData && mRelayoutData->relayoutEnabled;
1533 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1535 EnsureRelayoutData();
1537 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1539 if( dimension & ( 1 << i ) )
1541 mRelayoutData->dimensionDirty[ i ] = dirty;
1546 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1548 if ( mRelayoutData )
1550 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1552 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1562 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1564 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1567 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1569 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1572 unsigned int Actor::AddRenderer( Renderer& renderer )
1576 mRenderers = new RendererContainer;
1579 unsigned int index = mRenderers->size();
1580 RendererPtr rendererPtr = RendererPtr( &renderer );
1581 mRenderers->push_back( rendererPtr );
1582 AddRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1586 unsigned int Actor::GetRendererCount() const
1588 unsigned int rendererCount(0);
1591 rendererCount = mRenderers->size();
1594 return rendererCount;
1597 RendererPtr Actor::GetRendererAt( unsigned int index )
1599 RendererPtr renderer;
1600 if( index < GetRendererCount() )
1602 renderer = ( *mRenderers )[ index ];
1608 void Actor::RemoveRenderer( Renderer& renderer )
1612 RendererIter end = mRenderers->end();
1613 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1615 if( (*iter).Get() == &renderer )
1617 mRenderers->erase( iter );
1618 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1625 void Actor::RemoveRenderer( unsigned int index )
1627 if( index < GetRendererCount() )
1629 RendererPtr renderer = ( *mRenderers )[ index ];
1630 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.Get()->GetRendererSceneObject() );
1631 mRenderers->erase( mRenderers->begin()+index );
1635 bool Actor::IsOverlay() const
1637 return ( DrawMode::OVERLAY_2D == mDrawMode );
1640 void Actor::SetDrawMode( DrawMode::Type drawMode )
1642 // this flag is not animatable so keep the value
1643 mDrawMode = drawMode;
1644 if( ( NULL != mNode ) && ( drawMode != DrawMode::STENCIL ) )
1646 // mNode is being used in a separate thread; queue a message to set the value
1647 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1651 DrawMode::Type Actor::GetDrawMode() const
1656 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1658 // only valid when on-stage
1659 StagePtr stage = Stage::GetCurrent();
1660 if( stage && OnStage() )
1662 const RenderTaskList& taskList = stage->GetRenderTaskList();
1664 Vector2 converted( screenX, screenY );
1666 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1667 const int taskCount = taskList.GetTaskCount();
1668 for( int i = taskCount - 1; i >= 0; --i )
1670 Dali::RenderTask task = taskList.GetTask( i );
1671 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1673 // found a task where this conversion was ok so return
1681 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1683 bool retval = false;
1684 // only valid when on-stage
1687 CameraActor* camera = renderTask.GetCameraActor();
1691 renderTask.GetViewport( viewport );
1693 // need to translate coordinates to render tasks coordinate space
1694 Vector2 converted( screenX, screenY );
1695 if( renderTask.TranslateCoordinates( converted ) )
1697 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1704 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1706 // Early-out if mNode is NULL
1712 // Get the ModelView matrix
1714 Matrix::Multiply( modelView, mNode->GetWorldMatrix(0), viewMatrix );
1716 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1717 Matrix invertedMvp( false/*don't init*/);
1718 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1719 bool success = invertedMvp.Invert();
1721 // Convert to GL coordinates
1722 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1727 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1734 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1740 if( XyPlaneIntersect( nearPos, farPos, local ) )
1742 Vector3 size = GetCurrentSize();
1743 localX = local.x + size.x * 0.5f;
1744 localY = local.y + size.y * 0.5f;
1755 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1758 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1760 Mathematical Formulation
1762 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1764 ( p - c ) dot ( p - c ) = r^2
1766 Given a ray with a point of origin 'o', and a direction vector 'd':
1768 ray(t) = o + td, t >= 0
1770 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1772 (o + td - c ) dot ( o + td - c ) = r^2
1774 To solve for t we first expand the above into a more recognisable quadratic equation form
1776 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1785 B = 2( o - c ) dot d
1786 C = ( o - c ) dot ( o - c ) - r^2
1788 which can be solved using a standard quadratic formula.
1790 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1792 Practical Simplification
1794 In a renderer, we often differentiate between world space and object space. In the object space
1795 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1796 into object space, the mathematical solution presented above can be simplified significantly.
1798 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1802 and we can find the t at which the (transformed) ray intersects the sphere by
1804 ( o + td ) dot ( o + td ) = r^2
1806 According to the reasoning above, we expand the above quadratic equation into the general form
1810 which now has coefficients:
1817 // Early out if mNode is NULL
1823 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1825 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1826 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1827 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1829 // Compute the radius is not needed, square radius it's enough.
1830 const Vector3& size( mNode->GetSize( bufferIndex ) );
1832 // Scale the sphere.
1833 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1835 const float width = size.width * scale.width;
1836 const float height = size.height * scale.height;
1838 float squareSphereRadius = 0.5f * ( width * width + height * height );
1840 float a = rayDir.Dot( rayDir ); // a
1841 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1842 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1844 return ( b2 * b2 - a * c ) >= 0.f;
1847 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector2& hitPointLocal, float& distance ) const
1851 if( OnStage() && NULL != mNode )
1853 // Transforms the ray to the local reference system.
1854 // Calculate the inverse of Model matrix
1855 Matrix invModelMatrix( false/*don't init*/);
1857 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1858 invModelMatrix = mNode->GetWorldMatrix(0);
1859 invModelMatrix.Invert();
1861 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1862 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1864 // Test with the actor's XY plane (Normal = 0 0 1 1).
1866 float a = -rayOriginLocal.z;
1867 float b = rayDirLocal.z;
1869 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1871 // Ray travels distance * rayDirLocal to intersect with plane.
1874 const Vector3& size = mNode->GetSize( bufferIndex );
1876 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1877 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1879 // Test with the actor's geometry.
1880 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1887 void Actor::SetLeaveRequired( bool required )
1889 mLeaveRequired = required;
1892 bool Actor::GetLeaveRequired() const
1894 return mLeaveRequired;
1897 void Actor::SetKeyboardFocusable( bool focusable )
1899 mKeyboardFocusable = focusable;
1902 bool Actor::IsKeyboardFocusable() const
1904 return mKeyboardFocusable;
1907 bool Actor::GetTouchRequired() const
1909 return !mTouchedSignal.Empty() || !mTouchSignal.Empty() || mDerivedRequiresTouch;
1912 bool Actor::GetHoverRequired() const
1914 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1917 bool Actor::GetWheelEventRequired() const
1919 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1922 bool Actor::IsHittable() const
1924 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1927 ActorGestureData& Actor::GetGestureData()
1929 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1930 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1931 if( NULL == mGestureData )
1933 mGestureData = new ActorGestureData;
1935 return *mGestureData;
1938 bool Actor::IsGestureRequred( Gesture::Type type ) const
1940 return mGestureData && mGestureData->IsGestureRequred( type );
1943 bool Actor::EmitTouchEventSignal( const TouchEvent& event, const Dali::TouchData& touch )
1945 bool consumed = false;
1947 if( !mTouchSignal.Empty() )
1949 Dali::Actor handle( this );
1950 consumed = mTouchSignal.Emit( handle, touch );
1953 if( !mTouchedSignal.Empty() )
1955 Dali::Actor handle( this );
1956 consumed |= mTouchedSignal.Emit( handle, event );
1961 // Notification for derived classes
1962 consumed = OnTouchEvent( event ); // TODO
1968 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1970 bool consumed = false;
1972 if( !mHoveredSignal.Empty() )
1974 Dali::Actor handle( this );
1975 consumed = mHoveredSignal.Emit( handle, event );
1980 // Notification for derived classes
1981 consumed = OnHoverEvent( event );
1987 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1989 bool consumed = false;
1991 if( !mWheelEventSignal.Empty() )
1993 Dali::Actor handle( this );
1994 consumed = mWheelEventSignal.Emit( handle, event );
1999 // Notification for derived classes
2000 consumed = OnWheelEvent( event );
2006 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
2008 if( ! mVisibilityChangedSignal.Empty() )
2010 Dali::Actor handle( this );
2011 mVisibilityChangedSignal.Emit( handle, visible, type );
2015 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
2017 return mTouchedSignal;
2020 Dali::Actor::TouchDataSignalType& Actor::TouchSignal()
2022 return mTouchSignal;
2025 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
2027 return mHoveredSignal;
2030 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
2032 return mWheelEventSignal;
2035 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
2037 return mOnStageSignal;
2040 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
2042 return mOffStageSignal;
2045 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
2047 return mOnRelayoutSignal;
2050 DevelActor::VisibilityChangedSignalType& Actor::VisibilityChangedSignal()
2052 return mVisibilityChangedSignal;
2055 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
2057 bool connected( true );
2058 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
2060 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
2062 actor->TouchedSignal().Connect( tracker, functor );
2064 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
2066 actor->HoveredSignal().Connect( tracker, functor );
2068 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
2070 actor->WheelEventSignal().Connect( tracker, functor );
2072 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
2074 actor->OnStageSignal().Connect( tracker, functor );
2076 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
2078 actor->OffStageSignal().Connect( tracker, functor );
2080 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
2082 actor->OnRelayoutSignal().Connect( tracker, functor );
2084 else if( 0 == signalName.compare( SIGNAL_TOUCH ) )
2086 actor->TouchSignal().Connect( tracker, functor );
2090 // signalName does not match any signal
2097 Actor::Actor( DerivedType derivedType )
2102 mParentOrigin( NULL ),
2103 mAnchorPoint( NULL ),
2104 mRelayoutData( NULL ),
2105 mGestureData( NULL ),
2106 mTargetOrientation( Quaternion::IDENTITY ),
2107 mTargetColor( Color::WHITE ),
2108 mTargetSize( Vector3::ZERO ),
2109 mTargetPosition( Vector3::ZERO ),
2110 mTargetScale( Vector3::ONE ),
2112 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
2116 mIsRoot( ROOT_LAYER == derivedType ),
2117 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2118 mIsOnStage( false ),
2120 mLeaveRequired( false ),
2121 mKeyboardFocusable( false ),
2122 mDerivedRequiresTouch( false ),
2123 mDerivedRequiresHover( false ),
2124 mDerivedRequiresWheelEvent( false ),
2125 mOnStageSignalled( false ),
2126 mInsideOnSizeSet( false ),
2127 mInheritPosition( true ),
2128 mInheritOrientation( true ),
2129 mInheritScale( true ),
2130 mPositionUsesAnchorPoint( true ),
2132 mDrawMode( DrawMode::NORMAL ),
2133 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2134 mColorMode( Node::DEFAULT_COLOR_MODE ),
2135 mClippingMode( ClippingMode::DISABLED )
2139 void Actor::Initialize()
2141 // Node creation, keep raw-pointer to Node for messaging
2142 mNode = CreateNode();
2143 OwnerPointer< SceneGraph::Node > transferOwnership( const_cast< SceneGraph::Node* >( mNode ) );
2144 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), transferOwnership );
2148 GetEventThreadServices().RegisterObject( this );
2153 // Remove mParent pointers from children even if we're destroying core,
2154 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2157 ActorConstIter endIter = mChildren->end();
2158 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2160 (*iter)->SetParent( NULL );
2166 // Guard to allow handle destruction after Core has been destroyed
2167 if( EventThreadServices::IsCoreRunning() )
2171 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2172 mNode = NULL; // Node is about to be destroyed
2175 GetEventThreadServices().UnregisterObject( this );
2178 // Cleanup optional gesture data
2179 delete mGestureData;
2181 // Cleanup optional parent origin and anchor
2182 delete mParentOrigin;
2183 delete mAnchorPoint;
2185 // Delete optional relayout data
2188 delete mRelayoutData;
2192 void Actor::ConnectToStage( unsigned int parentDepth )
2194 // This container is used instead of walking the Actor hierarchy.
2195 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
2196 ActorContainer connectionList;
2198 StagePtr stage = Stage::GetCurrent();
2201 stage->RequestRebuildDepthTree();
2204 // This stage is atomic i.e. not interrupted by user callbacks.
2205 RecursiveConnectToStage( connectionList, parentDepth + 1 );
2207 // Notify applications about the newly connected actors.
2208 const ActorIter endIter = connectionList.end();
2209 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2211 (*iter)->NotifyStageConnection();
2217 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth )
2219 DALI_ASSERT_ALWAYS( !OnStage() );
2224 ConnectToSceneGraph();
2226 // Notification for internal derived classes
2227 OnStageConnectionInternal();
2229 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2230 connectionList.push_back( ActorPtr( this ) );
2232 // Recursively connect children
2235 ActorConstIter endIter = mChildren->end();
2236 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2238 (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
2244 * This method is called when the Actor is connected to the Stage.
2245 * The parent must have added its Node to the scene-graph.
2246 * The child must connect its Node to the parent's Node.
2247 * This is recursive; the child calls ConnectToStage() for its children.
2249 void Actor::ConnectToSceneGraph()
2251 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2255 // Reparent Node in next Update
2256 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode );
2259 // Request relayout on all actors that are added to the scenegraph
2262 // Notification for Object::Observers
2266 void Actor::NotifyStageConnection()
2268 // Actors can be removed (in a callback), before the on-stage stage is reported.
2269 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2270 if( OnStage() && !mOnStageSignalled )
2272 // Notification for external (CustomActor) derived classes
2273 OnStageConnectionExternal( mDepth );
2275 if( !mOnStageSignal.Empty() )
2277 Dali::Actor handle( this );
2278 mOnStageSignal.Emit( handle );
2281 // Guard against Remove during callbacks
2284 mOnStageSignalled = true; // signal required next time Actor is removed
2289 void Actor::DisconnectFromStage()
2291 // This container is used instead of walking the Actor hierachy.
2292 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2293 ActorContainer disconnectionList;
2295 StagePtr stage = Stage::GetCurrent();
2298 stage->RequestRebuildDepthTree();
2301 // This stage is atomic i.e. not interrupted by user callbacks
2302 RecursiveDisconnectFromStage( disconnectionList );
2304 // Notify applications about the newly disconnected actors.
2305 const ActorIter endIter = disconnectionList.end();
2306 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2308 (*iter)->NotifyStageDisconnection();
2312 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2314 DALI_ASSERT_ALWAYS( OnStage() );
2316 // Recursively disconnect children
2319 ActorConstIter endIter = mChildren->end();
2320 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2322 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2326 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2327 disconnectionList.push_back( ActorPtr( this ) );
2329 // Notification for internal derived classes
2330 OnStageDisconnectionInternal();
2332 DisconnectFromSceneGraph();
2338 * This method is called by an actor or its parent, before a node removal message is sent.
2339 * This is recursive; the child calls DisconnectFromStage() for its children.
2341 void Actor::DisconnectFromSceneGraph()
2343 // Notification for Object::Observers
2344 OnSceneObjectRemove();
2347 void Actor::NotifyStageDisconnection()
2349 // Actors can be added (in a callback), before the off-stage state is reported.
2350 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2351 // only do this step if there is a stage, i.e. Core is not being shut down
2352 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2354 // Notification for external (CustomeActor) derived classes
2355 OnStageDisconnectionExternal();
2357 if( !mOffStageSignal.Empty() )
2359 Dali::Actor handle( this );
2360 mOffStageSignal.Emit( handle );
2363 // Guard against Add during callbacks
2366 mOnStageSignalled = false; // signal required next time Actor is added
2371 bool Actor::IsNodeConnected() const
2373 bool connected( false );
2375 if( OnStage() && ( NULL != mNode ) )
2377 if( IsRoot() || mNode->GetParent() )
2386 // This method generates the depth tree using the recursive function below,
2387 // then walks the tree and sets a depth index based on traversal order. It
2388 // sends a single message to update manager to update all the actor's nodes in this
2389 // tree with the depth index. The sceneGraphNodeDepths vector's elements are ordered
2390 // by depth, and could be used to reduce sorting in the update thread.
2391 void Actor::RebuildDepthTree()
2393 DALI_LOG_TIMER_START(depthTimer);
2395 DepthNodeMemoryPool nodeMemoryPool;
2396 ActorDepthTreeNode* rootNode = new (nodeMemoryPool.AllocateRaw()) ActorDepthTreeNode( this, mSiblingOrder );
2398 int actorCount = BuildDepthTree( nodeMemoryPool, rootNode );
2400 // Vector of scene-graph nodes and their depths to send to UpdateManager
2401 // in a single message
2402 OwnerPointer< SceneGraph::NodeDepths > sceneGraphNodeDepths = new SceneGraph::NodeDepths(actorCount);
2404 // Traverse depth tree and set mSortedDepth on each actor and scenegraph node
2405 uint32_t sortOrder = 1u; // Don't start at zero, as visual depth can be negative
2406 ActorDepthTreeNode* currentNode = rootNode;
2407 bool firstVisit = true;
2408 while( currentNode != rootNode || firstVisit)
2412 // Visit node, performing action
2413 for( std::vector<Actor*>::iterator iter = currentNode->mActors.begin(); iter != currentNode->mActors.end(); ++iter )
2415 (*iter)->mSortedDepth = sortOrder * DevelLayer::SIBLING_ORDER_MULTIPLIER;
2416 sceneGraphNodeDepths->Add( const_cast<SceneGraph::Node*>((*iter)->mNode), (*iter)->mSortedDepth );
2421 if( currentNode->mFirstChildNode )
2423 currentNode = currentNode->mFirstChildNode;
2425 else // leaf node, goto next sibling, or return up tree.
2427 bool breakout=false;
2428 while( ! currentNode->mNextSiblingNode )
2430 if( currentNode == rootNode ) // If we get to root of tree, stop
2435 currentNode = currentNode->mParentNode;
2442 currentNode = currentNode->mNextSiblingNode;
2446 SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths );
2447 DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree create time: ");
2451 * Structure to store the actor's associated node in the depth tree for child
2454 struct ActorNodePair
2457 ActorDepthTreeNode* node;
2458 ActorNodePair( Actor* actor, ActorDepthTreeNode* node )
2466 * Descend actor tree, building a depth tree based on actor's sibling order.
2467 * Actors with the same sibling order share the same depth tree. Siblings
2468 * in the depth tree are ordered by actor's sibling order.
2470 * An actor tree like this:
2477 * A(SO:1) B(SO:2) C(SO:1)
2480 * D(SO:0) E(SO:0) F(SO:0) G(SO:1) H(SO:0)
2482 * will end up as a depth tree like this:
2484 * RootNode [ Root ] -> NULL
2487 * Node [ A, C ] ------------------------> Node [ B ] -> NULL
2490 * Node [ D, E, H ] -> Node [ G ] -> NULL Node [ F ] -> NULL
2495 * (All nodes also point to their parents to enable storage free traversal)
2497 int Actor::BuildDepthTree( DepthNodeMemoryPool& nodeMemoryPool, ActorDepthTreeNode* node )
2499 int treeCount=1; // Count self and children
2501 // Create/add to children of this node
2504 std::vector<ActorNodePair> storedChildren;
2505 storedChildren.reserve( mChildren->size() );
2507 for( ActorContainer::iterator it = mChildren->begin(); it != mChildren->end(); ++it )
2509 Actor* childActor = (*it).Get();
2510 if( childActor->IsLayer() )
2512 Layer* layer = static_cast<Layer*>(childActor);
2513 if( layer->GetBehavior() == Dali::Layer::LAYER_3D )
2515 // Ignore this actor and children.
2520 // If no existing depth node children
2521 if( node->mFirstChildNode == NULL )
2523 node->mFirstChildNode = new (nodeMemoryPool.AllocateRaw()) ActorDepthTreeNode( childActor, childActor->mSiblingOrder );
2524 node->mFirstChildNode->mParentNode = node;
2525 storedChildren.push_back(ActorNodePair( childActor, node->mFirstChildNode ));
2527 else // find child node with matching sibling order (insertion sort)
2529 bool addedChildActor = false;
2531 // depth tree child nodes ordered by sibling order
2532 ActorDepthTreeNode* lastNode = NULL;
2533 for( ActorDepthTreeNode* childNode = node->mFirstChildNode; childNode != NULL; childNode = childNode->mNextSiblingNode )
2535 uint16_t actorSiblingOrder = childActor->mSiblingOrder;
2536 uint16_t currentSiblingOrder = childNode->GetSiblingOrder();
2538 if( actorSiblingOrder == currentSiblingOrder )
2540 // Don't need a new depth node, add to existing node
2541 childNode->AddActor( childActor );
2542 storedChildren.push_back(ActorNodePair( childActor, childNode ));
2543 addedChildActor = true;
2546 else if( actorSiblingOrder < currentSiblingOrder )
2550 lastNode = childNode;
2553 // No matching sibling order - create new node and insert into sibling list
2554 if( !addedChildActor )
2556 ActorDepthTreeNode* newNode = new (nodeMemoryPool.AllocateRaw()) ActorDepthTreeNode( childActor, childActor->mSiblingOrder );
2558 newNode->mParentNode = node;
2559 storedChildren.push_back(ActorNodePair( childActor, newNode ));
2561 if( lastNode == NULL ) // Insert at start of siblings
2563 ActorDepthTreeNode* nextNode = node->mFirstChildNode;
2564 node->mFirstChildNode = newNode;
2565 newNode->mNextSiblingNode = nextNode;
2567 else // insert into siblings after last node
2569 newNode->mNextSiblingNode = lastNode->mNextSiblingNode;
2570 lastNode->mNextSiblingNode = newNode;
2576 // Order of descent doesn't matter; we're using insertion to sort.
2577 for( std::vector<ActorNodePair>::iterator iter = storedChildren.begin(); iter != storedChildren.end(); ++iter )
2579 treeCount += iter->actor->BuildDepthTree( nodeMemoryPool, iter->node );
2585 unsigned int Actor::GetDefaultPropertyCount() const
2587 return DEFAULT_PROPERTY_COUNT;
2590 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2592 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2594 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2596 indices.PushBack( i );
2600 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2602 if( index < DEFAULT_PROPERTY_COUNT )
2604 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2610 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2612 Property::Index index = Property::INVALID_INDEX;
2614 // Look for name in default properties
2615 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2617 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2618 if( 0 == name.compare( property->name ) )
2628 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2630 if( index < DEFAULT_PROPERTY_COUNT )
2632 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2638 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2640 if( index < DEFAULT_PROPERTY_COUNT )
2642 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2648 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2650 if( index < DEFAULT_PROPERTY_COUNT )
2652 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2658 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2660 if( index < DEFAULT_PROPERTY_COUNT )
2662 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2665 // index out of range...return Property::NONE
2666 return Property::NONE;
2669 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2673 case Dali::Actor::Property::PARENT_ORIGIN:
2675 Property::Type type = property.GetType();
2676 if( type == Property::VECTOR3 )
2678 SetParentOrigin( property.Get< Vector3 >() );
2680 else if ( type == Property::STRING )
2682 std::string parentOriginString;
2683 property.Get( parentOriginString );
2684 Vector3 parentOrigin;
2685 if( GetParentOriginConstant( parentOriginString, parentOrigin ) )
2687 SetParentOrigin( parentOrigin );
2693 case Dali::Actor::Property::PARENT_ORIGIN_X:
2695 SetParentOriginX( property.Get< float >() );
2699 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2701 SetParentOriginY( property.Get< float >() );
2705 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2707 SetParentOriginZ( property.Get< float >() );
2711 case Dali::Actor::Property::ANCHOR_POINT:
2713 Property::Type type = property.GetType();
2714 if( type == Property::VECTOR3 )
2716 SetAnchorPoint( property.Get< Vector3 >() );
2718 else if ( type == Property::STRING )
2720 std::string anchorPointString;
2721 property.Get( anchorPointString );
2723 if( GetAnchorPointConstant( anchorPointString, anchor ) )
2725 SetAnchorPoint( anchor );
2731 case Dali::Actor::Property::ANCHOR_POINT_X:
2733 SetAnchorPointX( property.Get< float >() );
2737 case Dali::Actor::Property::ANCHOR_POINT_Y:
2739 SetAnchorPointY( property.Get< float >() );
2743 case Dali::Actor::Property::ANCHOR_POINT_Z:
2745 SetAnchorPointZ( property.Get< float >() );
2749 case Dali::Actor::Property::SIZE:
2751 SetSize( property.Get< Vector3 >() );
2755 case Dali::Actor::Property::SIZE_WIDTH:
2757 SetWidth( property.Get< float >() );
2761 case Dali::Actor::Property::SIZE_HEIGHT:
2763 SetHeight( property.Get< float >() );
2767 case Dali::Actor::Property::SIZE_DEPTH:
2769 SetDepth( property.Get< float >() );
2773 case Dali::Actor::Property::POSITION:
2775 SetPosition( property.Get< Vector3 >() );
2779 case Dali::Actor::Property::POSITION_X:
2781 SetX( property.Get< float >() );
2785 case Dali::Actor::Property::POSITION_Y:
2787 SetY( property.Get< float >() );
2791 case Dali::Actor::Property::POSITION_Z:
2793 SetZ( property.Get< float >() );
2797 case Dali::Actor::Property::ORIENTATION:
2799 SetOrientation( property.Get< Quaternion >() );
2803 case Dali::Actor::Property::SCALE:
2805 SetScale( property.Get< Vector3 >() );
2809 case Dali::Actor::Property::SCALE_X:
2811 SetScaleX( property.Get< float >() );
2815 case Dali::Actor::Property::SCALE_Y:
2817 SetScaleY( property.Get< float >() );
2821 case Dali::Actor::Property::SCALE_Z:
2823 SetScaleZ( property.Get< float >() );
2827 case Dali::Actor::Property::VISIBLE:
2829 SetVisible( property.Get< bool >() );
2833 case Dali::Actor::Property::COLOR:
2835 SetColor( property.Get< Vector4 >() );
2839 case Dali::Actor::Property::COLOR_RED:
2841 SetColorRed( property.Get< float >() );
2845 case Dali::Actor::Property::COLOR_GREEN:
2847 SetColorGreen( property.Get< float >() );
2851 case Dali::Actor::Property::COLOR_BLUE:
2853 SetColorBlue( property.Get< float >() );
2857 case Dali::Actor::Property::COLOR_ALPHA:
2858 case Dali::DevelActor::Property::OPACITY:
2861 if( property.Get( value ) )
2863 SetOpacity( value );
2868 case Dali::Actor::Property::NAME:
2870 SetName( property.Get< std::string >() );
2874 case Dali::Actor::Property::SENSITIVE:
2876 SetSensitive( property.Get< bool >() );
2880 case Dali::Actor::Property::LEAVE_REQUIRED:
2882 SetLeaveRequired( property.Get< bool >() );
2886 case Dali::Actor::Property::INHERIT_POSITION:
2888 SetInheritPosition( property.Get< bool >() );
2892 case Dali::Actor::Property::INHERIT_ORIENTATION:
2894 SetInheritOrientation( property.Get< bool >() );
2898 case Dali::Actor::Property::INHERIT_SCALE:
2900 SetInheritScale( property.Get< bool >() );
2904 case Dali::Actor::Property::COLOR_MODE:
2906 ColorMode mode = mColorMode;
2907 if ( Scripting::GetEnumerationProperty< ColorMode >( property, COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT, mode ) )
2909 SetColorMode( mode );
2914 case Dali::Actor::Property::POSITION_INHERITANCE:
2916 PositionInheritanceMode mode = mPositionInheritanceMode;
2917 if( Scripting::GetEnumerationProperty< PositionInheritanceMode >( property, POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT, mode ) )
2919 SetPositionInheritanceMode( mode );
2924 case Dali::Actor::Property::DRAW_MODE:
2926 DrawMode::Type mode = mDrawMode;
2927 if( Scripting::GetEnumerationProperty< DrawMode::Type >( property, DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT, mode ) )
2929 SetDrawMode( mode );
2934 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2936 SetSizeModeFactor( property.Get< Vector3 >() );
2940 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2942 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
2943 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2945 SetResizePolicy( type, Dimension::WIDTH );
2950 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2952 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
2953 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2955 SetResizePolicy( type, Dimension::HEIGHT );
2960 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2962 SizeScalePolicy::Type type;
2963 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT, type ) )
2965 SetSizeScalePolicy( type );
2970 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2972 if( property.Get< bool >() )
2974 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2979 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2981 if( property.Get< bool >() )
2983 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2988 case Dali::Actor::Property::PADDING:
2990 Vector4 padding = property.Get< Vector4 >();
2991 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2992 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2996 case Dali::Actor::Property::MINIMUM_SIZE:
2998 Vector2 size = property.Get< Vector2 >();
2999 SetMinimumSize( size.x, Dimension::WIDTH );
3000 SetMinimumSize( size.y, Dimension::HEIGHT );
3004 case Dali::Actor::Property::MAXIMUM_SIZE:
3006 Vector2 size = property.Get< Vector2 >();
3007 SetMaximumSize( size.x, Dimension::WIDTH );
3008 SetMaximumSize( size.y, Dimension::HEIGHT );
3012 case Dali::DevelActor::Property::SIBLING_ORDER:
3016 if( property.Get( value ) )
3018 if( static_cast<unsigned int>(value) != mSiblingOrder )
3020 SetSiblingOrder( value );
3026 case Dali::Actor::Property::CLIPPING_MODE:
3028 ClippingMode::Type convertedValue = mClippingMode;
3029 if( Scripting::GetEnumerationProperty< ClippingMode::Type >( property, CLIPPING_MODE_TABLE, CLIPPING_MODE_TABLE_COUNT, convertedValue ) )
3031 mClippingMode = convertedValue;
3034 SetClippingModeMessage( GetEventThreadServices(), *mNode, mClippingMode );
3040 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
3043 if( property.Get( value ) && value != mPositionUsesAnchorPoint )
3045 mPositionUsesAnchorPoint = value;
3048 SetPositionUsesAnchorPointMessage( GetEventThreadServices(), *mNode, mPositionUsesAnchorPoint );
3056 // this can happen in the case of a non-animatable default property so just do nothing
3062 // TODO: This method needs to be removed
3063 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
3065 switch( entry.GetType() )
3067 case Property::BOOLEAN:
3069 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
3070 DALI_ASSERT_DEBUG( NULL != property );
3072 // property is being used in a separate thread; queue a message to set the property
3073 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
3078 case Property::INTEGER:
3080 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
3081 DALI_ASSERT_DEBUG( NULL != property );
3083 // property is being used in a separate thread; queue a message to set the property
3084 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
3089 case Property::FLOAT:
3091 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
3092 DALI_ASSERT_DEBUG( NULL != property );
3094 // property is being used in a separate thread; queue a message to set the property
3095 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
3100 case Property::VECTOR2:
3102 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
3103 DALI_ASSERT_DEBUG( NULL != property );
3105 // property is being used in a separate thread; queue a message to set the property
3106 if(entry.componentIndex == 0)
3108 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
3110 else if(entry.componentIndex == 1)
3112 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
3116 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
3122 case Property::VECTOR3:
3124 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
3125 DALI_ASSERT_DEBUG( NULL != property );
3127 // property is being used in a separate thread; queue a message to set the property
3128 if(entry.componentIndex == 0)
3130 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
3132 else if(entry.componentIndex == 1)
3134 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
3136 else if(entry.componentIndex == 2)
3138 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
3142 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
3148 case Property::VECTOR4:
3150 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
3151 DALI_ASSERT_DEBUG( NULL != property );
3153 // property is being used in a separate thread; queue a message to set the property
3154 if(entry.componentIndex == 0)
3156 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
3158 else if(entry.componentIndex == 1)
3160 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
3162 else if(entry.componentIndex == 2)
3164 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
3166 else if(entry.componentIndex == 3)
3168 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
3172 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3178 case Property::ROTATION:
3180 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3181 DALI_ASSERT_DEBUG( NULL != property );
3183 // property is being used in a separate thread; queue a message to set the property
3184 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3189 case Property::MATRIX:
3191 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3192 DALI_ASSERT_DEBUG( NULL != property );
3194 // property is being used in a separate thread; queue a message to set the property
3195 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3200 case Property::MATRIX3:
3202 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3203 DALI_ASSERT_DEBUG( NULL != property );
3205 // property is being used in a separate thread; queue a message to set the property
3206 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3213 // nothing to do for other types
3218 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3220 Property::Value value;
3222 if( ! GetCachedPropertyValue( index, value ) )
3224 // If property value is not stored in the event-side, then it must be a scene-graph only property
3225 GetCurrentPropertyValue( index, value );
3231 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
3233 Property::Value value;
3235 if( ! GetCurrentPropertyValue( index, value ) )
3237 // If unable to retrieve scene-graph property value, then it must be an event-side only property
3238 GetCachedPropertyValue( index, value );
3244 void Actor::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
3246 switch( animationType )
3249 case Animation::BETWEEN:
3253 case Dali::Actor::Property::SIZE:
3255 if( value.Get( mTargetSize ) )
3257 // Notify deriving classes
3258 OnSizeAnimation( animation, mTargetSize );
3263 case Dali::Actor::Property::SIZE_WIDTH:
3265 if( value.Get( mTargetSize.width ) )
3267 // Notify deriving classes
3268 OnSizeAnimation( animation, mTargetSize );
3273 case Dali::Actor::Property::SIZE_HEIGHT:
3275 if( value.Get( mTargetSize.height ) )
3277 // Notify deriving classes
3278 OnSizeAnimation( animation, mTargetSize );
3283 case Dali::Actor::Property::SIZE_DEPTH:
3285 if( value.Get( mTargetSize.depth ) )
3287 // Notify deriving classes
3288 OnSizeAnimation( animation, mTargetSize );
3293 case Dali::Actor::Property::POSITION:
3295 value.Get( mTargetPosition );
3299 case Dali::Actor::Property::POSITION_X:
3301 value.Get( mTargetPosition.x );
3305 case Dali::Actor::Property::POSITION_Y:
3307 value.Get( mTargetPosition.y );
3311 case Dali::Actor::Property::POSITION_Z:
3313 value.Get( mTargetPosition.z );
3317 case Dali::Actor::Property::ORIENTATION:
3319 value.Get( mTargetOrientation );
3323 case Dali::Actor::Property::SCALE:
3325 value.Get( mTargetScale );
3329 case Dali::Actor::Property::SCALE_X:
3331 value.Get( mTargetScale.x );
3335 case Dali::Actor::Property::SCALE_Y:
3337 value.Get( mTargetScale.y );
3341 case Dali::Actor::Property::SCALE_Z:
3343 value.Get( mTargetScale.z );
3347 case Dali::Actor::Property::VISIBLE:
3349 SetVisibleInternal( value.Get< bool >(), SendMessage::FALSE );
3353 case Dali::Actor::Property::COLOR:
3355 value.Get( mTargetColor );
3359 case Dali::Actor::Property::COLOR_RED:
3361 value.Get( mTargetColor.r );
3365 case Dali::Actor::Property::COLOR_GREEN:
3367 value.Get( mTargetColor.g );
3371 case Dali::Actor::Property::COLOR_BLUE:
3373 value.Get( mTargetColor.b );
3377 case Dali::Actor::Property::COLOR_ALPHA:
3378 case Dali::DevelActor::Property::OPACITY:
3380 value.Get( mTargetColor.a );
3386 // Not an animatable property. Do nothing.
3397 case Dali::Actor::Property::SIZE:
3399 if( AdjustValue< Vector3 >( mTargetSize, value ) )
3401 // Notify deriving classes
3402 OnSizeAnimation( animation, mTargetSize );
3407 case Dali::Actor::Property::SIZE_WIDTH:
3409 if( AdjustValue< float >( mTargetSize.width, value ) )
3411 // Notify deriving classes
3412 OnSizeAnimation( animation, mTargetSize );
3417 case Dali::Actor::Property::SIZE_HEIGHT:
3419 if( AdjustValue< float >( mTargetSize.height, value ) )
3421 // Notify deriving classes
3422 OnSizeAnimation( animation, mTargetSize );
3427 case Dali::Actor::Property::SIZE_DEPTH:
3429 if( AdjustValue< float >( mTargetSize.depth, value ) )
3431 // Notify deriving classes
3432 OnSizeAnimation( animation, mTargetSize );
3437 case Dali::Actor::Property::POSITION:
3439 AdjustValue< Vector3 >( mTargetPosition, value );
3443 case Dali::Actor::Property::POSITION_X:
3445 AdjustValue< float >( mTargetPosition.x, value );
3449 case Dali::Actor::Property::POSITION_Y:
3451 AdjustValue< float >( mTargetPosition.y, value );
3455 case Dali::Actor::Property::POSITION_Z:
3457 AdjustValue< float >( mTargetPosition.z, value );
3461 case Dali::Actor::Property::ORIENTATION:
3463 Quaternion relativeValue;
3464 if( value.Get( relativeValue ) )
3466 mTargetOrientation *= relativeValue;
3471 case Dali::Actor::Property::SCALE:
3473 AdjustValue< Vector3 >( mTargetScale, value );
3477 case Dali::Actor::Property::SCALE_X:
3479 AdjustValue< float >( mTargetScale.x, value );
3483 case Dali::Actor::Property::SCALE_Y:
3485 AdjustValue< float >( mTargetScale.y, value );
3489 case Dali::Actor::Property::SCALE_Z:
3491 AdjustValue< float >( mTargetScale.z, value );
3495 case Dali::Actor::Property::VISIBLE:
3497 bool relativeValue = false;
3498 if( value.Get( relativeValue ) )
3500 bool visible = mVisible || relativeValue;
3501 SetVisibleInternal( visible, SendMessage::FALSE );
3506 case Dali::Actor::Property::COLOR:
3508 AdjustValue< Vector4 >( mTargetColor, value );
3512 case Dali::Actor::Property::COLOR_RED:
3514 AdjustValue< float >( mTargetColor.r, value );
3518 case Dali::Actor::Property::COLOR_GREEN:
3520 AdjustValue< float >( mTargetColor.g, value );
3524 case Dali::Actor::Property::COLOR_BLUE:
3526 AdjustValue< float >( mTargetColor.b, value );
3530 case Dali::Actor::Property::COLOR_ALPHA:
3531 case Dali::DevelActor::Property::OPACITY:
3533 AdjustValue< float >( mTargetColor.a, value );
3539 // Not an animatable property. Do nothing.
3548 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3553 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3555 // This method should only return an object connected to the scene-graph
3556 return OnStage() ? mNode : NULL;
3559 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3561 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3563 const PropertyBase* property( NULL );
3565 // This method should only return a property of an object connected to the scene-graph
3571 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3573 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3574 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3576 property = animatable->GetSceneGraphProperty();
3578 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3579 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3581 CustomPropertyMetadata* custom = FindCustomProperty( index );
3582 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3584 property = custom->GetSceneGraphProperty();
3586 else if( NULL != mNode )
3590 case Dali::Actor::Property::SIZE:
3591 property = &mNode->mSize;
3594 case Dali::Actor::Property::SIZE_WIDTH:
3595 property = &mNode->mSize;
3598 case Dali::Actor::Property::SIZE_HEIGHT:
3599 property = &mNode->mSize;
3602 case Dali::Actor::Property::SIZE_DEPTH:
3603 property = &mNode->mSize;
3606 case Dali::Actor::Property::POSITION:
3607 property = &mNode->mPosition;
3610 case Dali::Actor::Property::POSITION_X:
3611 property = &mNode->mPosition;
3614 case Dali::Actor::Property::POSITION_Y:
3615 property = &mNode->mPosition;
3618 case Dali::Actor::Property::POSITION_Z:
3619 property = &mNode->mPosition;
3622 case Dali::Actor::Property::ORIENTATION:
3623 property = &mNode->mOrientation;
3626 case Dali::Actor::Property::SCALE:
3627 property = &mNode->mScale;
3630 case Dali::Actor::Property::SCALE_X:
3631 property = &mNode->mScale;
3634 case Dali::Actor::Property::SCALE_Y:
3635 property = &mNode->mScale;
3638 case Dali::Actor::Property::SCALE_Z:
3639 property = &mNode->mScale;
3642 case Dali::Actor::Property::VISIBLE:
3643 property = &mNode->mVisible;
3646 case Dali::Actor::Property::COLOR:
3647 property = &mNode->mColor;
3650 case Dali::Actor::Property::COLOR_RED:
3651 property = &mNode->mColor;
3654 case Dali::Actor::Property::COLOR_GREEN:
3655 property = &mNode->mColor;
3658 case Dali::Actor::Property::COLOR_BLUE:
3659 property = &mNode->mColor;
3662 case Dali::Actor::Property::COLOR_ALPHA:
3663 case Dali::DevelActor::Property::OPACITY:
3664 property = &mNode->mColor;
3675 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3677 const PropertyInputImpl* property( NULL );
3679 // This method should only return a property of an object connected to the scene-graph
3685 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3687 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3688 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3690 property = animatable->GetSceneGraphProperty();
3692 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3693 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3695 CustomPropertyMetadata* custom = FindCustomProperty( index );
3696 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3697 property = custom->GetSceneGraphProperty();
3699 else if( NULL != mNode )
3703 case Dali::Actor::Property::PARENT_ORIGIN:
3704 property = &mNode->mParentOrigin;
3707 case Dali::Actor::Property::PARENT_ORIGIN_X:
3708 property = &mNode->mParentOrigin;
3711 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3712 property = &mNode->mParentOrigin;
3715 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3716 property = &mNode->mParentOrigin;
3719 case Dali::Actor::Property::ANCHOR_POINT:
3720 property = &mNode->mAnchorPoint;
3723 case Dali::Actor::Property::ANCHOR_POINT_X:
3724 property = &mNode->mAnchorPoint;
3727 case Dali::Actor::Property::ANCHOR_POINT_Y:
3728 property = &mNode->mAnchorPoint;
3731 case Dali::Actor::Property::ANCHOR_POINT_Z:
3732 property = &mNode->mAnchorPoint;
3735 case Dali::Actor::Property::SIZE:
3736 property = &mNode->mSize;
3739 case Dali::Actor::Property::SIZE_WIDTH:
3740 property = &mNode->mSize;
3743 case Dali::Actor::Property::SIZE_HEIGHT:
3744 property = &mNode->mSize;
3747 case Dali::Actor::Property::SIZE_DEPTH:
3748 property = &mNode->mSize;
3751 case Dali::Actor::Property::POSITION:
3752 property = &mNode->mPosition;
3755 case Dali::Actor::Property::POSITION_X:
3756 property = &mNode->mPosition;
3759 case Dali::Actor::Property::POSITION_Y:
3760 property = &mNode->mPosition;
3763 case Dali::Actor::Property::POSITION_Z:
3764 property = &mNode->mPosition;
3767 case Dali::Actor::Property::WORLD_POSITION:
3768 property = &mNode->mWorldPosition;
3771 case Dali::Actor::Property::WORLD_POSITION_X:
3772 property = &mNode->mWorldPosition;
3775 case Dali::Actor::Property::WORLD_POSITION_Y:
3776 property = &mNode->mWorldPosition;
3779 case Dali::Actor::Property::WORLD_POSITION_Z:
3780 property = &mNode->mWorldPosition;
3783 case Dali::Actor::Property::ORIENTATION:
3784 property = &mNode->mOrientation;
3787 case Dali::Actor::Property::WORLD_ORIENTATION:
3788 property = &mNode->mWorldOrientation;
3791 case Dali::Actor::Property::SCALE:
3792 property = &mNode->mScale;
3795 case Dali::Actor::Property::SCALE_X:
3796 property = &mNode->mScale;
3799 case Dali::Actor::Property::SCALE_Y:
3800 property = &mNode->mScale;
3803 case Dali::Actor::Property::SCALE_Z:
3804 property = &mNode->mScale;
3807 case Dali::Actor::Property::WORLD_SCALE:
3808 property = &mNode->mWorldScale;
3811 case Dali::Actor::Property::VISIBLE:
3812 property = &mNode->mVisible;
3815 case Dali::Actor::Property::COLOR:
3816 property = &mNode->mColor;
3819 case Dali::Actor::Property::COLOR_RED:
3820 property = &mNode->mColor;
3823 case Dali::Actor::Property::COLOR_GREEN:
3824 property = &mNode->mColor;
3827 case Dali::Actor::Property::COLOR_BLUE:
3828 property = &mNode->mColor;
3831 case Dali::Actor::Property::COLOR_ALPHA:
3832 case Dali::DevelActor::Property::OPACITY:
3834 property = &mNode->mColor;
3838 case Dali::Actor::Property::WORLD_COLOR:
3839 property = &mNode->mWorldColor;
3842 case Dali::Actor::Property::WORLD_MATRIX:
3843 property = &mNode->mWorldMatrix;
3854 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3856 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3858 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3860 // check whether the animatable property is registered already, if not then register one.
3861 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3862 if( animatableProperty )
3864 componentIndex = animatableProperty->componentIndex;
3871 case Dali::Actor::Property::PARENT_ORIGIN_X:
3872 case Dali::Actor::Property::ANCHOR_POINT_X:
3873 case Dali::Actor::Property::SIZE_WIDTH:
3874 case Dali::Actor::Property::POSITION_X:
3875 case Dali::Actor::Property::WORLD_POSITION_X:
3876 case Dali::Actor::Property::SCALE_X:
3877 case Dali::Actor::Property::COLOR_RED:
3883 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3884 case Dali::Actor::Property::ANCHOR_POINT_Y:
3885 case Dali::Actor::Property::SIZE_HEIGHT:
3886 case Dali::Actor::Property::POSITION_Y:
3887 case Dali::Actor::Property::WORLD_POSITION_Y:
3888 case Dali::Actor::Property::SCALE_Y:
3889 case Dali::Actor::Property::COLOR_GREEN:
3895 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3896 case Dali::Actor::Property::ANCHOR_POINT_Z:
3897 case Dali::Actor::Property::SIZE_DEPTH:
3898 case Dali::Actor::Property::POSITION_Z:
3899 case Dali::Actor::Property::WORLD_POSITION_Z:
3900 case Dali::Actor::Property::SCALE_Z:
3901 case Dali::Actor::Property::COLOR_BLUE:
3907 case Dali::Actor::Property::COLOR_ALPHA:
3908 case Dali::DevelActor::Property::OPACITY:
3922 return componentIndex;
3925 void Actor::SetParent( Actor* parent )
3929 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3933 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3936 // Instruct each actor to create a corresponding node in the scene graph
3937 ConnectToStage( parent->GetHierarchyDepth() );
3940 // Resolve the name and index for the child properties if any
3941 ResolveChildProperties();
3943 else // parent being set to NULL
3945 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3949 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3952 DALI_ASSERT_ALWAYS( mNode != NULL );
3956 // Disconnect the Node & its children from the scene-graph.
3957 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3960 // Instruct each actor to discard pointers to the scene-graph
3961 DisconnectFromStage();
3966 SceneGraph::Node* Actor::CreateNode() const
3971 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3974 Actor* actor = dynamic_cast< Actor* >( object );
3978 if( 0 == actionName.compare( ACTION_SHOW ) )
3980 actor->SetVisible( true );
3983 else if( 0 == actionName.compare( ACTION_HIDE ) )
3985 actor->SetVisible( false );
3993 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
3995 bool valueSet = true;
3999 case Dali::Actor::Property::PARENT_ORIGIN:
4001 value = GetCurrentParentOrigin();
4005 case Dali::Actor::Property::PARENT_ORIGIN_X:
4007 value = GetCurrentParentOrigin().x;
4011 case Dali::Actor::Property::PARENT_ORIGIN_Y:
4013 value = GetCurrentParentOrigin().y;
4017 case Dali::Actor::Property::PARENT_ORIGIN_Z:
4019 value = GetCurrentParentOrigin().z;
4023 case Dali::Actor::Property::ANCHOR_POINT:
4025 value = GetCurrentAnchorPoint();
4029 case Dali::Actor::Property::ANCHOR_POINT_X:
4031 value = GetCurrentAnchorPoint().x;
4035 case Dali::Actor::Property::ANCHOR_POINT_Y:
4037 value = GetCurrentAnchorPoint().y;
4041 case Dali::Actor::Property::ANCHOR_POINT_Z:
4043 value = GetCurrentAnchorPoint().z;
4047 case Dali::Actor::Property::SIZE:
4049 value = GetTargetSize();
4053 case Dali::Actor::Property::SIZE_WIDTH:
4055 value = GetTargetSize().width;
4059 case Dali::Actor::Property::SIZE_HEIGHT:
4061 value = GetTargetSize().height;
4065 case Dali::Actor::Property::SIZE_DEPTH:
4067 value = GetTargetSize().depth;
4071 case Dali::Actor::Property::POSITION:
4073 value = GetTargetPosition();
4077 case Dali::Actor::Property::POSITION_X:
4079 value = GetTargetPosition().x;
4083 case Dali::Actor::Property::POSITION_Y:
4085 value = GetTargetPosition().y;
4089 case Dali::Actor::Property::POSITION_Z:
4091 value = GetTargetPosition().z;
4095 case Dali::Actor::Property::ORIENTATION:
4097 value = mTargetOrientation;
4101 case Dali::Actor::Property::SCALE:
4103 value = mTargetScale;
4107 case Dali::Actor::Property::SCALE_X:
4109 value = mTargetScale.x;
4113 case Dali::Actor::Property::SCALE_Y:
4115 value = mTargetScale.y;
4119 case Dali::Actor::Property::SCALE_Z:
4121 value = mTargetScale.z;
4125 case Dali::Actor::Property::VISIBLE:
4131 case Dali::Actor::Property::COLOR:
4133 value = mTargetColor;
4137 case Dali::Actor::Property::COLOR_RED:
4139 value = mTargetColor.r;
4143 case Dali::Actor::Property::COLOR_GREEN:
4145 value = mTargetColor.g;
4149 case Dali::Actor::Property::COLOR_BLUE:
4151 value = mTargetColor.b;
4155 case Dali::Actor::Property::COLOR_ALPHA:
4156 case Dali::DevelActor::Property::OPACITY:
4158 value = mTargetColor.a;
4162 case Dali::Actor::Property::NAME:
4168 case Dali::Actor::Property::SENSITIVE:
4170 value = IsSensitive();
4174 case Dali::Actor::Property::LEAVE_REQUIRED:
4176 value = GetLeaveRequired();
4180 case Dali::Actor::Property::INHERIT_POSITION:
4182 value = IsPositionInherited();
4186 case Dali::Actor::Property::INHERIT_ORIENTATION:
4188 value = IsOrientationInherited();
4192 case Dali::Actor::Property::INHERIT_SCALE:
4194 value = IsScaleInherited();
4198 case Dali::Actor::Property::COLOR_MODE:
4200 value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
4204 case Dali::Actor::Property::POSITION_INHERITANCE:
4206 value = Scripting::GetLinearEnumerationName< PositionInheritanceMode >( GetPositionInheritanceMode(), POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT );
4210 case Dali::Actor::Property::DRAW_MODE:
4212 value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
4216 case Dali::Actor::Property::SIZE_MODE_FACTOR:
4218 value = GetSizeModeFactor();
4222 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
4224 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
4228 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
4230 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
4234 case Dali::Actor::Property::SIZE_SCALE_POLICY:
4236 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT );
4240 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
4242 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
4246 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
4248 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
4252 case Dali::Actor::Property::PADDING:
4254 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
4255 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
4256 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
4260 case Dali::Actor::Property::MINIMUM_SIZE:
4262 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
4266 case Dali::Actor::Property::MAXIMUM_SIZE:
4268 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
4272 case Dali::Actor::Property::CLIPPING_MODE:
4274 value = mClippingMode;
4278 case Dali::DevelActor::Property::SIBLING_ORDER:
4280 value = static_cast<int>(mSiblingOrder);
4284 case Dali::DevelActor::Property::SCREEN_POSITION:
4286 value = GetCurrentScreenPosition();
4290 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
4292 value = mPositionUsesAnchorPoint;
4298 // Must be a scene-graph only property
4307 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
4309 bool valueSet = true;
4313 case Dali::Actor::Property::SIZE:
4315 value = GetCurrentSize();
4319 case Dali::Actor::Property::SIZE_WIDTH:
4321 value = GetCurrentSize().width;
4325 case Dali::Actor::Property::SIZE_HEIGHT:
4327 value = GetCurrentSize().height;
4331 case Dali::Actor::Property::SIZE_DEPTH:
4333 value = GetCurrentSize().depth;
4337 case Dali::Actor::Property::POSITION:
4339 value = GetCurrentPosition();
4343 case Dali::Actor::Property::POSITION_X:
4345 value = GetCurrentPosition().x;
4349 case Dali::Actor::Property::POSITION_Y:
4351 value = GetCurrentPosition().y;
4355 case Dali::Actor::Property::POSITION_Z:
4357 value = GetCurrentPosition().z;
4361 case Dali::Actor::Property::WORLD_POSITION:
4363 value = GetCurrentWorldPosition();
4367 case Dali::Actor::Property::WORLD_POSITION_X:
4369 value = GetCurrentWorldPosition().x;
4373 case Dali::Actor::Property::WORLD_POSITION_Y:
4375 value = GetCurrentWorldPosition().y;
4379 case Dali::Actor::Property::WORLD_POSITION_Z:
4381 value = GetCurrentWorldPosition().z;
4385 case Dali::Actor::Property::ORIENTATION:
4387 value = GetCurrentOrientation();
4391 case Dali::Actor::Property::WORLD_ORIENTATION:
4393 value = GetCurrentWorldOrientation();
4397 case Dali::Actor::Property::SCALE:
4399 value = GetCurrentScale();
4403 case Dali::Actor::Property::SCALE_X:
4405 value = GetCurrentScale().x;
4409 case Dali::Actor::Property::SCALE_Y:
4411 value = GetCurrentScale().y;
4415 case Dali::Actor::Property::SCALE_Z:
4417 value = GetCurrentScale().z;
4421 case Dali::Actor::Property::WORLD_SCALE:
4423 value = GetCurrentWorldScale();
4427 case Dali::Actor::Property::COLOR:
4429 value = GetCurrentColor();
4433 case Dali::Actor::Property::COLOR_RED:
4435 value = GetCurrentColor().r;
4439 case Dali::Actor::Property::COLOR_GREEN:
4441 value = GetCurrentColor().g;
4445 case Dali::Actor::Property::COLOR_BLUE:
4447 value = GetCurrentColor().b;
4451 case Dali::Actor::Property::COLOR_ALPHA:
4452 case Dali::DevelActor::Property::OPACITY:
4454 value = GetCurrentColor().a;
4458 case Dali::Actor::Property::WORLD_COLOR:
4460 value = GetCurrentWorldColor();
4464 case Dali::Actor::Property::WORLD_MATRIX:
4466 value = GetCurrentWorldMatrix();
4470 case Dali::Actor::Property::VISIBLE:
4472 value = IsVisible();
4478 // Must be an event-side only property
4487 void Actor::EnsureRelayoutData()
4489 // Assign relayout data.
4490 if( !mRelayoutData )
4492 mRelayoutData = new RelayoutData();
4496 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
4498 // Check if actor is dependent on parent
4499 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4501 if( ( dimension & ( 1 << i ) ) )
4503 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4504 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
4514 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
4516 // Check if actor is dependent on children
4517 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4519 if( ( dimension & ( 1 << i ) ) )
4521 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4522 switch( resizePolicy )
4524 case ResizePolicy::FIT_TO_CHILDREN:
4525 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
4541 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
4543 return Actor::RelayoutDependentOnChildren( dimension );
4546 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
4548 // Check each possible dimension and see if it is dependent on the input one
4549 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4551 if( dimension & ( 1 << i ) )
4553 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
4560 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
4562 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4564 if( dimension & ( 1 << i ) )
4566 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
4571 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
4573 // If more than one dimension is requested, just return the first one found
4574 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4576 if( ( dimension & ( 1 << i ) ) )
4578 return mRelayoutData->negotiatedDimensions[ i ];
4582 return 0.0f; // Default
4585 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
4587 EnsureRelayoutData();
4589 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4591 if( dimension & ( 1 << i ) )
4593 mRelayoutData->dimensionPadding[ i ] = padding;
4598 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4600 if ( mRelayoutData )
4602 // If more than one dimension is requested, just return the first one found
4603 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4605 if( ( dimension & ( 1 << i ) ) )
4607 return mRelayoutData->dimensionPadding[ i ];
4612 return GetDefaultDimensionPadding();
4615 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4617 EnsureRelayoutData();
4619 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4621 if( dimension & ( 1 << i ) )
4623 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4628 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4630 if ( mRelayoutData )
4632 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4634 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4644 float Actor::GetHeightForWidthBase( float width )
4646 float height = 0.0f;
4648 const Vector3 naturalSize = GetNaturalSize();
4649 if( naturalSize.width > 0.0f )
4651 height = naturalSize.height * width / naturalSize.width;
4653 else // we treat 0 as 1:1 aspect ratio
4661 float Actor::GetWidthForHeightBase( float height )
4665 const Vector3 naturalSize = GetNaturalSize();
4666 if( naturalSize.height > 0.0f )
4668 width = naturalSize.width * height / naturalSize.height;
4670 else // we treat 0 as 1:1 aspect ratio
4678 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4680 // Fill to parent, taking size mode factor into account
4681 switch( child.GetResizePolicy( dimension ) )
4683 case ResizePolicy::FILL_TO_PARENT:
4685 return GetLatestSize( dimension );
4688 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4690 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4693 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4695 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4700 return GetLatestSize( dimension );
4705 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4707 // Can be overridden in derived class
4708 return CalculateChildSizeBase( child, dimension );
4711 float Actor::GetHeightForWidth( float width )
4713 // Can be overridden in derived class
4714 return GetHeightForWidthBase( width );
4717 float Actor::GetWidthForHeight( float height )
4719 // Can be overridden in derived class
4720 return GetWidthForHeightBase( height );
4723 float Actor::GetLatestSize( Dimension::Type dimension ) const
4725 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4728 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4730 Vector2 padding = GetPadding( dimension );
4732 return GetLatestSize( dimension ) + padding.x + padding.y;
4735 float Actor::NegotiateFromParent( Dimension::Type dimension )
4737 Actor* parent = GetParent();
4740 Vector2 padding( GetPadding( dimension ) );
4741 Vector2 parentPadding( parent->GetPadding( dimension ) );
4742 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4748 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4750 float maxDimensionPoint = 0.0f;
4752 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4754 ActorPtr child = GetChildAt( i );
4756 if( !child->RelayoutDependentOnParent( dimension ) )
4758 // Calculate the min and max points that the children range across
4759 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
4760 float dimensionSize = child->GetRelayoutSize( dimension );
4761 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4765 return maxDimensionPoint;
4768 float Actor::GetSize( Dimension::Type dimension ) const
4770 return GetDimensionValue( mTargetSize, dimension );
4773 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4775 return GetDimensionValue( GetNaturalSize(), dimension );
4778 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4780 switch( GetResizePolicy( dimension ) )
4782 case ResizePolicy::USE_NATURAL_SIZE:
4784 return GetNaturalSize( dimension );
4787 case ResizePolicy::FIXED:
4789 return GetDimensionValue( GetPreferredSize(), dimension );
4792 case ResizePolicy::USE_ASSIGNED_SIZE:
4794 return GetDimensionValue( maximumSize, dimension );
4797 case ResizePolicy::FILL_TO_PARENT:
4798 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4799 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4801 return NegotiateFromParent( dimension );
4804 case ResizePolicy::FIT_TO_CHILDREN:
4806 return NegotiateFromChildren( dimension );
4809 case ResizePolicy::DIMENSION_DEPENDENCY:
4811 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4814 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4816 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4819 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4821 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4833 return 0.0f; // Default
4836 float Actor::ClampDimension( float size, Dimension::Type dimension )
4838 const float minSize = GetMinimumSize( dimension );
4839 const float maxSize = GetMaximumSize( dimension );
4841 return std::max( minSize, std::min( size, maxSize ) );
4844 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4846 // Check if it needs to be negotiated
4847 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4849 // Check that we havn't gotten into an infinite loop
4850 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4851 bool recursionFound = false;
4852 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4854 if( *it == searchActor )
4856 recursionFound = true;
4861 if( !recursionFound )
4863 // Record the path that we have taken
4864 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4866 // Dimension dependency check
4867 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4869 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4871 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4873 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4877 // Parent dependency check
4878 Actor* parent = GetParent();
4879 if( parent && RelayoutDependentOnParent( dimension ) )
4881 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4884 // Children dependency check
4885 if( RelayoutDependentOnChildren( dimension ) )
4887 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4889 ActorPtr child = GetChildAt( i );
4891 // Only relayout child first if it is not dependent on this actor
4892 if( !child->RelayoutDependentOnParent( dimension ) )
4894 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
4899 // For deriving classes
4900 OnCalculateRelayoutSize( dimension );
4902 // All dependencies checked, calculate the size and set negotiated flag
4903 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4905 SetNegotiatedDimension( newSize, dimension );
4906 SetLayoutNegotiated( true, dimension );
4908 // For deriving classes
4909 OnLayoutNegotiated( newSize, dimension );
4911 // This actor has been successfully processed, pop it off the recursion stack
4912 recursionStack.pop_back();
4916 // TODO: Break infinite loop
4917 SetLayoutNegotiated( true, dimension );
4922 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4924 // Negotiate all dimensions that require it
4925 ActorDimensionStack recursionStack;
4927 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4929 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4932 NegotiateDimension( dimension, allocatedSize, recursionStack );
4936 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4938 switch( mRelayoutData->sizeSetPolicy )
4940 case SizeScalePolicy::USE_SIZE_SET:
4945 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4947 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4948 const Vector3 naturalSize = GetNaturalSize();
4949 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4951 const float sizeRatio = size.width / size.height;
4952 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4954 if( naturalSizeRatio < sizeRatio )
4956 return Vector2( naturalSizeRatio * size.height, size.height );
4958 else if( naturalSizeRatio > sizeRatio )
4960 return Vector2( size.width, size.width / naturalSizeRatio );
4971 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4973 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4974 const Vector3 naturalSize = GetNaturalSize();
4975 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4977 const float sizeRatio = size.width / size.height;
4978 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4980 if( naturalSizeRatio < sizeRatio )
4982 return Vector2( size.width, size.width / naturalSizeRatio );
4984 else if( naturalSizeRatio > sizeRatio )
4986 return Vector2( naturalSizeRatio * size.height, size.height );
5005 void Actor::SetNegotiatedSize( RelayoutContainer& container )
5007 // Do the set actor size
5008 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
5010 // Adjust for size set policy
5011 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
5013 // Lock the flag to stop recursive relayouts on set size
5014 mRelayoutData->insideRelayout = true;
5015 SetSize( negotiatedSize );
5016 mRelayoutData->insideRelayout = false;
5018 // Clear flags for all dimensions
5019 SetLayoutDirty( false );
5021 // Give deriving classes a chance to respond
5022 OnRelayout( negotiatedSize, container );
5024 if( !mOnRelayoutSignal.Empty() )
5026 Dali::Actor handle( this );
5027 mOnRelayoutSignal.Emit( handle );
5031 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
5033 // Force a size negotiation for actors that has assigned size during relayout
5034 // This is required as otherwise the flags that force a relayout will not
5035 // necessarilly be set. This will occur if the actor has already been laid out.
5036 // The dirty flags are then cleared. Then if the actor is added back into the
5037 // relayout container afterwards, the dirty flags would still be clear...
5038 // causing a relayout to be skipped. Here we force any actors added to the
5039 // container to be relayed out.
5040 DALI_LOG_TIMER_START( NegSizeTimer1 );
5042 if( GetUseAssignedSize(Dimension::WIDTH ) )
5044 SetLayoutNegotiated( false, Dimension::WIDTH );
5046 if( GetUseAssignedSize( Dimension::HEIGHT ) )
5048 SetLayoutNegotiated( false, Dimension::HEIGHT );
5051 // Do the negotiation
5052 NegotiateDimensions( allocatedSize );
5054 // Set the actor size
5055 SetNegotiatedSize( container );
5057 // Negotiate down to children
5058 const Vector2 newBounds = mTargetSize.GetVectorXY();
5060 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
5062 ActorPtr child = GetChildAt( i );
5064 // Forces children that have already been laid out to be relayed out
5065 // if they have assigned size during relayout.
5066 if( child->GetUseAssignedSize(Dimension::WIDTH) )
5068 child->SetLayoutNegotiated(false, Dimension::WIDTH);
5069 child->SetLayoutDirty(true, Dimension::WIDTH);
5072 if( child->GetUseAssignedSize(Dimension::HEIGHT) )
5074 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
5075 child->SetLayoutDirty(true, Dimension::HEIGHT);
5078 // Only relayout if required
5079 if( child->RelayoutRequired() )
5081 container.Add( Dali::Actor( child.Get() ), newBounds );
5084 DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
5087 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
5091 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5093 if( dimension & ( 1 << i ) )
5095 mRelayoutData->useAssignedSize[ i ] = use;
5101 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
5103 if ( mRelayoutData )
5105 // If more than one dimension is requested, just return the first one found
5106 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5108 if( dimension & ( 1 << i ) )
5110 return mRelayoutData->useAssignedSize[ i ];
5118 void Actor::RelayoutRequest( Dimension::Type dimension )
5120 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
5121 if( relayoutController )
5123 Dali::Actor self( this );
5124 relayoutController->RequestRelayout( self, dimension );
5128 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
5132 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
5136 void Actor::SetPreferredSize( const Vector2& size )
5138 EnsureRelayoutData();
5140 if( size.width > 0.0f )
5142 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
5145 if( size.height > 0.0f )
5147 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
5150 mRelayoutData->preferredSize = size;
5155 Vector2 Actor::GetPreferredSize() const
5157 if ( mRelayoutData )
5159 return Vector2( mRelayoutData->preferredSize );
5162 return GetDefaultPreferredSize();
5165 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
5167 EnsureRelayoutData();
5169 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5171 if( dimension & ( 1 << i ) )
5173 mRelayoutData->minimumSize[ i ] = size;
5180 float Actor::GetMinimumSize( Dimension::Type dimension ) const
5182 if ( mRelayoutData )
5184 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5186 if( dimension & ( 1 << i ) )
5188 return mRelayoutData->minimumSize[ i ];
5193 return 0.0f; // Default
5196 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
5198 EnsureRelayoutData();
5200 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5202 if( dimension & ( 1 << i ) )
5204 mRelayoutData->maximumSize[ i ] = size;
5211 float Actor::GetMaximumSize( Dimension::Type dimension ) const
5213 if ( mRelayoutData )
5215 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5217 if( dimension & ( 1 << i ) )
5219 return mRelayoutData->maximumSize[ i ];
5224 return FLT_MAX; // Default
5227 Object* Actor::GetParentObject() const
5232 void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
5234 if( mVisible != visible )
5236 if( sendMessage == SendMessage::TRUE && NULL != mNode )
5238 // mNode is being used in a separate thread; queue a message to set the value & base value
5239 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
5244 // Emit the signal on this actor and all its children
5245 EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
5249 void Actor::SetSiblingOrder( unsigned int order )
5251 mSiblingOrder = std::min( order, static_cast<unsigned int>( DevelLayer::SIBLING_ORDER_MULTIPLIER ) );
5255 StagePtr stage = Stage::GetCurrent();
5258 stage->RequestRebuildDepthTree();
5263 void Actor::DefragmentSiblingIndexes( ActorContainer& siblings )
5265 // Sibling index may not be in consecutive order as the sibling range is limited ( DevelLayer::SIBLING_ORDER_MULTIPLIER )
5266 // we need to remove the gaps and ensure the number start from 0 and consecutive hence have a full range.
5268 // Start at index 0, while index <= highest order
5269 // Find next index higher than 0
5270 // if nextHigher > index+1
5271 // set all nextHigher orders to index+1
5273 // Limitation: May reach the ceiling of DevelLayer::SIBLING_ORDER_MULTIPLIER with highest sibling.
5275 ActorIter end = siblings.end();
5276 int highestOrder = 0;
5277 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
5279 ActorPtr sibling = (*iter);
5280 int siblingOrder = sibling->mSiblingOrder;
5281 highestOrder = std::max( highestOrder, siblingOrder );
5284 for ( int index = 0; index <= highestOrder; index++ )
5286 int nextHighest = -1;
5288 // Find Next highest
5289 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
5291 ActorPtr sibling = (*iter);
5292 int siblingOrder = sibling->mSiblingOrder;
5294 if ( siblingOrder > index )
5296 if ( nextHighest == -1 )
5298 nextHighest = siblingOrder;
5300 nextHighest = std::min( nextHighest, siblingOrder );
5304 // Check if a gap exists between indexes, if so set next index to consecutive number
5305 if ( ( nextHighest - index ) > 1 )
5307 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
5309 ActorPtr sibling = (*iter);
5310 int siblingOrder = sibling->mSiblingOrder;
5311 if ( siblingOrder == nextHighest )
5313 sibling->mSiblingOrder = index + 1;
5314 if ( sibling->mSiblingOrder >= Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER )
5316 DALI_LOG_WARNING( "Reached max sibling order level for raising / lowering actors\n" );
5317 sibling->mSiblingOrder = Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER;
5319 sibling->SetSiblingOrder( sibling->mSiblingOrder );
5326 bool Actor::ShiftSiblingsLevels( ActorContainer& siblings, int targetLevelToShiftFrom )
5328 // Allows exclusive levels for an actor by shifting all sibling levels at the target and above by 1
5329 bool defragmentationRequired( false );
5330 ActorIter end = siblings.end();
5331 for( ActorIter iter = siblings.begin(); ( iter != end ) ; ++iter )
5333 // Move actors at nearest order and above up by 1
5334 ActorPtr sibling = (*iter);
5335 if ( sibling != this )
5337 // Iterate through container of actors, any actor with a sibling order of the target or greater should
5338 // be incremented by 1.
5339 if ( sibling->mSiblingOrder >= targetLevelToShiftFrom )
5341 sibling->mSiblingOrder++;
5342 if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
5344 // If a sibling order raises so that it is only 1 from the maximum allowed then set flag so
5345 // can re-order all sibling orders.
5346 defragmentationRequired = true;
5348 sibling->SetSiblingOrder( sibling->mSiblingOrder );
5352 return defragmentationRequired;
5358 1) Check if already at top and nothing to be done.
5359 This Actor can have highest sibling order but if not exclusive then another actor at same sibling
5360 order can be positioned above it due to insertion order of actors.
5361 2) Find nearest sibling level above, these are the siblings this actor needs to be above
5362 3) a) There may be other levels above this target level
5363 b) Increment all sibling levels at the level above nearest(target)
5364 c) Now have a vacant sibling level
5365 4) Set this actor's sibling level to nearest +1 as now vacated.
5367 Note May not just be sibling level + 1 as could be empty levels in-between
5372 ActorC ( sibling level 4 )
5373 ActorB ( sibling level 3 )
5374 ActorA ( sibling level 1 )
5376 2 ) ACTION: Raise A above B
5377 a) Find nearest level above A = Level 3
5378 b) Increment levels above Level 3
5380 ActorC ( sibling level 5 )
5381 ActorB ( sibling level 3 ) NEAREST
5382 ActorA ( sibling level 1 )
5384 3 ) Set Actor A sibling level to nearest +1 as vacant
5386 ActorC ( sibling level 5 )
5387 ActorA ( sibling level 4 )
5388 ActorB ( sibling level 3 )
5390 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5391 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5392 remove any empty sibling order gaps and start from sibling level 0 again.
5393 If the number of actors reaches this maximum and all using exclusive sibling order values then
5394 defragmention will stop and new sibling orders will be set to same max value.
5398 int nearestLevel = mSiblingOrder;
5399 int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
5400 bool defragmentationRequired( false );
5402 ActorContainer* siblings = mParent->mChildren;
5404 // Find Nearest sibling level above this actor
5405 ActorIter end = siblings->end();
5406 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
5408 ActorPtr sibling = (*iter);
5409 if ( sibling != this )
5411 int order = GetSiblingOrder( sibling );
5413 if ( ( order >= mSiblingOrder ) )
5415 int distanceToNextLevel = order - mSiblingOrder;
5416 if ( distanceToNextLevel < shortestDistanceToNextLevel )
5418 nearestLevel = order;
5419 shortestDistanceToNextLevel = distanceToNextLevel;
5425 if ( nearestLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at top
5427 mSiblingOrder = nearestLevel + 1; // Set sibling level to that above the nearest level
5428 defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
5429 // Move current actor to newly vacated order level
5430 SetSiblingOrder( mSiblingOrder );
5431 if ( defragmentationRequired )
5433 DefragmentSiblingIndexes( *siblings );
5436 SetSiblingOrder( mSiblingOrder );
5440 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5447 1) Check if actor already at bottom and if nothing needs to be done
5448 This Actor can have lowest sibling order but if not exclusive then another actor at same sibling
5449 order can be positioned above it due to insertion order of actors so need to move this actor below it.
5450 2) Find nearest sibling level below, this Actor needs to be below it
5451 3) a) Need to vacate a sibling level below nearest for this actor to occupy
5452 b) Shift up all sibling order values of actor at the nearest level and levels above it to vacate a level.
5453 c) Set this actor's sibling level to this newly vacated level.
5454 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5455 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5456 remove any empty sibling order gaps and start from sibling level 0 again.
5457 If the number of actors reaches this maximum and all using exclusive sibling order values then
5458 defragmention will stop and new sibling orders will be set to same max value.
5463 // 1) Find nearest level below
5464 int nearestLevel = mSiblingOrder;
5465 int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
5467 ActorContainer* siblings = mParent->mChildren;
5469 ActorIter end = siblings->end();
5470 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
5472 ActorPtr sibling = (*iter);
5473 if ( sibling != this )
5475 int order = GetSiblingOrder( sibling );
5477 if ( order <= mSiblingOrder )
5479 int distanceToNextLevel = mSiblingOrder - order;
5480 if ( distanceToNextLevel < shortestDistanceToNextLevel )
5482 nearestLevel = order;
5483 shortestDistanceToNextLevel = distanceToNextLevel;
5489 bool defragmentationRequired ( false );
5491 // 2) If actor already not at bottom, raise all actors at required level and above
5492 if ( shortestDistanceToNextLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at bottom
5494 mSiblingOrder = nearestLevel;
5495 defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
5496 // Move current actor to newly vacated order
5497 SetSiblingOrder( mSiblingOrder );
5498 if ( defragmentationRequired )
5500 DefragmentSiblingIndexes( *siblings );
5506 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5510 void Actor::RaiseToTop()
5513 1 ) Find highest sibling order actor
5514 2 ) If highest sibling level not itself then set sibling order to that + 1
5515 3 ) highest sibling order can be same as itself so need to increment over that
5516 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5517 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5518 remove any empty sibling order gaps and start from sibling level 0 again.
5519 If the number of actors reaches this maximum and all using exclusive sibling order values then
5520 defragmention will stop and new sibling orders will be set to same max value.
5527 ActorContainer* siblings = mParent->mChildren;
5529 ActorIter end = siblings->end();
5530 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
5532 ActorPtr sibling = (*iter);
5533 if ( sibling != this )
5535 maxOrder = std::max( GetSiblingOrder( sibling ), maxOrder );
5539 bool defragmentationRequired( false );
5541 if ( maxOrder >= mSiblingOrder )
5543 mSiblingOrder = maxOrder + 1;
5544 if ( mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
5546 defragmentationRequired = true;
5550 SetSiblingOrder( mSiblingOrder );
5552 if ( defragmentationRequired )
5554 DefragmentSiblingIndexes( *siblings );
5559 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5563 void Actor::LowerToBottom()
5566 See Actor::LowerToBottom()
5568 1 ) Check if this actor already at exclusively at the bottom, if so then no more to be done.
5569 2 ) a ) Check if the bottom position 0 is vacant.
5570 b ) If 0 position is not vacant then shift up all sibling order values from 0 and above
5571 c ) 0 sibling position is vacant.
5572 3 ) Set this actor to vacant sibling order 0;
5573 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5574 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5575 remove any empty sibling order gaps and start from sibling level 0 again.
5576 If the number of actors reaches this maximum and all using exclusive sibling order values then
5577 defragmention will stop and new sibling orders will be set to same max value.
5582 bool defragmentationRequired( false );
5583 bool orderZeroFree ( true );
5585 ActorContainer* siblings = mParent->mChildren;
5587 bool actorAtLowestOrder = true;
5588 ActorIter end = siblings->end();
5589 for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
5591 ActorPtr sibling = (*iter);
5592 if ( sibling != this )
5594 int siblingOrder = GetSiblingOrder( sibling );
5595 if ( siblingOrder <= mSiblingOrder )
5597 actorAtLowestOrder = false;
5600 if ( siblingOrder == 0 )
5602 orderZeroFree = false;
5607 if ( ! actorAtLowestOrder )
5609 if ( ! orderZeroFree )
5611 defragmentationRequired = ShiftSiblingsLevels( *siblings, 0 );
5614 SetSiblingOrder( mSiblingOrder );
5616 if ( defragmentationRequired )
5618 DefragmentSiblingIndexes( *siblings );
5624 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5628 void Actor::RaiseAbove( Internal::Actor& target )
5631 1 ) a) Find target actor's sibling order
5632 b) If sibling order of target is the same as this actor then need to this Actor's sibling order
5633 needs to be above it or the insertion order will determine which is drawn on top.
5634 2 ) Shift up by 1 all sibling order greater than target sibling order
5635 3 ) Set this actor to the sibling order to target +1 as will be a newly vacated gap above
5636 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5637 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5638 remove any empty sibling order gaps and start from sibling level 0 again.
5639 If the number of actors reaches this maximum and all using exclusive sibling order values then
5640 defragmention will stop and new sibling orders will be set to same max value.
5645 if ( ValidateActors( *this, target ) )
5647 // Find target's sibling order
5648 // Set actor sibling order to this number +1
5649 int targetSiblingOrder = GetSiblingOrder( &target );
5650 ActorContainer* siblings = mParent->mChildren;
5651 mSiblingOrder = targetSiblingOrder + 1;
5652 bool defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
5654 SetSiblingOrder( mSiblingOrder );
5656 if ( defragmentationRequired )
5658 DefragmentSiblingIndexes( *(mParent->mChildren) );
5664 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5668 void Actor::LowerBelow( Internal::Actor& target )
5671 1 ) a) Find target actor's sibling order
5672 b) If sibling order of target is the same as this actor then need to this Actor's sibling order
5673 needs to be below it or the insertion order will determine which is drawn on top.
5674 2 ) Shift the target sibling order and all sibling orders at that level or above by 1
5675 3 ) Set this actor to the sibling order of the target before it changed.
5676 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5677 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5678 remove any empty sibling order gaps and start from sibling level 0 again.
5679 If the number of actors reaches this maximum and all using exclusive sibling order values then
5680 defragmention will stop and new sibling orders will be set to same max value.
5685 if ( ValidateActors( *this, target ) )
5687 bool defragmentationRequired ( false );
5688 // Find target's sibling order
5689 // Set actor sibling order to target sibling order - 1
5690 int targetSiblingOrder = GetSiblingOrder( &target);
5691 ActorContainer* siblings = mParent->mChildren;
5692 if ( targetSiblingOrder == 0 )
5695 ActorIter end = siblings->end();
5696 for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
5698 ActorPtr sibling = (*iter);
5699 if ( sibling != this )
5701 sibling->mSiblingOrder++;
5702 if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
5704 defragmentationRequired = true;
5706 sibling->SetSiblingOrder( sibling->mSiblingOrder );
5713 defragmentationRequired = ShiftSiblingsLevels( *siblings, targetSiblingOrder );
5715 mSiblingOrder = targetSiblingOrder;
5717 SetSiblingOrder( mSiblingOrder );
5719 if ( defragmentationRequired )
5721 DefragmentSiblingIndexes( *(mParent->mChildren) );
5727 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5731 } // namespace Internal