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 /// Helper to adjust the current value of a variable from the given property-value
420 /// Returns true if value adjusted, false otherwise
421 template< typename PropertyType >
422 inline bool AdjustValue( PropertyType& currentValue, const Property::Value& value )
424 PropertyType relativeValue;
425 if( value.Get( relativeValue ) )
427 currentValue += relativeValue;
433 } // unnamed namespace
435 ActorPtr Actor::New()
437 ActorPtr actor( new Actor( BASIC ) );
439 // Second-phase construction
445 const std::string& Actor::GetName() const
450 void Actor::SetName( const std::string& name )
456 // ATTENTION: string for debug purposes is not thread safe.
457 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
461 unsigned int Actor::GetId() const
466 bool Actor::OnStage() const
471 Dali::Layer Actor::GetLayer()
475 // Short-circuit for Layer derived actors
478 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
481 // Find the immediate Layer parent
482 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
484 if( parent->IsLayer() )
486 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
493 void Actor::Add( Actor& child )
495 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
496 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
500 mChildren = new ActorContainer;
503 Actor* const oldParent( child.mParent );
505 // child might already be ours
506 if( this != oldParent )
508 // if we already have parent, unparent us first
511 oldParent->Remove( child ); // This causes OnChildRemove callback
513 // Old parent may need to readjust to missing child
514 if( oldParent->RelayoutDependentOnChildren() )
516 oldParent->RelayoutRequest();
520 // Guard against Add() during previous OnChildRemove callback
523 // Do this first, since user callbacks from within SetParent() may need to remove child
524 mChildren->push_back( ActorPtr( &child ) );
526 // SetParent asserts that child can be added
527 child.SetParent( this );
529 // Notification for derived classes
532 // Only put in a relayout request if there is a suitable dependency
533 if( RelayoutDependentOnChildren() )
541 void Actor::Remove( Actor& child )
543 if( (this == &child) || (!mChildren) )
545 // no children or removing itself
551 // Find the child in mChildren, and unparent it
552 ActorIter end = mChildren->end();
553 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
555 ActorPtr actor = (*iter);
557 if( actor.Get() == &child )
559 // Keep handle for OnChildRemove notification
562 // Do this first, since user callbacks from within SetParent() may need to add the child
563 mChildren->erase( iter );
565 DALI_ASSERT_DEBUG( actor->GetParent() == this );
566 actor->SetParent( NULL );
574 // Only put in a relayout request if there is a suitable dependency
575 if( RelayoutDependentOnChildren() )
581 // Notification for derived classes
582 OnChildRemove( child );
585 void Actor::Unparent()
589 // Remove this actor from the parent. The remove will put a relayout request in for
590 // the parent if required
591 mParent->Remove( *this );
592 // mParent is now NULL!
596 unsigned int Actor::GetChildCount() const
598 return ( NULL != mChildren ) ? mChildren->size() : 0;
601 ActorPtr Actor::GetChildAt( unsigned int index ) const
603 DALI_ASSERT_ALWAYS( index < GetChildCount() );
605 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
608 ActorPtr Actor::FindChildByName( const std::string& actorName )
611 if( actorName == mName )
617 ActorIter end = mChildren->end();
618 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
620 child = (*iter)->FindChildByName( actorName );
631 ActorPtr Actor::FindChildById( const unsigned int id )
640 ActorIter end = mChildren->end();
641 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
643 child = (*iter)->FindChildById( id );
654 void Actor::SetParentOrigin( const Vector3& origin )
658 // mNode is being used in a separate thread; queue a message to set the value & base value
659 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
662 // Cache for event-thread access
665 // not allocated, check if different from default
666 if( ParentOrigin::DEFAULT != origin )
668 mParentOrigin = new Vector3( origin );
673 // check if different from current costs more than just set
674 *mParentOrigin = origin;
678 void Actor::SetParentOriginX( float x )
680 const Vector3& current = GetCurrentParentOrigin();
682 SetParentOrigin( Vector3( x, current.y, current.z ) );
685 void Actor::SetParentOriginY( float y )
687 const Vector3& current = GetCurrentParentOrigin();
689 SetParentOrigin( Vector3( current.x, y, current.z ) );
692 void Actor::SetParentOriginZ( float z )
694 const Vector3& current = GetCurrentParentOrigin();
696 SetParentOrigin( Vector3( current.x, current.y, z ) );
699 const Vector3& Actor::GetCurrentParentOrigin() const
701 // Cached for event-thread access
702 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
705 void Actor::SetAnchorPoint( const Vector3& anchor )
709 // mNode is being used in a separate thread; queue a message to set the value & base value
710 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
713 // Cache for event-thread access
716 // not allocated, check if different from default
717 if( AnchorPoint::DEFAULT != anchor )
719 mAnchorPoint = new Vector3( anchor );
724 // check if different from current costs more than just set
725 *mAnchorPoint = anchor;
729 void Actor::SetAnchorPointX( float x )
731 const Vector3& current = GetCurrentAnchorPoint();
733 SetAnchorPoint( Vector3( x, current.y, current.z ) );
736 void Actor::SetAnchorPointY( float y )
738 const Vector3& current = GetCurrentAnchorPoint();
740 SetAnchorPoint( Vector3( current.x, y, current.z ) );
743 void Actor::SetAnchorPointZ( float z )
745 const Vector3& current = GetCurrentAnchorPoint();
747 SetAnchorPoint( Vector3( current.x, current.y, z ) );
750 const Vector3& Actor::GetCurrentAnchorPoint() const
752 // Cached for event-thread access
753 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
756 void Actor::SetPosition( float x, float y )
758 SetPosition( Vector3( x, y, 0.0f ) );
761 void Actor::SetPosition( float x, float y, float z )
763 SetPosition( Vector3( x, y, z ) );
766 void Actor::SetPosition( const Vector3& position )
768 mTargetPosition = position;
772 // mNode is being used in a separate thread; queue a message to set the value & base value
773 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
777 void Actor::SetX( float x )
779 mTargetPosition.x = x;
783 // mNode is being used in a separate thread; queue a message to set the value & base value
784 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
788 void Actor::SetY( float y )
790 mTargetPosition.y = y;
794 // mNode is being used in a separate thread; queue a message to set the value & base value
795 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
799 void Actor::SetZ( float z )
801 mTargetPosition.z = z;
805 // mNode is being used in a separate thread; queue a message to set the value & base value
806 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
810 void Actor::TranslateBy( const Vector3& distance )
812 mTargetPosition += distance;
816 // mNode is being used in a separate thread; queue a message to set the value & base value
817 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
821 const Vector3& Actor::GetCurrentPosition() const
825 // mNode is being used in a separate thread; copy the value from the previous update
826 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
829 return Vector3::ZERO;
832 const Vector3& Actor::GetTargetPosition() const
834 return mTargetPosition;
837 const Vector3& Actor::GetCurrentWorldPosition() const
841 // mNode is being used in a separate thread; copy the value from the previous update
842 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
845 return Vector3::ZERO;
848 const Vector2 Actor::GetCurrentScreenPosition() const
850 if( OnStage() && NULL != mNode )
852 StagePtr stage = Stage::GetCurrent();
853 Vector3 worldPosition = mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
854 Vector3 actorSize = GetCurrentSize() * GetCurrentScale();
855 Vector2 halfStageSize( stage->GetSize() * 0.5f ); // World position origin is center of stage
856 Vector3 halfActorSize( actorSize * 0.5f );
857 Vector3 anchorPointOffSet = halfActorSize - actorSize * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
859 return Vector2( halfStageSize.width + worldPosition.x - anchorPointOffSet.x,
860 halfStageSize.height + worldPosition.y - anchorPointOffSet.y );
863 return Vector2::ZERO;
866 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
868 // this flag is not animatable so keep the value
869 mPositionInheritanceMode = mode;
872 // mNode is being used in a separate thread; queue a message to set the value
873 SetInheritPositionMessage( GetEventThreadServices(), *mNode, mode == INHERIT_PARENT_POSITION );
877 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
879 // Cached for event-thread access
880 return mPositionInheritanceMode;
883 void Actor::SetInheritPosition( bool inherit )
885 if( mInheritPosition != inherit && NULL != mNode )
887 // non animateable so keep local copy
888 mInheritPosition = inherit;
889 SetInheritPositionMessage( GetEventThreadServices(), *mNode, inherit );
893 bool Actor::IsPositionInherited() const
895 return mInheritPosition;
898 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
900 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
901 normalizedAxis.Normalize();
903 Quaternion orientation( angle, normalizedAxis );
905 SetOrientation( orientation );
908 void Actor::SetOrientation( const Quaternion& orientation )
910 mTargetOrientation = orientation;
914 // mNode is being used in a separate thread; queue a message to set the value & base value
915 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation );
919 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
921 RotateBy( Quaternion(angle, axis) );
924 void Actor::RotateBy( const Quaternion& relativeRotation )
926 mTargetOrientation *= Quaternion( relativeRotation );
930 // mNode is being used in a separate thread; queue a message to set the value & base value
931 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
935 const Quaternion& Actor::GetCurrentOrientation() const
939 // mNode is being used in a separate thread; copy the value from the previous update
940 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
943 return Quaternion::IDENTITY;
946 const Quaternion& Actor::GetCurrentWorldOrientation() const
950 // mNode is being used in a separate thread; copy the value from the previous update
951 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
954 return Quaternion::IDENTITY;
957 void Actor::SetScale( float scale )
959 SetScale( Vector3( scale, scale, scale ) );
962 void Actor::SetScale( float x, float y, float z )
964 SetScale( Vector3( x, y, z ) );
967 void Actor::SetScale( const Vector3& scale )
969 mTargetScale = scale;
973 // mNode is being used in a separate thread; queue a message to set the value & base value
974 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
978 void Actor::SetScaleX( float x )
984 // mNode is being used in a separate thread; queue a message to set the value & base value
985 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
989 void Actor::SetScaleY( float y )
995 // mNode is being used in a separate thread; queue a message to set the value & base value
996 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
1000 void Actor::SetScaleZ( float z )
1006 // mNode is being used in a separate thread; queue a message to set the value & base value
1007 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
1011 void Actor::ScaleBy(const Vector3& relativeScale)
1013 mTargetScale *= relativeScale;
1017 // mNode is being used in a separate thread; queue a message to set the value & base value
1018 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
1022 const Vector3& Actor::GetCurrentScale() const
1026 // mNode is being used in a separate thread; copy the value from the previous update
1027 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
1030 return Vector3::ONE;
1033 const Vector3& Actor::GetCurrentWorldScale() const
1037 // mNode is being used in a separate thread; copy the value from the previous update
1038 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
1041 return Vector3::ONE;
1044 void Actor::SetInheritScale( bool inherit )
1047 if( mInheritScale != inherit && NULL != mNode )
1049 // non animateable so keep local copy
1050 mInheritScale = inherit;
1051 // mNode is being used in a separate thread; queue a message to set the value
1052 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
1056 bool Actor::IsScaleInherited() const
1058 return mInheritScale;
1061 Matrix Actor::GetCurrentWorldMatrix() const
1065 return mNode->GetWorldMatrix(0);
1068 return Matrix::IDENTITY;
1071 void Actor::SetVisible( bool visible )
1073 SetVisibleInternal( visible, SendMessage::TRUE );
1076 bool Actor::IsVisible() const
1080 // mNode is being used in a separate thread; copy the value from the previous update
1081 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
1087 void Actor::SetOpacity( float opacity )
1089 mTargetColor.a = opacity;
1093 // mNode is being used in a separate thread; queue a message to set the value & base value
1094 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
1098 float Actor::GetCurrentOpacity() const
1102 // mNode is being used in a separate thread; copy the value from the previous update
1103 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1109 ClippingMode::Type Actor::GetClippingMode() const
1111 return mClippingMode;
1114 unsigned int Actor::GetSortingDepth()
1116 return mSortedDepth;
1119 const Vector4& Actor::GetCurrentWorldColor() const
1123 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1126 return Color::WHITE;
1129 void Actor::SetColor( const Vector4& color )
1131 mTargetColor = color;
1135 // mNode is being used in a separate thread; queue a message to set the value & base value
1136 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1140 void Actor::SetColorRed( float red )
1142 mTargetColor.r = red;
1146 // mNode is being used in a separate thread; queue a message to set the value & base value
1147 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1151 void Actor::SetColorGreen( float green )
1153 mTargetColor.g = green;
1157 // mNode is being used in a separate thread; queue a message to set the value & base value
1158 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1162 void Actor::SetColorBlue( float blue )
1164 mTargetColor.b = blue;
1168 // mNode is being used in a separate thread; queue a message to set the value & base value
1169 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1173 const Vector4& Actor::GetCurrentColor() const
1177 // mNode is being used in a separate thread; copy the value from the previous update
1178 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1181 return Color::WHITE;
1184 void Actor::SetInheritOrientation( bool inherit )
1186 if( mInheritOrientation != inherit && NULL != mNode)
1188 // non animateable so keep local copy
1189 mInheritOrientation = inherit;
1190 // mNode is being used in a separate thread; queue a message to set the value
1191 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1195 bool Actor::IsOrientationInherited() const
1197 return mInheritOrientation;
1200 void Actor::SetSizeModeFactor( const Vector3& factor )
1202 EnsureRelayoutData();
1204 mRelayoutData->sizeModeFactor = factor;
1207 const Vector3& Actor::GetSizeModeFactor() const
1209 if ( mRelayoutData )
1211 return mRelayoutData->sizeModeFactor;
1214 return GetDefaultSizeModeFactor();
1217 void Actor::SetColorMode( ColorMode colorMode )
1219 // non animateable so keep local copy
1220 mColorMode = colorMode;
1223 // mNode is being used in a separate thread; queue a message to set the value
1224 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1228 ColorMode Actor::GetColorMode() const
1230 // we have cached copy
1234 void Actor::SetSize( float width, float height )
1236 SetSize( Vector2( width, height ) );
1239 void Actor::SetSize( float width, float height, float depth )
1241 SetSize( Vector3( width, height, depth ) );
1244 void Actor::SetSize( const Vector2& size )
1246 SetSize( Vector3( size.width, size.height, 0.f ) );
1249 void Actor::SetSizeInternal( const Vector2& size )
1251 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1254 void Actor::SetSize( const Vector3& size )
1256 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1258 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1259 SetPreferredSize( size.GetVectorXY() );
1263 SetSizeInternal( size );
1267 void Actor::SetSizeInternal( const Vector3& size )
1269 // dont allow recursive loop
1270 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1271 // 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
1272 if( ( NULL != mNode )&&
1273 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1274 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1275 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1279 // mNode is being used in a separate thread; queue a message to set the value & base value
1280 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
1282 // Notification for derived classes
1283 mInsideOnSizeSet = true;
1284 OnSizeSet( mTargetSize );
1285 mInsideOnSizeSet = false;
1287 // Raise a relayout request if the flag is not locked
1288 if( mRelayoutData && !mRelayoutData->insideRelayout )
1295 void Actor::SetWidth( float width )
1297 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1299 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
1300 mRelayoutData->preferredSize.width = width;
1304 mTargetSize.width = width;
1308 // mNode is being used in a separate thread; queue a message to set the value & base value
1309 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1316 void Actor::SetHeight( float height )
1318 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1320 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
1321 mRelayoutData->preferredSize.height = height;
1325 mTargetSize.height = height;
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>::BakeY, height );
1337 void Actor::SetDepth( float depth )
1339 mTargetSize.depth = depth;
1343 // mNode is being used in a separate thread; queue a message to set the value & base value
1344 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1348 Vector3 Actor::GetTargetSize() const
1350 Vector3 size = mTargetSize;
1352 // Should return preferred size if size is fixed as set by SetSize
1353 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
1355 size.width = GetPreferredSize().width;
1357 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
1359 size.height = GetPreferredSize().height;
1365 const Vector3& Actor::GetCurrentSize() const
1369 // mNode is being used in a separate thread; copy the value from the previous update
1370 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1373 return Vector3::ZERO;
1376 Vector3 Actor::GetNaturalSize() const
1378 // It is up to deriving classes to return the appropriate natural size
1379 return Vector3( 0.0f, 0.0f, 0.0f );
1382 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1384 EnsureRelayoutData();
1386 ResizePolicy::Type originalWidthPolicy = GetResizePolicy(Dimension::WIDTH);
1387 ResizePolicy::Type originalHeightPolicy = GetResizePolicy(Dimension::HEIGHT);
1389 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1391 if( dimension & ( 1 << i ) )
1393 if ( policy == ResizePolicy::USE_ASSIGNED_SIZE )
1395 mRelayoutData->useAssignedSize[ i ] = true;
1399 mRelayoutData->resizePolicies[ i ] = policy;
1400 mRelayoutData->useAssignedSize[ i ] = false;
1405 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1407 if( dimension & Dimension::WIDTH )
1409 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1412 if( dimension & Dimension::HEIGHT )
1414 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1418 // If calling SetResizePolicy, assume we want relayout enabled
1419 SetRelayoutEnabled( true );
1421 // If the resize policy is set to be FIXED, the preferred size
1422 // should be overrided by the target size. Otherwise the target
1423 // size should be overrided by the preferred size.
1425 if( dimension & Dimension::WIDTH )
1427 if( originalWidthPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1429 mRelayoutData->preferredSize.width = mTargetSize.width;
1431 else if( originalWidthPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1433 mTargetSize.width = mRelayoutData->preferredSize.width;
1437 if( dimension & Dimension::HEIGHT )
1439 if( originalHeightPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1441 mRelayoutData->preferredSize.height = mTargetSize.height;
1443 else if( originalHeightPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1445 mTargetSize.height = mRelayoutData->preferredSize.height;
1449 OnSetResizePolicy( policy, dimension );
1451 // Trigger relayout on this control
1455 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1457 if ( mRelayoutData )
1459 // If more than one dimension is requested, just return the first one found
1460 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1462 if( ( dimension & ( 1 << i ) ) )
1464 if( mRelayoutData->useAssignedSize[ i ] )
1466 return ResizePolicy::USE_ASSIGNED_SIZE;
1470 return mRelayoutData->resizePolicies[ i ];
1476 return ResizePolicy::DEFAULT;
1479 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1481 EnsureRelayoutData();
1483 mRelayoutData->sizeSetPolicy = policy;
1486 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1488 if ( mRelayoutData )
1490 return mRelayoutData->sizeSetPolicy;
1493 return DEFAULT_SIZE_SCALE_POLICY;
1496 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1498 EnsureRelayoutData();
1500 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1502 if( dimension & ( 1 << i ) )
1504 mRelayoutData->dimensionDependencies[ i ] = dependency;
1509 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1511 if ( mRelayoutData )
1513 // If more than one dimension is requested, just return the first one found
1514 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1516 if( ( dimension & ( 1 << i ) ) )
1518 return mRelayoutData->dimensionDependencies[ i ];
1523 return Dimension::ALL_DIMENSIONS; // Default
1526 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1528 // If relayout data has not been allocated yet and the client is requesting
1529 // to disable it, do nothing
1530 if( mRelayoutData || relayoutEnabled )
1532 EnsureRelayoutData();
1534 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1536 mRelayoutData->relayoutEnabled = relayoutEnabled;
1540 bool Actor::IsRelayoutEnabled() const
1542 // Assume that if relayout data has not been allocated yet then
1543 // relayout is disabled
1544 return mRelayoutData && mRelayoutData->relayoutEnabled;
1547 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1549 EnsureRelayoutData();
1551 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1553 if( dimension & ( 1 << i ) )
1555 mRelayoutData->dimensionDirty[ i ] = dirty;
1560 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1562 if ( mRelayoutData )
1564 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1566 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1576 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1578 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1581 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1583 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1586 unsigned int Actor::AddRenderer( Renderer& renderer )
1590 mRenderers = new RendererContainer;
1593 unsigned int index = mRenderers->size();
1594 RendererPtr rendererPtr = RendererPtr( &renderer );
1595 mRenderers->push_back( rendererPtr );
1596 AddRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1600 unsigned int Actor::GetRendererCount() const
1602 unsigned int rendererCount(0);
1605 rendererCount = mRenderers->size();
1608 return rendererCount;
1611 RendererPtr Actor::GetRendererAt( unsigned int index )
1613 RendererPtr renderer;
1614 if( index < GetRendererCount() )
1616 renderer = ( *mRenderers )[ index ];
1622 void Actor::RemoveRenderer( Renderer& renderer )
1626 RendererIter end = mRenderers->end();
1627 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1629 if( (*iter).Get() == &renderer )
1631 mRenderers->erase( iter );
1632 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1639 void Actor::RemoveRenderer( unsigned int index )
1641 if( index < GetRendererCount() )
1643 RendererPtr renderer = ( *mRenderers )[ index ];
1644 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.Get()->GetRendererSceneObject() );
1645 mRenderers->erase( mRenderers->begin()+index );
1649 bool Actor::IsOverlay() const
1651 return ( DrawMode::OVERLAY_2D == mDrawMode );
1654 void Actor::SetDrawMode( DrawMode::Type drawMode )
1656 // this flag is not animatable so keep the value
1657 mDrawMode = drawMode;
1658 if( ( NULL != mNode ) && ( drawMode != DrawMode::STENCIL ) )
1660 // mNode is being used in a separate thread; queue a message to set the value
1661 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1665 DrawMode::Type Actor::GetDrawMode() const
1670 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1672 // only valid when on-stage
1673 StagePtr stage = Stage::GetCurrent();
1674 if( stage && OnStage() )
1676 const RenderTaskList& taskList = stage->GetRenderTaskList();
1678 Vector2 converted( screenX, screenY );
1680 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1681 const int taskCount = taskList.GetTaskCount();
1682 for( int i = taskCount - 1; i >= 0; --i )
1684 Dali::RenderTask task = taskList.GetTask( i );
1685 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1687 // found a task where this conversion was ok so return
1695 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1697 bool retval = false;
1698 // only valid when on-stage
1701 CameraActor* camera = renderTask.GetCameraActor();
1705 renderTask.GetViewport( viewport );
1707 // need to translate coordinates to render tasks coordinate space
1708 Vector2 converted( screenX, screenY );
1709 if( renderTask.TranslateCoordinates( converted ) )
1711 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1718 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1720 // Early-out if mNode is NULL
1726 // Get the ModelView matrix
1728 Matrix::Multiply( modelView, mNode->GetWorldMatrix(0), viewMatrix );
1730 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1731 Matrix invertedMvp( false/*don't init*/);
1732 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1733 bool success = invertedMvp.Invert();
1735 // Convert to GL coordinates
1736 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1741 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1748 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1754 if( XyPlaneIntersect( nearPos, farPos, local ) )
1756 Vector3 size = GetCurrentSize();
1757 localX = local.x + size.x * 0.5f;
1758 localY = local.y + size.y * 0.5f;
1769 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1772 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1774 Mathematical Formulation
1776 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1778 ( p - c ) dot ( p - c ) = r^2
1780 Given a ray with a point of origin 'o', and a direction vector 'd':
1782 ray(t) = o + td, t >= 0
1784 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1786 (o + td - c ) dot ( o + td - c ) = r^2
1788 To solve for t we first expand the above into a more recognisable quadratic equation form
1790 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1799 B = 2( o - c ) dot d
1800 C = ( o - c ) dot ( o - c ) - r^2
1802 which can be solved using a standard quadratic formula.
1804 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1806 Practical Simplification
1808 In a renderer, we often differentiate between world space and object space. In the object space
1809 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1810 into object space, the mathematical solution presented above can be simplified significantly.
1812 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1816 and we can find the t at which the (transformed) ray intersects the sphere by
1818 ( o + td ) dot ( o + td ) = r^2
1820 According to the reasoning above, we expand the above quadratic equation into the general form
1824 which now has coefficients:
1831 // Early out if mNode is NULL
1837 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1839 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1840 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1841 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1843 // Compute the radius is not needed, square radius it's enough.
1844 const Vector3& size( mNode->GetSize( bufferIndex ) );
1846 // Scale the sphere.
1847 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1849 const float width = size.width * scale.width;
1850 const float height = size.height * scale.height;
1852 float squareSphereRadius = 0.5f * ( width * width + height * height );
1854 float a = rayDir.Dot( rayDir ); // a
1855 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1856 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1858 return ( b2 * b2 - a * c ) >= 0.f;
1861 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector2& hitPointLocal, float& distance ) const
1865 if( OnStage() && NULL != mNode )
1867 // Transforms the ray to the local reference system.
1868 // Calculate the inverse of Model matrix
1869 Matrix invModelMatrix( false/*don't init*/);
1871 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1872 invModelMatrix = mNode->GetWorldMatrix(0);
1873 invModelMatrix.Invert();
1875 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1876 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1878 // Test with the actor's XY plane (Normal = 0 0 1 1).
1880 float a = -rayOriginLocal.z;
1881 float b = rayDirLocal.z;
1883 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1885 // Ray travels distance * rayDirLocal to intersect with plane.
1888 const Vector3& size = mNode->GetSize( bufferIndex );
1890 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1891 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1893 // Test with the actor's geometry.
1894 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1901 void Actor::SetLeaveRequired( bool required )
1903 mLeaveRequired = required;
1906 bool Actor::GetLeaveRequired() const
1908 return mLeaveRequired;
1911 void Actor::SetKeyboardFocusable( bool focusable )
1913 mKeyboardFocusable = focusable;
1916 bool Actor::IsKeyboardFocusable() const
1918 return mKeyboardFocusable;
1921 bool Actor::GetTouchRequired() const
1923 return !mTouchedSignal.Empty() || !mTouchSignal.Empty() || mDerivedRequiresTouch;
1926 bool Actor::GetHoverRequired() const
1928 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1931 bool Actor::GetWheelEventRequired() const
1933 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1936 bool Actor::IsHittable() const
1938 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1941 ActorGestureData& Actor::GetGestureData()
1943 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1944 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1945 if( NULL == mGestureData )
1947 mGestureData = new ActorGestureData;
1949 return *mGestureData;
1952 bool Actor::IsGestureRequred( Gesture::Type type ) const
1954 return mGestureData && mGestureData->IsGestureRequred( type );
1957 bool Actor::EmitTouchEventSignal( const TouchEvent& event, const Dali::TouchData& touch )
1959 bool consumed = false;
1961 if( !mTouchSignal.Empty() )
1963 Dali::Actor handle( this );
1964 consumed = mTouchSignal.Emit( handle, touch );
1967 if( !mTouchedSignal.Empty() )
1969 Dali::Actor handle( this );
1970 consumed |= mTouchedSignal.Emit( handle, event );
1975 // Notification for derived classes
1976 consumed = OnTouchEvent( event ); // TODO
1982 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1984 bool consumed = false;
1986 if( !mHoveredSignal.Empty() )
1988 Dali::Actor handle( this );
1989 consumed = mHoveredSignal.Emit( handle, event );
1994 // Notification for derived classes
1995 consumed = OnHoverEvent( event );
2001 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
2003 bool consumed = false;
2005 if( !mWheelEventSignal.Empty() )
2007 Dali::Actor handle( this );
2008 consumed = mWheelEventSignal.Emit( handle, event );
2013 // Notification for derived classes
2014 consumed = OnWheelEvent( event );
2020 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
2022 if( ! mVisibilityChangedSignal.Empty() )
2024 Dali::Actor handle( this );
2025 mVisibilityChangedSignal.Emit( handle, visible, type );
2029 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
2031 return mTouchedSignal;
2034 Dali::Actor::TouchDataSignalType& Actor::TouchSignal()
2036 return mTouchSignal;
2039 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
2041 return mHoveredSignal;
2044 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
2046 return mWheelEventSignal;
2049 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
2051 return mOnStageSignal;
2054 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
2056 return mOffStageSignal;
2059 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
2061 return mOnRelayoutSignal;
2064 DevelActor::VisibilityChangedSignalType& Actor::VisibilityChangedSignal()
2066 return mVisibilityChangedSignal;
2069 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
2071 bool connected( true );
2072 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
2074 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
2076 actor->TouchedSignal().Connect( tracker, functor );
2078 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
2080 actor->HoveredSignal().Connect( tracker, functor );
2082 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
2084 actor->WheelEventSignal().Connect( tracker, functor );
2086 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
2088 actor->OnStageSignal().Connect( tracker, functor );
2090 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
2092 actor->OffStageSignal().Connect( tracker, functor );
2094 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
2096 actor->OnRelayoutSignal().Connect( tracker, functor );
2098 else if( 0 == signalName.compare( SIGNAL_TOUCH ) )
2100 actor->TouchSignal().Connect( tracker, functor );
2104 // signalName does not match any signal
2111 Actor::Actor( DerivedType derivedType )
2116 mParentOrigin( NULL ),
2117 mAnchorPoint( NULL ),
2118 mRelayoutData( NULL ),
2119 mGestureData( NULL ),
2120 mTargetOrientation( Quaternion::IDENTITY ),
2121 mTargetColor( Color::WHITE ),
2122 mTargetSize( Vector3::ZERO ),
2123 mTargetPosition( Vector3::ZERO ),
2124 mTargetScale( Vector3::ONE ),
2126 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
2130 mIsRoot( ROOT_LAYER == derivedType ),
2131 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2132 mIsOnStage( false ),
2134 mLeaveRequired( false ),
2135 mKeyboardFocusable( false ),
2136 mDerivedRequiresTouch( false ),
2137 mDerivedRequiresHover( false ),
2138 mDerivedRequiresWheelEvent( false ),
2139 mOnStageSignalled( false ),
2140 mInsideOnSizeSet( false ),
2141 mInheritPosition( true ),
2142 mInheritOrientation( true ),
2143 mInheritScale( true ),
2144 mPositionUsesAnchorPoint( true ),
2146 mDrawMode( DrawMode::NORMAL ),
2147 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2148 mColorMode( Node::DEFAULT_COLOR_MODE ),
2149 mClippingMode( ClippingMode::DISABLED )
2153 void Actor::Initialize()
2156 SceneGraph::Node* node = CreateNode();
2158 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
2159 mNode = node; // Keep raw-pointer to Node
2163 GetEventThreadServices().RegisterObject( this );
2168 // Remove mParent pointers from children even if we're destroying core,
2169 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2172 ActorConstIter endIter = mChildren->end();
2173 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2175 (*iter)->SetParent( NULL );
2181 // Guard to allow handle destruction after Core has been destroyed
2182 if( EventThreadServices::IsCoreRunning() )
2186 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2187 mNode = NULL; // Node is about to be destroyed
2190 GetEventThreadServices().UnregisterObject( this );
2193 // Cleanup optional gesture data
2194 delete mGestureData;
2196 // Cleanup optional parent origin and anchor
2197 delete mParentOrigin;
2198 delete mAnchorPoint;
2200 // Delete optional relayout data
2203 delete mRelayoutData;
2207 void Actor::ConnectToStage( unsigned int parentDepth )
2209 // This container is used instead of walking the Actor hierarchy.
2210 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
2211 ActorContainer connectionList;
2213 StagePtr stage = Stage::GetCurrent();
2216 stage->RequestRebuildDepthTree();
2219 // This stage is atomic i.e. not interrupted by user callbacks.
2220 RecursiveConnectToStage( connectionList, parentDepth + 1 );
2222 // Notify applications about the newly connected actors.
2223 const ActorIter endIter = connectionList.end();
2224 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2226 (*iter)->NotifyStageConnection();
2232 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth )
2234 DALI_ASSERT_ALWAYS( !OnStage() );
2239 ConnectToSceneGraph();
2241 // Notification for internal derived classes
2242 OnStageConnectionInternal();
2244 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2245 connectionList.push_back( ActorPtr( this ) );
2247 // Recursively connect children
2250 ActorConstIter endIter = mChildren->end();
2251 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2253 (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
2259 * This method is called when the Actor is connected to the Stage.
2260 * The parent must have added its Node to the scene-graph.
2261 * The child must connect its Node to the parent's Node.
2262 * This is recursive; the child calls ConnectToStage() for its children.
2264 void Actor::ConnectToSceneGraph()
2266 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2270 // Reparent Node in next Update
2271 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode );
2274 // Request relayout on all actors that are added to the scenegraph
2277 // Notification for Object::Observers
2281 void Actor::NotifyStageConnection()
2283 // Actors can be removed (in a callback), before the on-stage stage is reported.
2284 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2285 if( OnStage() && !mOnStageSignalled )
2287 // Notification for external (CustomActor) derived classes
2288 OnStageConnectionExternal( mDepth );
2290 if( !mOnStageSignal.Empty() )
2292 Dali::Actor handle( this );
2293 mOnStageSignal.Emit( handle );
2296 // Guard against Remove during callbacks
2299 mOnStageSignalled = true; // signal required next time Actor is removed
2304 void Actor::DisconnectFromStage()
2306 // This container is used instead of walking the Actor hierachy.
2307 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2308 ActorContainer disconnectionList;
2310 StagePtr stage = Stage::GetCurrent();
2313 stage->RequestRebuildDepthTree();
2316 // This stage is atomic i.e. not interrupted by user callbacks
2317 RecursiveDisconnectFromStage( disconnectionList );
2319 // Notify applications about the newly disconnected actors.
2320 const ActorIter endIter = disconnectionList.end();
2321 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2323 (*iter)->NotifyStageDisconnection();
2327 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2329 DALI_ASSERT_ALWAYS( OnStage() );
2331 // Recursively disconnect children
2334 ActorConstIter endIter = mChildren->end();
2335 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2337 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2341 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2342 disconnectionList.push_back( ActorPtr( this ) );
2344 // Notification for internal derived classes
2345 OnStageDisconnectionInternal();
2347 DisconnectFromSceneGraph();
2353 * This method is called by an actor or its parent, before a node removal message is sent.
2354 * This is recursive; the child calls DisconnectFromStage() for its children.
2356 void Actor::DisconnectFromSceneGraph()
2358 // Notification for Object::Observers
2359 OnSceneObjectRemove();
2362 void Actor::NotifyStageDisconnection()
2364 // Actors can be added (in a callback), before the off-stage state is reported.
2365 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2366 // only do this step if there is a stage, i.e. Core is not being shut down
2367 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2369 // Notification for external (CustomeActor) derived classes
2370 OnStageDisconnectionExternal();
2372 if( !mOffStageSignal.Empty() )
2374 Dali::Actor handle( this );
2375 mOffStageSignal.Emit( handle );
2378 // Guard against Add during callbacks
2381 mOnStageSignalled = false; // signal required next time Actor is added
2386 bool Actor::IsNodeConnected() const
2388 bool connected( false );
2390 if( OnStage() && ( NULL != mNode ) )
2392 if( IsRoot() || mNode->GetParent() )
2401 // This method generates the depth tree using the recursive function below,
2402 // then walks the tree and sets a depth index based on traversal order. It
2403 // sends a single message to update manager to update all the actor's nodes in this
2404 // tree with the depth index. The sceneGraphNodeDepths vector's elements are ordered
2405 // by depth, and could be used to reduce sorting in the update thread.
2406 void Actor::RebuildDepthTree()
2408 DALI_LOG_TIMER_START(depthTimer);
2410 DepthNodeMemoryPool nodeMemoryPool;
2411 ActorDepthTreeNode* rootNode = new (nodeMemoryPool.AllocateRaw()) ActorDepthTreeNode( this, mSiblingOrder );
2413 int actorCount = BuildDepthTree( nodeMemoryPool, rootNode );
2415 // Vector of scene-graph nodes and their depths to send to UpdateManager
2416 // in a single message
2417 SceneGraph::NodeDepths* sceneGraphNodeDepths = new SceneGraph::NodeDepths(actorCount);
2419 // Traverse depth tree and set mSortedDepth on each actor and scenegraph node
2420 uint32_t sortOrder = 1u; // Don't start at zero, as visual depth can be negative
2421 ActorDepthTreeNode* currentNode = rootNode;
2422 bool firstVisit = true;
2423 while( currentNode != rootNode || firstVisit)
2427 // Visit node, performing action
2428 for( std::vector<Actor*>::iterator iter = currentNode->mActors.begin(); iter != currentNode->mActors.end(); ++iter )
2430 (*iter)->mSortedDepth = sortOrder * DevelLayer::SIBLING_ORDER_MULTIPLIER;
2431 sceneGraphNodeDepths->Add( const_cast<SceneGraph::Node*>((*iter)->mNode), (*iter)->mSortedDepth );
2436 if( currentNode->mFirstChildNode )
2438 currentNode = currentNode->mFirstChildNode;
2440 else // leaf node, goto next sibling, or return up tree.
2442 bool breakout=false;
2443 while( ! currentNode->mNextSiblingNode )
2445 if( currentNode == rootNode ) // If we get to root of tree, stop
2450 currentNode = currentNode->mParentNode;
2457 currentNode = currentNode->mNextSiblingNode;
2461 SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths );
2462 DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree create time: ");
2466 * Structure to store the actor's associated node in the depth tree for child
2469 struct ActorNodePair
2472 ActorDepthTreeNode* node;
2473 ActorNodePair( Actor* actor, ActorDepthTreeNode* node )
2481 * Descend actor tree, building a depth tree based on actor's sibling order.
2482 * Actors with the same sibling order share the same depth tree. Siblings
2483 * in the depth tree are ordered by actor's sibling order.
2485 * An actor tree like this:
2492 * A(SO:1) B(SO:2) C(SO:1)
2495 * D(SO:0) E(SO:0) F(SO:0) G(SO:1) H(SO:0)
2497 * will end up as a depth tree like this:
2499 * RootNode [ Root ] -> NULL
2502 * Node [ A, C ] ------------------------> Node [ B ] -> NULL
2505 * Node [ D, E, H ] -> Node [ G ] -> NULL Node [ F ] -> NULL
2510 * (All nodes also point to their parents to enable storage free traversal)
2512 int Actor::BuildDepthTree( DepthNodeMemoryPool& nodeMemoryPool, ActorDepthTreeNode* node )
2514 int treeCount=1; // Count self and children
2516 // Create/add to children of this node
2519 std::vector<ActorNodePair> storedChildren;
2520 storedChildren.reserve( mChildren->size() );
2522 for( ActorContainer::iterator it = mChildren->begin(); it != mChildren->end(); ++it )
2524 Actor* childActor = (*it).Get();
2525 if( childActor->IsLayer() )
2527 Layer* layer = static_cast<Layer*>(childActor);
2528 if( layer->GetBehavior() == Dali::Layer::LAYER_3D )
2530 // Ignore this actor and children.
2535 // If no existing depth node children
2536 if( node->mFirstChildNode == NULL )
2538 node->mFirstChildNode = new (nodeMemoryPool.AllocateRaw()) ActorDepthTreeNode( childActor, childActor->mSiblingOrder );
2539 node->mFirstChildNode->mParentNode = node;
2540 storedChildren.push_back(ActorNodePair( childActor, node->mFirstChildNode ));
2542 else // find child node with matching sibling order (insertion sort)
2544 bool addedChildActor = false;
2546 // depth tree child nodes ordered by sibling order
2547 ActorDepthTreeNode* lastNode = NULL;
2548 for( ActorDepthTreeNode* childNode = node->mFirstChildNode; childNode != NULL; childNode = childNode->mNextSiblingNode )
2550 uint16_t actorSiblingOrder = childActor->mSiblingOrder;
2551 uint16_t currentSiblingOrder = childNode->GetSiblingOrder();
2553 if( actorSiblingOrder == currentSiblingOrder )
2555 // Don't need a new depth node, add to existing node
2556 childNode->AddActor( childActor );
2557 storedChildren.push_back(ActorNodePair( childActor, childNode ));
2558 addedChildActor = true;
2561 else if( actorSiblingOrder < currentSiblingOrder )
2565 lastNode = childNode;
2568 // No matching sibling order - create new node and insert into sibling list
2569 if( !addedChildActor )
2571 ActorDepthTreeNode* newNode = new (nodeMemoryPool.AllocateRaw()) ActorDepthTreeNode( childActor, childActor->mSiblingOrder );
2573 newNode->mParentNode = node;
2574 storedChildren.push_back(ActorNodePair( childActor, newNode ));
2576 if( lastNode == NULL ) // Insert at start of siblings
2578 ActorDepthTreeNode* nextNode = node->mFirstChildNode;
2579 node->mFirstChildNode = newNode;
2580 newNode->mNextSiblingNode = nextNode;
2582 else // insert into siblings after last node
2584 newNode->mNextSiblingNode = lastNode->mNextSiblingNode;
2585 lastNode->mNextSiblingNode = newNode;
2591 // Order of descent doesn't matter; we're using insertion to sort.
2592 for( std::vector<ActorNodePair>::iterator iter = storedChildren.begin(); iter != storedChildren.end(); ++iter )
2594 treeCount += iter->actor->BuildDepthTree( nodeMemoryPool, iter->node );
2600 unsigned int Actor::GetDefaultPropertyCount() const
2602 return DEFAULT_PROPERTY_COUNT;
2605 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2607 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2609 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2611 indices.PushBack( i );
2615 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2617 if( index < DEFAULT_PROPERTY_COUNT )
2619 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2625 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2627 Property::Index index = Property::INVALID_INDEX;
2629 // Look for name in default properties
2630 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2632 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2633 if( 0 == name.compare( property->name ) )
2643 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2645 if( index < DEFAULT_PROPERTY_COUNT )
2647 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2653 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2655 if( index < DEFAULT_PROPERTY_COUNT )
2657 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2663 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2665 if( index < DEFAULT_PROPERTY_COUNT )
2667 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2673 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2675 if( index < DEFAULT_PROPERTY_COUNT )
2677 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2680 // index out of range...return Property::NONE
2681 return Property::NONE;
2684 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2688 case Dali::Actor::Property::PARENT_ORIGIN:
2690 Property::Type type = property.GetType();
2691 if( type == Property::VECTOR3 )
2693 SetParentOrigin( property.Get< Vector3 >() );
2695 else if ( type == Property::STRING )
2697 std::string parentOriginString;
2698 property.Get( parentOriginString );
2699 Vector3 parentOrigin;
2700 if( GetParentOriginConstant( parentOriginString, parentOrigin ) )
2702 SetParentOrigin( parentOrigin );
2708 case Dali::Actor::Property::PARENT_ORIGIN_X:
2710 SetParentOriginX( property.Get< float >() );
2714 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2716 SetParentOriginY( property.Get< float >() );
2720 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2722 SetParentOriginZ( property.Get< float >() );
2726 case Dali::Actor::Property::ANCHOR_POINT:
2728 Property::Type type = property.GetType();
2729 if( type == Property::VECTOR3 )
2731 SetAnchorPoint( property.Get< Vector3 >() );
2733 else if ( type == Property::STRING )
2735 std::string anchorPointString;
2736 property.Get( anchorPointString );
2738 if( GetAnchorPointConstant( anchorPointString, anchor ) )
2740 SetAnchorPoint( anchor );
2746 case Dali::Actor::Property::ANCHOR_POINT_X:
2748 SetAnchorPointX( property.Get< float >() );
2752 case Dali::Actor::Property::ANCHOR_POINT_Y:
2754 SetAnchorPointY( property.Get< float >() );
2758 case Dali::Actor::Property::ANCHOR_POINT_Z:
2760 SetAnchorPointZ( property.Get< float >() );
2764 case Dali::Actor::Property::SIZE:
2766 SetSize( property.Get< Vector3 >() );
2770 case Dali::Actor::Property::SIZE_WIDTH:
2772 SetWidth( property.Get< float >() );
2776 case Dali::Actor::Property::SIZE_HEIGHT:
2778 SetHeight( property.Get< float >() );
2782 case Dali::Actor::Property::SIZE_DEPTH:
2784 SetDepth( property.Get< float >() );
2788 case Dali::Actor::Property::POSITION:
2790 SetPosition( property.Get< Vector3 >() );
2794 case Dali::Actor::Property::POSITION_X:
2796 SetX( property.Get< float >() );
2800 case Dali::Actor::Property::POSITION_Y:
2802 SetY( property.Get< float >() );
2806 case Dali::Actor::Property::POSITION_Z:
2808 SetZ( property.Get< float >() );
2812 case Dali::Actor::Property::ORIENTATION:
2814 SetOrientation( property.Get< Quaternion >() );
2818 case Dali::Actor::Property::SCALE:
2820 SetScale( property.Get< Vector3 >() );
2824 case Dali::Actor::Property::SCALE_X:
2826 SetScaleX( property.Get< float >() );
2830 case Dali::Actor::Property::SCALE_Y:
2832 SetScaleY( property.Get< float >() );
2836 case Dali::Actor::Property::SCALE_Z:
2838 SetScaleZ( property.Get< float >() );
2842 case Dali::Actor::Property::VISIBLE:
2844 SetVisible( property.Get< bool >() );
2848 case Dali::Actor::Property::COLOR:
2850 SetColor( property.Get< Vector4 >() );
2854 case Dali::Actor::Property::COLOR_RED:
2856 SetColorRed( property.Get< float >() );
2860 case Dali::Actor::Property::COLOR_GREEN:
2862 SetColorGreen( property.Get< float >() );
2866 case Dali::Actor::Property::COLOR_BLUE:
2868 SetColorBlue( property.Get< float >() );
2872 case Dali::Actor::Property::COLOR_ALPHA:
2873 case Dali::DevelActor::Property::OPACITY:
2876 if( property.Get( value ) )
2878 SetOpacity( value );
2883 case Dali::Actor::Property::NAME:
2885 SetName( property.Get< std::string >() );
2889 case Dali::Actor::Property::SENSITIVE:
2891 SetSensitive( property.Get< bool >() );
2895 case Dali::Actor::Property::LEAVE_REQUIRED:
2897 SetLeaveRequired( property.Get< bool >() );
2901 case Dali::Actor::Property::INHERIT_POSITION:
2903 SetInheritPosition( property.Get< bool >() );
2907 case Dali::Actor::Property::INHERIT_ORIENTATION:
2909 SetInheritOrientation( property.Get< bool >() );
2913 case Dali::Actor::Property::INHERIT_SCALE:
2915 SetInheritScale( property.Get< bool >() );
2919 case Dali::Actor::Property::COLOR_MODE:
2921 ColorMode mode = mColorMode;
2922 if ( Scripting::GetEnumerationProperty< ColorMode >( property, COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT, mode ) )
2924 SetColorMode( mode );
2929 case Dali::Actor::Property::POSITION_INHERITANCE:
2931 PositionInheritanceMode mode = mPositionInheritanceMode;
2932 if( Scripting::GetEnumerationProperty< PositionInheritanceMode >( property, POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT, mode ) )
2934 SetPositionInheritanceMode( mode );
2939 case Dali::Actor::Property::DRAW_MODE:
2941 DrawMode::Type mode = mDrawMode;
2942 if( Scripting::GetEnumerationProperty< DrawMode::Type >( property, DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT, mode ) )
2944 SetDrawMode( mode );
2949 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2951 SetSizeModeFactor( property.Get< Vector3 >() );
2955 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2957 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
2958 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2960 SetResizePolicy( type, Dimension::WIDTH );
2965 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2967 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
2968 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2970 SetResizePolicy( type, Dimension::HEIGHT );
2975 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2977 SizeScalePolicy::Type type;
2978 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT, type ) )
2980 SetSizeScalePolicy( type );
2985 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2987 if( property.Get< bool >() )
2989 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2994 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2996 if( property.Get< bool >() )
2998 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
3003 case Dali::Actor::Property::PADDING:
3005 Vector4 padding = property.Get< Vector4 >();
3006 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
3007 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
3011 case Dali::Actor::Property::MINIMUM_SIZE:
3013 Vector2 size = property.Get< Vector2 >();
3014 SetMinimumSize( size.x, Dimension::WIDTH );
3015 SetMinimumSize( size.y, Dimension::HEIGHT );
3019 case Dali::Actor::Property::MAXIMUM_SIZE:
3021 Vector2 size = property.Get< Vector2 >();
3022 SetMaximumSize( size.x, Dimension::WIDTH );
3023 SetMaximumSize( size.y, Dimension::HEIGHT );
3027 case Dali::DevelActor::Property::SIBLING_ORDER:
3031 if( property.Get( value ) )
3033 if( static_cast<unsigned int>(value) != mSiblingOrder )
3035 SetSiblingOrder( value );
3041 case Dali::Actor::Property::CLIPPING_MODE:
3043 ClippingMode::Type convertedValue = mClippingMode;
3044 if( Scripting::GetEnumerationProperty< ClippingMode::Type >( property, CLIPPING_MODE_TABLE, CLIPPING_MODE_TABLE_COUNT, convertedValue ) )
3046 mClippingMode = convertedValue;
3049 SetClippingModeMessage( GetEventThreadServices(), *mNode, mClippingMode );
3055 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
3058 if( property.Get( value ) && value != mPositionUsesAnchorPoint )
3060 mPositionUsesAnchorPoint = value;
3063 SetPositionUsesAnchorPointMessage( GetEventThreadServices(), *mNode, mPositionUsesAnchorPoint );
3071 // this can happen in the case of a non-animatable default property so just do nothing
3077 // TODO: This method needs to be removed
3078 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
3080 switch( entry.GetType() )
3082 case Property::BOOLEAN:
3084 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
3085 DALI_ASSERT_DEBUG( NULL != property );
3087 // property is being used in a separate thread; queue a message to set the property
3088 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
3093 case Property::INTEGER:
3095 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
3096 DALI_ASSERT_DEBUG( NULL != property );
3098 // property is being used in a separate thread; queue a message to set the property
3099 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
3104 case Property::FLOAT:
3106 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
3107 DALI_ASSERT_DEBUG( NULL != property );
3109 // property is being used in a separate thread; queue a message to set the property
3110 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
3115 case Property::VECTOR2:
3117 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
3118 DALI_ASSERT_DEBUG( NULL != property );
3120 // property is being used in a separate thread; queue a message to set the property
3121 if(entry.componentIndex == 0)
3123 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
3125 else if(entry.componentIndex == 1)
3127 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
3131 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
3137 case Property::VECTOR3:
3139 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
3140 DALI_ASSERT_DEBUG( NULL != property );
3142 // property is being used in a separate thread; queue a message to set the property
3143 if(entry.componentIndex == 0)
3145 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
3147 else if(entry.componentIndex == 1)
3149 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
3151 else if(entry.componentIndex == 2)
3153 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
3157 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
3163 case Property::VECTOR4:
3165 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
3166 DALI_ASSERT_DEBUG( NULL != property );
3168 // property is being used in a separate thread; queue a message to set the property
3169 if(entry.componentIndex == 0)
3171 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
3173 else if(entry.componentIndex == 1)
3175 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
3177 else if(entry.componentIndex == 2)
3179 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
3181 else if(entry.componentIndex == 3)
3183 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
3187 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3193 case Property::ROTATION:
3195 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3196 DALI_ASSERT_DEBUG( NULL != property );
3198 // property is being used in a separate thread; queue a message to set the property
3199 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3204 case Property::MATRIX:
3206 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3207 DALI_ASSERT_DEBUG( NULL != property );
3209 // property is being used in a separate thread; queue a message to set the property
3210 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3215 case Property::MATRIX3:
3217 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3218 DALI_ASSERT_DEBUG( NULL != property );
3220 // property is being used in a separate thread; queue a message to set the property
3221 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3228 // nothing to do for other types
3233 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3235 Property::Value value;
3237 if( ! GetCachedPropertyValue( index, value ) )
3239 // If property value is not stored in the event-side, then it must be a scene-graph only property
3240 GetCurrentPropertyValue( index, value );
3246 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
3248 Property::Value value;
3250 if( ! GetCurrentPropertyValue( index, value ) )
3252 // If unable to retrieve scene-graph property value, then it must be an event-side only property
3253 GetCachedPropertyValue( index, value );
3259 void Actor::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, PropertyChange::Type propertyChangeType )
3261 if( propertyChangeType == Object::PropertyChange::SET )
3265 case Dali::Actor::Property::SIZE:
3267 if( value.Get( mTargetSize ) )
3269 // Notify deriving classes
3270 OnSizeAnimation( animation, mTargetSize );
3275 case Dali::Actor::Property::SIZE_WIDTH:
3277 if( value.Get( mTargetSize.width ) )
3279 // Notify deriving classes
3280 OnSizeAnimation( animation, mTargetSize );
3285 case Dali::Actor::Property::SIZE_HEIGHT:
3287 if( value.Get( mTargetSize.height ) )
3289 // Notify deriving classes
3290 OnSizeAnimation( animation, mTargetSize );
3295 case Dali::Actor::Property::SIZE_DEPTH:
3297 if( value.Get( mTargetSize.depth ) )
3299 // Notify deriving classes
3300 OnSizeAnimation( animation, mTargetSize );
3305 case Dali::Actor::Property::POSITION:
3307 value.Get( mTargetPosition );
3311 case Dali::Actor::Property::POSITION_X:
3313 value.Get( mTargetPosition.x );
3317 case Dali::Actor::Property::POSITION_Y:
3319 value.Get( mTargetPosition.y );
3323 case Dali::Actor::Property::POSITION_Z:
3325 value.Get( mTargetPosition.z );
3329 case Dali::Actor::Property::ORIENTATION:
3331 value.Get( mTargetOrientation );
3335 case Dali::Actor::Property::SCALE:
3337 value.Get( mTargetScale );
3341 case Dali::Actor::Property::SCALE_X:
3343 value.Get( mTargetScale.x );
3347 case Dali::Actor::Property::SCALE_Y:
3349 value.Get( mTargetScale.y );
3353 case Dali::Actor::Property::SCALE_Z:
3355 value.Get( mTargetScale.z );
3359 case Dali::Actor::Property::VISIBLE:
3361 SetVisibleInternal( value.Get< bool >(), SendMessage::FALSE );
3365 case Dali::Actor::Property::COLOR:
3367 value.Get( mTargetColor );
3371 case Dali::Actor::Property::COLOR_RED:
3373 value.Get( mTargetColor.r );
3377 case Dali::Actor::Property::COLOR_GREEN:
3379 value.Get( mTargetColor.g );
3383 case Dali::Actor::Property::COLOR_BLUE:
3385 value.Get( mTargetColor.b );
3389 case Dali::Actor::Property::COLOR_ALPHA:
3390 case Dali::DevelActor::Property::OPACITY:
3392 value.Get( mTargetColor.a );
3398 // Not an animatable property. Do nothing.
3407 case Dali::Actor::Property::SIZE:
3409 if( AdjustValue< Vector3 >( mTargetSize, value ) )
3411 // Notify deriving classes
3412 OnSizeAnimation( animation, mTargetSize );
3417 case Dali::Actor::Property::SIZE_WIDTH:
3419 if( AdjustValue< float >( mTargetSize.width, value ) )
3421 // Notify deriving classes
3422 OnSizeAnimation( animation, mTargetSize );
3427 case Dali::Actor::Property::SIZE_HEIGHT:
3429 if( AdjustValue< float >( mTargetSize.height, value ) )
3431 // Notify deriving classes
3432 OnSizeAnimation( animation, mTargetSize );
3437 case Dali::Actor::Property::SIZE_DEPTH:
3439 if( AdjustValue< float >( mTargetSize.depth, value ) )
3441 // Notify deriving classes
3442 OnSizeAnimation( animation, mTargetSize );
3447 case Dali::Actor::Property::POSITION:
3449 AdjustValue< Vector3 >( mTargetPosition, value );
3453 case Dali::Actor::Property::POSITION_X:
3455 AdjustValue< float >( mTargetPosition.x, value );
3459 case Dali::Actor::Property::POSITION_Y:
3461 AdjustValue< float >( mTargetPosition.y, value );
3465 case Dali::Actor::Property::POSITION_Z:
3467 AdjustValue< float >( mTargetPosition.z, value );
3471 case Dali::Actor::Property::ORIENTATION:
3473 Quaternion relativeValue;
3474 if( value.Get( relativeValue ) )
3476 mTargetOrientation *= relativeValue;
3481 case Dali::Actor::Property::SCALE:
3483 AdjustValue< Vector3 >( mTargetScale, value );
3487 case Dali::Actor::Property::SCALE_X:
3489 AdjustValue< float >( mTargetScale.x, value );
3493 case Dali::Actor::Property::SCALE_Y:
3495 AdjustValue< float >( mTargetScale.y, value );
3499 case Dali::Actor::Property::SCALE_Z:
3501 AdjustValue< float >( mTargetScale.z, value );
3505 case Dali::Actor::Property::VISIBLE:
3507 bool relativeValue = false;
3508 if( value.Get( relativeValue ) )
3510 bool visible = mVisible || relativeValue;
3511 SetVisibleInternal( visible, SendMessage::FALSE );
3516 case Dali::Actor::Property::COLOR:
3518 AdjustValue< Vector4 >( mTargetColor, value );
3522 case Dali::Actor::Property::COLOR_RED:
3524 AdjustValue< float >( mTargetColor.r, value );
3528 case Dali::Actor::Property::COLOR_GREEN:
3530 AdjustValue< float >( mTargetColor.g, value );
3534 case Dali::Actor::Property::COLOR_BLUE:
3536 AdjustValue< float >( mTargetColor.b, value );
3540 case Dali::Actor::Property::COLOR_ALPHA:
3541 case Dali::DevelActor::Property::OPACITY:
3543 AdjustValue< float >( mTargetColor.a, value );
3549 // Not an animatable property. Do nothing.
3556 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3561 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3563 // This method should only return an object connected to the scene-graph
3564 return OnStage() ? mNode : NULL;
3567 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3569 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3571 const PropertyBase* property( NULL );
3573 // This method should only return a property of an object connected to the scene-graph
3579 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3581 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3582 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3584 property = animatable->GetSceneGraphProperty();
3586 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3587 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3589 CustomPropertyMetadata* custom = FindCustomProperty( index );
3590 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3592 property = custom->GetSceneGraphProperty();
3594 else if( NULL != mNode )
3598 case Dali::Actor::Property::SIZE:
3599 property = &mNode->mSize;
3602 case Dali::Actor::Property::SIZE_WIDTH:
3603 property = &mNode->mSize;
3606 case Dali::Actor::Property::SIZE_HEIGHT:
3607 property = &mNode->mSize;
3610 case Dali::Actor::Property::SIZE_DEPTH:
3611 property = &mNode->mSize;
3614 case Dali::Actor::Property::POSITION:
3615 property = &mNode->mPosition;
3618 case Dali::Actor::Property::POSITION_X:
3619 property = &mNode->mPosition;
3622 case Dali::Actor::Property::POSITION_Y:
3623 property = &mNode->mPosition;
3626 case Dali::Actor::Property::POSITION_Z:
3627 property = &mNode->mPosition;
3630 case Dali::Actor::Property::ORIENTATION:
3631 property = &mNode->mOrientation;
3634 case Dali::Actor::Property::SCALE:
3635 property = &mNode->mScale;
3638 case Dali::Actor::Property::SCALE_X:
3639 property = &mNode->mScale;
3642 case Dali::Actor::Property::SCALE_Y:
3643 property = &mNode->mScale;
3646 case Dali::Actor::Property::SCALE_Z:
3647 property = &mNode->mScale;
3650 case Dali::Actor::Property::VISIBLE:
3651 property = &mNode->mVisible;
3654 case Dali::Actor::Property::COLOR:
3655 property = &mNode->mColor;
3658 case Dali::Actor::Property::COLOR_RED:
3659 property = &mNode->mColor;
3662 case Dali::Actor::Property::COLOR_GREEN:
3663 property = &mNode->mColor;
3666 case Dali::Actor::Property::COLOR_BLUE:
3667 property = &mNode->mColor;
3670 case Dali::Actor::Property::COLOR_ALPHA:
3671 case Dali::DevelActor::Property::OPACITY:
3672 property = &mNode->mColor;
3683 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3685 const PropertyInputImpl* property( NULL );
3687 // This method should only return a property of an object connected to the scene-graph
3693 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3695 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3696 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3698 property = animatable->GetSceneGraphProperty();
3700 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3701 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3703 CustomPropertyMetadata* custom = FindCustomProperty( index );
3704 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3705 property = custom->GetSceneGraphProperty();
3707 else if( NULL != mNode )
3711 case Dali::Actor::Property::PARENT_ORIGIN:
3712 property = &mNode->mParentOrigin;
3715 case Dali::Actor::Property::PARENT_ORIGIN_X:
3716 property = &mNode->mParentOrigin;
3719 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3720 property = &mNode->mParentOrigin;
3723 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3724 property = &mNode->mParentOrigin;
3727 case Dali::Actor::Property::ANCHOR_POINT:
3728 property = &mNode->mAnchorPoint;
3731 case Dali::Actor::Property::ANCHOR_POINT_X:
3732 property = &mNode->mAnchorPoint;
3735 case Dali::Actor::Property::ANCHOR_POINT_Y:
3736 property = &mNode->mAnchorPoint;
3739 case Dali::Actor::Property::ANCHOR_POINT_Z:
3740 property = &mNode->mAnchorPoint;
3743 case Dali::Actor::Property::SIZE:
3744 property = &mNode->mSize;
3747 case Dali::Actor::Property::SIZE_WIDTH:
3748 property = &mNode->mSize;
3751 case Dali::Actor::Property::SIZE_HEIGHT:
3752 property = &mNode->mSize;
3755 case Dali::Actor::Property::SIZE_DEPTH:
3756 property = &mNode->mSize;
3759 case Dali::Actor::Property::POSITION:
3760 property = &mNode->mPosition;
3763 case Dali::Actor::Property::POSITION_X:
3764 property = &mNode->mPosition;
3767 case Dali::Actor::Property::POSITION_Y:
3768 property = &mNode->mPosition;
3771 case Dali::Actor::Property::POSITION_Z:
3772 property = &mNode->mPosition;
3775 case Dali::Actor::Property::WORLD_POSITION:
3776 property = &mNode->mWorldPosition;
3779 case Dali::Actor::Property::WORLD_POSITION_X:
3780 property = &mNode->mWorldPosition;
3783 case Dali::Actor::Property::WORLD_POSITION_Y:
3784 property = &mNode->mWorldPosition;
3787 case Dali::Actor::Property::WORLD_POSITION_Z:
3788 property = &mNode->mWorldPosition;
3791 case Dali::Actor::Property::ORIENTATION:
3792 property = &mNode->mOrientation;
3795 case Dali::Actor::Property::WORLD_ORIENTATION:
3796 property = &mNode->mWorldOrientation;
3799 case Dali::Actor::Property::SCALE:
3800 property = &mNode->mScale;
3803 case Dali::Actor::Property::SCALE_X:
3804 property = &mNode->mScale;
3807 case Dali::Actor::Property::SCALE_Y:
3808 property = &mNode->mScale;
3811 case Dali::Actor::Property::SCALE_Z:
3812 property = &mNode->mScale;
3815 case Dali::Actor::Property::WORLD_SCALE:
3816 property = &mNode->mWorldScale;
3819 case Dali::Actor::Property::VISIBLE:
3820 property = &mNode->mVisible;
3823 case Dali::Actor::Property::COLOR:
3824 property = &mNode->mColor;
3827 case Dali::Actor::Property::COLOR_RED:
3828 property = &mNode->mColor;
3831 case Dali::Actor::Property::COLOR_GREEN:
3832 property = &mNode->mColor;
3835 case Dali::Actor::Property::COLOR_BLUE:
3836 property = &mNode->mColor;
3839 case Dali::Actor::Property::COLOR_ALPHA:
3840 case Dali::DevelActor::Property::OPACITY:
3842 property = &mNode->mColor;
3846 case Dali::Actor::Property::WORLD_COLOR:
3847 property = &mNode->mWorldColor;
3850 case Dali::Actor::Property::WORLD_MATRIX:
3851 property = &mNode->mWorldMatrix;
3862 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3864 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3866 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3868 // check whether the animatable property is registered already, if not then register one.
3869 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3870 if( animatableProperty )
3872 componentIndex = animatableProperty->componentIndex;
3879 case Dali::Actor::Property::PARENT_ORIGIN_X:
3880 case Dali::Actor::Property::ANCHOR_POINT_X:
3881 case Dali::Actor::Property::SIZE_WIDTH:
3882 case Dali::Actor::Property::POSITION_X:
3883 case Dali::Actor::Property::WORLD_POSITION_X:
3884 case Dali::Actor::Property::SCALE_X:
3885 case Dali::Actor::Property::COLOR_RED:
3891 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3892 case Dali::Actor::Property::ANCHOR_POINT_Y:
3893 case Dali::Actor::Property::SIZE_HEIGHT:
3894 case Dali::Actor::Property::POSITION_Y:
3895 case Dali::Actor::Property::WORLD_POSITION_Y:
3896 case Dali::Actor::Property::SCALE_Y:
3897 case Dali::Actor::Property::COLOR_GREEN:
3903 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3904 case Dali::Actor::Property::ANCHOR_POINT_Z:
3905 case Dali::Actor::Property::SIZE_DEPTH:
3906 case Dali::Actor::Property::POSITION_Z:
3907 case Dali::Actor::Property::WORLD_POSITION_Z:
3908 case Dali::Actor::Property::SCALE_Z:
3909 case Dali::Actor::Property::COLOR_BLUE:
3915 case Dali::Actor::Property::COLOR_ALPHA:
3916 case Dali::DevelActor::Property::OPACITY:
3930 return componentIndex;
3933 void Actor::SetParent( Actor* parent )
3937 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3941 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3944 // Instruct each actor to create a corresponding node in the scene graph
3945 ConnectToStage( parent->GetHierarchyDepth() );
3948 // Resolve the name and index for the child properties if any
3949 ResolveChildProperties();
3951 else // parent being set to NULL
3953 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3957 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3960 DALI_ASSERT_ALWAYS( mNode != NULL );
3964 // Disconnect the Node & its children from the scene-graph.
3965 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3968 // Instruct each actor to discard pointers to the scene-graph
3969 DisconnectFromStage();
3974 SceneGraph::Node* Actor::CreateNode() const
3979 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3982 Actor* actor = dynamic_cast< Actor* >( object );
3986 if( 0 == actionName.compare( ACTION_SHOW ) )
3988 actor->SetVisible( true );
3991 else if( 0 == actionName.compare( ACTION_HIDE ) )
3993 actor->SetVisible( false );
4001 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
4003 bool valueSet = true;
4007 case Dali::Actor::Property::PARENT_ORIGIN:
4009 value = GetCurrentParentOrigin();
4013 case Dali::Actor::Property::PARENT_ORIGIN_X:
4015 value = GetCurrentParentOrigin().x;
4019 case Dali::Actor::Property::PARENT_ORIGIN_Y:
4021 value = GetCurrentParentOrigin().y;
4025 case Dali::Actor::Property::PARENT_ORIGIN_Z:
4027 value = GetCurrentParentOrigin().z;
4031 case Dali::Actor::Property::ANCHOR_POINT:
4033 value = GetCurrentAnchorPoint();
4037 case Dali::Actor::Property::ANCHOR_POINT_X:
4039 value = GetCurrentAnchorPoint().x;
4043 case Dali::Actor::Property::ANCHOR_POINT_Y:
4045 value = GetCurrentAnchorPoint().y;
4049 case Dali::Actor::Property::ANCHOR_POINT_Z:
4051 value = GetCurrentAnchorPoint().z;
4055 case Dali::Actor::Property::SIZE:
4057 value = GetTargetSize();
4061 case Dali::Actor::Property::SIZE_WIDTH:
4063 value = GetTargetSize().width;
4067 case Dali::Actor::Property::SIZE_HEIGHT:
4069 value = GetTargetSize().height;
4073 case Dali::Actor::Property::SIZE_DEPTH:
4075 value = GetTargetSize().depth;
4079 case Dali::Actor::Property::POSITION:
4081 value = GetTargetPosition();
4085 case Dali::Actor::Property::POSITION_X:
4087 value = GetTargetPosition().x;
4091 case Dali::Actor::Property::POSITION_Y:
4093 value = GetTargetPosition().y;
4097 case Dali::Actor::Property::POSITION_Z:
4099 value = GetTargetPosition().z;
4103 case Dali::Actor::Property::ORIENTATION:
4105 value = mTargetOrientation;
4109 case Dali::Actor::Property::SCALE:
4111 value = mTargetScale;
4115 case Dali::Actor::Property::SCALE_X:
4117 value = mTargetScale.x;
4121 case Dali::Actor::Property::SCALE_Y:
4123 value = mTargetScale.y;
4127 case Dali::Actor::Property::SCALE_Z:
4129 value = mTargetScale.z;
4133 case Dali::Actor::Property::VISIBLE:
4139 case Dali::Actor::Property::COLOR:
4141 value = mTargetColor;
4145 case Dali::Actor::Property::COLOR_RED:
4147 value = mTargetColor.r;
4151 case Dali::Actor::Property::COLOR_GREEN:
4153 value = mTargetColor.g;
4157 case Dali::Actor::Property::COLOR_BLUE:
4159 value = mTargetColor.b;
4163 case Dali::Actor::Property::COLOR_ALPHA:
4164 case Dali::DevelActor::Property::OPACITY:
4166 value = mTargetColor.a;
4170 case Dali::Actor::Property::NAME:
4176 case Dali::Actor::Property::SENSITIVE:
4178 value = IsSensitive();
4182 case Dali::Actor::Property::LEAVE_REQUIRED:
4184 value = GetLeaveRequired();
4188 case Dali::Actor::Property::INHERIT_POSITION:
4190 value = IsPositionInherited();
4194 case Dali::Actor::Property::INHERIT_ORIENTATION:
4196 value = IsOrientationInherited();
4200 case Dali::Actor::Property::INHERIT_SCALE:
4202 value = IsScaleInherited();
4206 case Dali::Actor::Property::COLOR_MODE:
4208 value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
4212 case Dali::Actor::Property::POSITION_INHERITANCE:
4214 value = Scripting::GetLinearEnumerationName< PositionInheritanceMode >( GetPositionInheritanceMode(), POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT );
4218 case Dali::Actor::Property::DRAW_MODE:
4220 value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
4224 case Dali::Actor::Property::SIZE_MODE_FACTOR:
4226 value = GetSizeModeFactor();
4230 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
4232 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
4236 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
4238 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
4242 case Dali::Actor::Property::SIZE_SCALE_POLICY:
4244 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT );
4248 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
4250 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
4254 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
4256 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
4260 case Dali::Actor::Property::PADDING:
4262 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
4263 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
4264 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
4268 case Dali::Actor::Property::MINIMUM_SIZE:
4270 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
4274 case Dali::Actor::Property::MAXIMUM_SIZE:
4276 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
4280 case Dali::Actor::Property::CLIPPING_MODE:
4282 value = mClippingMode;
4286 case Dali::DevelActor::Property::SIBLING_ORDER:
4288 value = static_cast<int>(mSiblingOrder);
4292 case Dali::DevelActor::Property::SCREEN_POSITION:
4294 value = GetCurrentScreenPosition();
4298 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
4300 value = mPositionUsesAnchorPoint;
4306 // Must be a scene-graph only property
4315 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
4317 bool valueSet = true;
4321 case Dali::Actor::Property::SIZE:
4323 value = GetCurrentSize();
4327 case Dali::Actor::Property::SIZE_WIDTH:
4329 value = GetCurrentSize().width;
4333 case Dali::Actor::Property::SIZE_HEIGHT:
4335 value = GetCurrentSize().height;
4339 case Dali::Actor::Property::SIZE_DEPTH:
4341 value = GetCurrentSize().depth;
4345 case Dali::Actor::Property::POSITION:
4347 value = GetCurrentPosition();
4351 case Dali::Actor::Property::POSITION_X:
4353 value = GetCurrentPosition().x;
4357 case Dali::Actor::Property::POSITION_Y:
4359 value = GetCurrentPosition().y;
4363 case Dali::Actor::Property::POSITION_Z:
4365 value = GetCurrentPosition().z;
4369 case Dali::Actor::Property::WORLD_POSITION:
4371 value = GetCurrentWorldPosition();
4375 case Dali::Actor::Property::WORLD_POSITION_X:
4377 value = GetCurrentWorldPosition().x;
4381 case Dali::Actor::Property::WORLD_POSITION_Y:
4383 value = GetCurrentWorldPosition().y;
4387 case Dali::Actor::Property::WORLD_POSITION_Z:
4389 value = GetCurrentWorldPosition().z;
4393 case Dali::Actor::Property::ORIENTATION:
4395 value = GetCurrentOrientation();
4399 case Dali::Actor::Property::WORLD_ORIENTATION:
4401 value = GetCurrentWorldOrientation();
4405 case Dali::Actor::Property::SCALE:
4407 value = GetCurrentScale();
4411 case Dali::Actor::Property::SCALE_X:
4413 value = GetCurrentScale().x;
4417 case Dali::Actor::Property::SCALE_Y:
4419 value = GetCurrentScale().y;
4423 case Dali::Actor::Property::SCALE_Z:
4425 value = GetCurrentScale().z;
4429 case Dali::Actor::Property::WORLD_SCALE:
4431 value = GetCurrentWorldScale();
4435 case Dali::Actor::Property::COLOR:
4437 value = GetCurrentColor();
4441 case Dali::Actor::Property::COLOR_RED:
4443 value = GetCurrentColor().r;
4447 case Dali::Actor::Property::COLOR_GREEN:
4449 value = GetCurrentColor().g;
4453 case Dali::Actor::Property::COLOR_BLUE:
4455 value = GetCurrentColor().b;
4459 case Dali::Actor::Property::COLOR_ALPHA:
4460 case Dali::DevelActor::Property::OPACITY:
4462 value = GetCurrentColor().a;
4466 case Dali::Actor::Property::WORLD_COLOR:
4468 value = GetCurrentWorldColor();
4472 case Dali::Actor::Property::WORLD_MATRIX:
4474 value = GetCurrentWorldMatrix();
4478 case Dali::Actor::Property::VISIBLE:
4480 value = IsVisible();
4486 // Must be an event-side only property
4495 void Actor::EnsureRelayoutData()
4497 // Assign relayout data.
4498 if( !mRelayoutData )
4500 mRelayoutData = new RelayoutData();
4504 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
4506 // Check if actor is dependent on parent
4507 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4509 if( ( dimension & ( 1 << i ) ) )
4511 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4512 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
4522 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
4524 // Check if actor is dependent on children
4525 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4527 if( ( dimension & ( 1 << i ) ) )
4529 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4530 switch( resizePolicy )
4532 case ResizePolicy::FIT_TO_CHILDREN:
4533 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
4549 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
4551 return Actor::RelayoutDependentOnChildren( dimension );
4554 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
4556 // Check each possible dimension and see if it is dependent on the input one
4557 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4559 if( dimension & ( 1 << i ) )
4561 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
4568 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
4570 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4572 if( dimension & ( 1 << i ) )
4574 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
4579 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
4581 // If more than one dimension is requested, just return the first one found
4582 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4584 if( ( dimension & ( 1 << i ) ) )
4586 return mRelayoutData->negotiatedDimensions[ i ];
4590 return 0.0f; // Default
4593 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
4595 EnsureRelayoutData();
4597 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4599 if( dimension & ( 1 << i ) )
4601 mRelayoutData->dimensionPadding[ i ] = padding;
4606 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4608 if ( mRelayoutData )
4610 // If more than one dimension is requested, just return the first one found
4611 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4613 if( ( dimension & ( 1 << i ) ) )
4615 return mRelayoutData->dimensionPadding[ i ];
4620 return GetDefaultDimensionPadding();
4623 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4625 EnsureRelayoutData();
4627 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4629 if( dimension & ( 1 << i ) )
4631 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4636 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4638 if ( mRelayoutData )
4640 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4642 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4652 float Actor::GetHeightForWidthBase( float width )
4654 float height = 0.0f;
4656 const Vector3 naturalSize = GetNaturalSize();
4657 if( naturalSize.width > 0.0f )
4659 height = naturalSize.height * width / naturalSize.width;
4661 else // we treat 0 as 1:1 aspect ratio
4669 float Actor::GetWidthForHeightBase( float height )
4673 const Vector3 naturalSize = GetNaturalSize();
4674 if( naturalSize.height > 0.0f )
4676 width = naturalSize.width * height / naturalSize.height;
4678 else // we treat 0 as 1:1 aspect ratio
4686 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4688 // Fill to parent, taking size mode factor into account
4689 switch( child.GetResizePolicy( dimension ) )
4691 case ResizePolicy::FILL_TO_PARENT:
4693 return GetLatestSize( dimension );
4696 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4698 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4701 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4703 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4708 return GetLatestSize( dimension );
4713 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4715 // Can be overridden in derived class
4716 return CalculateChildSizeBase( child, dimension );
4719 float Actor::GetHeightForWidth( float width )
4721 // Can be overridden in derived class
4722 return GetHeightForWidthBase( width );
4725 float Actor::GetWidthForHeight( float height )
4727 // Can be overridden in derived class
4728 return GetWidthForHeightBase( height );
4731 float Actor::GetLatestSize( Dimension::Type dimension ) const
4733 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4736 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4738 Vector2 padding = GetPadding( dimension );
4740 return GetLatestSize( dimension ) + padding.x + padding.y;
4743 float Actor::NegotiateFromParent( Dimension::Type dimension )
4745 Actor* parent = GetParent();
4748 Vector2 padding( GetPadding( dimension ) );
4749 Vector2 parentPadding( parent->GetPadding( dimension ) );
4750 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4756 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4758 float maxDimensionPoint = 0.0f;
4760 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4762 ActorPtr child = GetChildAt( i );
4764 if( !child->RelayoutDependentOnParent( dimension ) )
4766 // Calculate the min and max points that the children range across
4767 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
4768 float dimensionSize = child->GetRelayoutSize( dimension );
4769 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4773 return maxDimensionPoint;
4776 float Actor::GetSize( Dimension::Type dimension ) const
4778 return GetDimensionValue( mTargetSize, dimension );
4781 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4783 return GetDimensionValue( GetNaturalSize(), dimension );
4786 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4788 switch( GetResizePolicy( dimension ) )
4790 case ResizePolicy::USE_NATURAL_SIZE:
4792 return GetNaturalSize( dimension );
4795 case ResizePolicy::FIXED:
4797 return GetDimensionValue( GetPreferredSize(), dimension );
4800 case ResizePolicy::USE_ASSIGNED_SIZE:
4802 return GetDimensionValue( maximumSize, dimension );
4805 case ResizePolicy::FILL_TO_PARENT:
4806 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4807 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4809 return NegotiateFromParent( dimension );
4812 case ResizePolicy::FIT_TO_CHILDREN:
4814 return NegotiateFromChildren( dimension );
4817 case ResizePolicy::DIMENSION_DEPENDENCY:
4819 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4822 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4824 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4827 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4829 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4841 return 0.0f; // Default
4844 float Actor::ClampDimension( float size, Dimension::Type dimension )
4846 const float minSize = GetMinimumSize( dimension );
4847 const float maxSize = GetMaximumSize( dimension );
4849 return std::max( minSize, std::min( size, maxSize ) );
4852 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4854 // Check if it needs to be negotiated
4855 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4857 // Check that we havn't gotten into an infinite loop
4858 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4859 bool recursionFound = false;
4860 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4862 if( *it == searchActor )
4864 recursionFound = true;
4869 if( !recursionFound )
4871 // Record the path that we have taken
4872 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4874 // Dimension dependency check
4875 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4877 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4879 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4881 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4885 // Parent dependency check
4886 Actor* parent = GetParent();
4887 if( parent && RelayoutDependentOnParent( dimension ) )
4889 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4892 // Children dependency check
4893 if( RelayoutDependentOnChildren( dimension ) )
4895 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4897 ActorPtr child = GetChildAt( i );
4899 // Only relayout child first if it is not dependent on this actor
4900 if( !child->RelayoutDependentOnParent( dimension ) )
4902 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
4907 // For deriving classes
4908 OnCalculateRelayoutSize( dimension );
4910 // All dependencies checked, calculate the size and set negotiated flag
4911 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4913 SetNegotiatedDimension( newSize, dimension );
4914 SetLayoutNegotiated( true, dimension );
4916 // For deriving classes
4917 OnLayoutNegotiated( newSize, dimension );
4919 // This actor has been successfully processed, pop it off the recursion stack
4920 recursionStack.pop_back();
4924 // TODO: Break infinite loop
4925 SetLayoutNegotiated( true, dimension );
4930 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4932 // Negotiate all dimensions that require it
4933 ActorDimensionStack recursionStack;
4935 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4937 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4940 NegotiateDimension( dimension, allocatedSize, recursionStack );
4944 Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
4946 switch( mRelayoutData->sizeSetPolicy )
4948 case SizeScalePolicy::USE_SIZE_SET:
4953 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4955 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4956 const Vector3 naturalSize = GetNaturalSize();
4957 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4959 const float sizeRatio = size.width / size.height;
4960 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4962 if( naturalSizeRatio < sizeRatio )
4964 return Vector2( naturalSizeRatio * size.height, size.height );
4966 else if( naturalSizeRatio > sizeRatio )
4968 return Vector2( size.width, size.width / naturalSizeRatio );
4979 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4981 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4982 const Vector3 naturalSize = GetNaturalSize();
4983 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4985 const float sizeRatio = size.width / size.height;
4986 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4988 if( naturalSizeRatio < sizeRatio )
4990 return Vector2( size.width, size.width / naturalSizeRatio );
4992 else if( naturalSizeRatio > sizeRatio )
4994 return Vector2( naturalSizeRatio * size.height, size.height );
5013 void Actor::SetNegotiatedSize( RelayoutContainer& container )
5015 // Do the set actor size
5016 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
5018 // Adjust for size set policy
5019 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
5021 // Lock the flag to stop recursive relayouts on set size
5022 mRelayoutData->insideRelayout = true;
5023 SetSize( negotiatedSize );
5024 mRelayoutData->insideRelayout = false;
5026 // Clear flags for all dimensions
5027 SetLayoutDirty( false );
5029 // Give deriving classes a chance to respond
5030 OnRelayout( negotiatedSize, container );
5032 if( !mOnRelayoutSignal.Empty() )
5034 Dali::Actor handle( this );
5035 mOnRelayoutSignal.Emit( handle );
5039 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
5041 // Force a size negotiation for actors that has assigned size during relayout
5042 // This is required as otherwise the flags that force a relayout will not
5043 // necessarilly be set. This will occur if the actor has already been laid out.
5044 // The dirty flags are then cleared. Then if the actor is added back into the
5045 // relayout container afterwards, the dirty flags would still be clear...
5046 // causing a relayout to be skipped. Here we force any actors added to the
5047 // container to be relayed out.
5048 DALI_LOG_TIMER_START( NegSizeTimer1 );
5050 if( GetUseAssignedSize(Dimension::WIDTH ) )
5052 SetLayoutNegotiated( false, Dimension::WIDTH );
5054 if( GetUseAssignedSize( Dimension::HEIGHT ) )
5056 SetLayoutNegotiated( false, Dimension::HEIGHT );
5059 // Do the negotiation
5060 NegotiateDimensions( allocatedSize );
5062 // Set the actor size
5063 SetNegotiatedSize( container );
5065 // Negotiate down to children
5066 const Vector2 newBounds = mTargetSize.GetVectorXY();
5068 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
5070 ActorPtr child = GetChildAt( i );
5072 // Forces children that have already been laid out to be relayed out
5073 // if they have assigned size during relayout.
5074 if( child->GetUseAssignedSize(Dimension::WIDTH) )
5076 child->SetLayoutNegotiated(false, Dimension::WIDTH);
5077 child->SetLayoutDirty(true, Dimension::WIDTH);
5080 if( child->GetUseAssignedSize(Dimension::HEIGHT) )
5082 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
5083 child->SetLayoutDirty(true, Dimension::HEIGHT);
5086 // Only relayout if required
5087 if( child->RelayoutRequired() )
5089 container.Add( Dali::Actor( child.Get() ), newBounds );
5092 DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
5095 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
5099 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5101 if( dimension & ( 1 << i ) )
5103 mRelayoutData->useAssignedSize[ i ] = use;
5109 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
5111 if ( mRelayoutData )
5113 // If more than one dimension is requested, just return the first one found
5114 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5116 if( dimension & ( 1 << i ) )
5118 return mRelayoutData->useAssignedSize[ i ];
5126 void Actor::RelayoutRequest( Dimension::Type dimension )
5128 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
5129 if( relayoutController )
5131 Dali::Actor self( this );
5132 relayoutController->RequestRelayout( self, dimension );
5136 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
5140 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
5144 void Actor::SetPreferredSize( const Vector2& size )
5146 EnsureRelayoutData();
5148 if( size.width > 0.0f )
5150 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
5153 if( size.height > 0.0f )
5155 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
5158 mRelayoutData->preferredSize = size;
5163 Vector2 Actor::GetPreferredSize() const
5165 if ( mRelayoutData )
5167 return Vector2( mRelayoutData->preferredSize );
5170 return GetDefaultPreferredSize();
5173 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
5175 EnsureRelayoutData();
5177 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5179 if( dimension & ( 1 << i ) )
5181 mRelayoutData->minimumSize[ i ] = size;
5188 float Actor::GetMinimumSize( Dimension::Type dimension ) const
5190 if ( mRelayoutData )
5192 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5194 if( dimension & ( 1 << i ) )
5196 return mRelayoutData->minimumSize[ i ];
5201 return 0.0f; // Default
5204 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
5206 EnsureRelayoutData();
5208 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5210 if( dimension & ( 1 << i ) )
5212 mRelayoutData->maximumSize[ i ] = size;
5219 float Actor::GetMaximumSize( Dimension::Type dimension ) const
5221 if ( mRelayoutData )
5223 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5225 if( dimension & ( 1 << i ) )
5227 return mRelayoutData->maximumSize[ i ];
5232 return FLT_MAX; // Default
5235 Object* Actor::GetParentObject() const
5240 void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
5242 if( mVisible != visible )
5244 if( sendMessage == SendMessage::TRUE && NULL != mNode )
5246 // mNode is being used in a separate thread; queue a message to set the value & base value
5247 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
5252 // Emit the signal on this actor and all its children
5253 EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
5257 void Actor::SetSiblingOrder( unsigned int order )
5259 mSiblingOrder = std::min( order, static_cast<unsigned int>( DevelLayer::SIBLING_ORDER_MULTIPLIER ) );
5263 StagePtr stage = Stage::GetCurrent();
5266 stage->RequestRebuildDepthTree();
5271 void Actor::DefragmentSiblingIndexes( ActorContainer& siblings )
5273 // Sibling index may not be in consecutive order as the sibling range is limited ( DevelLayer::SIBLING_ORDER_MULTIPLIER )
5274 // we need to remove the gaps and ensure the number start from 0 and consecutive hence have a full range.
5276 // Start at index 0, while index <= highest order
5277 // Find next index higher than 0
5278 // if nextHigher > index+1
5279 // set all nextHigher orders to index+1
5281 // Limitation: May reach the ceiling of DevelLayer::SIBLING_ORDER_MULTIPLIER with highest sibling.
5283 ActorIter end = siblings.end();
5284 int highestOrder = 0;
5285 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
5287 ActorPtr sibling = (*iter);
5288 int siblingOrder = sibling->mSiblingOrder;
5289 highestOrder = std::max( highestOrder, siblingOrder );
5292 for ( int index = 0; index <= highestOrder; index++ )
5294 int nextHighest = -1;
5296 // Find Next highest
5297 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
5299 ActorPtr sibling = (*iter);
5300 int siblingOrder = sibling->mSiblingOrder;
5302 if ( siblingOrder > index )
5304 if ( nextHighest == -1 )
5306 nextHighest = siblingOrder;
5308 nextHighest = std::min( nextHighest, siblingOrder );
5312 // Check if a gap exists between indexes, if so set next index to consecutive number
5313 if ( ( nextHighest - index ) > 1 )
5315 for( ActorIter iter = siblings.begin(); iter != end; ++iter )
5317 ActorPtr sibling = (*iter);
5318 int siblingOrder = sibling->mSiblingOrder;
5319 if ( siblingOrder == nextHighest )
5321 sibling->mSiblingOrder = index + 1;
5322 if ( sibling->mSiblingOrder >= Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER )
5324 DALI_LOG_WARNING( "Reached max sibling order level for raising / lowering actors\n" );
5325 sibling->mSiblingOrder = Dali::DevelLayer::SIBLING_ORDER_MULTIPLIER;
5327 sibling->SetSiblingOrder( sibling->mSiblingOrder );
5334 bool Actor::ShiftSiblingsLevels( ActorContainer& siblings, int targetLevelToShiftFrom )
5336 // Allows exclusive levels for an actor by shifting all sibling levels at the target and above by 1
5337 bool defragmentationRequired( false );
5338 ActorIter end = siblings.end();
5339 for( ActorIter iter = siblings.begin(); ( iter != end ) ; ++iter )
5341 // Move actors at nearest order and above up by 1
5342 ActorPtr sibling = (*iter);
5343 if ( sibling != this )
5345 // Iterate through container of actors, any actor with a sibling order of the target or greater should
5346 // be incremented by 1.
5347 if ( sibling->mSiblingOrder >= targetLevelToShiftFrom )
5349 sibling->mSiblingOrder++;
5350 if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
5352 // If a sibling order raises so that it is only 1 from the maximum allowed then set flag so
5353 // can re-order all sibling orders.
5354 defragmentationRequired = true;
5356 sibling->SetSiblingOrder( sibling->mSiblingOrder );
5360 return defragmentationRequired;
5366 1) Check if already at top and nothing to be done.
5367 This Actor can have highest sibling order but if not exclusive then another actor at same sibling
5368 order can be positioned above it due to insertion order of actors.
5369 2) Find nearest sibling level above, these are the siblings this actor needs to be above
5370 3) a) There may be other levels above this target level
5371 b) Increment all sibling levels at the level above nearest(target)
5372 c) Now have a vacant sibling level
5373 4) Set this actor's sibling level to nearest +1 as now vacated.
5375 Note May not just be sibling level + 1 as could be empty levels in-between
5380 ActorC ( sibling level 4 )
5381 ActorB ( sibling level 3 )
5382 ActorA ( sibling level 1 )
5384 2 ) ACTION: Raise A above B
5385 a) Find nearest level above A = Level 3
5386 b) Increment levels above Level 3
5388 ActorC ( sibling level 5 )
5389 ActorB ( sibling level 3 ) NEAREST
5390 ActorA ( sibling level 1 )
5392 3 ) Set Actor A sibling level to nearest +1 as vacant
5394 ActorC ( sibling level 5 )
5395 ActorA ( sibling level 4 )
5396 ActorB ( sibling level 3 )
5398 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5399 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5400 remove any empty sibling order gaps and start from sibling level 0 again.
5401 If the number of actors reaches this maximum and all using exclusive sibling order values then
5402 defragmention will stop and new sibling orders will be set to same max value.
5406 int nearestLevel = mSiblingOrder;
5407 int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
5408 bool defragmentationRequired( false );
5410 ActorContainer* siblings = mParent->mChildren;
5412 // Find Nearest sibling level above this actor
5413 ActorIter end = siblings->end();
5414 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
5416 ActorPtr sibling = (*iter);
5417 if ( sibling != this )
5419 int order = GetSiblingOrder( sibling );
5421 if ( ( order >= mSiblingOrder ) )
5423 int distanceToNextLevel = order - mSiblingOrder;
5424 if ( distanceToNextLevel < shortestDistanceToNextLevel )
5426 nearestLevel = order;
5427 shortestDistanceToNextLevel = distanceToNextLevel;
5433 if ( nearestLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at top
5435 mSiblingOrder = nearestLevel + 1; // Set sibling level to that above the nearest level
5436 defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
5437 // Move current actor to newly vacated order level
5438 SetSiblingOrder( mSiblingOrder );
5439 if ( defragmentationRequired )
5441 DefragmentSiblingIndexes( *siblings );
5444 SetSiblingOrder( mSiblingOrder );
5448 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5455 1) Check if actor already at bottom and if nothing needs to be done
5456 This Actor can have lowest sibling order but if not exclusive then another actor at same sibling
5457 order can be positioned above it due to insertion order of actors so need to move this actor below it.
5458 2) Find nearest sibling level below, this Actor needs to be below it
5459 3) a) Need to vacate a sibling level below nearest for this actor to occupy
5460 b) Shift up all sibling order values of actor at the nearest level and levels above it to vacate a level.
5461 c) Set this actor's sibling level to this newly vacated level.
5462 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5463 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5464 remove any empty sibling order gaps and start from sibling level 0 again.
5465 If the number of actors reaches this maximum and all using exclusive sibling order values then
5466 defragmention will stop and new sibling orders will be set to same max value.
5471 // 1) Find nearest level below
5472 int nearestLevel = mSiblingOrder;
5473 int shortestDistanceToNextLevel = DevelLayer::SIBLING_ORDER_MULTIPLIER;
5475 ActorContainer* siblings = mParent->mChildren;
5477 ActorIter end = siblings->end();
5478 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
5480 ActorPtr sibling = (*iter);
5481 if ( sibling != this )
5483 int order = GetSiblingOrder( sibling );
5485 if ( order <= mSiblingOrder )
5487 int distanceToNextLevel = mSiblingOrder - order;
5488 if ( distanceToNextLevel < shortestDistanceToNextLevel )
5490 nearestLevel = order;
5491 shortestDistanceToNextLevel = distanceToNextLevel;
5497 bool defragmentationRequired ( false );
5499 // 2) If actor already not at bottom, raise all actors at required level and above
5500 if ( shortestDistanceToNextLevel < DevelLayer::SIBLING_ORDER_MULTIPLIER ) // Actor is not already exclusively at bottom
5502 mSiblingOrder = nearestLevel;
5503 defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
5504 // Move current actor to newly vacated order
5505 SetSiblingOrder( mSiblingOrder );
5506 if ( defragmentationRequired )
5508 DefragmentSiblingIndexes( *siblings );
5514 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5518 void Actor::RaiseToTop()
5521 1 ) Find highest sibling order actor
5522 2 ) If highest sibling level not itself then set sibling order to that + 1
5523 3 ) highest sibling order can be same as itself so need to increment over that
5524 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5525 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5526 remove any empty sibling order gaps and start from sibling level 0 again.
5527 If the number of actors reaches this maximum and all using exclusive sibling order values then
5528 defragmention will stop and new sibling orders will be set to same max value.
5535 ActorContainer* siblings = mParent->mChildren;
5537 ActorIter end = siblings->end();
5538 for( ActorIter iter = siblings->begin(); iter != end; ++iter )
5540 ActorPtr sibling = (*iter);
5541 if ( sibling != this )
5543 maxOrder = std::max( GetSiblingOrder( sibling ), maxOrder );
5547 bool defragmentationRequired( false );
5549 if ( maxOrder >= mSiblingOrder )
5551 mSiblingOrder = maxOrder + 1;
5552 if ( mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
5554 defragmentationRequired = true;
5558 SetSiblingOrder( mSiblingOrder );
5560 if ( defragmentationRequired )
5562 DefragmentSiblingIndexes( *siblings );
5567 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5571 void Actor::LowerToBottom()
5574 See Actor::LowerToBottom()
5576 1 ) Check if this actor already at exclusively at the bottom, if so then no more to be done.
5577 2 ) a ) Check if the bottom position 0 is vacant.
5578 b ) If 0 position is not vacant then shift up all sibling order values from 0 and above
5579 c ) 0 sibling position is vacant.
5580 3 ) Set this actor to vacant sibling order 0;
5581 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5582 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5583 remove any empty sibling order gaps and start from sibling level 0 again.
5584 If the number of actors reaches this maximum and all using exclusive sibling order values then
5585 defragmention will stop and new sibling orders will be set to same max value.
5590 bool defragmentationRequired( false );
5591 bool orderZeroFree ( true );
5593 ActorContainer* siblings = mParent->mChildren;
5595 bool actorAtLowestOrder = true;
5596 ActorIter end = siblings->end();
5597 for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
5599 ActorPtr sibling = (*iter);
5600 if ( sibling != this )
5602 int siblingOrder = GetSiblingOrder( sibling );
5603 if ( siblingOrder <= mSiblingOrder )
5605 actorAtLowestOrder = false;
5608 if ( siblingOrder == 0 )
5610 orderZeroFree = false;
5615 if ( ! actorAtLowestOrder )
5617 if ( ! orderZeroFree )
5619 defragmentationRequired = ShiftSiblingsLevels( *siblings, 0 );
5622 SetSiblingOrder( mSiblingOrder );
5624 if ( defragmentationRequired )
5626 DefragmentSiblingIndexes( *siblings );
5632 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5636 void Actor::RaiseAbove( Internal::Actor& target )
5639 1 ) a) Find target actor's sibling order
5640 b) If sibling order of target is the same as this actor then need to this Actor's sibling order
5641 needs to be above it or the insertion order will determine which is drawn on top.
5642 2 ) Shift up by 1 all sibling order greater than target sibling order
5643 3 ) Set this actor to the sibling order to target +1 as will be a newly vacated gap above
5644 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5645 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5646 remove any empty sibling order gaps and start from sibling level 0 again.
5647 If the number of actors reaches this maximum and all using exclusive sibling order values then
5648 defragmention will stop and new sibling orders will be set to same max value.
5653 if ( ValidateActors( *this, target ) )
5655 // Find target's sibling order
5656 // Set actor sibling order to this number +1
5657 int targetSiblingOrder = GetSiblingOrder( &target );
5658 ActorContainer* siblings = mParent->mChildren;
5659 mSiblingOrder = targetSiblingOrder + 1;
5660 bool defragmentationRequired = ShiftSiblingsLevels( *siblings, mSiblingOrder );
5662 SetSiblingOrder( mSiblingOrder );
5664 if ( defragmentationRequired )
5666 DefragmentSiblingIndexes( *(mParent->mChildren) );
5672 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5676 void Actor::LowerBelow( Internal::Actor& target )
5679 1 ) a) Find target actor's sibling order
5680 b) If sibling order of target is the same as this actor then need to this Actor's sibling order
5681 needs to be below it or the insertion order will determine which is drawn on top.
5682 2 ) Shift the target sibling order and all sibling orders at that level or above by 1
5683 3 ) Set this actor to the sibling order of the target before it changed.
5684 4 ) Sibling order levels have a maximum defined in DevelLayer::SIBLING_ORDER_MULTIPLIER
5685 If shifting causes this ceiling to be reached. then a defragmentation can be performed to
5686 remove any empty sibling order gaps and start from sibling level 0 again.
5687 If the number of actors reaches this maximum and all using exclusive sibling order values then
5688 defragmention will stop and new sibling orders will be set to same max value.
5693 if ( ValidateActors( *this, target ) )
5695 bool defragmentationRequired ( false );
5696 // Find target's sibling order
5697 // Set actor sibling order to target sibling order - 1
5698 int targetSiblingOrder = GetSiblingOrder( &target);
5699 ActorContainer* siblings = mParent->mChildren;
5700 if ( targetSiblingOrder == 0 )
5703 ActorIter end = siblings->end();
5704 for( ActorIter iter = siblings->begin(); ( iter != end ) ; ++iter )
5706 ActorPtr sibling = (*iter);
5707 if ( sibling != this )
5709 sibling->mSiblingOrder++;
5710 if ( sibling->mSiblingOrder + 1 >= DevelLayer::SIBLING_ORDER_MULTIPLIER )
5712 defragmentationRequired = true;
5714 sibling->SetSiblingOrder( sibling->mSiblingOrder );
5721 defragmentationRequired = ShiftSiblingsLevels( *siblings, targetSiblingOrder );
5723 mSiblingOrder = targetSiblingOrder;
5725 SetSiblingOrder( mSiblingOrder );
5727 if ( defragmentationRequired )
5729 DefragmentSiblingIndexes( *(mParent->mChildren) );
5735 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5739 } // namespace Internal