2 * Copyright (c) 2017 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/event/actors/actor-impl.h>
27 #include <dali/devel-api/actors/layer-devel.h>
28 #include <dali/public-api/common/dali-common.h>
29 #include <dali/public-api/common/constants.h>
30 #include <dali/public-api/events/touch-data.h>
31 #include <dali/public-api/math/vector2.h>
32 #include <dali/public-api/math/vector3.h>
33 #include <dali/public-api/math/radian.h>
34 #include <dali/public-api/object/type-registry.h>
35 #include <dali/devel-api/actors/actor-devel.h>
36 #include <dali/devel-api/object/weak-handle.h>
37 #include <dali/devel-api/scripting/scripting.h>
38 #include <dali/internal/common/internal-constants.h>
39 #include <dali/internal/event/common/event-thread-services.h>
40 #include <dali/internal/event/render-tasks/render-task-impl.h>
41 #include <dali/internal/event/actors/camera-actor-impl.h>
42 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
43 #include <dali/internal/event/common/property-helper.h>
44 #include <dali/internal/event/common/stage-impl.h>
45 #include <dali/internal/event/common/type-info-impl.h>
46 #include <dali/internal/event/animation/constraint-impl.h>
47 #include <dali/internal/event/common/projection.h>
48 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
49 #include <dali/internal/update/common/animatable-property.h>
50 #include <dali/internal/update/nodes/node-messages.h>
51 #include <dali/internal/update/nodes/node-declarations.h>
52 #include <dali/internal/update/animation/scene-graph-constraint.h>
53 #include <dali/internal/event/events/actor-gesture-data.h>
54 #include <dali/internal/common/message.h>
55 #include <dali/integration-api/debug.h>
57 using Dali::Internal::SceneGraph::Node;
58 using Dali::Internal::SceneGraph::AnimatableProperty;
59 using Dali::Internal::SceneGraph::PropertyBase;
61 #if defined(DEBUG_ENABLED)
62 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_DEPTH_TIMER" );
63 Debug::Filter* gLogRelayoutFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_TIMER" );
72 unsigned int Actor::mActorCounter = 0;
76 /// Using a function because of library initialisation order. Vector3::ONE may not have been initialised yet.
77 inline const Vector3& GetDefaultSizeModeFactor()
82 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
83 inline const Vector2& GetDefaultPreferredSize()
88 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
89 inline const Vector2& GetDefaultDimensionPadding()
94 const SizeScalePolicy::Type DEFAULT_SIZE_SCALE_POLICY = SizeScalePolicy::USE_SIZE_SET;
96 int GetSiblingOrder( ActorPtr actor )
98 Property::Value value = actor->GetProperty(Dali::DevelActor::Property::SIBLING_ORDER );
104 bool ValidateActors( const Internal::Actor& actor, const Internal::Actor& target )
106 bool validTarget = true;
108 if( &actor == &target )
110 DALI_LOG_WARNING( "Source actor and target actor can not be the same, Sibling order not changed.\n" );
113 else if( actor.GetParent() != target.GetParent() )
115 DALI_LOG_WARNING( "Source actor and target actor need to have common parent, Sibling order not changed.\n" );
122 } // unnamed namespace
125 * Struct to collect relayout variables
127 struct Actor::RelayoutData
130 : sizeModeFactor( GetDefaultSizeModeFactor() ), preferredSize( GetDefaultPreferredSize() ), sizeSetPolicy( DEFAULT_SIZE_SCALE_POLICY ), relayoutEnabled( false ), insideRelayout( false )
132 // Set size negotiation defaults
133 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
135 resizePolicies[ i ] = ResizePolicy::DEFAULT;
136 useAssignedSize[ i ] = false;
137 negotiatedDimensions[ i ] = 0.0f;
138 dimensionNegotiated[ i ] = false;
139 dimensionDirty[ i ] = false;
140 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
141 dimensionPadding[ i ] = GetDefaultDimensionPadding();
142 minimumSize[ i ] = 0.0f;
143 maximumSize[ i ] = FLT_MAX;
147 ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies
148 bool useAssignedSize[ Dimension::DIMENSION_COUNT ]; ///< The flag to specify whether the size should be assigned to the actor
150 Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies
152 Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
154 float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
156 float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be
157 float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be
159 bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated
160 bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
162 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
164 Vector2 preferredSize; ///< The preferred size of the actor
166 SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
168 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
169 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
172 namespace // unnamed namespace
178 * We want to discourage the use of property strings (minimize string comparisons),
179 * particularly for the default properties.
180 * Name Type writable animatable constraint-input enum for index-checking
182 DALI_PROPERTY_TABLE_BEGIN
183 DALI_PROPERTY( "parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
184 DALI_PROPERTY( "parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
185 DALI_PROPERTY( "parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
186 DALI_PROPERTY( "parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
187 DALI_PROPERTY( "anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
188 DALI_PROPERTY( "anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
189 DALI_PROPERTY( "anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
190 DALI_PROPERTY( "anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
191 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
192 DALI_PROPERTY( "sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
193 DALI_PROPERTY( "sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
194 DALI_PROPERTY( "sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
195 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
196 DALI_PROPERTY( "positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
197 DALI_PROPERTY( "positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
198 DALI_PROPERTY( "positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
199 DALI_PROPERTY( "worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
200 DALI_PROPERTY( "worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
201 DALI_PROPERTY( "worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
202 DALI_PROPERTY( "worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
203 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
204 DALI_PROPERTY( "worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
205 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
206 DALI_PROPERTY( "scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
207 DALI_PROPERTY( "scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
208 DALI_PROPERTY( "scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
209 DALI_PROPERTY( "worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
210 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
211 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
212 DALI_PROPERTY( "colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
213 DALI_PROPERTY( "colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
214 DALI_PROPERTY( "colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
215 DALI_PROPERTY( "colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
216 DALI_PROPERTY( "worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
217 DALI_PROPERTY( "worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
218 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
219 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
220 DALI_PROPERTY( "leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
221 DALI_PROPERTY( "inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
222 DALI_PROPERTY( "inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
223 DALI_PROPERTY( "colorMode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
224 DALI_PROPERTY( "positionInheritance", STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE )
225 DALI_PROPERTY( "drawMode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
226 DALI_PROPERTY( "sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
227 DALI_PROPERTY( "widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
228 DALI_PROPERTY( "heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
229 DALI_PROPERTY( "sizeScalePolicy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
230 DALI_PROPERTY( "widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
231 DALI_PROPERTY( "heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
232 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
233 DALI_PROPERTY( "minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
234 DALI_PROPERTY( "maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
235 DALI_PROPERTY( "inheritPosition", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_POSITION )
236 DALI_PROPERTY( "clippingMode", STRING, true, false, false, Dali::Actor::Property::CLIPPING_MODE )
237 DALI_PROPERTY( "siblingOrder", INTEGER, true, false, false, Dali::DevelActor::Property::SIBLING_ORDER )
238 DALI_PROPERTY( "opacity", FLOAT, true, true, true, Dali::DevelActor::Property::OPACITY )
239 DALI_PROPERTY( "screenPosition", VECTOR2, false, false, false, Dali::DevelActor::Property::SCREEN_POSITION )
240 DALI_PROPERTY( "positionUsesAnchorPoint", BOOLEAN, true, false, false, Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT )
241 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
245 const char* const SIGNAL_TOUCHED = "touched";
246 const char* const SIGNAL_HOVERED = "hovered";
247 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
248 const char* const SIGNAL_ON_STAGE = "onStage";
249 const char* const SIGNAL_OFF_STAGE = "offStage";
250 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
251 const char* const SIGNAL_TOUCH = "touch";
255 const char* const ACTION_SHOW = "show";
256 const char* const ACTION_HIDE = "hide";
258 BaseHandle CreateActor()
260 return Dali::Actor::New();
263 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
265 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
266 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
267 SignalConnectorType signalConnector3( mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal );
268 SignalConnectorType signalConnector4( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
269 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
270 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
271 SignalConnectorType signalConnector7( mType, SIGNAL_TOUCH, &Actor::DoConnectSignal );
273 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
274 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
279 const Vector3& value;
282 DALI_ENUM_TO_STRING_TABLE_BEGIN_WITH_TYPE( AnchorValue, ANCHOR_CONSTANT )
283 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_LEFT )
284 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_CENTER )
285 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_RIGHT )
286 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_LEFT )
287 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER )
288 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_RIGHT )
289 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_LEFT )
290 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_CENTER )
291 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_RIGHT )
292 DALI_ENUM_TO_STRING_TABLE_END( ANCHOR_CONSTANT )
294 DALI_ENUM_TO_STRING_TABLE_BEGIN( COLOR_MODE )
295 DALI_ENUM_TO_STRING( USE_OWN_COLOR )
296 DALI_ENUM_TO_STRING( USE_PARENT_COLOR )
297 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_COLOR )
298 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_ALPHA )
299 DALI_ENUM_TO_STRING_TABLE_END( COLOR_MODE )
301 DALI_ENUM_TO_STRING_TABLE_BEGIN( POSITION_INHERITANCE_MODE )
302 DALI_ENUM_TO_STRING( INHERIT_PARENT_POSITION )
303 DALI_ENUM_TO_STRING( USE_PARENT_POSITION )
304 DALI_ENUM_TO_STRING( USE_PARENT_POSITION_PLUS_LOCAL_POSITION )
305 DALI_ENUM_TO_STRING( DONT_INHERIT_POSITION )
306 DALI_ENUM_TO_STRING_TABLE_END( POSITION_INHERITANCE_MODE )
308 DALI_ENUM_TO_STRING_TABLE_BEGIN( DRAW_MODE )
309 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, NORMAL )
310 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, OVERLAY_2D )
311 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, STENCIL )
312 DALI_ENUM_TO_STRING_TABLE_END( DRAW_MODE )
314 DALI_ENUM_TO_STRING_TABLE_BEGIN( RESIZE_POLICY )
315 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIXED )
316 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_NATURAL_SIZE )
317 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FILL_TO_PARENT )
318 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_RELATIVE_TO_PARENT )
319 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_FIXED_OFFSET_FROM_PARENT )
320 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIT_TO_CHILDREN )
321 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, DIMENSION_DEPENDENCY )
322 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_ASSIGNED_SIZE )
323 DALI_ENUM_TO_STRING_TABLE_END( RESIZE_POLICY )
325 DALI_ENUM_TO_STRING_TABLE_BEGIN( SIZE_SCALE_POLICY )
326 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, USE_SIZE_SET )
327 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FIT_WITH_ASPECT_RATIO )
328 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FILL_WITH_ASPECT_RATIO )
329 DALI_ENUM_TO_STRING_TABLE_END( SIZE_SCALE_POLICY )
331 DALI_ENUM_TO_STRING_TABLE_BEGIN( CLIPPING_MODE )
332 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, DISABLED )
333 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, CLIP_CHILDREN )
334 DALI_ENUM_TO_STRING_TABLE_END( CLIPPING_MODE )
337 bool GetAnchorPointConstant( const std::string& value, Vector3& anchor )
339 for( unsigned int i = 0; i < ANCHOR_CONSTANT_TABLE_COUNT; ++i )
341 size_t sizeIgnored = 0;
342 if( CompareTokens( value.c_str(), ANCHOR_CONSTANT_TABLE[ i ].name, sizeIgnored ) )
344 anchor = ANCHOR_CONSTANT_TABLE[ i ].value;
351 inline bool GetParentOriginConstant( const std::string& value, Vector3& parentOrigin )
353 // Values are the same so just use the same table as anchor-point
354 return GetAnchorPointConstant( value, parentOrigin );
358 * @brief Extract a given dimension from a Vector2
360 * @param[in] values The values to extract from
361 * @param[in] dimension The dimension to extract
362 * @return Return the value for the dimension
364 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
368 case Dimension::WIDTH:
372 case Dimension::HEIGHT:
374 return values.height;
385 * @brief Extract a given dimension from a Vector3
387 * @param[in] values The values to extract from
388 * @param[in] dimension The dimension to extract
389 * @return Return the value for the dimension
391 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
393 return GetDimensionValue( values.GetVectorXY(), dimension );
397 * @brief Recursively emits the visibility-changed-signal on the actor tree.
398 * @param[in] actor The actor to emit the signal on
399 * @param[in] visible The new visibility of the actor
400 * @param[in] type Whether the actor's visible property has changed or a parent's
402 void EmitVisibilityChangedSignalRecursively( ActorPtr actor, bool visible, DevelActor::VisibilityChange::Type type )
406 actor->EmitVisibilityChangedSignal( visible, type );
408 if( actor->GetChildCount() > 0 )
410 ActorContainer& children = actor->GetChildrenInternal();
411 for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter )
413 EmitVisibilityChangedSignalRecursively( *iter, visible, DevelActor::VisibilityChange::PARENT );
419 } // unnamed namespace
421 ActorPtr Actor::New()
423 ActorPtr actor( new Actor( BASIC ) );
425 // Second-phase construction
431 const std::string& Actor::GetName() const
436 void Actor::SetName( const std::string& name )
442 // ATTENTION: string for debug purposes is not thread safe.
443 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
447 unsigned int Actor::GetId() const
452 bool Actor::OnStage() const
457 Dali::Layer Actor::GetLayer()
461 // Short-circuit for Layer derived actors
464 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
467 // Find the immediate Layer parent
468 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
470 if( parent->IsLayer() )
472 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
479 void Actor::Add( Actor& child )
481 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
482 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
486 mChildren = new ActorContainer;
489 Actor* const oldParent( child.mParent );
491 // child might already be ours
492 if( this != oldParent )
494 // if we already have parent, unparent us first
497 oldParent->Remove( child ); // This causes OnChildRemove callback
499 // Old parent may need to readjust to missing child
500 if( oldParent->RelayoutDependentOnChildren() )
502 oldParent->RelayoutRequest();
506 // Guard against Add() during previous OnChildRemove callback
509 // Do this first, since user callbacks from within SetParent() may need to remove child
510 mChildren->push_back( ActorPtr( &child ) );
512 // SetParent asserts that child can be added
513 child.SetParent( this );
515 // Notification for derived classes
518 // Only put in a relayout request if there is a suitable dependency
519 if( RelayoutDependentOnChildren() )
527 void Actor::Remove( Actor& child )
529 if( (this == &child) || (!mChildren) )
531 // no children or removing itself
537 // Find the child in mChildren, and unparent it
538 ActorIter end = mChildren->end();
539 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
541 ActorPtr actor = (*iter);
543 if( actor.Get() == &child )
545 // Keep handle for OnChildRemove notification
548 // Do this first, since user callbacks from within SetParent() may need to add the child
549 mChildren->erase( iter );
551 DALI_ASSERT_DEBUG( actor->GetParent() == this );
552 actor->SetParent( NULL );
560 // Only put in a relayout request if there is a suitable dependency
561 if( RelayoutDependentOnChildren() )
567 // Notification for derived classes
568 OnChildRemove( child );
571 void Actor::Unparent()
575 // Remove this actor from the parent. The remove will put a relayout request in for
576 // the parent if required
577 mParent->Remove( *this );
578 // mParent is now NULL!
582 unsigned int Actor::GetChildCount() const
584 return ( NULL != mChildren ) ? mChildren->size() : 0;
587 ActorPtr Actor::GetChildAt( unsigned int index ) const
589 DALI_ASSERT_ALWAYS( index < GetChildCount() );
591 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
594 ActorPtr Actor::FindChildByName( const std::string& actorName )
597 if( actorName == mName )
603 ActorIter end = mChildren->end();
604 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
606 child = (*iter)->FindChildByName( actorName );
617 ActorPtr Actor::FindChildById( const unsigned int id )
626 ActorIter end = mChildren->end();
627 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
629 child = (*iter)->FindChildById( id );
640 void Actor::SetParentOrigin( const Vector3& origin )
644 // mNode is being used in a separate thread; queue a message to set the value & base value
645 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
648 // Cache for event-thread access
651 // not allocated, check if different from default
652 if( ParentOrigin::DEFAULT != origin )
654 mParentOrigin = new Vector3( origin );
659 // check if different from current costs more than just set
660 *mParentOrigin = origin;
664 void Actor::SetParentOriginX( float x )
666 const Vector3& current = GetCurrentParentOrigin();
668 SetParentOrigin( Vector3( x, current.y, current.z ) );
671 void Actor::SetParentOriginY( float y )
673 const Vector3& current = GetCurrentParentOrigin();
675 SetParentOrigin( Vector3( current.x, y, current.z ) );
678 void Actor::SetParentOriginZ( float z )
680 const Vector3& current = GetCurrentParentOrigin();
682 SetParentOrigin( Vector3( current.x, current.y, z ) );
685 const Vector3& Actor::GetCurrentParentOrigin() const
687 // Cached for event-thread access
688 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
691 void Actor::SetAnchorPoint( const Vector3& anchor )
695 // mNode is being used in a separate thread; queue a message to set the value & base value
696 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
699 // Cache for event-thread access
702 // not allocated, check if different from default
703 if( AnchorPoint::DEFAULT != anchor )
705 mAnchorPoint = new Vector3( anchor );
710 // check if different from current costs more than just set
711 *mAnchorPoint = anchor;
715 void Actor::SetAnchorPointX( float x )
717 const Vector3& current = GetCurrentAnchorPoint();
719 SetAnchorPoint( Vector3( x, current.y, current.z ) );
722 void Actor::SetAnchorPointY( float y )
724 const Vector3& current = GetCurrentAnchorPoint();
726 SetAnchorPoint( Vector3( current.x, y, current.z ) );
729 void Actor::SetAnchorPointZ( float z )
731 const Vector3& current = GetCurrentAnchorPoint();
733 SetAnchorPoint( Vector3( current.x, current.y, z ) );
736 const Vector3& Actor::GetCurrentAnchorPoint() const
738 // Cached for event-thread access
739 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
742 void Actor::SetPosition( float x, float y )
744 SetPosition( Vector3( x, y, 0.0f ) );
747 void Actor::SetPosition( float x, float y, float z )
749 SetPosition( Vector3( x, y, z ) );
752 void Actor::SetPosition( const Vector3& position )
754 mTargetPosition = position;
758 // mNode is being used in a separate thread; queue a message to set the value & base value
759 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
763 void Actor::SetX( float x )
765 mTargetPosition.x = x;
769 // mNode is being used in a separate thread; queue a message to set the value & base value
770 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
774 void Actor::SetY( float y )
776 mTargetPosition.y = y;
780 // mNode is being used in a separate thread; queue a message to set the value & base value
781 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
785 void Actor::SetZ( float z )
787 mTargetPosition.z = z;
791 // mNode is being used in a separate thread; queue a message to set the value & base value
792 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
796 void Actor::TranslateBy( const Vector3& distance )
798 mTargetPosition += distance;
802 // mNode is being used in a separate thread; queue a message to set the value & base value
803 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
807 const Vector3& Actor::GetCurrentPosition() const
811 // mNode is being used in a separate thread; copy the value from the previous update
812 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
815 return Vector3::ZERO;
818 const Vector3& Actor::GetTargetPosition() const
820 return mTargetPosition;
823 const Vector3& Actor::GetCurrentWorldPosition() const
827 // mNode is being used in a separate thread; copy the value from the previous update
828 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
831 return Vector3::ZERO;
834 const Vector2 Actor::GetCurrentScreenPosition() const
836 if( OnStage() && NULL != mNode )
838 StagePtr stage = Stage::GetCurrent();
839 Vector3 worldPosition = mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
840 Vector3 actorSize = GetCurrentSize() * GetCurrentScale();
841 Vector2 halfStageSize( stage->GetSize() * 0.5f ); // World position origin is center of stage
842 Vector3 halfActorSize( actorSize * 0.5f );
843 Vector3 anchorPointOffSet = halfActorSize - actorSize * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
845 return Vector2( halfStageSize.width + worldPosition.x - anchorPointOffSet.x,
846 halfStageSize.height + worldPosition.y - anchorPointOffSet.y );
849 return Vector2::ZERO;
852 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
854 // this flag is not animatable so keep the value
855 mPositionInheritanceMode = mode;
858 // mNode is being used in a separate thread; queue a message to set the value
859 SetInheritPositionMessage( GetEventThreadServices(), *mNode, mode == INHERIT_PARENT_POSITION );
863 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
865 // Cached for event-thread access
866 return mPositionInheritanceMode;
869 void Actor::SetInheritPosition( bool inherit )
871 if( mInheritPosition != inherit && NULL != mNode )
873 // non animateable so keep local copy
874 mInheritPosition = inherit;
875 SetInheritPositionMessage( GetEventThreadServices(), *mNode, inherit );
879 bool Actor::IsPositionInherited() const
881 return mInheritPosition;
884 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
886 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
887 normalizedAxis.Normalize();
889 Quaternion orientation( angle, normalizedAxis );
891 SetOrientation( orientation );
894 void Actor::SetOrientation( const Quaternion& orientation )
896 mTargetOrientation = orientation;
900 // mNode is being used in a separate thread; queue a message to set the value & base value
901 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation );
905 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
907 RotateBy( Quaternion(angle, axis) );
910 void Actor::RotateBy( const Quaternion& relativeRotation )
912 mTargetOrientation *= Quaternion( relativeRotation );
916 // mNode is being used in a separate thread; queue a message to set the value & base value
917 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
921 const Quaternion& Actor::GetCurrentOrientation() const
925 // mNode is being used in a separate thread; copy the value from the previous update
926 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
929 return Quaternion::IDENTITY;
932 const Quaternion& Actor::GetCurrentWorldOrientation() const
936 // mNode is being used in a separate thread; copy the value from the previous update
937 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
940 return Quaternion::IDENTITY;
943 void Actor::SetScale( float scale )
945 SetScale( Vector3( scale, scale, scale ) );
948 void Actor::SetScale( float x, float y, float z )
950 SetScale( Vector3( x, y, z ) );
953 void Actor::SetScale( const Vector3& scale )
955 mTargetScale = scale;
959 // mNode is being used in a separate thread; queue a message to set the value & base value
960 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
964 void Actor::SetScaleX( float x )
970 // mNode is being used in a separate thread; queue a message to set the value & base value
971 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
975 void Actor::SetScaleY( float y )
981 // mNode is being used in a separate thread; queue a message to set the value & base value
982 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
986 void Actor::SetScaleZ( float z )
992 // mNode is being used in a separate thread; queue a message to set the value & base value
993 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
997 void Actor::ScaleBy(const Vector3& relativeScale)
999 mTargetScale *= relativeScale;
1003 // mNode is being used in a separate thread; queue a message to set the value & base value
1004 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
1008 const Vector3& Actor::GetCurrentScale() const
1012 // mNode is being used in a separate thread; copy the value from the previous update
1013 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
1016 return Vector3::ONE;
1019 const Vector3& Actor::GetCurrentWorldScale() const
1023 // mNode is being used in a separate thread; copy the value from the previous update
1024 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
1027 return Vector3::ONE;
1030 void Actor::SetInheritScale( bool inherit )
1033 if( mInheritScale != inherit && NULL != mNode )
1035 // non animateable so keep local copy
1036 mInheritScale = inherit;
1037 // mNode is being used in a separate thread; queue a message to set the value
1038 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
1042 bool Actor::IsScaleInherited() const
1044 return mInheritScale;
1047 Matrix Actor::GetCurrentWorldMatrix() const
1051 return mNode->GetWorldMatrix(0);
1054 return Matrix::IDENTITY;
1057 void Actor::SetVisible( bool visible )
1059 SetVisibleInternal( visible, SendMessage::TRUE );
1062 bool Actor::IsVisible() const
1066 // mNode is being used in a separate thread; copy the value from the previous update
1067 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
1073 void Actor::SetOpacity( float opacity )
1075 mTargetColor.a = opacity;
1079 // mNode is being used in a separate thread; queue a message to set the value & base value
1080 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
1084 float Actor::GetCurrentOpacity() const
1088 // mNode is being used in a separate thread; copy the value from the previous update
1089 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1095 ClippingMode::Type Actor::GetClippingMode() const
1097 return mClippingMode;
1100 unsigned int Actor::GetSortingDepth()
1102 return mSortedDepth;
1105 const Vector4& Actor::GetCurrentWorldColor() const
1109 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1112 return Color::WHITE;
1115 void Actor::SetColor( const Vector4& color )
1117 mTargetColor = color;
1121 // mNode is being used in a separate thread; queue a message to set the value & base value
1122 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1126 void Actor::SetColorRed( float red )
1128 mTargetColor.r = red;
1132 // mNode is being used in a separate thread; queue a message to set the value & base value
1133 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1137 void Actor::SetColorGreen( float green )
1139 mTargetColor.g = green;
1143 // mNode is being used in a separate thread; queue a message to set the value & base value
1144 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1148 void Actor::SetColorBlue( float blue )
1150 mTargetColor.b = blue;
1154 // mNode is being used in a separate thread; queue a message to set the value & base value
1155 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1159 const Vector4& Actor::GetCurrentColor() const
1163 // mNode is being used in a separate thread; copy the value from the previous update
1164 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1167 return Color::WHITE;
1170 void Actor::SetInheritOrientation( bool inherit )
1172 if( mInheritOrientation != inherit && NULL != mNode)
1174 // non animateable so keep local copy
1175 mInheritOrientation = inherit;
1176 // mNode is being used in a separate thread; queue a message to set the value
1177 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1181 bool Actor::IsOrientationInherited() const
1183 return mInheritOrientation;
1186 void Actor::SetSizeModeFactor( const Vector3& factor )
1188 EnsureRelayoutData();
1190 mRelayoutData->sizeModeFactor = factor;
1193 const Vector3& Actor::GetSizeModeFactor() const
1195 if ( mRelayoutData )
1197 return mRelayoutData->sizeModeFactor;
1200 return GetDefaultSizeModeFactor();
1203 void Actor::SetColorMode( ColorMode colorMode )
1205 // non animateable so keep local copy
1206 mColorMode = colorMode;
1209 // mNode is being used in a separate thread; queue a message to set the value
1210 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1214 ColorMode Actor::GetColorMode() const
1216 // we have cached copy
1220 void Actor::SetSize( float width, float height )
1222 SetSize( Vector2( width, height ) );
1225 void Actor::SetSize( float width, float height, float depth )
1227 SetSize( Vector3( width, height, depth ) );
1230 void Actor::SetSize( const Vector2& size )
1232 SetSize( Vector3( size.width, size.height, 0.f ) );
1235 void Actor::SetSizeInternal( const Vector2& size )
1237 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1240 void Actor::SetSize( const Vector3& size )
1242 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1244 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1245 SetPreferredSize( size.GetVectorXY() );
1249 SetSizeInternal( size );
1253 void Actor::SetSizeInternal( const Vector3& size )
1255 // dont allow recursive loop
1256 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1257 // check that we have a node AND the new size width, height or depth is at least a little bit different from the old one
1258 if( ( NULL != mNode )&&
1259 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1260 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1261 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1265 // mNode is being used in a separate thread; queue a message to set the value & base value
1266 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
1268 // Notification for derived classes
1269 mInsideOnSizeSet = true;
1270 OnSizeSet( mTargetSize );
1271 mInsideOnSizeSet = false;
1273 // Raise a relayout request if the flag is not locked
1274 if( mRelayoutData && !mRelayoutData->insideRelayout )
1281 void Actor::SetWidth( float width )
1283 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1285 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
1286 mRelayoutData->preferredSize.width = width;
1290 mTargetSize.width = width;
1294 // mNode is being used in a separate thread; queue a message to set the value & base value
1295 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1302 void Actor::SetHeight( float height )
1304 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1306 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
1307 mRelayoutData->preferredSize.height = height;
1311 mTargetSize.height = height;
1315 // mNode is being used in a separate thread; queue a message to set the value & base value
1316 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1323 void Actor::SetDepth( float depth )
1325 mTargetSize.depth = depth;
1329 // mNode is being used in a separate thread; queue a message to set the value & base value
1330 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1334 Vector3 Actor::GetTargetSize() const
1336 Vector3 size = mTargetSize;
1338 // Should return preferred size if size is fixed as set by SetSize
1339 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
1341 size.width = GetPreferredSize().width;
1343 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
1345 size.height = GetPreferredSize().height;
1351 const Vector3& Actor::GetCurrentSize() const
1355 // mNode is being used in a separate thread; copy the value from the previous update
1356 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1359 return Vector3::ZERO;
1362 Vector3 Actor::GetNaturalSize() const
1364 // It is up to deriving classes to return the appropriate natural size
1365 return Vector3( 0.0f, 0.0f, 0.0f );
1368 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1370 EnsureRelayoutData();
1372 ResizePolicy::Type originalWidthPolicy = GetResizePolicy(Dimension::WIDTH);
1373 ResizePolicy::Type originalHeightPolicy = GetResizePolicy(Dimension::HEIGHT);
1375 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1377 if( dimension & ( 1 << i ) )
1379 if ( policy == ResizePolicy::USE_ASSIGNED_SIZE )
1381 mRelayoutData->useAssignedSize[ i ] = true;
1385 mRelayoutData->resizePolicies[ i ] = policy;
1386 mRelayoutData->useAssignedSize[ i ] = false;
1391 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1393 if( dimension & Dimension::WIDTH )
1395 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1398 if( dimension & Dimension::HEIGHT )
1400 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1404 // If calling SetResizePolicy, assume we want relayout enabled
1405 SetRelayoutEnabled( true );
1407 // If the resize policy is set to be FIXED, the preferred size
1408 // should be overrided by the target size. Otherwise the target
1409 // size should be overrided by the preferred size.
1411 if( dimension & Dimension::WIDTH )
1413 if( originalWidthPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1415 mRelayoutData->preferredSize.width = mTargetSize.width;
1417 else if( originalWidthPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1419 mTargetSize.width = mRelayoutData->preferredSize.width;
1423 if( dimension & Dimension::HEIGHT )
1425 if( originalHeightPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1427 mRelayoutData->preferredSize.height = mTargetSize.height;
1429 else if( originalHeightPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1431 mTargetSize.height = mRelayoutData->preferredSize.height;
1435 OnSetResizePolicy( policy, dimension );
1437 // Trigger relayout on this control
1441 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1443 if ( mRelayoutData )
1445 // If more than one dimension is requested, just return the first one found
1446 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1448 if( ( dimension & ( 1 << i ) ) )
1450 if( mRelayoutData->useAssignedSize[ i ] )
1452 return ResizePolicy::USE_ASSIGNED_SIZE;
1456 return mRelayoutData->resizePolicies[ i ];
1462 return ResizePolicy::DEFAULT;
1465 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1467 EnsureRelayoutData();
1469 mRelayoutData->sizeSetPolicy = policy;
1472 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1474 if ( mRelayoutData )
1476 return mRelayoutData->sizeSetPolicy;
1479 return DEFAULT_SIZE_SCALE_POLICY;
1482 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1484 EnsureRelayoutData();
1486 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1488 if( dimension & ( 1 << i ) )
1490 mRelayoutData->dimensionDependencies[ i ] = dependency;
1495 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1497 if ( mRelayoutData )
1499 // If more than one dimension is requested, just return the first one found
1500 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1502 if( ( dimension & ( 1 << i ) ) )
1504 return mRelayoutData->dimensionDependencies[ i ];
1509 return Dimension::ALL_DIMENSIONS; // Default
1512 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1514 // If relayout data has not been allocated yet and the client is requesting
1515 // to disable it, do nothing
1516 if( mRelayoutData || relayoutEnabled )
1518 EnsureRelayoutData();
1520 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1522 mRelayoutData->relayoutEnabled = relayoutEnabled;
1526 bool Actor::IsRelayoutEnabled() const
1528 // Assume that if relayout data has not been allocated yet then
1529 // relayout is disabled
1530 return mRelayoutData && mRelayoutData->relayoutEnabled;
1533 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1535 EnsureRelayoutData();
1537 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1539 if( dimension & ( 1 << i ) )
1541 mRelayoutData->dimensionDirty[ i ] = dirty;
1546 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1548 if ( mRelayoutData )
1550 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1552 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1562 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1564 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1567 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1569 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1572 unsigned int Actor::AddRenderer( Renderer& renderer )
1576 mRenderers = new RendererContainer;
1579 unsigned int index = mRenderers->size();
1580 RendererPtr rendererPtr = RendererPtr( &renderer );
1581 mRenderers->push_back( rendererPtr );
1582 AddRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1586 unsigned int Actor::GetRendererCount() const
1588 unsigned int rendererCount(0);
1591 rendererCount = mRenderers->size();
1594 return rendererCount;
1597 RendererPtr Actor::GetRendererAt( unsigned int index )
1599 RendererPtr renderer;
1600 if( index < GetRendererCount() )
1602 renderer = ( *mRenderers )[ index ];
1608 void Actor::RemoveRenderer( Renderer& renderer )
1612 RendererIter end = mRenderers->end();
1613 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1615 if( (*iter).Get() == &renderer )
1617 mRenderers->erase( iter );
1618 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1625 void Actor::RemoveRenderer( unsigned int index )
1627 if( index < GetRendererCount() )
1629 RendererPtr renderer = ( *mRenderers )[ index ];
1630 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.Get()->GetRendererSceneObject() );
1631 mRenderers->erase( mRenderers->begin()+index );
1635 bool Actor::IsOverlay() const
1637 return ( DrawMode::OVERLAY_2D == mDrawMode );
1640 void Actor::SetDrawMode( DrawMode::Type drawMode )
1642 // this flag is not animatable so keep the value
1643 mDrawMode = drawMode;
1644 if( ( NULL != mNode ) && ( drawMode != DrawMode::STENCIL ) )
1646 // mNode is being used in a separate thread; queue a message to set the value
1647 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1651 DrawMode::Type Actor::GetDrawMode() const
1656 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1658 // only valid when on-stage
1659 StagePtr stage = Stage::GetCurrent();
1660 if( stage && OnStage() )
1662 const RenderTaskList& taskList = stage->GetRenderTaskList();
1664 Vector2 converted( screenX, screenY );
1666 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1667 const int taskCount = taskList.GetTaskCount();
1668 for( int i = taskCount - 1; i >= 0; --i )
1670 Dali::RenderTask task = taskList.GetTask( i );
1671 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1673 // found a task where this conversion was ok so return
1681 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1683 bool retval = false;
1684 // only valid when on-stage
1687 CameraActor* camera = renderTask.GetCameraActor();
1691 renderTask.GetViewport( viewport );
1693 // need to translate coordinates to render tasks coordinate space
1694 Vector2 converted( screenX, screenY );
1695 if( renderTask.TranslateCoordinates( converted ) )
1697 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1704 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1706 // Early-out if mNode is NULL
1712 // Get the ModelView matrix
1714 Matrix::Multiply( modelView, mNode->GetWorldMatrix(0), viewMatrix );
1716 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1717 Matrix invertedMvp( false/*don't init*/);
1718 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1719 bool success = invertedMvp.Invert();
1721 // Convert to GL coordinates
1722 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1727 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1734 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1740 if( XyPlaneIntersect( nearPos, farPos, local ) )
1742 Vector3 size = GetCurrentSize();
1743 localX = local.x + size.x * 0.5f;
1744 localY = local.y + size.y * 0.5f;
1755 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1758 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1760 Mathematical Formulation
1762 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1764 ( p - c ) dot ( p - c ) = r^2
1766 Given a ray with a point of origin 'o', and a direction vector 'd':
1768 ray(t) = o + td, t >= 0
1770 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1772 (o + td - c ) dot ( o + td - c ) = r^2
1774 To solve for t we first expand the above into a more recognisable quadratic equation form
1776 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1785 B = 2( o - c ) dot d
1786 C = ( o - c ) dot ( o - c ) - r^2
1788 which can be solved using a standard quadratic formula.
1790 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1792 Practical Simplification
1794 In a renderer, we often differentiate between world space and object space. In the object space
1795 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1796 into object space, the mathematical solution presented above can be simplified significantly.
1798 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1802 and we can find the t at which the (transformed) ray intersects the sphere by
1804 ( o + td ) dot ( o + td ) = r^2
1806 According to the reasoning above, we expand the above quadratic equation into the general form
1810 which now has coefficients:
1817 // Early out if mNode is NULL
1823 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1825 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1826 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1827 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1829 // Compute the radius is not needed, square radius it's enough.
1830 const Vector3& size( mNode->GetSize( bufferIndex ) );
1832 // Scale the sphere.
1833 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1835 const float width = size.width * scale.width;
1836 const float height = size.height * scale.height;
1838 float squareSphereRadius = 0.5f * ( width * width + height * height );
1840 float a = rayDir.Dot( rayDir ); // a
1841 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1842 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1844 return ( b2 * b2 - a * c ) >= 0.f;
1847 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector2& hitPointLocal, float& distance ) const
1851 if( OnStage() && NULL != mNode )
1853 // Transforms the ray to the local reference system.
1854 // Calculate the inverse of Model matrix
1855 Matrix invModelMatrix( false/*don't init*/);
1857 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1858 invModelMatrix = mNode->GetWorldMatrix(0);
1859 invModelMatrix.Invert();
1861 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1862 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1864 // Test with the actor's XY plane (Normal = 0 0 1 1).
1866 float a = -rayOriginLocal.z;
1867 float b = rayDirLocal.z;
1869 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1871 // Ray travels distance * rayDirLocal to intersect with plane.
1874 const Vector3& size = mNode->GetSize( bufferIndex );
1876 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1877 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1879 // Test with the actor's geometry.
1880 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1887 void Actor::SetLeaveRequired( bool required )
1889 mLeaveRequired = required;
1892 bool Actor::GetLeaveRequired() const
1894 return mLeaveRequired;
1897 void Actor::SetKeyboardFocusable( bool focusable )
1899 mKeyboardFocusable = focusable;
1902 bool Actor::IsKeyboardFocusable() const
1904 return mKeyboardFocusable;
1907 bool Actor::GetTouchRequired() const
1909 return !mTouchedSignal.Empty() || !mTouchSignal.Empty() || mDerivedRequiresTouch;
1912 bool Actor::GetHoverRequired() const
1914 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1917 bool Actor::GetWheelEventRequired() const
1919 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1922 bool Actor::IsHittable() const
1924 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1927 ActorGestureData& Actor::GetGestureData()
1929 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1930 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1931 if( NULL == mGestureData )
1933 mGestureData = new ActorGestureData;
1935 return *mGestureData;
1938 bool Actor::IsGestureRequred( Gesture::Type type ) const
1940 return mGestureData && mGestureData->IsGestureRequred( type );
1943 bool Actor::EmitTouchEventSignal( const TouchEvent& event, const Dali::TouchData& touch )
1945 bool consumed = false;
1947 if( !mTouchSignal.Empty() )
1949 Dali::Actor handle( this );
1950 consumed = mTouchSignal.Emit( handle, touch );
1953 if( !mTouchedSignal.Empty() )
1955 Dali::Actor handle( this );
1956 consumed |= mTouchedSignal.Emit( handle, event );
1961 // Notification for derived classes
1962 consumed = OnTouchEvent( event ); // TODO
1968 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1970 bool consumed = false;
1972 if( !mHoveredSignal.Empty() )
1974 Dali::Actor handle( this );
1975 consumed = mHoveredSignal.Emit( handle, event );
1980 // Notification for derived classes
1981 consumed = OnHoverEvent( event );
1987 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1989 bool consumed = false;
1991 if( !mWheelEventSignal.Empty() )
1993 Dali::Actor handle( this );
1994 consumed = mWheelEventSignal.Emit( handle, event );
1999 // Notification for derived classes
2000 consumed = OnWheelEvent( event );
2006 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
2008 if( ! mVisibilityChangedSignal.Empty() )
2010 Dali::Actor handle( this );
2011 mVisibilityChangedSignal.Emit( handle, visible, type );
2015 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
2017 return mTouchedSignal;
2020 Dali::Actor::TouchDataSignalType& Actor::TouchSignal()
2022 return mTouchSignal;
2025 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
2027 return mHoveredSignal;
2030 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
2032 return mWheelEventSignal;
2035 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
2037 return mOnStageSignal;
2040 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
2042 return mOffStageSignal;
2045 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
2047 return mOnRelayoutSignal;
2050 DevelActor::VisibilityChangedSignalType& Actor::VisibilityChangedSignal()
2052 return mVisibilityChangedSignal;
2055 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
2057 bool connected( true );
2058 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
2060 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
2062 actor->TouchedSignal().Connect( tracker, functor );
2064 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
2066 actor->HoveredSignal().Connect( tracker, functor );
2068 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
2070 actor->WheelEventSignal().Connect( tracker, functor );
2072 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
2074 actor->OnStageSignal().Connect( tracker, functor );
2076 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
2078 actor->OffStageSignal().Connect( tracker, functor );
2080 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
2082 actor->OnRelayoutSignal().Connect( tracker, functor );
2084 else if( 0 == signalName.compare( SIGNAL_TOUCH ) )
2086 actor->TouchSignal().Connect( tracker, functor );
2090 // signalName does not match any signal
2097 Actor::Actor( DerivedType derivedType )
2102 mParentOrigin( NULL ),
2103 mAnchorPoint( NULL ),
2104 mRelayoutData( NULL ),
2105 mGestureData( NULL ),
2106 mTargetOrientation( Quaternion::IDENTITY ),
2107 mTargetColor( Color::WHITE ),
2108 mTargetSize( Vector3::ZERO ),
2109 mTargetPosition( Vector3::ZERO ),
2110 mTargetScale( Vector3::ONE ),
2112 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
2116 mIsRoot( ROOT_LAYER == derivedType ),
2117 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2118 mIsOnStage( false ),
2120 mLeaveRequired( false ),
2121 mKeyboardFocusable( false ),
2122 mDerivedRequiresTouch( false ),
2123 mDerivedRequiresHover( false ),
2124 mDerivedRequiresWheelEvent( false ),
2125 mOnStageSignalled( false ),
2126 mInsideOnSizeSet( false ),
2127 mInheritPosition( true ),
2128 mInheritOrientation( true ),
2129 mInheritScale( true ),
2130 mPositionUsesAnchorPoint( true ),
2132 mDrawMode( DrawMode::NORMAL ),
2133 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2134 mColorMode( Node::DEFAULT_COLOR_MODE ),
2135 mClippingMode( ClippingMode::DISABLED )
2139 void Actor::Initialize()
2142 SceneGraph::Node* node = CreateNode();
2144 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
2145 mNode = node; // Keep raw-pointer to Node
2149 GetEventThreadServices().RegisterObject( this );
2154 // Remove mParent pointers from children even if we're destroying core,
2155 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2158 ActorConstIter endIter = mChildren->end();
2159 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2161 (*iter)->SetParent( NULL );
2167 // Guard to allow handle destruction after Core has been destroyed
2168 if( EventThreadServices::IsCoreRunning() )
2172 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2173 mNode = NULL; // Node is about to be destroyed
2176 GetEventThreadServices().UnregisterObject( this );
2179 // Cleanup optional gesture data
2180 delete mGestureData;
2182 // Cleanup optional parent origin and anchor
2183 delete mParentOrigin;
2184 delete mAnchorPoint;
2186 // Delete optional relayout data
2189 delete mRelayoutData;
2193 void Actor::ConnectToStage( unsigned int parentDepth )
2195 // This container is used instead of walking the Actor hierarchy.
2196 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
2197 ActorContainer connectionList;
2199 StagePtr stage = Stage::GetCurrent();
2202 stage->RequestRebuildDepthTree();
2205 // This stage is atomic i.e. not interrupted by user callbacks.
2206 RecursiveConnectToStage( connectionList, parentDepth + 1 );
2208 // Notify applications about the newly connected actors.
2209 const ActorIter endIter = connectionList.end();
2210 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2212 (*iter)->NotifyStageConnection();
2218 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth )
2220 DALI_ASSERT_ALWAYS( !OnStage() );
2225 ConnectToSceneGraph();
2227 // Notification for internal derived classes
2228 OnStageConnectionInternal();
2230 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2231 connectionList.push_back( ActorPtr( this ) );
2233 // Recursively connect children
2236 ActorConstIter endIter = mChildren->end();
2237 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2239 (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
2245 * This method is called when the Actor is connected to the Stage.
2246 * The parent must have added its Node to the scene-graph.
2247 * The child must connect its Node to the parent's Node.
2248 * This is recursive; the child calls ConnectToStage() for its children.
2250 void Actor::ConnectToSceneGraph()
2252 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2256 // Reparent Node in next Update
2257 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode );
2260 // Request relayout on all actors that are added to the scenegraph
2263 // Notification for Object::Observers
2267 void Actor::NotifyStageConnection()
2269 // Actors can be removed (in a callback), before the on-stage stage is reported.
2270 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2271 if( OnStage() && !mOnStageSignalled )
2273 // Notification for external (CustomActor) derived classes
2274 OnStageConnectionExternal( mDepth );
2276 if( !mOnStageSignal.Empty() )
2278 Dali::Actor handle( this );
2279 mOnStageSignal.Emit( handle );
2282 // Guard against Remove during callbacks
2285 mOnStageSignalled = true; // signal required next time Actor is removed
2290 void Actor::DisconnectFromStage()
2292 // This container is used instead of walking the Actor hierachy.
2293 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2294 ActorContainer disconnectionList;
2296 StagePtr stage = Stage::GetCurrent();
2299 stage->RequestRebuildDepthTree();
2302 // This stage is atomic i.e. not interrupted by user callbacks
2303 RecursiveDisconnectFromStage( disconnectionList );
2305 // Notify applications about the newly disconnected actors.
2306 const ActorIter endIter = disconnectionList.end();
2307 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2309 (*iter)->NotifyStageDisconnection();
2313 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2315 DALI_ASSERT_ALWAYS( OnStage() );
2317 // Recursively disconnect children
2320 ActorConstIter endIter = mChildren->end();
2321 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2323 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2327 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2328 disconnectionList.push_back( ActorPtr( this ) );
2330 // Notification for internal derived classes
2331 OnStageDisconnectionInternal();
2333 DisconnectFromSceneGraph();
2339 * This method is called by an actor or its parent, before a node removal message is sent.
2340 * This is recursive; the child calls DisconnectFromStage() for its children.
2342 void Actor::DisconnectFromSceneGraph()
2344 // Notification for Object::Observers
2345 OnSceneObjectRemove();
2348 void Actor::NotifyStageDisconnection()
2350 // Actors can be added (in a callback), before the off-stage state is reported.
2351 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2352 // only do this step if there is a stage, i.e. Core is not being shut down
2353 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2355 // Notification for external (CustomeActor) derived classes
2356 OnStageDisconnectionExternal();
2358 if( !mOffStageSignal.Empty() )
2360 Dali::Actor handle( this );
2361 mOffStageSignal.Emit( handle );
2364 // Guard against Add during callbacks
2367 mOnStageSignalled = false; // signal required next time Actor is added
2372 bool Actor::IsNodeConnected() const
2374 bool connected( false );
2376 if( OnStage() && ( NULL != mNode ) )
2378 if( IsRoot() || mNode->GetParent() )
2387 // This method generates the depth tree using the recursive function below,
2388 // then walks the tree and sets a depth index based on traversal order. It
2389 // sends a single message to update manager to update all the actor's nodes in this
2390 // tree with the depth index. The sceneGraphNodeDepths vector's elements are ordered
2391 // by depth, and could be used to reduce sorting in the update thread.
2392 void Actor::RebuildDepthTree()
2394 DALI_LOG_TIMER_START(depthTimer);
2396 DepthNodeMemoryPool nodeMemoryPool;
2397 ActorDepthTreeNode* rootNode = new (nodeMemoryPool.AllocateRaw()) ActorDepthTreeNode( this, mSiblingOrder );
2399 int actorCount = BuildDepthTree( nodeMemoryPool, rootNode );
2401 // Vector of scene-graph nodes and their depths to send to UpdateManager
2402 // in a single message
2403 SceneGraph::NodeDepths* sceneGraphNodeDepths = new SceneGraph::NodeDepths(actorCount);
2405 // Traverse depth tree and set mSortedDepth on each actor and scenegraph node
2406 uint32_t sortOrder = 1u; // Don't start at zero, as visual depth can be negative
2407 ActorDepthTreeNode* currentNode = rootNode;
2408 bool firstVisit = true;
2409 while( currentNode != rootNode || firstVisit)
2413 // Visit node, performing action
2414 for( std::vector<Actor*>::iterator iter = currentNode->mActors.begin(); iter != currentNode->mActors.end(); ++iter )
2416 (*iter)->mSortedDepth = sortOrder * DevelLayer::SIBLING_ORDER_MULTIPLIER;
2417 sceneGraphNodeDepths->Add( const_cast<SceneGraph::Node*>((*iter)->mNode), (*iter)->mSortedDepth );
2422 if( currentNode->mFirstChildNode )
2424 currentNode = currentNode->mFirstChildNode;
2426 else // leaf node, goto next sibling, or return up tree.
2428 bool breakout=false;
2429 while( ! currentNode->mNextSiblingNode )
2431 if( currentNode == rootNode ) // If we get to root of tree, stop
2436 currentNode = currentNode->mParentNode;
2443 currentNode = currentNode->mNextSiblingNode;
2447 SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths );
2448 DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree create time: ");
2452 * Structure to store the actor's associated node in the depth tree for child
2455 struct ActorNodePair
2458 ActorDepthTreeNode* node;
2459 ActorNodePair( Actor* actor, ActorDepthTreeNode* node )
2467 * Descend actor tree, building a depth tree based on actor's sibling order.
2468 * Actors with the same sibling order share the same depth tree. Siblings
2469 * in the depth tree are ordered by actor's sibling order.
2471 * An actor tree like this:
2478 * A(SO:1) B(SO:2) C(SO:1)
2481 * D(SO:0) E(SO:0) F(SO:0) G(SO:1) H(SO:0)
2483 * will end up as a depth tree like this:
2485 * RootNode [ Root ] -> NULL
2488 * Node [ A, C ] ------------------------> Node [ B ] -> NULL
2491 * Node [ D, E, H ] -> Node [ G ] -> NULL Node [ F ] -> NULL
2496 * (All nodes also point to their parents to enable storage free traversal)
2498 int Actor::BuildDepthTree( DepthNodeMemoryPool& nodeMemoryPool, ActorDepthTreeNode* node )
2500 int treeCount=1; // Count self and children
2502 // Create/add to children of this node
2505 std::vector<ActorNodePair> storedChildren;
2506 storedChildren.reserve( mChildren->size() );
2508 for( ActorContainer::iterator it = mChildren->begin(); it != mChildren->end(); ++it )
2510 Actor* childActor = (*it).Get();
2511 if( childActor->IsLayer() )
2513 Layer* layer = static_cast<Layer*>(childActor);
2514 if( layer->GetBehavior() == Dali::Layer::LAYER_3D )
2516 // Ignore this actor and children.
2521 // If no existing depth node children
2522 if( node->mFirstChildNode == NULL )
2524 node->mFirstChildNode = new (nodeMemoryPool.AllocateRaw()) ActorDepthTreeNode( childActor, childActor->mSiblingOrder );
2525 node->mFirstChildNode->mParentNode = node;
2526 storedChildren.push_back(ActorNodePair( childActor, node->mFirstChildNode ));
2528 else // find child node with matching sibling order (insertion sort)
2530 bool addedChildActor = false;
2532 // depth tree child nodes ordered by sibling order
2533 ActorDepthTreeNode* lastNode = NULL;
2534 for( ActorDepthTreeNode* childNode = node->mFirstChildNode; childNode != NULL; childNode = childNode->mNextSiblingNode )
2536 uint16_t actorSiblingOrder = childActor->mSiblingOrder;
2537 uint16_t currentSiblingOrder = childNode->GetSiblingOrder();
2539 if( actorSiblingOrder == currentSiblingOrder )
2541 // Don't need a new depth node, add to existing node
2542 childNode->AddActor( childActor );
2543 storedChildren.push_back(ActorNodePair( childActor, childNode ));
2544 addedChildActor = true;
2547 else if( actorSiblingOrder < currentSiblingOrder )
2551 lastNode = childNode;
2554 // No matching sibling order - create new node and insert into sibling list
2555 if( !addedChildActor )
2557 ActorDepthTreeNode* newNode = new (nodeMemoryPool.AllocateRaw()) ActorDepthTreeNode( childActor, childActor->mSiblingOrder );
2559 newNode->mParentNode = node;
2560 storedChildren.push_back(ActorNodePair( childActor, newNode ));
2562 if( lastNode == NULL ) // Insert at start of siblings
2564 ActorDepthTreeNode* nextNode = node->mFirstChildNode;
2565 node->mFirstChildNode = newNode;
2566 newNode->mNextSiblingNode = nextNode;
2568 else // insert into siblings after last node
2570 newNode->mNextSiblingNode = lastNode->mNextSiblingNode;
2571 lastNode->mNextSiblingNode = newNode;
2577 // Order of descent doesn't matter; we're using insertion to sort.
2578 for( std::vector<ActorNodePair>::iterator iter = storedChildren.begin(); iter != storedChildren.end(); ++iter )
2580 treeCount += iter->actor->BuildDepthTree( nodeMemoryPool, iter->node );
2586 unsigned int Actor::GetDefaultPropertyCount() const
2588 return DEFAULT_PROPERTY_COUNT;
2591 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2593 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2595 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2597 indices.PushBack( i );
2601 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2603 if( index < DEFAULT_PROPERTY_COUNT )
2605 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2611 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2613 Property::Index index = Property::INVALID_INDEX;
2615 // Look for name in default properties
2616 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2618 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2619 if( 0 == name.compare( property->name ) )
2629 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2631 if( index < DEFAULT_PROPERTY_COUNT )
2633 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2639 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2641 if( index < DEFAULT_PROPERTY_COUNT )
2643 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2649 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2651 if( index < DEFAULT_PROPERTY_COUNT )
2653 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2659 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2661 if( index < DEFAULT_PROPERTY_COUNT )
2663 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2666 // index out of range...return Property::NONE
2667 return Property::NONE;
2670 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2674 case Dali::Actor::Property::PARENT_ORIGIN:
2676 Property::Type type = property.GetType();
2677 if( type == Property::VECTOR3 )
2679 SetParentOrigin( property.Get< Vector3 >() );
2681 else if ( type == Property::STRING )
2683 std::string parentOriginString;
2684 property.Get( parentOriginString );
2685 Vector3 parentOrigin;
2686 if( GetParentOriginConstant( parentOriginString, parentOrigin ) )
2688 SetParentOrigin( parentOrigin );
2694 case Dali::Actor::Property::PARENT_ORIGIN_X:
2696 SetParentOriginX( property.Get< float >() );
2700 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2702 SetParentOriginY( property.Get< float >() );
2706 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2708 SetParentOriginZ( property.Get< float >() );
2712 case Dali::Actor::Property::ANCHOR_POINT:
2714 Property::Type type = property.GetType();
2715 if( type == Property::VECTOR3 )
2717 SetAnchorPoint( property.Get< Vector3 >() );
2719 else if ( type == Property::STRING )
2721 std::string anchorPointString;
2722 property.Get( anchorPointString );
2724 if( GetAnchorPointConstant( anchorPointString, anchor ) )
2726 SetAnchorPoint( anchor );
2732 case Dali::Actor::Property::ANCHOR_POINT_X:
2734 SetAnchorPointX( property.Get< float >() );
2738 case Dali::Actor::Property::ANCHOR_POINT_Y:
2740 SetAnchorPointY( property.Get< float >() );
2744 case Dali::Actor::Property::ANCHOR_POINT_Z:
2746 SetAnchorPointZ( property.Get< float >() );
2750 case Dali::Actor::Property::SIZE:
2752 SetSize( property.Get< Vector3 >() );
2756 case Dali::Actor::Property::SIZE_WIDTH:
2758 SetWidth( property.Get< float >() );
2762 case Dali::Actor::Property::SIZE_HEIGHT:
2764 SetHeight( property.Get< float >() );
2768 case Dali::Actor::Property::SIZE_DEPTH:
2770 SetDepth( property.Get< float >() );
2774 case Dali::Actor::Property::POSITION:
2776 SetPosition( property.Get< Vector3 >() );
2780 case Dali::Actor::Property::POSITION_X:
2782 SetX( property.Get< float >() );
2786 case Dali::Actor::Property::POSITION_Y:
2788 SetY( property.Get< float >() );
2792 case Dali::Actor::Property::POSITION_Z:
2794 SetZ( property.Get< float >() );
2798 case Dali::Actor::Property::ORIENTATION:
2800 SetOrientation( property.Get< Quaternion >() );
2804 case Dali::Actor::Property::SCALE:
2806 SetScale( property.Get< Vector3 >() );
2810 case Dali::Actor::Property::SCALE_X:
2812 SetScaleX( property.Get< float >() );
2816 case Dali::Actor::Property::SCALE_Y:
2818 SetScaleY( property.Get< float >() );
2822 case Dali::Actor::Property::SCALE_Z:
2824 SetScaleZ( property.Get< float >() );
2828 case Dali::Actor::Property::VISIBLE:
2830 SetVisible( property.Get< bool >() );
2834 case Dali::Actor::Property::COLOR:
2836 SetColor( property.Get< Vector4 >() );
2840 case Dali::Actor::Property::COLOR_RED:
2842 SetColorRed( property.Get< float >() );
2846 case Dali::Actor::Property::COLOR_GREEN:
2848 SetColorGreen( property.Get< float >() );
2852 case Dali::Actor::Property::COLOR_BLUE:
2854 SetColorBlue( property.Get< float >() );
2858 case Dali::Actor::Property::COLOR_ALPHA:
2859 case Dali::DevelActor::Property::OPACITY:
2862 if( property.Get( value ) )
2864 SetOpacity( value );
2869 case Dali::Actor::Property::NAME:
2871 SetName( property.Get< std::string >() );
2875 case Dali::Actor::Property::SENSITIVE:
2877 SetSensitive( property.Get< bool >() );
2881 case Dali::Actor::Property::LEAVE_REQUIRED:
2883 SetLeaveRequired( property.Get< bool >() );
2887 case Dali::Actor::Property::INHERIT_POSITION:
2889 SetInheritPosition( property.Get< bool >() );
2893 case Dali::Actor::Property::INHERIT_ORIENTATION:
2895 SetInheritOrientation( property.Get< bool >() );
2899 case Dali::Actor::Property::INHERIT_SCALE:
2901 SetInheritScale( property.Get< bool >() );
2905 case Dali::Actor::Property::COLOR_MODE:
2907 ColorMode mode = mColorMode;
2908 if ( Scripting::GetEnumerationProperty< ColorMode >( property, COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT, mode ) )
2910 SetColorMode( mode );
2915 case Dali::Actor::Property::POSITION_INHERITANCE:
2917 PositionInheritanceMode mode = mPositionInheritanceMode;
2918 if( Scripting::GetEnumerationProperty< PositionInheritanceMode >( property, POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT, mode ) )
2920 SetPositionInheritanceMode( mode );
2925 case Dali::Actor::Property::DRAW_MODE:
2927 DrawMode::Type mode = mDrawMode;
2928 if( Scripting::GetEnumerationProperty< DrawMode::Type >( property, DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT, mode ) )
2930 SetDrawMode( mode );
2935 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2937 SetSizeModeFactor( property.Get< Vector3 >() );
2941 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2943 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
2944 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2946 SetResizePolicy( type, Dimension::WIDTH );
2951 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2953 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
2954 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2956 SetResizePolicy( type, Dimension::HEIGHT );
2961 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2963 SizeScalePolicy::Type type;
2964 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT, type ) )
2966 SetSizeScalePolicy( type );
2971 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2973 if( property.Get< bool >() )
2975 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2980 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2982 if( property.Get< bool >() )
2984 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2989 case Dali::Actor::Property::PADDING:
2991 Vector4 padding = property.Get< Vector4 >();
2992 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2993 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2997 case Dali::Actor::Property::MINIMUM_SIZE:
2999 Vector2 size = property.Get< Vector2 >();
3000 SetMinimumSize( size.x, Dimension::WIDTH );
3001 SetMinimumSize( size.y, Dimension::HEIGHT );
3005 case Dali::Actor::Property::MAXIMUM_SIZE:
3007 Vector2 size = property.Get< Vector2 >();
3008 SetMaximumSize( size.x, Dimension::WIDTH );
3009 SetMaximumSize( size.y, Dimension::HEIGHT );
3013 case Dali::DevelActor::Property::SIBLING_ORDER:
3017 if( property.Get( value ) )
3019 if( static_cast<unsigned int>(value) != mSiblingOrder )
3021 SetSiblingOrder( value );
3027 case Dali::Actor::Property::CLIPPING_MODE:
3029 ClippingMode::Type convertedValue = mClippingMode;
3030 if( Scripting::GetEnumerationProperty< ClippingMode::Type >( property, CLIPPING_MODE_TABLE, CLIPPING_MODE_TABLE_COUNT, convertedValue ) )
3032 mClippingMode = convertedValue;
3035 SetClippingModeMessage( GetEventThreadServices(), *mNode, mClippingMode );
3041 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
3044 if( property.Get( value ) && value != mPositionUsesAnchorPoint )
3046 mPositionUsesAnchorPoint = value;
3049 SetPositionUsesAnchorPointMessage( GetEventThreadServices(), *mNode, mPositionUsesAnchorPoint );
3057 // this can happen in the case of a non-animatable default property so just do nothing
3063 // TODO: This method needs to be removed
3064 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
3066 switch( entry.GetType() )
3068 case Property::BOOLEAN:
3070 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
3071 DALI_ASSERT_DEBUG( NULL != property );
3073 // property is being used in a separate thread; queue a message to set the property
3074 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
3079 case Property::INTEGER:
3081 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
3082 DALI_ASSERT_DEBUG( NULL != property );
3084 // property is being used in a separate thread; queue a message to set the property
3085 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
3090 case Property::FLOAT:
3092 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
3093 DALI_ASSERT_DEBUG( NULL != property );
3095 // property is being used in a separate thread; queue a message to set the property
3096 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
3101 case Property::VECTOR2:
3103 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
3104 DALI_ASSERT_DEBUG( NULL != property );
3106 // property is being used in a separate thread; queue a message to set the property
3107 if(entry.componentIndex == 0)
3109 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
3111 else if(entry.componentIndex == 1)
3113 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
3117 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
3123 case Property::VECTOR3:
3125 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
3126 DALI_ASSERT_DEBUG( NULL != property );
3128 // property is being used in a separate thread; queue a message to set the property
3129 if(entry.componentIndex == 0)
3131 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
3133 else if(entry.componentIndex == 1)
3135 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
3137 else if(entry.componentIndex == 2)
3139 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
3143 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
3149 case Property::VECTOR4:
3151 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
3152 DALI_ASSERT_DEBUG( NULL != property );
3154 // property is being used in a separate thread; queue a message to set the property
3155 if(entry.componentIndex == 0)
3157 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
3159 else if(entry.componentIndex == 1)
3161 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
3163 else if(entry.componentIndex == 2)
3165 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
3167 else if(entry.componentIndex == 3)
3169 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
3173 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3179 case Property::ROTATION:
3181 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3182 DALI_ASSERT_DEBUG( NULL != property );
3184 // property is being used in a separate thread; queue a message to set the property
3185 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3190 case Property::MATRIX:
3192 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3193 DALI_ASSERT_DEBUG( NULL != property );
3195 // property is being used in a separate thread; queue a message to set the property
3196 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3201 case Property::MATRIX3:
3203 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3204 DALI_ASSERT_DEBUG( NULL != property );
3206 // property is being used in a separate thread; queue a message to set the property
3207 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3214 // nothing to do for other types
3219 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3221 Property::Value value;
3223 if( ! GetCachedPropertyValue( index, value ) )
3225 // If property value is not stored in the event-side, then it must be a scene-graph only property
3226 GetCurrentPropertyValue( index, value );
3232 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
3234 Property::Value value;
3236 if( ! GetCurrentPropertyValue( index, value ) )
3238 // If unable to retrieve scene-graph property value, then it must be an event-side only property
3239 GetCachedPropertyValue( index, value );
3245 void Actor::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
3247 switch( animationType )
3250 case Animation::BETWEEN:
3254 case Dali::Actor::Property::SIZE:
3256 if( value.Get( mTargetSize ) )
3258 // Notify deriving classes
3259 OnSizeAnimation( animation, mTargetSize );
3264 case Dali::Actor::Property::SIZE_WIDTH:
3266 if( value.Get( mTargetSize.width ) )
3268 // Notify deriving classes
3269 OnSizeAnimation( animation, mTargetSize );
3274 case Dali::Actor::Property::SIZE_HEIGHT:
3276 if( value.Get( mTargetSize.height ) )
3278 // Notify deriving classes
3279 OnSizeAnimation( animation, mTargetSize );
3284 case Dali::Actor::Property::SIZE_DEPTH:
3286 if( value.Get( mTargetSize.depth ) )
3288 // Notify deriving classes
3289 OnSizeAnimation( animation, mTargetSize );
3294 case Dali::Actor::Property::POSITION:
3296 value.Get( mTargetPosition );
3300 case Dali::Actor::Property::POSITION_X:
3302 value.Get( mTargetPosition.x );
3306 case Dali::Actor::Property::POSITION_Y:
3308 value.Get( mTargetPosition.y );
3312 case Dali::Actor::Property::POSITION_Z:
3314 value.Get( mTargetPosition.z );
3318 case Dali::Actor::Property::ORIENTATION:
3320 value.Get( mTargetOrientation );
3324 case Dali::Actor::Property::SCALE:
3326 value.Get( mTargetScale );
3330 case Dali::Actor::Property::SCALE_X:
3332 value.Get( mTargetScale.x );
3336 case Dali::Actor::Property::SCALE_Y:
3338 value.Get( mTargetScale.y );
3342 case Dali::Actor::Property::SCALE_Z:
3344 value.Get( mTargetScale.z );
3348 case Dali::Actor::Property::VISIBLE:
3350 SetVisibleInternal( value.Get< bool >(), SendMessage::FALSE );
3354 case Dali::Actor::Property::COLOR:
3356 value.Get( mTargetColor );
3360 case Dali::Actor::Property::COLOR_RED:
3362 value.Get( mTargetColor.r );
3366 case Dali::Actor::Property::COLOR_GREEN:
3368 value.Get( mTargetColor.g );
3372 case Dali::Actor::Property::COLOR_BLUE:
3374 value.Get( mTargetColor.b );
3378 case Dali::Actor::Property::COLOR_ALPHA:
3379 case Dali::DevelActor::Property::OPACITY:
3381 value.Get( mTargetColor.a );
3387 // Not an animatable property. Do nothing.
3398 case Dali::Actor::Property::SIZE:
3400 if( AdjustValue< Vector3 >( mTargetSize, value ) )
3402 // Notify deriving classes
3403 OnSizeAnimation( animation, mTargetSize );
3408 case Dali::Actor::Property::SIZE_WIDTH:
3410 if( AdjustValue< float >( mTargetSize.width, value ) )
3412 // Notify deriving classes
3413 OnSizeAnimation( animation, mTargetSize );
3418 case Dali::Actor::Property::SIZE_HEIGHT:
3420 if( AdjustValue< float >( mTargetSize.height, value ) )
3422 // Notify deriving classes
3423 OnSizeAnimation( animation, mTargetSize );
3428 case Dali::Actor::Property::SIZE_DEPTH:
3430 if( AdjustValue< float >( mTargetSize.depth, value ) )
3432 // Notify deriving classes
3433 OnSizeAnimation( animation, mTargetSize );
3438 case Dali::Actor::Property::POSITION:
3440 AdjustValue< Vector3 >( mTargetPosition, value );
3444 case Dali::Actor::Property::POSITION_X:
3446 AdjustValue< float >( mTargetPosition.x, value );
3450 case Dali::Actor::Property::POSITION_Y:
3452 AdjustValue< float >( mTargetPosition.y, value );
3456 case Dali::Actor::Property::POSITION_Z:
3458 AdjustValue< float >( mTargetPosition.z, value );
3462 case Dali::Actor::Property::ORIENTATION:
3464 Quaternion relativeValue;
3465 if( value.Get( relativeValue ) )
3467 mTargetOrientation *= relativeValue;
3472 case Dali::Actor::Property::SCALE:
3474 AdjustValue< Vector3 >( mTargetScale, value );
3478 case Dali::Actor::Property::SCALE_X:
3480 AdjustValue< float >( mTargetScale.x, value );
3484 case Dali::Actor::Property::SCALE_Y:
3486 AdjustValue< float >( mTargetScale.y, value );
3490 case Dali::Actor::Property::SCALE_Z:
3492 AdjustValue< float >( mTargetScale.z, value );
3496 case Dali::Actor::Property::VISIBLE:
3498 bool relativeValue = false;
3499 if( value.Get( relativeValue ) )
3501 bool visible = mVisible || relativeValue;
3502 SetVisibleInternal( visible, SendMessage::FALSE );
3507 case Dali::Actor::Property::COLOR:
3509 AdjustValue< Vector4 >( mTargetColor, value );
3513 case Dali::Actor::Property::COLOR_RED:
3515 AdjustValue< float >( mTargetColor.r, value );
3519 case Dali::Actor::Property::COLOR_GREEN:
3521 AdjustValue< float >( mTargetColor.g, value );
3525 case Dali::Actor::Property::COLOR_BLUE:
3527 AdjustValue< float >( mTargetColor.b, value );
3531 case Dali::Actor::Property::COLOR_ALPHA:
3532 case Dali::DevelActor::Property::OPACITY:
3534 AdjustValue< float >( mTargetColor.a, value );
3540 // Not an animatable property. Do nothing.
3549 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3554 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3556 // This method should only return an object connected to the scene-graph
3557 return OnStage() ? mNode : NULL;
3560 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3562 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3564 const PropertyBase* property( NULL );
3566 // This method should only return a property of an object connected to the scene-graph
3572 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3574 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3575 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3577 property = animatable->GetSceneGraphProperty();
3579 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3580 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3582 CustomPropertyMetadata* custom = FindCustomProperty( index );
3583 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3585 property = custom->GetSceneGraphProperty();
3587 else if( NULL != mNode )
3591 case Dali::Actor::Property::SIZE:
3592 property = &mNode->mSize;
3595 case Dali::Actor::Property::SIZE_WIDTH:
3596 property = &mNode->mSize;
3599 case Dali::Actor::Property::SIZE_HEIGHT:
3600 property = &mNode->mSize;
3603 case Dali::Actor::Property::SIZE_DEPTH:
3604 property = &mNode->mSize;
3607 case Dali::Actor::Property::POSITION:
3608 property = &mNode->mPosition;
3611 case Dali::Actor::Property::POSITION_X:
3612 property = &mNode->mPosition;
3615 case Dali::Actor::Property::POSITION_Y:
3616 property = &mNode->mPosition;
3619 case Dali::Actor::Property::POSITION_Z:
3620 property = &mNode->mPosition;
3623 case Dali::Actor::Property::ORIENTATION:
3624 property = &mNode->mOrientation;
3627 case Dali::Actor::Property::SCALE:
3628 property = &mNode->mScale;
3631 case Dali::Actor::Property::SCALE_X:
3632 property = &mNode->mScale;
3635 case Dali::Actor::Property::SCALE_Y:
3636 property = &mNode->mScale;
3639 case Dali::Actor::Property::SCALE_Z:
3640 property = &mNode->mScale;
3643 case Dali::Actor::Property::VISIBLE:
3644 property = &mNode->mVisible;
3647 case Dali::Actor::Property::COLOR:
3648 property = &mNode->mColor;
3651 case Dali::Actor::Property::COLOR_RED:
3652 property = &mNode->mColor;
3655 case Dali::Actor::Property::COLOR_GREEN:
3656 property = &mNode->mColor;
3659 case Dali::Actor::Property::COLOR_BLUE:
3660 property = &mNode->mColor;
3663 case Dali::Actor::Property::COLOR_ALPHA:
3664 case Dali::DevelActor::Property::OPACITY:
3665 property = &mNode->mColor;
3676 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3678 const PropertyInputImpl* property( NULL );
3680 // This method should only return a property of an object connected to the scene-graph
3686 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3688 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3689 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3691 property = animatable->GetSceneGraphProperty();
3693 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3694 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3696 CustomPropertyMetadata* custom = FindCustomProperty( index );
3697 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3698 property = custom->GetSceneGraphProperty();
3700 else if( NULL != mNode )
3704 case Dali::Actor::Property::PARENT_ORIGIN:
3705 property = &mNode->mParentOrigin;
3708 case Dali::Actor::Property::PARENT_ORIGIN_X:
3709 property = &mNode->mParentOrigin;
3712 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3713 property = &mNode->mParentOrigin;
3716 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3717 property = &mNode->mParentOrigin;
3720 case Dali::Actor::Property::ANCHOR_POINT:
3721 property = &mNode->mAnchorPoint;
3724 case Dali::Actor::Property::ANCHOR_POINT_X:
3725 property = &mNode->mAnchorPoint;
3728 case Dali::Actor::Property::ANCHOR_POINT_Y:
3729 property = &mNode->mAnchorPoint;
3732 case Dali::Actor::Property::ANCHOR_POINT_Z:
3733 property = &mNode->mAnchorPoint;
3736 case Dali::Actor::Property::SIZE:
3737 property = &mNode->mSize;
3740 case Dali::Actor::Property::SIZE_WIDTH:
3741 property = &mNode->mSize;
3744 case Dali::Actor::Property::SIZE_HEIGHT:
3745 property = &mNode->mSize;
3748 case Dali::Actor::Property::SIZE_DEPTH:
3749 property = &mNode->mSize;
3752 case Dali::Actor::Property::POSITION:
3753 property = &mNode->mPosition;
3756 case Dali::Actor::Property::POSITION_X:
3757 property = &mNode->mPosition;
3760 case Dali::Actor::Property::POSITION_Y:
3761 property = &mNode->mPosition;
3764 case Dali::Actor::Property::POSITION_Z:
3765 property = &mNode->mPosition;
3768 case Dali::Actor::Property::WORLD_POSITION:
3769 property = &mNode->mWorldPosition;
3772 case Dali::Actor::Property::WORLD_POSITION_X:
3773 property = &mNode->mWorldPosition;
3776 case Dali::Actor::Property::WORLD_POSITION_Y:
3777 property = &mNode->mWorldPosition;
3780 case Dali::Actor::Property::WORLD_POSITION_Z:
3781 property = &mNode->mWorldPosition;
3784 case Dali::Actor::Property::ORIENTATION:
3785 property = &mNode->mOrientation;
3788 case Dali::Actor::Property::WORLD_ORIENTATION:
3789 property = &mNode->mWorldOrientation;
3792 case Dali::Actor::Property::SCALE:
3793 property = &mNode->mScale;
3796 case Dali::Actor::Property::SCALE_X:
3797 property = &mNode->mScale;
3800 case Dali::Actor::Property::SCALE_Y:
3801 property = &mNode->mScale;
3804 case Dali::Actor::Property::SCALE_Z:
3805 property = &mNode->mScale;
3808 case Dali::Actor::Property::WORLD_SCALE:
3809 property = &mNode->mWorldScale;
3812 case Dali::Actor::Property::VISIBLE:
3813 property = &mNode->mVisible;
3816 case Dali::Actor::Property::COLOR:
3817 property = &mNode->mColor;
3820 case Dali::Actor::Property::COLOR_RED:
3821 property = &mNode->mColor;
3824 case Dali::Actor::Property::COLOR_GREEN:
3825 property = &mNode->mColor;
3828 case Dali::Actor::Property::COLOR_BLUE:
3829 property = &mNode->mColor;
3832 case Dali::Actor::Property::COLOR_ALPHA:
3833 case Dali::DevelActor::Property::OPACITY:
3835 property = &mNode->mColor;
3839 case Dali::Actor::Property::WORLD_COLOR:
3840 property = &mNode->mWorldColor;
3843 case Dali::Actor::Property::WORLD_MATRIX:
3844 property = &mNode->mWorldMatrix;
3855 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3857 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3859 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3861 // check whether the animatable property is registered already, if not then register one.
3862 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3863 if( animatableProperty )
3865 componentIndex = animatableProperty->componentIndex;
3872 case Dali::Actor::Property::PARENT_ORIGIN_X:
3873 case Dali::Actor::Property::ANCHOR_POINT_X:
3874 case Dali::Actor::Property::SIZE_WIDTH:
3875 case Dali::Actor::Property::POSITION_X:
3876 case Dali::Actor::Property::WORLD_POSITION_X:
3877 case Dali::Actor::Property::SCALE_X:
3878 case Dali::Actor::Property::COLOR_RED:
3884 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3885 case Dali::Actor::Property::ANCHOR_POINT_Y:
3886 case Dali::Actor::Property::SIZE_HEIGHT:
3887 case Dali::Actor::Property::POSITION_Y:
3888 case Dali::Actor::Property::WORLD_POSITION_Y:
3889 case Dali::Actor::Property::SCALE_Y:
3890 case Dali::Actor::Property::COLOR_GREEN:
3896 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3897 case Dali::Actor::Property::ANCHOR_POINT_Z:
3898 case Dali::Actor::Property::SIZE_DEPTH:
3899 case Dali::Actor::Property::POSITION_Z:
3900 case Dali::Actor::Property::WORLD_POSITION_Z:
3901 case Dali::Actor::Property::SCALE_Z:
3902 case Dali::Actor::Property::COLOR_BLUE:
3908 case Dali::Actor::Property::COLOR_ALPHA:
3909 case Dali::DevelActor::Property::OPACITY:
3923 return componentIndex;
3926 void Actor::SetParent( Actor* parent )
3930 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3934 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3937 // Instruct each actor to create a corresponding node in the scene graph
3938 ConnectToStage( parent->GetHierarchyDepth() );
3941 // Resolve the name and index for the child properties if any
3942 ResolveChildProperties();
3944 else // parent being set to NULL
3946 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3950 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3953 DALI_ASSERT_ALWAYS( mNode != NULL );
3957 // Disconnect the Node & its children from the scene-graph.
3958 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3961 // Instruct each actor to discard pointers to the scene-graph
3962 DisconnectFromStage();
3967 SceneGraph::Node* Actor::CreateNode() const
3972 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3975 Actor* actor = dynamic_cast< Actor* >( object );
3979 if( 0 == actionName.compare( ACTION_SHOW ) )
3981 actor->SetVisible( true );
3984 else if( 0 == actionName.compare( ACTION_HIDE ) )
3986 actor->SetVisible( false );
3994 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
3996 bool valueSet = true;
4000 case Dali::Actor::Property::PARENT_ORIGIN:
4002 value = GetCurrentParentOrigin();
4006 case Dali::Actor::Property::PARENT_ORIGIN_X:
4008 value = GetCurrentParentOrigin().x;
4012 case Dali::Actor::Property::PARENT_ORIGIN_Y:
4014 value = GetCurrentParentOrigin().y;
4018 case Dali::Actor::Property::PARENT_ORIGIN_Z:
4020 value = GetCurrentParentOrigin().z;
4024 case Dali::Actor::Property::ANCHOR_POINT:
4026 value = GetCurrentAnchorPoint();
4030 case Dali::Actor::Property::ANCHOR_POINT_X:
4032 value = GetCurrentAnchorPoint().x;
4036 case Dali::Actor::Property::ANCHOR_POINT_Y:
4038 value = GetCurrentAnchorPoint().y;
4042 case Dali::Actor::Property::ANCHOR_POINT_Z:
4044 value = GetCurrentAnchorPoint().z;
4048 case Dali::Actor::Property::SIZE:
4050 value = GetTargetSize();
4054 case Dali::Actor::Property::SIZE_WIDTH:
4056 value = GetTargetSize().width;
4060 case Dali::Actor::Property::SIZE_HEIGHT:
4062 value = GetTargetSize().height;
4066 case Dali::Actor::Property::SIZE_DEPTH:
4068 value = GetTargetSize().depth;
4072 case Dali::Actor::Property::POSITION:
4074 value = GetTargetPosition();
4078 case Dali::Actor::Property::POSITION_X:
4080 value = GetTargetPosition().x;
4084 case Dali::Actor::Property::POSITION_Y:
4086 value = GetTargetPosition().y;
4090 case Dali::Actor::Property::POSITION_Z:
4092 value = GetTargetPosition().z;
4096 case Dali::Actor::Property::ORIENTATION:
4098 value = mTargetOrientation;
4102 case Dali::Actor::Property::SCALE:
4104 value = mTargetScale;
4108 case Dali::Actor::Property::SCALE_X:
4110 value = mTargetScale.x;
4114 case Dali::Actor::Property::SCALE_Y:
4116 value = mTargetScale.y;
4120 case Dali::Actor::Property::SCALE_Z:
4122 value = mTargetScale.z;
4126 case Dali::Actor::Property::VISIBLE:
4132 case Dali::Actor::Property::COLOR:
4134 value = mTargetColor;
4138 case Dali::Actor::Property::COLOR_RED:
4140 value = mTargetColor.r;
4144 case Dali::Actor::Property::COLOR_GREEN:
4146 value = mTargetColor.g;
4150 case Dali::Actor::Property::COLOR_BLUE:
4152 value = mTargetColor.b;
4156 case Dali::Actor::Property::COLOR_ALPHA:
4157 case Dali::DevelActor::Property::OPACITY:
4159 value = mTargetColor.a;
4163 case Dali::Actor::Property::NAME:
4169 case Dali::Actor::Property::SENSITIVE:
4171 value = IsSensitive();
4175 case Dali::Actor::Property::LEAVE_REQUIRED:
4177 value = GetLeaveRequired();
4181 case Dali::Actor::Property::INHERIT_POSITION:
4183 value = IsPositionInherited();
4187 case Dali::Actor::Property::INHERIT_ORIENTATION:
4189 value = IsOrientationInherited();
4193 case Dali::Actor::Property::INHERIT_SCALE:
4195 value = IsScaleInherited();
4199 case Dali::Actor::Property::COLOR_MODE:
4201 value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
4205 case Dali::Actor::Property::POSITION_INHERITANCE:
4207 value = Scripting::GetLinearEnumerationName< PositionInheritanceMode >( GetPositionInheritanceMode(), POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT );
4211 case Dali::Actor::Property::DRAW_MODE:
4213 value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
4217 case Dali::Actor::Property::SIZE_MODE_FACTOR:
4219 value = GetSizeModeFactor();
4223 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
4225 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
4229 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
4231 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
4235 case Dali::Actor::Property::SIZE_SCALE_POLICY:
4237 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT );
4241 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
4243 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
4247 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
4249 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
4253 case Dali::Actor::Property::PADDING:
4255 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
4256 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
4257 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
4261 case Dali::Actor::Property::MINIMUM_SIZE:
4263 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
4267 case Dali::Actor::Property::MAXIMUM_SIZE:
4269 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
4273 case Dali::Actor::Property::CLIPPING_MODE:
4275 value = mClippingMode;
4279 case Dali::DevelActor::Property::SIBLING_ORDER:
4281 value = static_cast<int>(mSiblingOrder);
4285 case Dali::DevelActor::Property::SCREEN_POSITION:
4287 value = GetCurrentScreenPosition();
4291 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
4293 value = mPositionUsesAnchorPoint;
4299 // Must be a scene-graph only property
4308 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
4310 bool valueSet = true;
4314 case Dali::Actor::Property::SIZE:
4316 value = GetCurrentSize();
4320 case Dali::Actor::Property::SIZE_WIDTH:
4322 value = GetCurrentSize().width;
4326 case Dali::Actor::Property::SIZE_HEIGHT:
4328 value = GetCurrentSize().height;
4332 case Dali::Actor::Property::SIZE_DEPTH:
4334 value = GetCurrentSize().depth;
4338 case Dali::Actor::Property::POSITION:
4340 value = GetCurrentPosition();
4344 case Dali::Actor::Property::POSITION_X:
4346 value = GetCurrentPosition().x;
4350 case Dali::Actor::Property::POSITION_Y:
4352 value = GetCurrentPosition().y;
4356 case Dali::Actor::Property::POSITION_Z:
4358 value = GetCurrentPosition().z;
4362 case Dali::Actor::Property::WORLD_POSITION:
4364 value = GetCurrentWorldPosition();
4368 case Dali::Actor::Property::WORLD_POSITION_X:
4370 value = GetCurrentWorldPosition().x;
4374 case Dali::Actor::Property::WORLD_POSITION_Y:
4376 value = GetCurrentWorldPosition().y;
4380 case Dali::Actor::Property::WORLD_POSITION_Z:
4382 value = GetCurrentWorldPosition().z;
4386 case Dali::Actor::Property::ORIENTATION:
4388 value = GetCurrentOrientation();
4392 case Dali::Actor::Property::WORLD_ORIENTATION:
4394 value = GetCurrentWorldOrientation();
4398 case Dali::Actor::Property::SCALE:
4400 value = GetCurrentScale();
4404 case Dali::Actor::Property::SCALE_X:
4406 value = GetCurrentScale().x;
4410 case Dali::Actor::Property::SCALE_Y:
4412 value = GetCurrentScale().y;
4416 case Dali::Actor::Property::SCALE_Z:
4418 value = GetCurrentScale().z;
4422 case Dali::Actor::Property::WORLD_SCALE:
4424 value = GetCurrentWorldScale();
4428 case Dali::Actor::Property::COLOR:
4430 value = GetCurrentColor();
4434 case Dali::Actor::Property::COLOR_RED:
4436 value = GetCurrentColor().r;
4440 case Dali::Actor::Property::COLOR_GREEN:
4442 value = GetCurrentColor().g;
4446 case Dali::Actor::Property::COLOR_BLUE:
4448 value = GetCurrentColor().b;
4452 case Dali::Actor::Property::COLOR_ALPHA:
4453 case Dali::DevelActor::Property::OPACITY:
4455 value = GetCurrentColor().a;
4459 case Dali::Actor::Property::WORLD_COLOR:
4461 value = GetCurrentWorldColor();
4465 case Dali::Actor::Property::WORLD_MATRIX:
4467 value = GetCurrentWorldMatrix();
4471 case Dali::Actor::Property::VISIBLE:
4473 value = IsVisible();
4479 // Must be an event-side only property
4488 void Actor::EnsureRelayoutData()
4490 // Assign relayout data.
4491 if( !mRelayoutData )
4493 mRelayoutData = new RelayoutData();
4497 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
4499 // Check if actor is dependent on parent
4500 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4502 if( ( dimension & ( 1 << i ) ) )
4504 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4505 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
4515 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
4517 // Check if actor is dependent on children
4518 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4520 if( ( dimension & ( 1 << i ) ) )
4522 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4523 switch( resizePolicy )
4525 case ResizePolicy::FIT_TO_CHILDREN:
4526 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
4542 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
4544 return Actor::RelayoutDependentOnChildren( dimension );
4547 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
4549 // Check each possible dimension and see if it is dependent on the input one
4550 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4552 if( dimension & ( 1 << i ) )
4554 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
4561 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
4563 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4565 if( dimension & ( 1 << i ) )
4567 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
4572 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
4574 // If more than one dimension is requested, just return the first one found
4575 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4577 if( ( dimension & ( 1 << i ) ) )
4579 return mRelayoutData->negotiatedDimensions[ i ];
4583 return 0.0f; // Default
4586 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
4588 EnsureRelayoutData();
4590 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4592 if( dimension & ( 1 << i ) )
4594 mRelayoutData->dimensionPadding[ i ] = padding;
4599 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4601 if ( mRelayoutData )
4603 // If more than one dimension is requested, just return the first one found
4604 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4606 if( ( dimension & ( 1 << i ) ) )
4608 return mRelayoutData->dimensionPadding[ i ];
4613 return GetDefaultDimensionPadding();
4616 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4618 EnsureRelayoutData();
4620 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4622 if( dimension & ( 1 << i ) )
4624 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4629 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4631 if ( mRelayoutData )
4633 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4635 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4645 float Actor::GetHeightForWidthBase( float width )
4647 float height = 0.0f;
4649 const Vector3 naturalSize = GetNaturalSize();
4650 if( naturalSize.width > 0.0f )
4652 height = naturalSize.height * width / naturalSize.width;
4654 else // we treat 0 as 1:1 aspect ratio
4662 float Actor::GetWidthForHeightBase( float height )
4666 const Vector3 naturalSize = GetNaturalSize();
4667 if( naturalSize.height > 0.0f )
4669 width = naturalSize.width * height / naturalSize.height;
4671 else // we treat 0 as 1:1 aspect ratio
4679 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4681 // Fill to parent, taking size mode factor into account
4682 switch( child.GetResizePolicy( dimension ) )
4684 case ResizePolicy::FILL_TO_PARENT:
4686 return GetLatestSize( dimension );
4689 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4691 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4694 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4696 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4701 return GetLatestSize( dimension );
4706 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4708 // Can be overridden in derived class
4709 return CalculateChildSizeBase( child, dimension );
4712 float Actor::GetHeightForWidth( float width )
4714 // Can be overridden in derived class
4715 return GetHeightForWidthBase( width );
4718 float Actor::GetWidthForHeight( float height )
4720 // Can be overridden in derived class
4721 return GetWidthForHeightBase( height );
4724 float Actor::GetLatestSize( Dimension::Type dimension ) const
4726 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4729 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4731 Vector2 padding = GetPadding( dimension );
4733 return GetLatestSize( dimension ) + padding.x + padding.y;
4736 float Actor::NegotiateFromParent( Dimension::Type dimension )
4738 Actor* parent = GetParent();
4741 Vector2 padding( GetPadding( dimension ) );
4742 Vector2 parentPadding( parent->GetPadding( dimension ) );
4743 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4749 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4751 float maxDimensionPoint = 0.0f;
4753 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4755 ActorPtr child = GetChildAt( i );
4757 if( !child->RelayoutDependentOnParent( dimension ) )
4759 // Calculate the min and max points that the children range across
4760 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
4761 float dimensionSize = child->GetRelayoutSize( dimension );
4762 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4766 return maxDimensionPoint;
4769 float Actor::GetSize( Dimension::Type dimension ) const
4771 return GetDimensionValue( mTargetSize, dimension );
4774 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4776 return GetDimensionValue( GetNaturalSize(), dimension );
4779 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4781 switch( GetResizePolicy( dimension ) )
4783 case ResizePolicy::USE_NATURAL_SIZE:
4785 return GetNaturalSize( dimension );
4788 case ResizePolicy::FIXED:
4790 return GetDimensionValue( GetPreferredSize(), dimension );
4793 case ResizePolicy::USE_ASSIGNED_SIZE:
4795 return GetDimensionValue( maximumSize, dimension );
4798 case ResizePolicy::FILL_TO_PARENT:
4799 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4800 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4802 return NegotiateFromParent( dimension );
4805 case ResizePolicy::FIT_TO_CHILDREN:
4807 return NegotiateFromChildren( dimension );
4810 case ResizePolicy::DIMENSION_DEPENDENCY:
4812 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4815 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4817 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4820 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4822 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4834 return 0.0f; // Default
4837 float Actor::ClampDimension( float size, Dimension::Type dimension )
4839 const float minSize = GetMinimumSize( dimension );
4840 const float maxSize = GetMaximumSize( dimension );
4842 return std::max( minSize, std::min( size, maxSize ) );
4845 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4847 // Check if it needs to be negotiated
4848 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4850 // Check that we havn't gotten into an infinite loop
4851 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4852 bool recursionFound = false;
4853 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4855 if( *it == searchActor )
4857 recursionFound = true;
4862 if( !recursionFound )
4864 // Record the path that we have taken
4865 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4867 // Dimension dependency check
4868 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4870 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4872 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4874 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4878 // Parent dependency check
4879 Actor* parent = GetParent();
4880 if( parent && RelayoutDependentOnParent( dimension ) )
4882 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4885 // Children dependency check
4886 if( RelayoutDependentOnChildren( dimension ) )
4888 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4890 ActorPtr child = GetChildAt( i );
4892 // Only relayout child first if it is not dependent on this actor
4893 if( !child->RelayoutDependentOnParent( dimension ) )
4895 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
4900 // For deriving classes
4901 OnCalculateRelayoutSize( dimension );
4903 // All dependencies checked, calculate the size and set negotiated flag
4904 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4906 SetNegotiatedDimension( newSize, dimension );
4907 SetLayoutNegotiated( true, dimension );
4909 // For deriving classes
4910 OnLayoutNegotiated( newSize, dimension );
4912 // This actor has been successfully processed, pop it off the recursion stack
4913 recursionStack.pop_back();
4917 // TODO: Break infinite loop
4918 SetLayoutNegotiated( true, dimension );
4923 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4925 // Negotiate all dimensions that require it
4926 ActorDimensionStack recursionStack;
4928 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4930 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4933 NegotiateDimension( dimension, allocatedSize, recursionStack );
4937 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4939 switch( mRelayoutData->sizeSetPolicy )
4941 case SizeScalePolicy::USE_SIZE_SET:
4946 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4948 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4949 const Vector3 naturalSize = GetNaturalSize();
4950 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4952 const float sizeRatio = size.width / size.height;
4953 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4955 if( naturalSizeRatio < sizeRatio )
4957 return Vector2( naturalSizeRatio * size.height, size.height );
4959 else if( naturalSizeRatio > sizeRatio )
4961 return Vector2( size.width, size.width / naturalSizeRatio );
4972 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4974 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4975 const Vector3 naturalSize = GetNaturalSize();
4976 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4978 const float sizeRatio = size.width / size.height;
4979 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4981 if( naturalSizeRatio < sizeRatio )
4983 return Vector2( size.width, size.width / naturalSizeRatio );
4985 else if( naturalSizeRatio > sizeRatio )
4987 return Vector2( naturalSizeRatio * size.height, size.height );
5006 void Actor::SetNegotiatedSize( RelayoutContainer& container )
5008 // Do the set actor size
5009 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
5011 // Adjust for size set policy
5012 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
5014 // Lock the flag to stop recursive relayouts on set size
5015 mRelayoutData->insideRelayout = true;
5016 SetSize( negotiatedSize );
5017 mRelayoutData->insideRelayout = false;
5019 // Clear flags for all dimensions
5020 SetLayoutDirty( false );
5022 // Give deriving classes a chance to respond
5023 OnRelayout( negotiatedSize, container );
5025 if( !mOnRelayoutSignal.Empty() )
5027 Dali::Actor handle( this );
5028 mOnRelayoutSignal.Emit( handle );
5032 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
5034 // Force a size negotiation for actors that has assigned size during relayout
5035 // This is required as otherwise the flags that force a relayout will not
5036 // necessarilly be set. This will occur if the actor has already been laid out.
5037 // The dirty flags are then cleared. Then if the actor is added back into the
5038 // relayout container afterwards, the dirty flags would still be clear...
5039 // causing a relayout to be skipped. Here we force any actors added to the
5040 // container to be relayed out.
5041 DALI_LOG_TIMER_START( NegSizeTimer1 );
5043 if( GetUseAssignedSize(Dimension::WIDTH ) )
5045 SetLayoutNegotiated( false, Dimension::WIDTH );
5047 if( GetUseAssignedSize( Dimension::HEIGHT ) )
5049 SetLayoutNegotiated( false, Dimension::HEIGHT );
5052 // Do the negotiation
5053 NegotiateDimensions( allocatedSize );
5055 // Set the actor size
5056 SetNegotiatedSize( container );
5058 // Negotiate down to children
5059 const Vector2 newBounds = mTargetSize.GetVectorXY();
5061 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
5063 ActorPtr child = GetChildAt( i );
5065 // Forces children that have already been laid out to be relayed out
5066 // if they have assigned size during relayout.
5067 if( child->GetUseAssignedSize(Dimension::WIDTH) )
5069 child->SetLayoutNegotiated(false, Dimension::WIDTH);
5070 child->SetLayoutDirty(true, Dimension::WIDTH);
5073 if( child->GetUseAssignedSize(Dimension::HEIGHT) )
5075 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
5076 child->SetLayoutDirty(true, Dimension::HEIGHT);
5079 // Only relayout if required
5080 if( child->RelayoutRequired() )
5082 container.Add( Dali::Actor( child.Get() ), newBounds );
5085 DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
5088 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
5092 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5094 if( dimension & ( 1 << i ) )
5096 mRelayoutData->useAssignedSize[ i ] = use;
5102 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
5104 if ( mRelayoutData )
5106 // If more than one dimension is requested, just return the first one found
5107 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5109 if( dimension & ( 1 << i ) )
5111 return mRelayoutData->useAssignedSize[ i ];
5119 void Actor::RelayoutRequest( Dimension::Type dimension )
5121 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
5122 if( relayoutController )
5124 Dali::Actor self( this );
5125 relayoutController->RequestRelayout( self, dimension );
5129 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
5133 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
5137 void Actor::SetPreferredSize( const Vector2& size )
5139 EnsureRelayoutData();
5141 if( size.width > 0.0f )
5143 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
5146 if( size.height > 0.0f )
5148 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
5151 mRelayoutData->preferredSize = size;
5156 Vector2 Actor::GetPreferredSize() const
5158 if ( mRelayoutData )
5160 return Vector2( mRelayoutData->preferredSize );
5163 return GetDefaultPreferredSize();
5166 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
5168 EnsureRelayoutData();
5170 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5172 if( dimension & ( 1 << i ) )
5174 mRelayoutData->minimumSize[ i ] = size;
5181 float Actor::GetMinimumSize( Dimension::Type dimension ) const
5183 if ( mRelayoutData )
5185 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5187 if( dimension & ( 1 << i ) )
5189 return mRelayoutData->minimumSize[ i ];
5194 return 0.0f; // Default
5197 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
5199 EnsureRelayoutData();
5201 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5203 if( dimension & ( 1 << i ) )
5205 mRelayoutData->maximumSize[ i ] = size;
5212 float Actor::GetMaximumSize( Dimension::Type dimension ) const
5214 if ( mRelayoutData )
5216 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5218 if( dimension & ( 1 << i ) )
5220 return mRelayoutData->maximumSize[ i ];
5225 return FLT_MAX; // Default
5228 Object* Actor::GetParentObject() const
5233 void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
5235 if( mVisible != visible )
5237 if( sendMessage == SendMessage::TRUE && NULL != mNode )
5239 // mNode is being used in a separate thread; queue a message to set the value & base value
5240 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
5245 // Emit the signal on this actor and all its children
5246 EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
5250 void Actor::SetSiblingOrder( unsigned int order )
5252 mSiblingOrder = std::min( order, static_cast<unsigned int>( DevelLayer::SIBLING_ORDER_MULTIPLIER ) );
5256 StagePtr stage = Stage::GetCurrent();
5259 stage->RequestRebuildDepthTree();
5264 void Actor::DefragmentSiblingIndexes( ActorContainer& siblings )
5266 // Sibling index may not be in consecutive order as the sibling range is limited ( DevelLayer::SIBLING_ORDER_MULTIPLIER )
5267 // we need to remove the gaps and ensure the number start from 0 and consecutive hence have a full range.
5269 // Start at index 0, while index <= highest order
5270 // Find next index higher than 0
5271 // if nextHigher > index+1
5272 // set all nextHigher orders to index+1
5274 // Limitation: May reach the ceiling of DevelLayer::SIBLING_ORDER_MULTIPLIER with highest sibling.
5276 ActorIter end = siblings.end();
5277 int highestOrder = 0;
5278 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
5280 ActorPtr sibling = (*iter);
5281 int siblingOrder = sibling->mSiblingOrder;
5282 highestOrder = std::max( highestOrder, siblingOrder );
5285 for ( int index = 0; index <= highestOrder; index++ )
5287 int nextHighest = -1;
5289 // Find Next highest
5290 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
5292 ActorPtr sibling = (*iter);
5293 int siblingOrder = sibling->mSiblingOrder;
5295 if ( siblingOrder > index )
5297 if ( nextHighest == -1 )
5299 nextHighest = siblingOrder;
5301 nextHighest = std::min( nextHighest, siblingOrder );
5305 // Check if a gap exists between indexes, if so set next index to consecutive number
5306 if ( ( nextHighest - index ) > 1 )
5308 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
5310 ActorPtr sibling = (*iter);
5311 int siblingOrder = sibling->mSiblingOrder;
5312 if ( siblingOrder == nextHighest )
5314 sibling->mSiblingOrder = index + 1;
5315 if ( sibling->mSiblingOrder >= Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER )
5317 DALI_LOG_WARNING( "Reached max sibling order level for raising / lowering actors\n" );
5318 sibling->mSiblingOrder = Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER;
5320 sibling->SetSiblingOrder( sibling->mSiblingOrder );
5327 bool Actor::ShiftSiblingsLevels( ActorContainer& siblings, int targetLevelToShiftFrom )
5329 // Allows exclusive levels for an actor by shifting all sibling levels at the target and above by 1
5330 bool defragmentationRequired( false );
5331 ActorIter end = siblings.end();
5332 for( ActorIter iter = siblings.begin(); ( iter != end ) ; ++iter )
5334 // Move actors at nearest order and above up by 1
5335 ActorPtr sibling = (*iter);
5336 if ( sibling != this )
5338 // Iterate through container of actors, any actor with a sibling order of the target or greater should
5339 // be incremented by 1.
5340 if ( sibling->mSiblingOrder >= targetLevelToShiftFrom )
5342 sibling->mSiblingOrder++;
5343 if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
5345 // If a sibling order raises so that it is only 1 from the maximum allowed then set flag so
5346 // can re-order all sibling orders.
5347 defragmentationRequired = true;
5349 sibling->SetSiblingOrder( sibling->mSiblingOrder );
5353 return defragmentationRequired;
5359 1) Check if already at top and nothing to be done.
5360 This Actor can have highest sibling order but if not exclusive then another actor at same sibling
5361 order can be positioned above it due to insertion order of actors.
5362 2) Find nearest sibling level above, these are the siblings this actor needs to be above
5363 3) a) There may be other levels above this target level
5364 b) Increment all sibling levels at the level above nearest(target)
5365 c) Now have a vacant sibling level
5366 4) Set this actor's sibling level to nearest +1 as now vacated.
5368 Note May not just be sibling level + 1 as could be empty levels in-between
5373 ActorC ( sibling level 4 )
5374 ActorB ( sibling level 3 )
5375 ActorA ( sibling level 1 )
5377 2 ) ACTION: Raise A above B
5378 a) Find nearest level above A = Level 3
5379 b) Increment levels above Level 3
5381 ActorC ( sibling level 5 )
5382 ActorB ( sibling level 3 ) NEAREST
5383 ActorA ( sibling level 1 )
5385 3 ) Set Actor A sibling level to nearest +1 as vacant
5387 ActorC ( sibling level 5 )
5388 ActorA ( sibling level 4 )
5389 ActorB ( sibling level 3 )
5391 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5392 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5393 remove any empty sibling order gaps and start from sibling level 0 again.
5394 If the number of actors reaches this maximum and all using exclusive sibling order values then
5395 defragmention will stop and new sibling orders will be set to same max value.
5399 int nearestLevel = mSiblingOrder;
5400 int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
5401 bool defragmentationRequired( false );
5403 ActorContainer* siblings = mParent->mChildren;
5405 // Find Nearest sibling level above this actor
5406 ActorIter end = siblings->end();
5407 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
5409 ActorPtr sibling = (*iter);
5410 if ( sibling != this )
5412 int order = GetSiblingOrder( sibling );
5414 if ( ( order >= mSiblingOrder ) )
5416 int distanceToNextLevel = order - mSiblingOrder;
5417 if ( distanceToNextLevel < shortestDistanceToNextLevel )
5419 nearestLevel = order;
5420 shortestDistanceToNextLevel = distanceToNextLevel;
5426 if ( nearestLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at top
5428 mSiblingOrder = nearestLevel + 1; // Set sibling level to that above the nearest level
5429 defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
5430 // Move current actor to newly vacated order level
5431 SetSiblingOrder( mSiblingOrder );
5432 if ( defragmentationRequired )
5434 DefragmentSiblingIndexes( *siblings );
5437 SetSiblingOrder( mSiblingOrder );
5441 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5448 1) Check if actor already at bottom and if nothing needs to be done
5449 This Actor can have lowest sibling order but if not exclusive then another actor at same sibling
5450 order can be positioned above it due to insertion order of actors so need to move this actor below it.
5451 2) Find nearest sibling level below, this Actor needs to be below it
5452 3) a) Need to vacate a sibling level below nearest for this actor to occupy
5453 b) Shift up all sibling order values of actor at the nearest level and levels above it to vacate a level.
5454 c) Set this actor's sibling level to this newly vacated level.
5455 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5456 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5457 remove any empty sibling order gaps and start from sibling level 0 again.
5458 If the number of actors reaches this maximum and all using exclusive sibling order values then
5459 defragmention will stop and new sibling orders will be set to same max value.
5464 // 1) Find nearest level below
5465 int nearestLevel = mSiblingOrder;
5466 int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
5468 ActorContainer* siblings = mParent->mChildren;
5470 ActorIter end = siblings->end();
5471 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
5473 ActorPtr sibling = (*iter);
5474 if ( sibling != this )
5476 int order = GetSiblingOrder( sibling );
5478 if ( order <= mSiblingOrder )
5480 int distanceToNextLevel = mSiblingOrder - order;
5481 if ( distanceToNextLevel < shortestDistanceToNextLevel )
5483 nearestLevel = order;
5484 shortestDistanceToNextLevel = distanceToNextLevel;
5490 bool defragmentationRequired ( false );
5492 // 2) If actor already not at bottom, raise all actors at required level and above
5493 if ( shortestDistanceToNextLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at bottom
5495 mSiblingOrder = nearestLevel;
5496 defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
5497 // Move current actor to newly vacated order
5498 SetSiblingOrder( mSiblingOrder );
5499 if ( defragmentationRequired )
5501 DefragmentSiblingIndexes( *siblings );
5507 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5511 void Actor::RaiseToTop()
5514 1 ) Find highest sibling order actor
5515 2 ) If highest sibling level not itself then set sibling order to that + 1
5516 3 ) highest sibling order can be same as itself so need to increment over that
5517 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5518 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5519 remove any empty sibling order gaps and start from sibling level 0 again.
5520 If the number of actors reaches this maximum and all using exclusive sibling order values then
5521 defragmention will stop and new sibling orders will be set to same max value.
5528 ActorContainer* siblings = mParent->mChildren;
5530 ActorIter end = siblings->end();
5531 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
5533 ActorPtr sibling = (*iter);
5534 if ( sibling != this )
5536 maxOrder = std::max( GetSiblingOrder( sibling ), maxOrder );
5540 bool defragmentationRequired( false );
5542 if ( maxOrder >= mSiblingOrder )
5544 mSiblingOrder = maxOrder + 1;
5545 if ( mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
5547 defragmentationRequired = true;
5551 SetSiblingOrder( mSiblingOrder );
5553 if ( defragmentationRequired )
5555 DefragmentSiblingIndexes( *siblings );
5560 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5564 void Actor::LowerToBottom()
5567 See Actor::LowerToBottom()
5569 1 ) Check if this actor already at exclusively at the bottom, if so then no more to be done.
5570 2 ) a ) Check if the bottom position 0 is vacant.
5571 b ) If 0 position is not vacant then shift up all sibling order values from 0 and above
5572 c ) 0 sibling position is vacant.
5573 3 ) Set this actor to vacant sibling order 0;
5574 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5575 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5576 remove any empty sibling order gaps and start from sibling level 0 again.
5577 If the number of actors reaches this maximum and all using exclusive sibling order values then
5578 defragmention will stop and new sibling orders will be set to same max value.
5583 bool defragmentationRequired( false );
5584 bool orderZeroFree ( true );
5586 ActorContainer* siblings = mParent->mChildren;
5588 bool actorAtLowestOrder = true;
5589 ActorIter end = siblings->end();
5590 for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
5592 ActorPtr sibling = (*iter);
5593 if ( sibling != this )
5595 int siblingOrder = GetSiblingOrder( sibling );
5596 if ( siblingOrder <= mSiblingOrder )
5598 actorAtLowestOrder = false;
5601 if ( siblingOrder == 0 )
5603 orderZeroFree = false;
5608 if ( ! actorAtLowestOrder )
5610 if ( ! orderZeroFree )
5612 defragmentationRequired = ShiftSiblingsLevels( *siblings, 0 );
5615 SetSiblingOrder( mSiblingOrder );
5617 if ( defragmentationRequired )
5619 DefragmentSiblingIndexes( *siblings );
5625 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5629 void Actor::RaiseAbove( Internal::Actor& target )
5632 1 ) a) Find target actor's sibling order
5633 b) If sibling order of target is the same as this actor then need to this Actor's sibling order
5634 needs to be above it or the insertion order will determine which is drawn on top.
5635 2 ) Shift up by 1 all sibling order greater than target sibling order
5636 3 ) Set this actor to the sibling order to target +1 as will be a newly vacated gap above
5637 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5638 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5639 remove any empty sibling order gaps and start from sibling level 0 again.
5640 If the number of actors reaches this maximum and all using exclusive sibling order values then
5641 defragmention will stop and new sibling orders will be set to same max value.
5646 if ( ValidateActors( *this, target ) )
5648 // Find target's sibling order
5649 // Set actor sibling order to this number +1
5650 int targetSiblingOrder = GetSiblingOrder( &target );
5651 ActorContainer* siblings = mParent->mChildren;
5652 mSiblingOrder = targetSiblingOrder + 1;
5653 bool defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
5655 SetSiblingOrder( mSiblingOrder );
5657 if ( defragmentationRequired )
5659 DefragmentSiblingIndexes( *(mParent->mChildren) );
5665 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5669 void Actor::LowerBelow( Internal::Actor& target )
5672 1 ) a) Find target actor's sibling order
5673 b) If sibling order of target is the same as this actor then need to this Actor's sibling order
5674 needs to be below it or the insertion order will determine which is drawn on top.
5675 2 ) Shift the target sibling order and all sibling orders at that level or above by 1
5676 3 ) Set this actor to the sibling order of the target before it changed.
5677 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5678 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5679 remove any empty sibling order gaps and start from sibling level 0 again.
5680 If the number of actors reaches this maximum and all using exclusive sibling order values then
5681 defragmention will stop and new sibling orders will be set to same max value.
5686 if ( ValidateActors( *this, target ) )
5688 bool defragmentationRequired ( false );
5689 // Find target's sibling order
5690 // Set actor sibling order to target sibling order - 1
5691 int targetSiblingOrder = GetSiblingOrder( &target);
5692 ActorContainer* siblings = mParent->mChildren;
5693 if ( targetSiblingOrder == 0 )
5696 ActorIter end = siblings->end();
5697 for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
5699 ActorPtr sibling = (*iter);
5700 if ( sibling != this )
5702 sibling->mSiblingOrder++;
5703 if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
5705 defragmentationRequired = true;
5707 sibling->SetSiblingOrder( sibling->mSiblingOrder );
5714 defragmentationRequired = ShiftSiblingsLevels( *siblings, targetSiblingOrder );
5716 mSiblingOrder = targetSiblingOrder;
5718 SetSiblingOrder( mSiblingOrder );
5720 if ( defragmentationRequired )
5722 DefragmentSiblingIndexes( *(mParent->mChildren) );
5728 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5732 } // namespace Internal