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: ");
2449 rootNode->~ActorDepthTreeNode();
2453 * Structure to store the actor's associated node in the depth tree for child
2456 struct ActorNodePair
2459 ActorDepthTreeNode* node;
2460 ActorNodePair( Actor* actor, ActorDepthTreeNode* node )
2468 * Descend actor tree, building a depth tree based on actor's sibling order.
2469 * Actors with the same sibling order share the same depth tree. Siblings
2470 * in the depth tree are ordered by actor's sibling order.
2472 * An actor tree like this:
2479 * A(SO:1) B(SO:2) C(SO:1)
2482 * D(SO:0) E(SO:0) F(SO:0) G(SO:1) H(SO:0)
2484 * will end up as a depth tree like this:
2486 * RootNode [ Root ] -> NULL
2489 * Node [ A, C ] ------------------------> Node [ B ] -> NULL
2492 * Node [ D, E, H ] -> Node [ G ] -> NULL Node [ F ] -> NULL
2497 * (All nodes also point to their parents to enable storage free traversal)
2499 int Actor::BuildDepthTree( DepthNodeMemoryPool& nodeMemoryPool, ActorDepthTreeNode* node )
2501 int treeCount=1; // Count self and children
2503 // Create/add to children of this node
2506 std::vector<ActorNodePair> storedChildren;
2507 storedChildren.reserve( mChildren->size() );
2509 for( ActorContainer::iterator it = mChildren->begin(); it != mChildren->end(); ++it )
2511 Actor* childActor = (*it).Get();
2512 if( childActor->IsLayer() )
2514 Layer* layer = static_cast<Layer*>(childActor);
2515 if( layer->GetBehavior() == Dali::Layer::LAYER_3D )
2517 // Ignore this actor and children.
2522 // If no existing depth node children
2523 if( node->mFirstChildNode == NULL )
2525 node->mFirstChildNode = new (nodeMemoryPool.AllocateRaw()) ActorDepthTreeNode( childActor, childActor->mSiblingOrder );
2526 node->mFirstChildNode->mParentNode = node;
2527 storedChildren.push_back(ActorNodePair( childActor, node->mFirstChildNode ));
2529 else // find child node with matching sibling order (insertion sort)
2531 bool addedChildActor = false;
2533 // depth tree child nodes ordered by sibling order
2534 ActorDepthTreeNode* lastNode = NULL;
2535 for( ActorDepthTreeNode* childNode = node->mFirstChildNode; childNode != NULL; childNode = childNode->mNextSiblingNode )
2537 uint16_t actorSiblingOrder = childActor->mSiblingOrder;
2538 uint16_t currentSiblingOrder = childNode->GetSiblingOrder();
2540 if( actorSiblingOrder == currentSiblingOrder )
2542 // Don't need a new depth node, add to existing node
2543 childNode->AddActor( childActor );
2544 storedChildren.push_back(ActorNodePair( childActor, childNode ));
2545 addedChildActor = true;
2548 else if( actorSiblingOrder < currentSiblingOrder )
2552 lastNode = childNode;
2555 // No matching sibling order - create new node and insert into sibling list
2556 if( !addedChildActor )
2558 ActorDepthTreeNode* newNode = new (nodeMemoryPool.AllocateRaw()) ActorDepthTreeNode( childActor, childActor->mSiblingOrder );
2560 newNode->mParentNode = node;
2561 storedChildren.push_back(ActorNodePair( childActor, newNode ));
2563 if( lastNode == NULL ) // Insert at start of siblings
2565 ActorDepthTreeNode* nextNode = node->mFirstChildNode;
2566 node->mFirstChildNode = newNode;
2567 newNode->mNextSiblingNode = nextNode;
2569 else // insert into siblings after last node
2571 newNode->mNextSiblingNode = lastNode->mNextSiblingNode;
2572 lastNode->mNextSiblingNode = newNode;
2578 // Order of descent doesn't matter; we're using insertion to sort.
2579 for( std::vector<ActorNodePair>::iterator iter = storedChildren.begin(); iter != storedChildren.end(); ++iter )
2581 treeCount += iter->actor->BuildDepthTree( nodeMemoryPool, iter->node );
2587 unsigned int Actor::GetDefaultPropertyCount() const
2589 return DEFAULT_PROPERTY_COUNT;
2592 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2594 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2596 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2598 indices.PushBack( i );
2602 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2604 if( index < DEFAULT_PROPERTY_COUNT )
2606 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2612 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2614 Property::Index index = Property::INVALID_INDEX;
2616 // Look for name in default properties
2617 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2619 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2620 if( 0 == name.compare( property->name ) )
2630 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2632 if( index < DEFAULT_PROPERTY_COUNT )
2634 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2640 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2642 if( index < DEFAULT_PROPERTY_COUNT )
2644 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2650 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2652 if( index < DEFAULT_PROPERTY_COUNT )
2654 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2660 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2662 if( index < DEFAULT_PROPERTY_COUNT )
2664 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2667 // index out of range...return Property::NONE
2668 return Property::NONE;
2671 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2675 case Dali::Actor::Property::PARENT_ORIGIN:
2677 Property::Type type = property.GetType();
2678 if( type == Property::VECTOR3 )
2680 SetParentOrigin( property.Get< Vector3 >() );
2682 else if ( type == Property::STRING )
2684 std::string parentOriginString;
2685 property.Get( parentOriginString );
2686 Vector3 parentOrigin;
2687 if( GetParentOriginConstant( parentOriginString, parentOrigin ) )
2689 SetParentOrigin( parentOrigin );
2695 case Dali::Actor::Property::PARENT_ORIGIN_X:
2697 SetParentOriginX( property.Get< float >() );
2701 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2703 SetParentOriginY( property.Get< float >() );
2707 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2709 SetParentOriginZ( property.Get< float >() );
2713 case Dali::Actor::Property::ANCHOR_POINT:
2715 Property::Type type = property.GetType();
2716 if( type == Property::VECTOR3 )
2718 SetAnchorPoint( property.Get< Vector3 >() );
2720 else if ( type == Property::STRING )
2722 std::string anchorPointString;
2723 property.Get( anchorPointString );
2725 if( GetAnchorPointConstant( anchorPointString, anchor ) )
2727 SetAnchorPoint( anchor );
2733 case Dali::Actor::Property::ANCHOR_POINT_X:
2735 SetAnchorPointX( property.Get< float >() );
2739 case Dali::Actor::Property::ANCHOR_POINT_Y:
2741 SetAnchorPointY( property.Get< float >() );
2745 case Dali::Actor::Property::ANCHOR_POINT_Z:
2747 SetAnchorPointZ( property.Get< float >() );
2751 case Dali::Actor::Property::SIZE:
2753 SetSize( property.Get< Vector3 >() );
2757 case Dali::Actor::Property::SIZE_WIDTH:
2759 SetWidth( property.Get< float >() );
2763 case Dali::Actor::Property::SIZE_HEIGHT:
2765 SetHeight( property.Get< float >() );
2769 case Dali::Actor::Property::SIZE_DEPTH:
2771 SetDepth( property.Get< float >() );
2775 case Dali::Actor::Property::POSITION:
2777 SetPosition( property.Get< Vector3 >() );
2781 case Dali::Actor::Property::POSITION_X:
2783 SetX( property.Get< float >() );
2787 case Dali::Actor::Property::POSITION_Y:
2789 SetY( property.Get< float >() );
2793 case Dali::Actor::Property::POSITION_Z:
2795 SetZ( property.Get< float >() );
2799 case Dali::Actor::Property::ORIENTATION:
2801 SetOrientation( property.Get< Quaternion >() );
2805 case Dali::Actor::Property::SCALE:
2807 SetScale( property.Get< Vector3 >() );
2811 case Dali::Actor::Property::SCALE_X:
2813 SetScaleX( property.Get< float >() );
2817 case Dali::Actor::Property::SCALE_Y:
2819 SetScaleY( property.Get< float >() );
2823 case Dali::Actor::Property::SCALE_Z:
2825 SetScaleZ( property.Get< float >() );
2829 case Dali::Actor::Property::VISIBLE:
2831 SetVisible( property.Get< bool >() );
2835 case Dali::Actor::Property::COLOR:
2837 SetColor( property.Get< Vector4 >() );
2841 case Dali::Actor::Property::COLOR_RED:
2843 SetColorRed( property.Get< float >() );
2847 case Dali::Actor::Property::COLOR_GREEN:
2849 SetColorGreen( property.Get< float >() );
2853 case Dali::Actor::Property::COLOR_BLUE:
2855 SetColorBlue( property.Get< float >() );
2859 case Dali::Actor::Property::COLOR_ALPHA:
2860 case Dali::DevelActor::Property::OPACITY:
2863 if( property.Get( value ) )
2865 SetOpacity( value );
2870 case Dali::Actor::Property::NAME:
2872 SetName( property.Get< std::string >() );
2876 case Dali::Actor::Property::SENSITIVE:
2878 SetSensitive( property.Get< bool >() );
2882 case Dali::Actor::Property::LEAVE_REQUIRED:
2884 SetLeaveRequired( property.Get< bool >() );
2888 case Dali::Actor::Property::INHERIT_POSITION:
2890 SetInheritPosition( property.Get< bool >() );
2894 case Dali::Actor::Property::INHERIT_ORIENTATION:
2896 SetInheritOrientation( property.Get< bool >() );
2900 case Dali::Actor::Property::INHERIT_SCALE:
2902 SetInheritScale( property.Get< bool >() );
2906 case Dali::Actor::Property::COLOR_MODE:
2908 ColorMode mode = mColorMode;
2909 if ( Scripting::GetEnumerationProperty< ColorMode >( property, COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT, mode ) )
2911 SetColorMode( mode );
2916 case Dali::Actor::Property::POSITION_INHERITANCE:
2918 PositionInheritanceMode mode = mPositionInheritanceMode;
2919 if( Scripting::GetEnumerationProperty< PositionInheritanceMode >( property, POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT, mode ) )
2921 SetPositionInheritanceMode( mode );
2926 case Dali::Actor::Property::DRAW_MODE:
2928 DrawMode::Type mode = mDrawMode;
2929 if( Scripting::GetEnumerationProperty< DrawMode::Type >( property, DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT, mode ) )
2931 SetDrawMode( mode );
2936 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2938 SetSizeModeFactor( property.Get< Vector3 >() );
2942 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2944 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
2945 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2947 SetResizePolicy( type, Dimension::WIDTH );
2952 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2954 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
2955 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2957 SetResizePolicy( type, Dimension::HEIGHT );
2962 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2964 SizeScalePolicy::Type type;
2965 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT, type ) )
2967 SetSizeScalePolicy( type );
2972 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2974 if( property.Get< bool >() )
2976 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2981 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2983 if( property.Get< bool >() )
2985 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2990 case Dali::Actor::Property::PADDING:
2992 Vector4 padding = property.Get< Vector4 >();
2993 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2994 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2998 case Dali::Actor::Property::MINIMUM_SIZE:
3000 Vector2 size = property.Get< Vector2 >();
3001 SetMinimumSize( size.x, Dimension::WIDTH );
3002 SetMinimumSize( size.y, Dimension::HEIGHT );
3006 case Dali::Actor::Property::MAXIMUM_SIZE:
3008 Vector2 size = property.Get< Vector2 >();
3009 SetMaximumSize( size.x, Dimension::WIDTH );
3010 SetMaximumSize( size.y, Dimension::HEIGHT );
3014 case Dali::DevelActor::Property::SIBLING_ORDER:
3018 if( property.Get( value ) )
3020 if( static_cast<unsigned int>(value) != mSiblingOrder )
3022 SetSiblingOrder( value );
3028 case Dali::Actor::Property::CLIPPING_MODE:
3030 ClippingMode::Type convertedValue = mClippingMode;
3031 if( Scripting::GetEnumerationProperty< ClippingMode::Type >( property, CLIPPING_MODE_TABLE, CLIPPING_MODE_TABLE_COUNT, convertedValue ) )
3033 mClippingMode = convertedValue;
3036 SetClippingModeMessage( GetEventThreadServices(), *mNode, mClippingMode );
3042 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
3045 if( property.Get( value ) && value != mPositionUsesAnchorPoint )
3047 mPositionUsesAnchorPoint = value;
3050 SetPositionUsesAnchorPointMessage( GetEventThreadServices(), *mNode, mPositionUsesAnchorPoint );
3058 // this can happen in the case of a non-animatable default property so just do nothing
3064 // TODO: This method needs to be removed
3065 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
3067 switch( entry.GetType() )
3069 case Property::BOOLEAN:
3071 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
3072 DALI_ASSERT_DEBUG( NULL != property );
3074 // property is being used in a separate thread; queue a message to set the property
3075 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
3080 case Property::INTEGER:
3082 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
3083 DALI_ASSERT_DEBUG( NULL != property );
3085 // property is being used in a separate thread; queue a message to set the property
3086 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
3091 case Property::FLOAT:
3093 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
3094 DALI_ASSERT_DEBUG( NULL != property );
3096 // property is being used in a separate thread; queue a message to set the property
3097 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
3102 case Property::VECTOR2:
3104 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
3105 DALI_ASSERT_DEBUG( NULL != property );
3107 // property is being used in a separate thread; queue a message to set the property
3108 if(entry.componentIndex == 0)
3110 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
3112 else if(entry.componentIndex == 1)
3114 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
3118 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
3124 case Property::VECTOR3:
3126 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
3127 DALI_ASSERT_DEBUG( NULL != property );
3129 // property is being used in a separate thread; queue a message to set the property
3130 if(entry.componentIndex == 0)
3132 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
3134 else if(entry.componentIndex == 1)
3136 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
3138 else if(entry.componentIndex == 2)
3140 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
3144 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
3150 case Property::VECTOR4:
3152 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
3153 DALI_ASSERT_DEBUG( NULL != property );
3155 // property is being used in a separate thread; queue a message to set the property
3156 if(entry.componentIndex == 0)
3158 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
3160 else if(entry.componentIndex == 1)
3162 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
3164 else if(entry.componentIndex == 2)
3166 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
3168 else if(entry.componentIndex == 3)
3170 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
3174 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3180 case Property::ROTATION:
3182 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3183 DALI_ASSERT_DEBUG( NULL != property );
3185 // property is being used in a separate thread; queue a message to set the property
3186 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3191 case Property::MATRIX:
3193 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3194 DALI_ASSERT_DEBUG( NULL != property );
3196 // property is being used in a separate thread; queue a message to set the property
3197 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3202 case Property::MATRIX3:
3204 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3205 DALI_ASSERT_DEBUG( NULL != property );
3207 // property is being used in a separate thread; queue a message to set the property
3208 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3215 // nothing to do for other types
3220 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3222 Property::Value value;
3224 if( ! GetCachedPropertyValue( index, value ) )
3226 // If property value is not stored in the event-side, then it must be a scene-graph only property
3227 GetCurrentPropertyValue( index, value );
3233 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
3235 Property::Value value;
3237 if( ! GetCurrentPropertyValue( index, value ) )
3239 // If unable to retrieve scene-graph property value, then it must be an event-side only property
3240 GetCachedPropertyValue( index, value );
3246 void Actor::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
3248 switch( animationType )
3251 case Animation::BETWEEN:
3255 case Dali::Actor::Property::SIZE:
3257 if( value.Get( mTargetSize ) )
3259 // Notify deriving classes
3260 OnSizeAnimation( animation, mTargetSize );
3265 case Dali::Actor::Property::SIZE_WIDTH:
3267 if( value.Get( mTargetSize.width ) )
3269 // Notify deriving classes
3270 OnSizeAnimation( animation, mTargetSize );
3275 case Dali::Actor::Property::SIZE_HEIGHT:
3277 if( value.Get( mTargetSize.height ) )
3279 // Notify deriving classes
3280 OnSizeAnimation( animation, mTargetSize );
3285 case Dali::Actor::Property::SIZE_DEPTH:
3287 if( value.Get( mTargetSize.depth ) )
3289 // Notify deriving classes
3290 OnSizeAnimation( animation, mTargetSize );
3295 case Dali::Actor::Property::POSITION:
3297 value.Get( mTargetPosition );
3301 case Dali::Actor::Property::POSITION_X:
3303 value.Get( mTargetPosition.x );
3307 case Dali::Actor::Property::POSITION_Y:
3309 value.Get( mTargetPosition.y );
3313 case Dali::Actor::Property::POSITION_Z:
3315 value.Get( mTargetPosition.z );
3319 case Dali::Actor::Property::ORIENTATION:
3321 value.Get( mTargetOrientation );
3325 case Dali::Actor::Property::SCALE:
3327 value.Get( mTargetScale );
3331 case Dali::Actor::Property::SCALE_X:
3333 value.Get( mTargetScale.x );
3337 case Dali::Actor::Property::SCALE_Y:
3339 value.Get( mTargetScale.y );
3343 case Dali::Actor::Property::SCALE_Z:
3345 value.Get( mTargetScale.z );
3349 case Dali::Actor::Property::VISIBLE:
3351 SetVisibleInternal( value.Get< bool >(), SendMessage::FALSE );
3355 case Dali::Actor::Property::COLOR:
3357 value.Get( mTargetColor );
3361 case Dali::Actor::Property::COLOR_RED:
3363 value.Get( mTargetColor.r );
3367 case Dali::Actor::Property::COLOR_GREEN:
3369 value.Get( mTargetColor.g );
3373 case Dali::Actor::Property::COLOR_BLUE:
3375 value.Get( mTargetColor.b );
3379 case Dali::Actor::Property::COLOR_ALPHA:
3380 case Dali::DevelActor::Property::OPACITY:
3382 value.Get( mTargetColor.a );
3388 // Not an animatable property. Do nothing.
3399 case Dali::Actor::Property::SIZE:
3401 if( AdjustValue< Vector3 >( mTargetSize, value ) )
3403 // Notify deriving classes
3404 OnSizeAnimation( animation, mTargetSize );
3409 case Dali::Actor::Property::SIZE_WIDTH:
3411 if( AdjustValue< float >( mTargetSize.width, value ) )
3413 // Notify deriving classes
3414 OnSizeAnimation( animation, mTargetSize );
3419 case Dali::Actor::Property::SIZE_HEIGHT:
3421 if( AdjustValue< float >( mTargetSize.height, value ) )
3423 // Notify deriving classes
3424 OnSizeAnimation( animation, mTargetSize );
3429 case Dali::Actor::Property::SIZE_DEPTH:
3431 if( AdjustValue< float >( mTargetSize.depth, value ) )
3433 // Notify deriving classes
3434 OnSizeAnimation( animation, mTargetSize );
3439 case Dali::Actor::Property::POSITION:
3441 AdjustValue< Vector3 >( mTargetPosition, value );
3445 case Dali::Actor::Property::POSITION_X:
3447 AdjustValue< float >( mTargetPosition.x, value );
3451 case Dali::Actor::Property::POSITION_Y:
3453 AdjustValue< float >( mTargetPosition.y, value );
3457 case Dali::Actor::Property::POSITION_Z:
3459 AdjustValue< float >( mTargetPosition.z, value );
3463 case Dali::Actor::Property::ORIENTATION:
3465 Quaternion relativeValue;
3466 if( value.Get( relativeValue ) )
3468 mTargetOrientation *= relativeValue;
3473 case Dali::Actor::Property::SCALE:
3475 AdjustValue< Vector3 >( mTargetScale, value );
3479 case Dali::Actor::Property::SCALE_X:
3481 AdjustValue< float >( mTargetScale.x, value );
3485 case Dali::Actor::Property::SCALE_Y:
3487 AdjustValue< float >( mTargetScale.y, value );
3491 case Dali::Actor::Property::SCALE_Z:
3493 AdjustValue< float >( mTargetScale.z, value );
3497 case Dali::Actor::Property::VISIBLE:
3499 bool relativeValue = false;
3500 if( value.Get( relativeValue ) )
3502 bool visible = mVisible || relativeValue;
3503 SetVisibleInternal( visible, SendMessage::FALSE );
3508 case Dali::Actor::Property::COLOR:
3510 AdjustValue< Vector4 >( mTargetColor, value );
3514 case Dali::Actor::Property::COLOR_RED:
3516 AdjustValue< float >( mTargetColor.r, value );
3520 case Dali::Actor::Property::COLOR_GREEN:
3522 AdjustValue< float >( mTargetColor.g, value );
3526 case Dali::Actor::Property::COLOR_BLUE:
3528 AdjustValue< float >( mTargetColor.b, value );
3532 case Dali::Actor::Property::COLOR_ALPHA:
3533 case Dali::DevelActor::Property::OPACITY:
3535 AdjustValue< float >( mTargetColor.a, value );
3541 // Not an animatable property. Do nothing.
3550 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3555 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3557 // This method should only return an object connected to the scene-graph
3558 return OnStage() ? mNode : NULL;
3561 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3563 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3565 const PropertyBase* property( NULL );
3567 // This method should only return a property of an object connected to the scene-graph
3573 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3575 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3576 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3578 property = animatable->GetSceneGraphProperty();
3580 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3581 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3583 CustomPropertyMetadata* custom = FindCustomProperty( index );
3584 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3586 property = custom->GetSceneGraphProperty();
3588 else if( NULL != mNode )
3592 case Dali::Actor::Property::SIZE:
3593 property = &mNode->mSize;
3596 case Dali::Actor::Property::SIZE_WIDTH:
3597 property = &mNode->mSize;
3600 case Dali::Actor::Property::SIZE_HEIGHT:
3601 property = &mNode->mSize;
3604 case Dali::Actor::Property::SIZE_DEPTH:
3605 property = &mNode->mSize;
3608 case Dali::Actor::Property::POSITION:
3609 property = &mNode->mPosition;
3612 case Dali::Actor::Property::POSITION_X:
3613 property = &mNode->mPosition;
3616 case Dali::Actor::Property::POSITION_Y:
3617 property = &mNode->mPosition;
3620 case Dali::Actor::Property::POSITION_Z:
3621 property = &mNode->mPosition;
3624 case Dali::Actor::Property::ORIENTATION:
3625 property = &mNode->mOrientation;
3628 case Dali::Actor::Property::SCALE:
3629 property = &mNode->mScale;
3632 case Dali::Actor::Property::SCALE_X:
3633 property = &mNode->mScale;
3636 case Dali::Actor::Property::SCALE_Y:
3637 property = &mNode->mScale;
3640 case Dali::Actor::Property::SCALE_Z:
3641 property = &mNode->mScale;
3644 case Dali::Actor::Property::VISIBLE:
3645 property = &mNode->mVisible;
3648 case Dali::Actor::Property::COLOR:
3649 property = &mNode->mColor;
3652 case Dali::Actor::Property::COLOR_RED:
3653 property = &mNode->mColor;
3656 case Dali::Actor::Property::COLOR_GREEN:
3657 property = &mNode->mColor;
3660 case Dali::Actor::Property::COLOR_BLUE:
3661 property = &mNode->mColor;
3664 case Dali::Actor::Property::COLOR_ALPHA:
3665 case Dali::DevelActor::Property::OPACITY:
3666 property = &mNode->mColor;
3677 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3679 const PropertyInputImpl* property( NULL );
3681 // This method should only return a property of an object connected to the scene-graph
3687 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3689 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3690 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3692 property = animatable->GetSceneGraphProperty();
3694 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3695 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3697 CustomPropertyMetadata* custom = FindCustomProperty( index );
3698 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3699 property = custom->GetSceneGraphProperty();
3701 else if( NULL != mNode )
3705 case Dali::Actor::Property::PARENT_ORIGIN:
3706 property = &mNode->mParentOrigin;
3709 case Dali::Actor::Property::PARENT_ORIGIN_X:
3710 property = &mNode->mParentOrigin;
3713 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3714 property = &mNode->mParentOrigin;
3717 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3718 property = &mNode->mParentOrigin;
3721 case Dali::Actor::Property::ANCHOR_POINT:
3722 property = &mNode->mAnchorPoint;
3725 case Dali::Actor::Property::ANCHOR_POINT_X:
3726 property = &mNode->mAnchorPoint;
3729 case Dali::Actor::Property::ANCHOR_POINT_Y:
3730 property = &mNode->mAnchorPoint;
3733 case Dali::Actor::Property::ANCHOR_POINT_Z:
3734 property = &mNode->mAnchorPoint;
3737 case Dali::Actor::Property::SIZE:
3738 property = &mNode->mSize;
3741 case Dali::Actor::Property::SIZE_WIDTH:
3742 property = &mNode->mSize;
3745 case Dali::Actor::Property::SIZE_HEIGHT:
3746 property = &mNode->mSize;
3749 case Dali::Actor::Property::SIZE_DEPTH:
3750 property = &mNode->mSize;
3753 case Dali::Actor::Property::POSITION:
3754 property = &mNode->mPosition;
3757 case Dali::Actor::Property::POSITION_X:
3758 property = &mNode->mPosition;
3761 case Dali::Actor::Property::POSITION_Y:
3762 property = &mNode->mPosition;
3765 case Dali::Actor::Property::POSITION_Z:
3766 property = &mNode->mPosition;
3769 case Dali::Actor::Property::WORLD_POSITION:
3770 property = &mNode->mWorldPosition;
3773 case Dali::Actor::Property::WORLD_POSITION_X:
3774 property = &mNode->mWorldPosition;
3777 case Dali::Actor::Property::WORLD_POSITION_Y:
3778 property = &mNode->mWorldPosition;
3781 case Dali::Actor::Property::WORLD_POSITION_Z:
3782 property = &mNode->mWorldPosition;
3785 case Dali::Actor::Property::ORIENTATION:
3786 property = &mNode->mOrientation;
3789 case Dali::Actor::Property::WORLD_ORIENTATION:
3790 property = &mNode->mWorldOrientation;
3793 case Dali::Actor::Property::SCALE:
3794 property = &mNode->mScale;
3797 case Dali::Actor::Property::SCALE_X:
3798 property = &mNode->mScale;
3801 case Dali::Actor::Property::SCALE_Y:
3802 property = &mNode->mScale;
3805 case Dali::Actor::Property::SCALE_Z:
3806 property = &mNode->mScale;
3809 case Dali::Actor::Property::WORLD_SCALE:
3810 property = &mNode->mWorldScale;
3813 case Dali::Actor::Property::VISIBLE:
3814 property = &mNode->mVisible;
3817 case Dali::Actor::Property::COLOR:
3818 property = &mNode->mColor;
3821 case Dali::Actor::Property::COLOR_RED:
3822 property = &mNode->mColor;
3825 case Dali::Actor::Property::COLOR_GREEN:
3826 property = &mNode->mColor;
3829 case Dali::Actor::Property::COLOR_BLUE:
3830 property = &mNode->mColor;
3833 case Dali::Actor::Property::COLOR_ALPHA:
3834 case Dali::DevelActor::Property::OPACITY:
3836 property = &mNode->mColor;
3840 case Dali::Actor::Property::WORLD_COLOR:
3841 property = &mNode->mWorldColor;
3844 case Dali::Actor::Property::WORLD_MATRIX:
3845 property = &mNode->mWorldMatrix;
3856 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3858 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3860 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3862 // check whether the animatable property is registered already, if not then register one.
3863 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3864 if( animatableProperty )
3866 componentIndex = animatableProperty->componentIndex;
3873 case Dali::Actor::Property::PARENT_ORIGIN_X:
3874 case Dali::Actor::Property::ANCHOR_POINT_X:
3875 case Dali::Actor::Property::SIZE_WIDTH:
3876 case Dali::Actor::Property::POSITION_X:
3877 case Dali::Actor::Property::WORLD_POSITION_X:
3878 case Dali::Actor::Property::SCALE_X:
3879 case Dali::Actor::Property::COLOR_RED:
3885 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3886 case Dali::Actor::Property::ANCHOR_POINT_Y:
3887 case Dali::Actor::Property::SIZE_HEIGHT:
3888 case Dali::Actor::Property::POSITION_Y:
3889 case Dali::Actor::Property::WORLD_POSITION_Y:
3890 case Dali::Actor::Property::SCALE_Y:
3891 case Dali::Actor::Property::COLOR_GREEN:
3897 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3898 case Dali::Actor::Property::ANCHOR_POINT_Z:
3899 case Dali::Actor::Property::SIZE_DEPTH:
3900 case Dali::Actor::Property::POSITION_Z:
3901 case Dali::Actor::Property::WORLD_POSITION_Z:
3902 case Dali::Actor::Property::SCALE_Z:
3903 case Dali::Actor::Property::COLOR_BLUE:
3909 case Dali::Actor::Property::COLOR_ALPHA:
3910 case Dali::DevelActor::Property::OPACITY:
3924 return componentIndex;
3927 void Actor::SetParent( Actor* parent )
3931 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3935 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3938 // Instruct each actor to create a corresponding node in the scene graph
3939 ConnectToStage( parent->GetHierarchyDepth() );
3942 // Resolve the name and index for the child properties if any
3943 ResolveChildProperties();
3945 else // parent being set to NULL
3947 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3951 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3954 DALI_ASSERT_ALWAYS( mNode != NULL );
3958 // Disconnect the Node & its children from the scene-graph.
3959 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3962 // Instruct each actor to discard pointers to the scene-graph
3963 DisconnectFromStage();
3968 SceneGraph::Node* Actor::CreateNode() const
3973 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3976 Actor* actor = dynamic_cast< Actor* >( object );
3980 if( 0 == actionName.compare( ACTION_SHOW ) )
3982 actor->SetVisible( true );
3985 else if( 0 == actionName.compare( ACTION_HIDE ) )
3987 actor->SetVisible( false );
3995 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
3997 bool valueSet = true;
4001 case Dali::Actor::Property::PARENT_ORIGIN:
4003 value = GetCurrentParentOrigin();
4007 case Dali::Actor::Property::PARENT_ORIGIN_X:
4009 value = GetCurrentParentOrigin().x;
4013 case Dali::Actor::Property::PARENT_ORIGIN_Y:
4015 value = GetCurrentParentOrigin().y;
4019 case Dali::Actor::Property::PARENT_ORIGIN_Z:
4021 value = GetCurrentParentOrigin().z;
4025 case Dali::Actor::Property::ANCHOR_POINT:
4027 value = GetCurrentAnchorPoint();
4031 case Dali::Actor::Property::ANCHOR_POINT_X:
4033 value = GetCurrentAnchorPoint().x;
4037 case Dali::Actor::Property::ANCHOR_POINT_Y:
4039 value = GetCurrentAnchorPoint().y;
4043 case Dali::Actor::Property::ANCHOR_POINT_Z:
4045 value = GetCurrentAnchorPoint().z;
4049 case Dali::Actor::Property::SIZE:
4051 value = GetTargetSize();
4055 case Dali::Actor::Property::SIZE_WIDTH:
4057 value = GetTargetSize().width;
4061 case Dali::Actor::Property::SIZE_HEIGHT:
4063 value = GetTargetSize().height;
4067 case Dali::Actor::Property::SIZE_DEPTH:
4069 value = GetTargetSize().depth;
4073 case Dali::Actor::Property::POSITION:
4075 value = GetTargetPosition();
4079 case Dali::Actor::Property::POSITION_X:
4081 value = GetTargetPosition().x;
4085 case Dali::Actor::Property::POSITION_Y:
4087 value = GetTargetPosition().y;
4091 case Dali::Actor::Property::POSITION_Z:
4093 value = GetTargetPosition().z;
4097 case Dali::Actor::Property::ORIENTATION:
4099 value = mTargetOrientation;
4103 case Dali::Actor::Property::SCALE:
4105 value = mTargetScale;
4109 case Dali::Actor::Property::SCALE_X:
4111 value = mTargetScale.x;
4115 case Dali::Actor::Property::SCALE_Y:
4117 value = mTargetScale.y;
4121 case Dali::Actor::Property::SCALE_Z:
4123 value = mTargetScale.z;
4127 case Dali::Actor::Property::VISIBLE:
4133 case Dali::Actor::Property::COLOR:
4135 value = mTargetColor;
4139 case Dali::Actor::Property::COLOR_RED:
4141 value = mTargetColor.r;
4145 case Dali::Actor::Property::COLOR_GREEN:
4147 value = mTargetColor.g;
4151 case Dali::Actor::Property::COLOR_BLUE:
4153 value = mTargetColor.b;
4157 case Dali::Actor::Property::COLOR_ALPHA:
4158 case Dali::DevelActor::Property::OPACITY:
4160 value = mTargetColor.a;
4164 case Dali::Actor::Property::NAME:
4170 case Dali::Actor::Property::SENSITIVE:
4172 value = IsSensitive();
4176 case Dali::Actor::Property::LEAVE_REQUIRED:
4178 value = GetLeaveRequired();
4182 case Dali::Actor::Property::INHERIT_POSITION:
4184 value = IsPositionInherited();
4188 case Dali::Actor::Property::INHERIT_ORIENTATION:
4190 value = IsOrientationInherited();
4194 case Dali::Actor::Property::INHERIT_SCALE:
4196 value = IsScaleInherited();
4200 case Dali::Actor::Property::COLOR_MODE:
4202 value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
4206 case Dali::Actor::Property::POSITION_INHERITANCE:
4208 value = Scripting::GetLinearEnumerationName< PositionInheritanceMode >( GetPositionInheritanceMode(), POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT );
4212 case Dali::Actor::Property::DRAW_MODE:
4214 value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
4218 case Dali::Actor::Property::SIZE_MODE_FACTOR:
4220 value = GetSizeModeFactor();
4224 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
4226 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
4230 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
4232 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
4236 case Dali::Actor::Property::SIZE_SCALE_POLICY:
4238 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT );
4242 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
4244 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
4248 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
4250 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
4254 case Dali::Actor::Property::PADDING:
4256 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
4257 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
4258 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
4262 case Dali::Actor::Property::MINIMUM_SIZE:
4264 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
4268 case Dali::Actor::Property::MAXIMUM_SIZE:
4270 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
4274 case Dali::Actor::Property::CLIPPING_MODE:
4276 value = mClippingMode;
4280 case Dali::DevelActor::Property::SIBLING_ORDER:
4282 value = static_cast<int>(mSiblingOrder);
4286 case Dali::DevelActor::Property::SCREEN_POSITION:
4288 value = GetCurrentScreenPosition();
4292 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
4294 value = mPositionUsesAnchorPoint;
4300 // Must be a scene-graph only property
4309 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
4311 bool valueSet = true;
4315 case Dali::Actor::Property::SIZE:
4317 value = GetCurrentSize();
4321 case Dali::Actor::Property::SIZE_WIDTH:
4323 value = GetCurrentSize().width;
4327 case Dali::Actor::Property::SIZE_HEIGHT:
4329 value = GetCurrentSize().height;
4333 case Dali::Actor::Property::SIZE_DEPTH:
4335 value = GetCurrentSize().depth;
4339 case Dali::Actor::Property::POSITION:
4341 value = GetCurrentPosition();
4345 case Dali::Actor::Property::POSITION_X:
4347 value = GetCurrentPosition().x;
4351 case Dali::Actor::Property::POSITION_Y:
4353 value = GetCurrentPosition().y;
4357 case Dali::Actor::Property::POSITION_Z:
4359 value = GetCurrentPosition().z;
4363 case Dali::Actor::Property::WORLD_POSITION:
4365 value = GetCurrentWorldPosition();
4369 case Dali::Actor::Property::WORLD_POSITION_X:
4371 value = GetCurrentWorldPosition().x;
4375 case Dali::Actor::Property::WORLD_POSITION_Y:
4377 value = GetCurrentWorldPosition().y;
4381 case Dali::Actor::Property::WORLD_POSITION_Z:
4383 value = GetCurrentWorldPosition().z;
4387 case Dali::Actor::Property::ORIENTATION:
4389 value = GetCurrentOrientation();
4393 case Dali::Actor::Property::WORLD_ORIENTATION:
4395 value = GetCurrentWorldOrientation();
4399 case Dali::Actor::Property::SCALE:
4401 value = GetCurrentScale();
4405 case Dali::Actor::Property::SCALE_X:
4407 value = GetCurrentScale().x;
4411 case Dali::Actor::Property::SCALE_Y:
4413 value = GetCurrentScale().y;
4417 case Dali::Actor::Property::SCALE_Z:
4419 value = GetCurrentScale().z;
4423 case Dali::Actor::Property::WORLD_SCALE:
4425 value = GetCurrentWorldScale();
4429 case Dali::Actor::Property::COLOR:
4431 value = GetCurrentColor();
4435 case Dali::Actor::Property::COLOR_RED:
4437 value = GetCurrentColor().r;
4441 case Dali::Actor::Property::COLOR_GREEN:
4443 value = GetCurrentColor().g;
4447 case Dali::Actor::Property::COLOR_BLUE:
4449 value = GetCurrentColor().b;
4453 case Dali::Actor::Property::COLOR_ALPHA:
4454 case Dali::DevelActor::Property::OPACITY:
4456 value = GetCurrentColor().a;
4460 case Dali::Actor::Property::WORLD_COLOR:
4462 value = GetCurrentWorldColor();
4466 case Dali::Actor::Property::WORLD_MATRIX:
4468 value = GetCurrentWorldMatrix();
4472 case Dali::Actor::Property::VISIBLE:
4474 value = IsVisible();
4480 // Must be an event-side only property
4489 void Actor::EnsureRelayoutData()
4491 // Assign relayout data.
4492 if( !mRelayoutData )
4494 mRelayoutData = new RelayoutData();
4498 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
4500 // Check if actor is dependent on parent
4501 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4503 if( ( dimension & ( 1 << i ) ) )
4505 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4506 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
4516 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
4518 // Check if actor is dependent on children
4519 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4521 if( ( dimension & ( 1 << i ) ) )
4523 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4524 switch( resizePolicy )
4526 case ResizePolicy::FIT_TO_CHILDREN:
4527 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
4543 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
4545 return Actor::RelayoutDependentOnChildren( dimension );
4548 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
4550 // Check each possible dimension and see if it is dependent on the input one
4551 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4553 if( dimension & ( 1 << i ) )
4555 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
4562 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
4564 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4566 if( dimension & ( 1 << i ) )
4568 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
4573 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
4575 // If more than one dimension is requested, just return the first one found
4576 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4578 if( ( dimension & ( 1 << i ) ) )
4580 return mRelayoutData->negotiatedDimensions[ i ];
4584 return 0.0f; // Default
4587 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
4589 EnsureRelayoutData();
4591 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4593 if( dimension & ( 1 << i ) )
4595 mRelayoutData->dimensionPadding[ i ] = padding;
4600 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4602 if ( mRelayoutData )
4604 // If more than one dimension is requested, just return the first one found
4605 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4607 if( ( dimension & ( 1 << i ) ) )
4609 return mRelayoutData->dimensionPadding[ i ];
4614 return GetDefaultDimensionPadding();
4617 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4619 EnsureRelayoutData();
4621 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4623 if( dimension & ( 1 << i ) )
4625 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4630 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4632 if ( mRelayoutData )
4634 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4636 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4646 float Actor::GetHeightForWidthBase( float width )
4648 float height = 0.0f;
4650 const Vector3 naturalSize = GetNaturalSize();
4651 if( naturalSize.width > 0.0f )
4653 height = naturalSize.height * width / naturalSize.width;
4655 else // we treat 0 as 1:1 aspect ratio
4663 float Actor::GetWidthForHeightBase( float height )
4667 const Vector3 naturalSize = GetNaturalSize();
4668 if( naturalSize.height > 0.0f )
4670 width = naturalSize.width * height / naturalSize.height;
4672 else // we treat 0 as 1:1 aspect ratio
4680 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4682 // Fill to parent, taking size mode factor into account
4683 switch( child.GetResizePolicy( dimension ) )
4685 case ResizePolicy::FILL_TO_PARENT:
4687 return GetLatestSize( dimension );
4690 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4692 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4695 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4697 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4702 return GetLatestSize( dimension );
4707 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4709 // Can be overridden in derived class
4710 return CalculateChildSizeBase( child, dimension );
4713 float Actor::GetHeightForWidth( float width )
4715 // Can be overridden in derived class
4716 return GetHeightForWidthBase( width );
4719 float Actor::GetWidthForHeight( float height )
4721 // Can be overridden in derived class
4722 return GetWidthForHeightBase( height );
4725 float Actor::GetLatestSize( Dimension::Type dimension ) const
4727 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4730 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4732 Vector2 padding = GetPadding( dimension );
4734 return GetLatestSize( dimension ) + padding.x + padding.y;
4737 float Actor::NegotiateFromParent( Dimension::Type dimension )
4739 Actor* parent = GetParent();
4742 Vector2 padding( GetPadding( dimension ) );
4743 Vector2 parentPadding( parent->GetPadding( dimension ) );
4744 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4750 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4752 float maxDimensionPoint = 0.0f;
4754 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4756 ActorPtr child = GetChildAt( i );
4758 if( !child->RelayoutDependentOnParent( dimension ) )
4760 // Calculate the min and max points that the children range across
4761 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
4762 float dimensionSize = child->GetRelayoutSize( dimension );
4763 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4767 return maxDimensionPoint;
4770 float Actor::GetSize( Dimension::Type dimension ) const
4772 return GetDimensionValue( mTargetSize, dimension );
4775 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4777 return GetDimensionValue( GetNaturalSize(), dimension );
4780 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4782 switch( GetResizePolicy( dimension ) )
4784 case ResizePolicy::USE_NATURAL_SIZE:
4786 return GetNaturalSize( dimension );
4789 case ResizePolicy::FIXED:
4791 return GetDimensionValue( GetPreferredSize(), dimension );
4794 case ResizePolicy::USE_ASSIGNED_SIZE:
4796 return GetDimensionValue( maximumSize, dimension );
4799 case ResizePolicy::FILL_TO_PARENT:
4800 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4801 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4803 return NegotiateFromParent( dimension );
4806 case ResizePolicy::FIT_TO_CHILDREN:
4808 return NegotiateFromChildren( dimension );
4811 case ResizePolicy::DIMENSION_DEPENDENCY:
4813 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4816 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4818 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4821 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4823 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4835 return 0.0f; // Default
4838 float Actor::ClampDimension( float size, Dimension::Type dimension )
4840 const float minSize = GetMinimumSize( dimension );
4841 const float maxSize = GetMaximumSize( dimension );
4843 return std::max( minSize, std::min( size, maxSize ) );
4846 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4848 // Check if it needs to be negotiated
4849 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4851 // Check that we havn't gotten into an infinite loop
4852 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4853 bool recursionFound = false;
4854 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4856 if( *it == searchActor )
4858 recursionFound = true;
4863 if( !recursionFound )
4865 // Record the path that we have taken
4866 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4868 // Dimension dependency check
4869 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4871 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4873 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4875 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4879 // Parent dependency check
4880 Actor* parent = GetParent();
4881 if( parent && RelayoutDependentOnParent( dimension ) )
4883 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4886 // Children dependency check
4887 if( RelayoutDependentOnChildren( dimension ) )
4889 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4891 ActorPtr child = GetChildAt( i );
4893 // Only relayout child first if it is not dependent on this actor
4894 if( !child->RelayoutDependentOnParent( dimension ) )
4896 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
4901 // For deriving classes
4902 OnCalculateRelayoutSize( dimension );
4904 // All dependencies checked, calculate the size and set negotiated flag
4905 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4907 SetNegotiatedDimension( newSize, dimension );
4908 SetLayoutNegotiated( true, dimension );
4910 // For deriving classes
4911 OnLayoutNegotiated( newSize, dimension );
4913 // This actor has been successfully processed, pop it off the recursion stack
4914 recursionStack.pop_back();
4918 // TODO: Break infinite loop
4919 SetLayoutNegotiated( true, dimension );
4924 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4926 // Negotiate all dimensions that require it
4927 ActorDimensionStack recursionStack;
4929 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4931 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4934 NegotiateDimension( dimension, allocatedSize, recursionStack );
4938 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4940 switch( mRelayoutData->sizeSetPolicy )
4942 case SizeScalePolicy::USE_SIZE_SET:
4947 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4949 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4950 const Vector3 naturalSize = GetNaturalSize();
4951 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4953 const float sizeRatio = size.width / size.height;
4954 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4956 if( naturalSizeRatio < sizeRatio )
4958 return Vector2( naturalSizeRatio * size.height, size.height );
4960 else if( naturalSizeRatio > sizeRatio )
4962 return Vector2( size.width, size.width / naturalSizeRatio );
4973 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4975 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4976 const Vector3 naturalSize = GetNaturalSize();
4977 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4979 const float sizeRatio = size.width / size.height;
4980 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4982 if( naturalSizeRatio < sizeRatio )
4984 return Vector2( size.width, size.width / naturalSizeRatio );
4986 else if( naturalSizeRatio > sizeRatio )
4988 return Vector2( naturalSizeRatio * size.height, size.height );
5007 void Actor::SetNegotiatedSize( RelayoutContainer& container )
5009 // Do the set actor size
5010 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
5012 // Adjust for size set policy
5013 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
5015 // Lock the flag to stop recursive relayouts on set size
5016 mRelayoutData->insideRelayout = true;
5017 SetSize( negotiatedSize );
5018 mRelayoutData->insideRelayout = false;
5020 // Clear flags for all dimensions
5021 SetLayoutDirty( false );
5023 // Give deriving classes a chance to respond
5024 OnRelayout( negotiatedSize, container );
5026 if( !mOnRelayoutSignal.Empty() )
5028 Dali::Actor handle( this );
5029 mOnRelayoutSignal.Emit( handle );
5033 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
5035 // Force a size negotiation for actors that has assigned size during relayout
5036 // This is required as otherwise the flags that force a relayout will not
5037 // necessarilly be set. This will occur if the actor has already been laid out.
5038 // The dirty flags are then cleared. Then if the actor is added back into the
5039 // relayout container afterwards, the dirty flags would still be clear...
5040 // causing a relayout to be skipped. Here we force any actors added to the
5041 // container to be relayed out.
5042 DALI_LOG_TIMER_START( NegSizeTimer1 );
5044 if( GetUseAssignedSize(Dimension::WIDTH ) )
5046 SetLayoutNegotiated( false, Dimension::WIDTH );
5048 if( GetUseAssignedSize( Dimension::HEIGHT ) )
5050 SetLayoutNegotiated( false, Dimension::HEIGHT );
5053 // Do the negotiation
5054 NegotiateDimensions( allocatedSize );
5056 // Set the actor size
5057 SetNegotiatedSize( container );
5059 // Negotiate down to children
5060 const Vector2 newBounds = mTargetSize.GetVectorXY();
5062 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
5064 ActorPtr child = GetChildAt( i );
5066 // Forces children that have already been laid out to be relayed out
5067 // if they have assigned size during relayout.
5068 if( child->GetUseAssignedSize(Dimension::WIDTH) )
5070 child->SetLayoutNegotiated(false, Dimension::WIDTH);
5071 child->SetLayoutDirty(true, Dimension::WIDTH);
5074 if( child->GetUseAssignedSize(Dimension::HEIGHT) )
5076 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
5077 child->SetLayoutDirty(true, Dimension::HEIGHT);
5080 // Only relayout if required
5081 if( child->RelayoutRequired() )
5083 container.Add( Dali::Actor( child.Get() ), newBounds );
5086 DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
5089 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
5093 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5095 if( dimension & ( 1 << i ) )
5097 mRelayoutData->useAssignedSize[ i ] = use;
5103 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
5105 if ( mRelayoutData )
5107 // If more than one dimension is requested, just return the first one found
5108 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5110 if( dimension & ( 1 << i ) )
5112 return mRelayoutData->useAssignedSize[ i ];
5120 void Actor::RelayoutRequest( Dimension::Type dimension )
5122 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
5123 if( relayoutController )
5125 Dali::Actor self( this );
5126 relayoutController->RequestRelayout( self, dimension );
5130 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
5134 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
5138 void Actor::SetPreferredSize( const Vector2& size )
5140 EnsureRelayoutData();
5142 if( size.width > 0.0f )
5144 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
5147 if( size.height > 0.0f )
5149 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
5152 mRelayoutData->preferredSize = size;
5157 Vector2 Actor::GetPreferredSize() const
5159 if ( mRelayoutData )
5161 return Vector2( mRelayoutData->preferredSize );
5164 return GetDefaultPreferredSize();
5167 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
5169 EnsureRelayoutData();
5171 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5173 if( dimension & ( 1 << i ) )
5175 mRelayoutData->minimumSize[ i ] = size;
5182 float Actor::GetMinimumSize( Dimension::Type dimension ) const
5184 if ( mRelayoutData )
5186 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5188 if( dimension & ( 1 << i ) )
5190 return mRelayoutData->minimumSize[ i ];
5195 return 0.0f; // Default
5198 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
5200 EnsureRelayoutData();
5202 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5204 if( dimension & ( 1 << i ) )
5206 mRelayoutData->maximumSize[ i ] = size;
5213 float Actor::GetMaximumSize( Dimension::Type dimension ) const
5215 if ( mRelayoutData )
5217 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5219 if( dimension & ( 1 << i ) )
5221 return mRelayoutData->maximumSize[ i ];
5226 return FLT_MAX; // Default
5229 Object* Actor::GetParentObject() const
5234 void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
5236 if( mVisible != visible )
5238 if( sendMessage == SendMessage::TRUE && NULL != mNode )
5240 // mNode is being used in a separate thread; queue a message to set the value & base value
5241 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
5246 // Emit the signal on this actor and all its children
5247 EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
5251 void Actor::SetSiblingOrder( unsigned int order )
5253 mSiblingOrder = std::min( order, static_cast<unsigned int>( DevelLayer::SIBLING_ORDER_MULTIPLIER ) );
5257 StagePtr stage = Stage::GetCurrent();
5260 stage->RequestRebuildDepthTree();
5265 void Actor::DefragmentSiblingIndexes( ActorContainer& siblings )
5267 // Sibling index may not be in consecutive order as the sibling range is limited ( DevelLayer::SIBLING_ORDER_MULTIPLIER )
5268 // we need to remove the gaps and ensure the number start from 0 and consecutive hence have a full range.
5270 // Start at index 0, while index <= highest order
5271 // Find next index higher than 0
5272 // if nextHigher > index+1
5273 // set all nextHigher orders to index+1
5275 // Limitation: May reach the ceiling of DevelLayer::SIBLING_ORDER_MULTIPLIER with highest sibling.
5277 ActorIter end = siblings.end();
5278 int highestOrder = 0;
5279 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
5281 ActorPtr sibling = (*iter);
5282 int siblingOrder = sibling->mSiblingOrder;
5283 highestOrder = std::max( highestOrder, siblingOrder );
5286 for ( int index = 0; index <= highestOrder; index++ )
5288 int nextHighest = -1;
5290 // Find Next highest
5291 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
5293 ActorPtr sibling = (*iter);
5294 int siblingOrder = sibling->mSiblingOrder;
5296 if ( siblingOrder > index )
5298 if ( nextHighest == -1 )
5300 nextHighest = siblingOrder;
5302 nextHighest = std::min( nextHighest, siblingOrder );
5306 // Check if a gap exists between indexes, if so set next index to consecutive number
5307 if ( ( nextHighest - index ) > 1 )
5309 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
5311 ActorPtr sibling = (*iter);
5312 int siblingOrder = sibling->mSiblingOrder;
5313 if ( siblingOrder == nextHighest )
5315 sibling->mSiblingOrder = index + 1;
5316 if ( sibling->mSiblingOrder >= Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER )
5318 DALI_LOG_WARNING( "Reached max sibling order level for raising / lowering actors\n" );
5319 sibling->mSiblingOrder = Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER;
5321 sibling->SetSiblingOrder( sibling->mSiblingOrder );
5328 bool Actor::ShiftSiblingsLevels( ActorContainer& siblings, int targetLevelToShiftFrom )
5330 // Allows exclusive levels for an actor by shifting all sibling levels at the target and above by 1
5331 bool defragmentationRequired( false );
5332 ActorIter end = siblings.end();
5333 for( ActorIter iter = siblings.begin(); ( iter != end ) ; ++iter )
5335 // Move actors at nearest order and above up by 1
5336 ActorPtr sibling = (*iter);
5337 if ( sibling != this )
5339 // Iterate through container of actors, any actor with a sibling order of the target or greater should
5340 // be incremented by 1.
5341 if ( sibling->mSiblingOrder >= targetLevelToShiftFrom )
5343 sibling->mSiblingOrder++;
5344 if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
5346 // If a sibling order raises so that it is only 1 from the maximum allowed then set flag so
5347 // can re-order all sibling orders.
5348 defragmentationRequired = true;
5350 sibling->SetSiblingOrder( sibling->mSiblingOrder );
5354 return defragmentationRequired;
5360 1) Check if already at top and nothing to be done.
5361 This Actor can have highest sibling order but if not exclusive then another actor at same sibling
5362 order can be positioned above it due to insertion order of actors.
5363 2) Find nearest sibling level above, these are the siblings this actor needs to be above
5364 3) a) There may be other levels above this target level
5365 b) Increment all sibling levels at the level above nearest(target)
5366 c) Now have a vacant sibling level
5367 4) Set this actor's sibling level to nearest +1 as now vacated.
5369 Note May not just be sibling level + 1 as could be empty levels in-between
5374 ActorC ( sibling level 4 )
5375 ActorB ( sibling level 3 )
5376 ActorA ( sibling level 1 )
5378 2 ) ACTION: Raise A above B
5379 a) Find nearest level above A = Level 3
5380 b) Increment levels above Level 3
5382 ActorC ( sibling level 5 )
5383 ActorB ( sibling level 3 ) NEAREST
5384 ActorA ( sibling level 1 )
5386 3 ) Set Actor A sibling level to nearest +1 as vacant
5388 ActorC ( sibling level 5 )
5389 ActorA ( sibling level 4 )
5390 ActorB ( sibling level 3 )
5392 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5393 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5394 remove any empty sibling order gaps and start from sibling level 0 again.
5395 If the number of actors reaches this maximum and all using exclusive sibling order values then
5396 defragmention will stop and new sibling orders will be set to same max value.
5400 int nearestLevel = mSiblingOrder;
5401 int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
5402 bool defragmentationRequired( false );
5404 ActorContainer* siblings = mParent->mChildren;
5406 // Find Nearest sibling level above this actor
5407 ActorIter end = siblings->end();
5408 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
5410 ActorPtr sibling = (*iter);
5411 if ( sibling != this )
5413 int order = GetSiblingOrder( sibling );
5415 if ( ( order >= mSiblingOrder ) )
5417 int distanceToNextLevel = order - mSiblingOrder;
5418 if ( distanceToNextLevel < shortestDistanceToNextLevel )
5420 nearestLevel = order;
5421 shortestDistanceToNextLevel = distanceToNextLevel;
5427 if ( nearestLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at top
5429 mSiblingOrder = nearestLevel + 1; // Set sibling level to that above the nearest level
5430 defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
5431 // Move current actor to newly vacated order level
5432 SetSiblingOrder( mSiblingOrder );
5433 if ( defragmentationRequired )
5435 DefragmentSiblingIndexes( *siblings );
5438 SetSiblingOrder( mSiblingOrder );
5442 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5449 1) Check if actor already at bottom and if nothing needs to be done
5450 This Actor can have lowest sibling order but if not exclusive then another actor at same sibling
5451 order can be positioned above it due to insertion order of actors so need to move this actor below it.
5452 2) Find nearest sibling level below, this Actor needs to be below it
5453 3) a) Need to vacate a sibling level below nearest for this actor to occupy
5454 b) Shift up all sibling order values of actor at the nearest level and levels above it to vacate a level.
5455 c) Set this actor's sibling level to this newly vacated level.
5456 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5457 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5458 remove any empty sibling order gaps and start from sibling level 0 again.
5459 If the number of actors reaches this maximum and all using exclusive sibling order values then
5460 defragmention will stop and new sibling orders will be set to same max value.
5465 // 1) Find nearest level below
5466 int nearestLevel = mSiblingOrder;
5467 int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
5469 ActorContainer* siblings = mParent->mChildren;
5471 ActorIter end = siblings->end();
5472 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
5474 ActorPtr sibling = (*iter);
5475 if ( sibling != this )
5477 int order = GetSiblingOrder( sibling );
5479 if ( order <= mSiblingOrder )
5481 int distanceToNextLevel = mSiblingOrder - order;
5482 if ( distanceToNextLevel < shortestDistanceToNextLevel )
5484 nearestLevel = order;
5485 shortestDistanceToNextLevel = distanceToNextLevel;
5491 bool defragmentationRequired ( false );
5493 // 2) If actor already not at bottom, raise all actors at required level and above
5494 if ( shortestDistanceToNextLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at bottom
5496 mSiblingOrder = nearestLevel;
5497 defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
5498 // Move current actor to newly vacated order
5499 SetSiblingOrder( mSiblingOrder );
5500 if ( defragmentationRequired )
5502 DefragmentSiblingIndexes( *siblings );
5508 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5512 void Actor::RaiseToTop()
5515 1 ) Find highest sibling order actor
5516 2 ) If highest sibling level not itself then set sibling order to that + 1
5517 3 ) highest sibling order can be same as itself so need to increment over that
5518 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5519 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5520 remove any empty sibling order gaps and start from sibling level 0 again.
5521 If the number of actors reaches this maximum and all using exclusive sibling order values then
5522 defragmention will stop and new sibling orders will be set to same max value.
5529 ActorContainer* siblings = mParent->mChildren;
5531 ActorIter end = siblings->end();
5532 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
5534 ActorPtr sibling = (*iter);
5535 if ( sibling != this )
5537 maxOrder = std::max( GetSiblingOrder( sibling ), maxOrder );
5541 bool defragmentationRequired( false );
5543 if ( maxOrder >= mSiblingOrder )
5545 mSiblingOrder = maxOrder + 1;
5546 if ( mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
5548 defragmentationRequired = true;
5552 SetSiblingOrder( mSiblingOrder );
5554 if ( defragmentationRequired )
5556 DefragmentSiblingIndexes( *siblings );
5561 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5565 void Actor::LowerToBottom()
5568 See Actor::LowerToBottom()
5570 1 ) Check if this actor already at exclusively at the bottom, if so then no more to be done.
5571 2 ) a ) Check if the bottom position 0 is vacant.
5572 b ) If 0 position is not vacant then shift up all sibling order values from 0 and above
5573 c ) 0 sibling position is vacant.
5574 3 ) Set this actor to vacant sibling order 0;
5575 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5576 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5577 remove any empty sibling order gaps and start from sibling level 0 again.
5578 If the number of actors reaches this maximum and all using exclusive sibling order values then
5579 defragmention will stop and new sibling orders will be set to same max value.
5584 bool defragmentationRequired( false );
5585 bool orderZeroFree ( true );
5587 ActorContainer* siblings = mParent->mChildren;
5589 bool actorAtLowestOrder = true;
5590 ActorIter end = siblings->end();
5591 for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
5593 ActorPtr sibling = (*iter);
5594 if ( sibling != this )
5596 int siblingOrder = GetSiblingOrder( sibling );
5597 if ( siblingOrder <= mSiblingOrder )
5599 actorAtLowestOrder = false;
5602 if ( siblingOrder == 0 )
5604 orderZeroFree = false;
5609 if ( ! actorAtLowestOrder )
5611 if ( ! orderZeroFree )
5613 defragmentationRequired = ShiftSiblingsLevels( *siblings, 0 );
5616 SetSiblingOrder( mSiblingOrder );
5618 if ( defragmentationRequired )
5620 DefragmentSiblingIndexes( *siblings );
5626 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5630 void Actor::RaiseAbove( Internal::Actor& target )
5633 1 ) a) Find target actor's sibling order
5634 b) If sibling order of target is the same as this actor then need to this Actor's sibling order
5635 needs to be above it or the insertion order will determine which is drawn on top.
5636 2 ) Shift up by 1 all sibling order greater than target sibling order
5637 3 ) Set this actor to the sibling order to target +1 as will be a newly vacated gap above
5638 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5639 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5640 remove any empty sibling order gaps and start from sibling level 0 again.
5641 If the number of actors reaches this maximum and all using exclusive sibling order values then
5642 defragmention will stop and new sibling orders will be set to same max value.
5647 if ( ValidateActors( *this, target ) )
5649 // Find target's sibling order
5650 // Set actor sibling order to this number +1
5651 int targetSiblingOrder = GetSiblingOrder( &target );
5652 ActorContainer* siblings = mParent->mChildren;
5653 mSiblingOrder = targetSiblingOrder + 1;
5654 bool defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
5656 SetSiblingOrder( mSiblingOrder );
5658 if ( defragmentationRequired )
5660 DefragmentSiblingIndexes( *(mParent->mChildren) );
5666 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5670 void Actor::LowerBelow( Internal::Actor& target )
5673 1 ) a) Find target actor's sibling order
5674 b) If sibling order of target is the same as this actor then need to this Actor's sibling order
5675 needs to be below it or the insertion order will determine which is drawn on top.
5676 2 ) Shift the target sibling order and all sibling orders at that level or above by 1
5677 3 ) Set this actor to the sibling order of the target before it changed.
5678 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5679 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5680 remove any empty sibling order gaps and start from sibling level 0 again.
5681 If the number of actors reaches this maximum and all using exclusive sibling order values then
5682 defragmention will stop and new sibling orders will be set to same max value.
5687 if ( ValidateActors( *this, target ) )
5689 bool defragmentationRequired ( false );
5690 // Find target's sibling order
5691 // Set actor sibling order to target sibling order - 1
5692 int targetSiblingOrder = GetSiblingOrder( &target);
5693 ActorContainer* siblings = mParent->mChildren;
5694 if ( targetSiblingOrder == 0 )
5697 ActorIter end = siblings->end();
5698 for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
5700 ActorPtr sibling = (*iter);
5701 if ( sibling != this )
5703 sibling->mSiblingOrder++;
5704 if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
5706 defragmentationRequired = true;
5708 sibling->SetSiblingOrder( sibling->mSiblingOrder );
5715 defragmentationRequired = ShiftSiblingsLevels( *siblings, targetSiblingOrder );
5717 mSiblingOrder = targetSiblingOrder;
5719 SetSiblingOrder( mSiblingOrder );
5721 if ( defragmentationRequired )
5723 DefragmentSiblingIndexes( *(mParent->mChildren) );
5729 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5733 } // namespace Internal