2 * Copyright (c) 2018 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/scripting/scripting.h>
37 #include <dali/internal/common/internal-constants.h>
38 #include <dali/internal/event/common/event-thread-services.h>
39 #include <dali/internal/event/render-tasks/render-task-impl.h>
40 #include <dali/internal/event/actors/camera-actor-impl.h>
41 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
42 #include <dali/internal/event/common/property-helper.h>
43 #include <dali/internal/event/common/stage-impl.h>
44 #include <dali/internal/event/common/type-info-impl.h>
45 #include <dali/internal/event/common/scene-impl.h>
46 #include <dali/internal/event/common/thread-local-storage.h>
47 #include <dali/internal/event/animation/constraint-impl.h>
48 #include <dali/internal/event/common/projection.h>
49 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
50 #include <dali/internal/update/common/animatable-property.h>
51 #include <dali/internal/update/nodes/node-messages.h>
52 #include <dali/internal/update/nodes/node-declarations.h>
53 #include <dali/internal/update/animation/scene-graph-constraint.h>
54 #include <dali/internal/event/events/actor-gesture-data.h>
55 #include <dali/internal/common/message.h>
56 #include <dali/integration-api/debug.h>
58 using Dali::Internal::SceneGraph::Node;
59 using Dali::Internal::SceneGraph::AnimatableProperty;
60 using Dali::Internal::SceneGraph::PropertyBase;
62 #if defined(DEBUG_ENABLED)
63 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_DEPTH_TIMER" );
64 Debug::Filter* gLogRelayoutFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_TIMER" );
75 /// Using a function because of library initialisation order. Vector3::ONE may not have been initialised yet.
76 inline const Vector3& GetDefaultSizeModeFactor()
81 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
82 inline const Vector2& GetDefaultPreferredSize()
87 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
88 inline const Vector2& GetDefaultDimensionPadding()
93 const SizeScalePolicy::Type DEFAULT_SIZE_SCALE_POLICY = SizeScalePolicy::USE_SIZE_SET;
95 } // unnamed namespace
98 * Struct to collect relayout variables
100 struct Actor::RelayoutData
103 : sizeModeFactor( GetDefaultSizeModeFactor() ), preferredSize( GetDefaultPreferredSize() ), sizeSetPolicy( DEFAULT_SIZE_SCALE_POLICY ), relayoutEnabled( false ), insideRelayout( false )
105 // Set size negotiation defaults
106 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
108 resizePolicies[ i ] = ResizePolicy::DEFAULT;
109 useAssignedSize[ i ] = false;
110 negotiatedDimensions[ i ] = 0.0f;
111 dimensionNegotiated[ i ] = false;
112 dimensionDirty[ i ] = false;
113 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
114 dimensionPadding[ i ] = GetDefaultDimensionPadding();
115 minimumSize[ i ] = 0.0f;
116 maximumSize[ i ] = FLT_MAX;
120 ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies
121 bool useAssignedSize[ Dimension::DIMENSION_COUNT ]; ///< The flag to specify whether the size should be assigned to the actor
123 Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies
125 Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
127 float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
129 float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be
130 float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be
132 bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated
133 bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
135 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
137 Vector2 preferredSize; ///< The preferred size of the actor
139 SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
141 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
142 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
145 namespace // unnamed namespace
151 * We want to discourage the use of property strings (minimize string comparisons),
152 * particularly for the default properties.
153 * Name Type writable animatable constraint-input enum for index-checking
155 DALI_PROPERTY_TABLE_BEGIN
156 DALI_PROPERTY( "parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
157 DALI_PROPERTY( "parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
158 DALI_PROPERTY( "parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
159 DALI_PROPERTY( "parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
160 DALI_PROPERTY( "anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
161 DALI_PROPERTY( "anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
162 DALI_PROPERTY( "anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
163 DALI_PROPERTY( "anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
164 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
165 DALI_PROPERTY( "sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
166 DALI_PROPERTY( "sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
167 DALI_PROPERTY( "sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
168 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
169 DALI_PROPERTY( "positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
170 DALI_PROPERTY( "positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
171 DALI_PROPERTY( "positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
172 DALI_PROPERTY( "worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
173 DALI_PROPERTY( "worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
174 DALI_PROPERTY( "worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
175 DALI_PROPERTY( "worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
176 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
177 DALI_PROPERTY( "worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
178 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
179 DALI_PROPERTY( "scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
180 DALI_PROPERTY( "scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
181 DALI_PROPERTY( "scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
182 DALI_PROPERTY( "worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
183 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
184 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
185 DALI_PROPERTY( "colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
186 DALI_PROPERTY( "colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
187 DALI_PROPERTY( "colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
188 DALI_PROPERTY( "colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
189 DALI_PROPERTY( "worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
190 DALI_PROPERTY( "worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
191 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
192 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
193 DALI_PROPERTY( "leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
194 DALI_PROPERTY( "inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
195 DALI_PROPERTY( "inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
196 DALI_PROPERTY( "colorMode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
197 DALI_PROPERTY( "reservedProperty01", STRING, true, false, false, Dali::Actor::Property::RESERVED_PROPERTY_01 ) // This property was removed, but to keep binary compatibility and TypeRegister test app, remain it here.
198 DALI_PROPERTY( "drawMode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
199 DALI_PROPERTY( "sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
200 DALI_PROPERTY( "widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
201 DALI_PROPERTY( "heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
202 DALI_PROPERTY( "sizeScalePolicy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
203 DALI_PROPERTY( "widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
204 DALI_PROPERTY( "heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
205 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
206 DALI_PROPERTY( "minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
207 DALI_PROPERTY( "maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
208 DALI_PROPERTY( "inheritPosition", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_POSITION )
209 DALI_PROPERTY( "clippingMode", STRING, true, false, false, Dali::Actor::Property::CLIPPING_MODE )
210 DALI_PROPERTY( "layoutDirection", STRING, true, false, false, Dali::Actor::Property::LAYOUT_DIRECTION )
211 DALI_PROPERTY( "inheritLayoutDirection", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION )
212 DALI_PROPERTY( "siblingOrder", INTEGER, true, false, false, Dali::DevelActor::Property::SIBLING_ORDER )
213 DALI_PROPERTY( "opacity", FLOAT, true, true, true, Dali::DevelActor::Property::OPACITY )
214 DALI_PROPERTY( "screenPosition", VECTOR2, false, false, false, Dali::DevelActor::Property::SCREEN_POSITION )
215 DALI_PROPERTY( "positionUsesAnchorPoint", BOOLEAN, true, false, false, Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT )
216 DALI_PROPERTY( "culled", BOOLEAN, false, false, true, Dali::DevelActor::Property::CULLED )
217 DALI_PROPERTY( "updateSizeHint", VECTOR2, true, true, true, Dali::DevelActor::Property::UPDATE_SIZE_HINT )
218 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperties )
222 const char* const SIGNAL_TOUCHED = "touched";
223 const char* const SIGNAL_HOVERED = "hovered";
224 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
225 const char* const SIGNAL_ON_STAGE = "onStage";
226 const char* const SIGNAL_OFF_STAGE = "offStage";
227 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
228 const char* const SIGNAL_TOUCH = "touch";
229 const char* const SIGNAL_VISIBILITY_CHANGED = "visibilityChanged";
230 const char* const SIGNAL_LAYOUT_DIRECTION_CHANGED = "layoutDirectionChanged";
231 const char* const SIGNAL_CHILD_ADDED = "childAdded";
232 const char* const SIGNAL_CHILD_REMOVED = "childRemoved";
236 const char* const ACTION_SHOW = "show";
237 const char* const ACTION_HIDE = "hide";
239 BaseHandle CreateActor()
241 return Dali::Actor::New();
244 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor, ActorDefaultProperties );
246 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
247 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
248 SignalConnectorType signalConnector3( mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal );
249 SignalConnectorType signalConnector4( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
250 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
251 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
252 SignalConnectorType signalConnector7( mType, SIGNAL_TOUCH, &Actor::DoConnectSignal );
253 SignalConnectorType signalConnector8( mType, SIGNAL_VISIBILITY_CHANGED, &Actor::DoConnectSignal );
254 SignalConnectorType signalConnector9( mType, SIGNAL_LAYOUT_DIRECTION_CHANGED, &Actor::DoConnectSignal );
255 SignalConnectorType signalConnector10( mType, SIGNAL_CHILD_ADDED, &Actor::DoConnectSignal );
256 SignalConnectorType signalConnector11( mType, SIGNAL_CHILD_REMOVED, &Actor::DoConnectSignal );
258 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
259 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
264 const Vector3& value;
267 DALI_ENUM_TO_STRING_TABLE_BEGIN_WITH_TYPE( AnchorValue, ANCHOR_CONSTANT )
268 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_LEFT )
269 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_CENTER )
270 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_RIGHT )
271 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_LEFT )
272 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER )
273 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_RIGHT )
274 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_LEFT )
275 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_CENTER )
276 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_RIGHT )
277 DALI_ENUM_TO_STRING_TABLE_END( ANCHOR_CONSTANT )
279 DALI_ENUM_TO_STRING_TABLE_BEGIN( COLOR_MODE )
280 DALI_ENUM_TO_STRING( USE_OWN_COLOR )
281 DALI_ENUM_TO_STRING( USE_PARENT_COLOR )
282 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_COLOR )
283 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_ALPHA )
284 DALI_ENUM_TO_STRING_TABLE_END( COLOR_MODE )
286 DALI_ENUM_TO_STRING_TABLE_BEGIN( DRAW_MODE )
287 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, NORMAL )
288 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, OVERLAY_2D )
289 DALI_ENUM_TO_STRING_TABLE_END( DRAW_MODE )
291 DALI_ENUM_TO_STRING_TABLE_BEGIN( RESIZE_POLICY )
292 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIXED )
293 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_NATURAL_SIZE )
294 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FILL_TO_PARENT )
295 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_RELATIVE_TO_PARENT )
296 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_FIXED_OFFSET_FROM_PARENT )
297 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIT_TO_CHILDREN )
298 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, DIMENSION_DEPENDENCY )
299 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_ASSIGNED_SIZE )
300 DALI_ENUM_TO_STRING_TABLE_END( RESIZE_POLICY )
302 DALI_ENUM_TO_STRING_TABLE_BEGIN( SIZE_SCALE_POLICY )
303 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, USE_SIZE_SET )
304 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FIT_WITH_ASPECT_RATIO )
305 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FILL_WITH_ASPECT_RATIO )
306 DALI_ENUM_TO_STRING_TABLE_END( SIZE_SCALE_POLICY )
308 DALI_ENUM_TO_STRING_TABLE_BEGIN( CLIPPING_MODE )
309 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, DISABLED )
310 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, CLIP_CHILDREN )
311 DALI_ENUM_TO_STRING_TABLE_END( CLIPPING_MODE )
313 DALI_ENUM_TO_STRING_TABLE_BEGIN( LAYOUT_DIRECTION )
314 DALI_ENUM_TO_STRING_WITH_SCOPE( LayoutDirection, LEFT_TO_RIGHT )
315 DALI_ENUM_TO_STRING_WITH_SCOPE( LayoutDirection, RIGHT_TO_LEFT )
316 DALI_ENUM_TO_STRING_TABLE_END( LAYOUT_DIRECTION )
318 bool GetAnchorPointConstant( const std::string& value, Vector3& anchor )
320 for( uint32_t i = 0; i < ANCHOR_CONSTANT_TABLE_COUNT; ++i )
322 uint32_t sizeIgnored = 0;
323 if( CompareTokens( value.c_str(), ANCHOR_CONSTANT_TABLE[ i ].name, sizeIgnored ) )
325 anchor = ANCHOR_CONSTANT_TABLE[ i ].value;
332 inline bool GetParentOriginConstant( const std::string& value, Vector3& parentOrigin )
334 // Values are the same so just use the same table as anchor-point
335 return GetAnchorPointConstant( value, parentOrigin );
339 * @brief Extract a given dimension from a Vector2
341 * @param[in] values The values to extract from
342 * @param[in] dimension The dimension to extract
343 * @return Return the value for the dimension
345 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
349 case Dimension::WIDTH:
353 case Dimension::HEIGHT:
355 return values.height;
366 * @brief Extract a given dimension from a Vector3
368 * @param[in] values The values to extract from
369 * @param[in] dimension The dimension to extract
370 * @return Return the value for the dimension
372 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
374 return GetDimensionValue( values.GetVectorXY(), dimension );
378 * @brief Recursively emits the visibility-changed-signal on the actor tree.
379 * @param[in] actor The actor to emit the signal on
380 * @param[in] visible The new visibility of the actor
381 * @param[in] type Whether the actor's visible property has changed or a parent's
383 void EmitVisibilityChangedSignalRecursively( ActorPtr actor, bool visible, DevelActor::VisibilityChange::Type type )
387 actor->EmitVisibilityChangedSignal( visible, type );
389 if( actor->GetChildCount() > 0 )
391 ActorContainer& children = actor->GetChildrenInternal();
392 for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter )
394 EmitVisibilityChangedSignalRecursively( *iter, visible, DevelActor::VisibilityChange::PARENT );
400 } // unnamed namespace
402 ActorPtr Actor::New()
404 // pass a reference to actor, actor does not own its node
405 ActorPtr actor( new Actor( BASIC, *CreateNode() ) );
407 // Second-phase construction
413 const SceneGraph::Node* Actor::CreateNode()
415 // create node. Nodes are owned by the update manager
416 SceneGraph::Node* node = SceneGraph::Node::New();
417 OwnerPointer< SceneGraph::Node > transferOwnership( node );
418 Internal::ThreadLocalStorage* tls = Internal::ThreadLocalStorage::GetInternal();
419 AddNodeMessage( tls->GetUpdateManager(), transferOwnership );
424 const std::string& Actor::GetName() const
429 void Actor::SetName( const std::string& name )
433 // ATTENTION: string for debug purposes is not thread safe.
434 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( &GetNode() ), name );
437 uint32_t Actor::GetId() const
439 return GetNode().GetId();
442 bool Actor::OnStage() const
447 Dali::Layer Actor::GetLayer()
451 // Short-circuit for Layer derived actors
454 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
457 // Find the immediate Layer parent
458 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
460 if( parent->IsLayer() )
462 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
469 void Actor::Add( Actor& child )
471 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
472 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
476 mChildren = new ActorContainer;
479 Actor* const oldParent( child.mParent );
481 // child might already be ours
482 if( this != oldParent )
484 // if we already have parent, unparent us first
487 oldParent->Remove( child ); // This causes OnChildRemove callback & ChildRemoved signal
489 // Old parent may need to readjust to missing child
490 if( oldParent->RelayoutDependentOnChildren() )
492 oldParent->RelayoutRequest();
496 // Guard against Add() during previous OnChildRemove callback
499 // Do this first, since user callbacks from within SetParent() may need to remove child
500 mChildren->push_back( ActorPtr( &child ) );
502 // SetParent asserts that child can be added
503 child.SetParent( this );
505 // Notification for derived classes
507 EmitChildAddedSignal( child );
509 InheritLayoutDirectionRecursively( ActorPtr( &child ), mLayoutDirection );
511 // Only put in a relayout request if there is a suitable dependency
512 if( RelayoutDependentOnChildren() )
520 void Actor::Remove( Actor& child )
522 if( (this == &child) || (!mChildren) )
524 // no children or removing itself
530 // Find the child in mChildren, and unparent it
531 ActorIter end = mChildren->end();
532 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
534 ActorPtr actor = (*iter);
536 if( actor.Get() == &child )
538 // Keep handle for OnChildRemove notification
541 // Do this first, since user callbacks from within SetParent() may need to add the child
542 mChildren->erase( iter );
544 DALI_ASSERT_DEBUG( actor->GetParent() == this );
545 actor->SetParent( NULL );
553 // Only put in a relayout request if there is a suitable dependency
554 if( RelayoutDependentOnChildren() )
560 // Notification for derived classes
561 OnChildRemove( child );
562 EmitChildRemovedSignal( child );
565 void Actor::Unparent()
569 // Remove this actor from the parent. The remove will put a relayout request in for
570 // the parent if required
571 mParent->Remove( *this );
572 // mParent is now NULL!
576 uint32_t Actor::GetChildCount() const
578 return ( NULL != mChildren ) ? static_cast<uint32_t>( mChildren->size() ) : 0; // only 4,294,967,295 children per actor
581 ActorPtr Actor::GetChildAt( uint32_t index ) const
583 DALI_ASSERT_ALWAYS( index < GetChildCount() );
585 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
588 ActorPtr Actor::FindChildByName( const std::string& actorName )
591 if( actorName == mName )
597 ActorIter end = mChildren->end();
598 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
600 child = (*iter)->FindChildByName( actorName );
611 ActorPtr Actor::FindChildById( const uint32_t id )
620 ActorIter end = mChildren->end();
621 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
623 child = (*iter)->FindChildById( id );
634 void Actor::SetParentOrigin( const Vector3& origin )
636 // node is being used in a separate thread; queue a message to set the value & base value
637 SetParentOriginMessage( GetEventThreadServices(), GetNode(), origin );
639 // Cache for event-thread access
642 // not allocated, check if different from default
643 if( ParentOrigin::DEFAULT != origin )
645 mParentOrigin = new Vector3( origin );
650 // check if different from current costs more than just set
651 *mParentOrigin = origin;
655 void Actor::SetParentOriginX( float x )
657 const Vector3& current = GetCurrentParentOrigin();
659 SetParentOrigin( Vector3( x, current.y, current.z ) );
662 void Actor::SetParentOriginY( float y )
664 const Vector3& current = GetCurrentParentOrigin();
666 SetParentOrigin( Vector3( current.x, y, current.z ) );
669 void Actor::SetParentOriginZ( float z )
671 const Vector3& current = GetCurrentParentOrigin();
673 SetParentOrigin( Vector3( current.x, current.y, z ) );
676 const Vector3& Actor::GetCurrentParentOrigin() const
678 // Cached for event-thread access
679 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
682 void Actor::SetAnchorPoint( const Vector3& anchor )
684 // node is being used in a separate thread; queue a message to set the value & base value
685 SetAnchorPointMessage( GetEventThreadServices(), GetNode(), anchor );
687 // Cache for event-thread access
690 // not allocated, check if different from default
691 if( AnchorPoint::DEFAULT != anchor )
693 mAnchorPoint = new Vector3( anchor );
698 // check if different from current costs more than just set
699 *mAnchorPoint = anchor;
703 void Actor::SetAnchorPointX( float x )
705 const Vector3& current = GetCurrentAnchorPoint();
707 SetAnchorPoint( Vector3( x, current.y, current.z ) );
710 void Actor::SetAnchorPointY( float y )
712 const Vector3& current = GetCurrentAnchorPoint();
714 SetAnchorPoint( Vector3( current.x, y, current.z ) );
717 void Actor::SetAnchorPointZ( float z )
719 const Vector3& current = GetCurrentAnchorPoint();
721 SetAnchorPoint( Vector3( current.x, current.y, z ) );
724 const Vector3& Actor::GetCurrentAnchorPoint() const
726 // Cached for event-thread access
727 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
730 void Actor::SetPosition( float x, float y )
732 SetPosition( Vector3( x, y, 0.0f ) );
735 void Actor::SetPosition( float x, float y, float z )
737 SetPosition( Vector3( x, y, z ) );
740 void Actor::SetPosition( const Vector3& position )
742 mTargetPosition = position;
744 // node is being used in a separate thread; queue a message to set the value & base value
745 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
748 void Actor::SetX( float x )
750 mTargetPosition.x = x;
752 // node is being used in a separate thread; queue a message to set the value & base value
753 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
756 void Actor::SetY( float y )
758 mTargetPosition.y = y;
760 // node is being used in a separate thread; queue a message to set the value & base value
761 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
764 void Actor::SetZ( float z )
766 mTargetPosition.z = z;
768 // node is being used in a separate thread; queue a message to set the value & base value
769 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
772 void Actor::TranslateBy( const Vector3& distance )
774 mTargetPosition += distance;
776 // node is being used in a separate thread; queue a message to set the value & base value
777 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
780 const Vector3& Actor::GetCurrentPosition() const
782 // node is being used in a separate thread; copy the value from the previous update
783 return GetNode().GetPosition(GetEventThreadServices().GetEventBufferIndex());
786 const Vector3& Actor::GetTargetPosition() const
788 return mTargetPosition;
791 const Vector3& Actor::GetCurrentWorldPosition() const
793 // node is being used in a separate thread; copy the value from the previous update
794 return GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
797 const Vector2 Actor::GetCurrentScreenPosition() const
799 if( mScene && OnStage() )
801 Vector3 worldPosition = GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
802 Vector3 cameraPosition = mScene->GetDefaultCameraActor().GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
803 worldPosition -= cameraPosition;
805 Vector3 actorSize = GetCurrentSize() * GetCurrentWorldScale();
806 Vector2 halfSceneSize( mScene->GetSize() * 0.5f ); // World position origin is center of scene
807 Vector3 halfActorSize( actorSize * 0.5f );
808 Vector3 anchorPointOffSet = halfActorSize - actorSize * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
810 return Vector2( halfSceneSize.width + worldPosition.x - anchorPointOffSet.x,
811 halfSceneSize.height + worldPosition.y - anchorPointOffSet.y );
814 return Vector2::ZERO;
817 void Actor::SetInheritPosition( bool inherit )
819 if( mInheritPosition != inherit )
821 // non animatable so keep local copy
822 mInheritPosition = inherit;
823 SetInheritPositionMessage( GetEventThreadServices(), GetNode(), inherit );
827 bool Actor::IsPositionInherited() const
829 return mInheritPosition;
832 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
834 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
835 normalizedAxis.Normalize();
837 Quaternion orientation( angle, normalizedAxis );
839 SetOrientation( orientation );
842 void Actor::SetOrientation( const Quaternion& orientation )
844 mTargetOrientation = orientation;
846 // node is being used in a separate thread; queue a message to set the value & base value
847 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation );
850 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
852 RotateBy( Quaternion(angle, axis) );
855 void Actor::RotateBy( const Quaternion& relativeRotation )
857 mTargetOrientation *= Quaternion( relativeRotation );
859 // node is being used in a separate thread; queue a message to set the value & base value
860 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
863 const Quaternion& Actor::GetCurrentOrientation() const
865 // node is being used in a separate thread; copy the value from the previous update
866 return GetNode().GetOrientation(GetEventThreadServices().GetEventBufferIndex());
869 const Quaternion& Actor::GetCurrentWorldOrientation() const
871 // node is being used in a separate thread; copy the value from the previous update
872 return GetNode().GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
875 void Actor::SetScale( float scale )
877 SetScale( Vector3( scale, scale, scale ) );
880 void Actor::SetScale( float x, float y, float z )
882 SetScale( Vector3( x, y, z ) );
885 void Actor::SetScale( const Vector3& scale )
887 mTargetScale = scale;
889 // node is being used in a separate thread; queue a message to set the value & base value
890 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
893 void Actor::SetScaleX( float x )
897 // node is being used in a separate thread; queue a message to set the value & base value
898 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
901 void Actor::SetScaleY( float y )
905 // node is being used in a separate thread; queue a message to set the value & base value
906 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
909 void Actor::SetScaleZ( float z )
913 // node is being used in a separate thread; queue a message to set the value & base value
914 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
917 void Actor::ScaleBy(const Vector3& relativeScale)
919 mTargetScale *= relativeScale;
921 // node is being used in a separate thread; queue a message to set the value & base value
922 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
925 const Vector3& Actor::GetCurrentScale() const
927 // node is being used in a separate thread; copy the value from the previous update
928 return GetNode().GetScale(GetEventThreadServices().GetEventBufferIndex());
931 const Vector3& Actor::GetCurrentWorldScale() const
933 // node is being used in a separate thread; copy the value from the previous update
934 return GetNode().GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
937 void Actor::SetInheritScale( bool inherit )
939 if( mInheritScale != inherit )
941 // non animatable so keep local copy
942 mInheritScale = inherit;
943 // node is being used in a separate thread; queue a message to set the value
944 SetInheritScaleMessage( GetEventThreadServices(), GetNode(), inherit );
948 bool Actor::IsScaleInherited() const
950 return mInheritScale;
953 Matrix Actor::GetCurrentWorldMatrix() const
955 return GetNode().GetWorldMatrix(0);
958 void Actor::SetVisible( bool visible )
960 SetVisibleInternal( visible, SendMessage::TRUE );
963 bool Actor::IsVisible() const
965 // node is being used in a separate thread; copy the value from the previous update
966 return GetNode().IsVisible( GetEventThreadServices().GetEventBufferIndex() );
969 void Actor::SetOpacity( float opacity )
971 mTargetColor.a = opacity;
973 // node is being used in a separate thread; queue a message to set the value & base value
974 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
977 float Actor::GetCurrentOpacity() const
979 // node is being used in a separate thread; copy the value from the previous update
980 return GetNode().GetOpacity(GetEventThreadServices().GetEventBufferIndex());
983 ClippingMode::Type Actor::GetClippingMode() const
985 return mClippingMode;
988 uint32_t Actor::GetSortingDepth()
993 const Vector4& Actor::GetCurrentWorldColor() const
995 return GetNode().GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
998 void Actor::SetColor( const Vector4& color )
1000 mTargetColor = color;
1002 // node is being used in a separate thread; queue a message to set the value & base value
1003 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::Bake, color );
1006 void Actor::SetColorRed( float red )
1008 mTargetColor.r = red;
1010 // node is being used in a separate thread; queue a message to set the value & base value
1011 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeX, red );
1014 void Actor::SetColorGreen( float green )
1016 mTargetColor.g = green;
1018 // node is being used in a separate thread; queue a message to set the value & base value
1019 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeY, green );
1022 void Actor::SetColorBlue( float blue )
1024 mTargetColor.b = blue;
1026 // node is being used in a separate thread; queue a message to set the value & base value
1027 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1030 const Vector4& Actor::GetCurrentColor() const
1032 // node is being used in a separate thread; copy the value from the previous update
1033 return GetNode().GetColor(GetEventThreadServices().GetEventBufferIndex());
1036 void Actor::SetInheritOrientation( bool inherit )
1038 if( mInheritOrientation != inherit )
1040 // non animatable so keep local copy
1041 mInheritOrientation = inherit;
1042 // node is being used in a separate thread; queue a message to set the value
1043 SetInheritOrientationMessage( GetEventThreadServices(), GetNode(), inherit );
1047 bool Actor::IsOrientationInherited() const
1049 return mInheritOrientation;
1052 void Actor::SetSizeModeFactor( const Vector3& factor )
1054 EnsureRelayoutData();
1056 mRelayoutData->sizeModeFactor = factor;
1059 const Vector3& Actor::GetSizeModeFactor() const
1061 if ( mRelayoutData )
1063 return mRelayoutData->sizeModeFactor;
1066 return GetDefaultSizeModeFactor();
1069 void Actor::SetColorMode( ColorMode colorMode )
1071 // non animatable so keep local copy
1072 mColorMode = colorMode;
1073 // node is being used in a separate thread; queue a message to set the value
1074 SetColorModeMessage( GetEventThreadServices(), GetNode(), colorMode );
1077 ColorMode Actor::GetColorMode() const
1079 // we have cached copy
1083 void Actor::SetSize( float width, float height )
1085 SetSize( Vector2( width, height ) );
1088 void Actor::SetSize( float width, float height, float depth )
1090 SetSize( Vector3( width, height, depth ) );
1093 void Actor::SetSize( const Vector2& size )
1095 SetSize( Vector3( size.width, size.height, 0.f ) );
1098 void Actor::SetSizeInternal( const Vector2& size )
1100 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1103 void Actor::SetSize( const Vector3& size )
1105 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1107 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1108 SetPreferredSize( size.GetVectorXY() );
1112 SetSizeInternal( size );
1116 void Actor::SetSizeInternal( const Vector3& size )
1118 // dont allow recursive loop
1119 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1120 // 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
1121 if( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1122 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1123 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) )
1127 // node is being used in a separate thread; queue a message to set the value & base value
1128 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
1130 // Notification for derived classes
1131 mInsideOnSizeSet = true;
1132 OnSizeSet( mTargetSize );
1133 mInsideOnSizeSet = false;
1135 // Raise a relayout request if the flag is not locked
1136 if( mRelayoutData && !mRelayoutData->insideRelayout )
1143 void Actor::SetWidth( float width )
1145 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1147 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
1148 mRelayoutData->preferredSize.width = width;
1152 mTargetSize.width = width;
1154 // node is being used in a separate thread; queue a message to set the value & base value
1155 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1161 void Actor::SetHeight( float height )
1163 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1165 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
1166 mRelayoutData->preferredSize.height = height;
1170 mTargetSize.height = height;
1172 // node is being used in a separate thread; queue a message to set the value & base value
1173 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1179 void Actor::SetDepth( float depth )
1181 mTargetSize.depth = depth;
1183 // node is being used in a separate thread; queue a message to set the value & base value
1184 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1187 Vector3 Actor::GetTargetSize() const
1189 Vector3 size = mTargetSize;
1191 // Should return preferred size if size is fixed as set by SetSize
1192 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
1194 size.width = GetPreferredSize().width;
1196 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
1198 size.height = GetPreferredSize().height;
1204 const Vector3& Actor::GetCurrentSize() const
1206 // node is being used in a separate thread; copy the value from the previous update
1207 return GetNode().GetSize( GetEventThreadServices().GetEventBufferIndex() );
1210 Vector3 Actor::GetNaturalSize() const
1212 // It is up to deriving classes to return the appropriate natural size
1213 return Vector3( 0.0f, 0.0f, 0.0f );
1216 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1218 EnsureRelayoutData();
1220 ResizePolicy::Type originalWidthPolicy = GetResizePolicy(Dimension::WIDTH);
1221 ResizePolicy::Type originalHeightPolicy = GetResizePolicy(Dimension::HEIGHT);
1223 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1225 if( dimension & ( 1 << i ) )
1227 if ( policy == ResizePolicy::USE_ASSIGNED_SIZE )
1229 mRelayoutData->useAssignedSize[ i ] = true;
1233 mRelayoutData->resizePolicies[ i ] = policy;
1234 mRelayoutData->useAssignedSize[ i ] = false;
1239 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1241 if( dimension & Dimension::WIDTH )
1243 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1246 if( dimension & Dimension::HEIGHT )
1248 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1252 // If calling SetResizePolicy, assume we want relayout enabled
1253 SetRelayoutEnabled( true );
1255 // If the resize policy is set to be FIXED, the preferred size
1256 // should be overrided by the target size. Otherwise the target
1257 // size should be overrided by the preferred size.
1259 if( dimension & Dimension::WIDTH )
1261 if( originalWidthPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1263 mRelayoutData->preferredSize.width = mTargetSize.width;
1265 else if( originalWidthPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1267 mTargetSize.width = mRelayoutData->preferredSize.width;
1271 if( dimension & Dimension::HEIGHT )
1273 if( originalHeightPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1275 mRelayoutData->preferredSize.height = mTargetSize.height;
1277 else if( originalHeightPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1279 mTargetSize.height = mRelayoutData->preferredSize.height;
1283 OnSetResizePolicy( policy, dimension );
1285 // Trigger relayout on this control
1289 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1291 if ( mRelayoutData )
1293 // If more than one dimension is requested, just return the first one found
1294 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1296 if( ( dimension & ( 1 << i ) ) )
1298 if( mRelayoutData->useAssignedSize[ i ] )
1300 return ResizePolicy::USE_ASSIGNED_SIZE;
1304 return mRelayoutData->resizePolicies[ i ];
1310 return ResizePolicy::DEFAULT;
1313 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1315 EnsureRelayoutData();
1317 mRelayoutData->sizeSetPolicy = policy;
1319 // Trigger relayout on this control
1323 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1325 if ( mRelayoutData )
1327 return mRelayoutData->sizeSetPolicy;
1330 return DEFAULT_SIZE_SCALE_POLICY;
1333 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1335 EnsureRelayoutData();
1337 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1339 if( dimension & ( 1 << i ) )
1341 mRelayoutData->dimensionDependencies[ i ] = dependency;
1346 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1348 if ( mRelayoutData )
1350 // If more than one dimension is requested, just return the first one found
1351 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1353 if( ( dimension & ( 1 << i ) ) )
1355 return mRelayoutData->dimensionDependencies[ i ];
1360 return Dimension::ALL_DIMENSIONS; // Default
1363 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1365 // If relayout data has not been allocated yet and the client is requesting
1366 // to disable it, do nothing
1367 if( mRelayoutData || relayoutEnabled )
1369 EnsureRelayoutData();
1371 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1373 mRelayoutData->relayoutEnabled = relayoutEnabled;
1377 bool Actor::IsRelayoutEnabled() const
1379 // Assume that if relayout data has not been allocated yet then
1380 // relayout is disabled
1381 return mRelayoutData && mRelayoutData->relayoutEnabled;
1384 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1386 EnsureRelayoutData();
1388 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1390 if( dimension & ( 1 << i ) )
1392 mRelayoutData->dimensionDirty[ i ] = dirty;
1397 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1399 if ( mRelayoutData )
1401 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1403 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1413 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1415 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1418 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1420 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1423 uint32_t Actor::AddRenderer( Renderer& renderer )
1427 mRenderers = new RendererContainer;
1430 uint32_t index = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1431 RendererPtr rendererPtr = RendererPtr( &renderer );
1432 mRenderers->push_back( rendererPtr );
1433 AttachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1437 uint32_t Actor::GetRendererCount() const
1439 uint32_t rendererCount(0);
1442 rendererCount = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1445 return rendererCount;
1448 RendererPtr Actor::GetRendererAt( uint32_t index )
1450 RendererPtr renderer;
1451 if( index < GetRendererCount() )
1453 renderer = ( *mRenderers )[ index ];
1459 void Actor::RemoveRenderer( Renderer& renderer )
1463 RendererIter end = mRenderers->end();
1464 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1466 if( (*iter).Get() == &renderer )
1468 mRenderers->erase( iter );
1469 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1476 void Actor::RemoveRenderer( uint32_t index )
1478 if( index < GetRendererCount() )
1480 RendererPtr renderer = ( *mRenderers )[ index ];
1481 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.Get()->GetRendererSceneObject() );
1482 mRenderers->erase( mRenderers->begin()+index );
1486 bool Actor::IsOverlay() const
1488 return ( DrawMode::OVERLAY_2D == mDrawMode );
1491 void Actor::SetDrawMode( DrawMode::Type drawMode )
1493 // this flag is not animatable so keep the value
1494 mDrawMode = drawMode;
1496 // node is being used in a separate thread; queue a message to set the value
1497 SetDrawModeMessage( GetEventThreadServices(), GetNode(), drawMode );
1500 DrawMode::Type Actor::GetDrawMode() const
1505 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1507 // only valid when on-stage
1508 if( mScene && OnStage() )
1510 const RenderTaskList& taskList = mScene->GetRenderTaskList();
1512 Vector2 converted( screenX, screenY );
1514 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1515 uint32_t taskCount = taskList.GetTaskCount();
1516 for( uint32_t i = taskCount; i > 0; --i )
1518 RenderTaskPtr task = taskList.GetTask( i - 1 );
1519 if( ScreenToLocal( *task, localX, localY, screenX, screenY ) )
1521 // found a task where this conversion was ok so return
1529 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1531 bool retval = false;
1532 // only valid when on-stage
1535 CameraActor* camera = renderTask.GetCameraActor();
1539 renderTask.GetViewport( viewport );
1541 // need to translate coordinates to render tasks coordinate space
1542 Vector2 converted( screenX, screenY );
1543 if( renderTask.TranslateCoordinates( converted ) )
1545 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1552 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1554 // Early-out if not on stage
1560 // Get the ModelView matrix
1562 Matrix::Multiply( modelView, GetNode().GetWorldMatrix(0), viewMatrix );
1564 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1565 Matrix invertedMvp( false/*don't init*/);
1566 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1567 bool success = invertedMvp.Invert();
1569 // Convert to GL coordinates
1570 Vector4 screenPos( screenX - static_cast<float>( viewport.x ), static_cast<float>( viewport.height ) - screenY - static_cast<float>( viewport.y ), 0.f, 1.f );
1575 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), nearPos );
1582 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), farPos );
1588 if( XyPlaneIntersect( nearPos, farPos, local ) )
1590 Vector3 size = GetCurrentSize();
1591 localX = local.x + size.x * 0.5f;
1592 localY = local.y + size.y * 0.5f;
1603 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1606 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1608 Mathematical Formulation
1610 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1612 ( p - c ) dot ( p - c ) = r^2
1614 Given a ray with a point of origin 'o', and a direction vector 'd':
1616 ray(t) = o + td, t >= 0
1618 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1620 (o + td - c ) dot ( o + td - c ) = r^2
1622 To solve for t we first expand the above into a more recognisable quadratic equation form
1624 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1633 B = 2( o - c ) dot d
1634 C = ( o - c ) dot ( o - c ) - r^2
1636 which can be solved using a standard quadratic formula.
1638 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1640 Practical Simplification
1642 In a renderer, we often differentiate between world space and object space. In the object space
1643 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1644 into object space, the mathematical solution presented above can be simplified significantly.
1646 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1650 and we can find the t at which the (transformed) ray intersects the sphere by
1652 ( o + td ) dot ( o + td ) = r^2
1654 According to the reasoning above, we expand the above quadratic equation into the general form
1658 which now has coefficients:
1665 // Early-out if not on stage
1671 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1673 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1674 const Vector3& translation( GetNode().GetWorldPosition( bufferIndex ) );
1675 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1677 // Compute the radius is not needed, square radius it's enough.
1678 const Vector3& size( GetNode().GetSize( bufferIndex ) );
1680 // Scale the sphere.
1681 const Vector3& scale( GetNode().GetWorldScale( bufferIndex ) );
1683 const float width = size.width * scale.width;
1684 const float height = size.height * scale.height;
1686 float squareSphereRadius = 0.5f * ( width * width + height * height );
1688 float a = rayDir.Dot( rayDir ); // a
1689 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1690 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1692 return ( b2 * b2 - a * c ) >= 0.f;
1695 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector2& hitPointLocal, float& distance ) const
1701 // Transforms the ray to the local reference system.
1702 // Calculate the inverse of Model matrix
1703 Matrix invModelMatrix( false/*don't init*/);
1705 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1706 invModelMatrix = GetNode().GetWorldMatrix(0);
1707 invModelMatrix.Invert();
1709 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1710 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1712 // Test with the actor's XY plane (Normal = 0 0 1 1).
1714 float a = -rayOriginLocal.z;
1715 float b = rayDirLocal.z;
1717 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1719 // Ray travels distance * rayDirLocal to intersect with plane.
1722 const Vector3& size = GetNode().GetSize( bufferIndex );
1724 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1725 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1727 // Test with the actor's geometry.
1728 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1735 void Actor::SetLeaveRequired( bool required )
1737 mLeaveRequired = required;
1740 bool Actor::GetLeaveRequired() const
1742 return mLeaveRequired;
1745 void Actor::SetKeyboardFocusable( bool focusable )
1747 mKeyboardFocusable = focusable;
1750 bool Actor::IsKeyboardFocusable() const
1752 return mKeyboardFocusable;
1755 bool Actor::GetTouchRequired() const
1757 return !mTouchedSignal.Empty() || !mTouchSignal.Empty() || mDerivedRequiresTouch;
1760 bool Actor::GetHoverRequired() const
1762 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1765 bool Actor::GetWheelEventRequired() const
1767 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1770 bool Actor::IsHittable() const
1772 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1775 ActorGestureData& Actor::GetGestureData()
1777 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1778 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1779 if( NULL == mGestureData )
1781 mGestureData = new ActorGestureData;
1783 return *mGestureData;
1786 bool Actor::IsGestureRequred( Gesture::Type type ) const
1788 return mGestureData && mGestureData->IsGestureRequred( type );
1791 bool Actor::EmitTouchEventSignal( const TouchEvent& event, const Dali::TouchData& touch )
1793 bool consumed = false;
1795 if( !mTouchSignal.Empty() )
1797 Dali::Actor handle( this );
1798 consumed = mTouchSignal.Emit( handle, touch );
1801 if( !mTouchedSignal.Empty() )
1803 Dali::Actor handle( this );
1804 consumed |= mTouchedSignal.Emit( handle, event );
1809 // Notification for derived classes
1810 consumed = OnTouchEvent( event ); // TODO
1816 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1818 bool consumed = false;
1820 if( !mHoveredSignal.Empty() )
1822 Dali::Actor handle( this );
1823 consumed = mHoveredSignal.Emit( handle, event );
1828 // Notification for derived classes
1829 consumed = OnHoverEvent( event );
1835 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1837 bool consumed = false;
1839 if( !mWheelEventSignal.Empty() )
1841 Dali::Actor handle( this );
1842 consumed = mWheelEventSignal.Emit( handle, event );
1847 // Notification for derived classes
1848 consumed = OnWheelEvent( event );
1854 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
1856 if( ! mVisibilityChangedSignal.Empty() )
1858 Dali::Actor handle( this );
1859 mVisibilityChangedSignal.Emit( handle, visible, type );
1863 void Actor::EmitLayoutDirectionChangedSignal( LayoutDirection::Type type )
1865 if( ! mLayoutDirectionChangedSignal.Empty() )
1867 Dali::Actor handle( this );
1868 mLayoutDirectionChangedSignal.Emit( handle, type );
1872 void Actor::EmitChildAddedSignal( Actor& child )
1874 if( ! mChildAddedSignal.Empty() )
1876 Dali::Actor handle( &child );
1877 mChildAddedSignal.Emit( handle );
1881 void Actor::EmitChildRemovedSignal( Actor& child )
1883 if( ! mChildRemovedSignal.Empty() )
1885 Dali::Actor handle( &child );
1886 mChildRemovedSignal.Emit( handle );
1890 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
1892 return mTouchedSignal;
1895 Dali::Actor::TouchDataSignalType& Actor::TouchSignal()
1897 return mTouchSignal;
1900 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
1902 return mHoveredSignal;
1905 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
1907 return mWheelEventSignal;
1910 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
1912 return mOnStageSignal;
1915 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
1917 return mOffStageSignal;
1920 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
1922 return mOnRelayoutSignal;
1925 DevelActor::VisibilityChangedSignalType& Actor::VisibilityChangedSignal()
1927 return mVisibilityChangedSignal;
1930 Dali::Actor::LayoutDirectionChangedSignalType& Actor::LayoutDirectionChangedSignal()
1932 return mLayoutDirectionChangedSignal;
1935 DevelActor::ChildChangedSignalType& Actor::ChildAddedSignal()
1937 return mChildAddedSignal;
1940 DevelActor::ChildChangedSignalType& Actor::ChildRemovedSignal()
1942 return mChildRemovedSignal;
1945 DevelActor::ChildOrderChangedSignalType& Actor::ChildOrderChangedSignal()
1947 return mChildOrderChangedSignal;
1950 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1952 bool connected( true );
1953 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
1955 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1957 actor->TouchedSignal().Connect( tracker, functor );
1959 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1961 actor->HoveredSignal().Connect( tracker, functor );
1963 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1965 actor->WheelEventSignal().Connect( tracker, functor );
1967 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
1969 actor->OnStageSignal().Connect( tracker, functor );
1971 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
1973 actor->OffStageSignal().Connect( tracker, functor );
1975 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
1977 actor->OnRelayoutSignal().Connect( tracker, functor );
1979 else if( 0 == signalName.compare( SIGNAL_TOUCH ) )
1981 actor->TouchSignal().Connect( tracker, functor );
1983 else if( 0 == signalName.compare( SIGNAL_VISIBILITY_CHANGED ) )
1985 actor->VisibilityChangedSignal().Connect( tracker, functor );
1987 else if( 0 == signalName.compare( SIGNAL_LAYOUT_DIRECTION_CHANGED ) )
1989 actor->LayoutDirectionChangedSignal().Connect( tracker, functor );
1991 else if( 0 == signalName.compare( SIGNAL_CHILD_ADDED ) )
1993 actor->ChildAddedSignal().Connect( tracker, functor );
1995 else if( 0 == signalName.compare( SIGNAL_CHILD_REMOVED ) )
1997 actor->ChildRemovedSignal().Connect( tracker, functor );
2001 // signalName does not match any signal
2008 Actor::Actor( DerivedType derivedType, const SceneGraph::Node& node )
2014 mParentOrigin( NULL ),
2015 mAnchorPoint( NULL ),
2016 mRelayoutData( NULL ),
2017 mGestureData( NULL ),
2021 mWheelEventSignal(),
2024 mOnRelayoutSignal(),
2025 mVisibilityChangedSignal(),
2026 mLayoutDirectionChangedSignal(),
2027 mChildAddedSignal(),
2028 mChildRemovedSignal(),
2029 mChildOrderChangedSignal(),
2030 mTargetOrientation( Quaternion::IDENTITY ),
2031 mTargetColor( Color::WHITE ),
2032 mTargetSize( Vector3::ZERO ),
2033 mTargetPosition( Vector3::ZERO ),
2034 mTargetScale( Vector3::ONE ),
2038 mIsRoot( ROOT_LAYER == derivedType ),
2039 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2040 mIsOnStage( false ),
2042 mLeaveRequired( false ),
2043 mKeyboardFocusable( false ),
2044 mDerivedRequiresTouch( false ),
2045 mDerivedRequiresHover( false ),
2046 mDerivedRequiresWheelEvent( false ),
2047 mOnStageSignalled( false ),
2048 mInsideOnSizeSet( false ),
2049 mInheritPosition( true ),
2050 mInheritOrientation( true ),
2051 mInheritScale( true ),
2052 mPositionUsesAnchorPoint( true ),
2054 mInheritLayoutDirection( true ),
2055 mLayoutDirection( LayoutDirection::LEFT_TO_RIGHT ),
2056 mDrawMode( DrawMode::NORMAL ),
2057 mColorMode( Node::DEFAULT_COLOR_MODE ),
2058 mClippingMode( ClippingMode::DISABLED )
2062 void Actor::Initialize()
2066 GetEventThreadServices().RegisterObject( this );
2071 // Remove mParent pointers from children even if we're destroying core,
2072 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2075 ActorConstIter endIter = mChildren->end();
2076 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2078 (*iter)->SetParent( NULL );
2084 // Guard to allow handle destruction after Core has been destroyed
2085 if( EventThreadServices::IsCoreRunning() )
2087 // Root layer will destroy its node in its own destructor
2090 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
2092 GetEventThreadServices().UnregisterObject( this );
2096 // Cleanup optional gesture data
2097 delete mGestureData;
2099 // Cleanup optional parent origin and anchor
2100 delete mParentOrigin;
2101 delete mAnchorPoint;
2103 // Delete optional relayout data
2104 delete mRelayoutData;
2107 void Actor::ConnectToStage( uint32_t parentDepth )
2109 // This container is used instead of walking the Actor hierarchy.
2110 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
2111 ActorContainer connectionList;
2115 mScene->RequestRebuildDepthTree();
2118 // This stage is atomic i.e. not interrupted by user callbacks.
2119 RecursiveConnectToStage( connectionList, parentDepth + 1 );
2121 // Notify applications about the newly connected actors.
2122 const ActorIter endIter = connectionList.end();
2123 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2125 (*iter)->NotifyStageConnection();
2131 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, uint32_t depth )
2133 DALI_ASSERT_ALWAYS( !OnStage() );
2136 mDepth = static_cast< uint16_t >( depth ); // overflow ignored, not expected in practice
2138 ConnectToSceneGraph();
2140 // Notification for internal derived classes
2141 OnStageConnectionInternal();
2143 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2144 connectionList.push_back( ActorPtr( this ) );
2146 // Recursively connect children
2149 ActorConstIter endIter = mChildren->end();
2150 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2152 (*iter)->SetScene( *mScene );
2153 (*iter)->RecursiveConnectToStage( connectionList, depth + 1 );
2159 * This method is called when the Actor is connected to the Stage.
2160 * The parent must have added its Node to the scene-graph.
2161 * The child must connect its Node to the parent's Node.
2162 * This is recursive; the child calls ConnectToStage() for its children.
2164 void Actor::ConnectToSceneGraph()
2166 DALI_ASSERT_DEBUG( mParent != NULL);
2168 // Reparent Node in next Update
2169 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), mParent->GetNode(), GetNode() );
2171 // Request relayout on all actors that are added to the scenegraph
2174 // Notification for Object::Observers
2178 void Actor::NotifyStageConnection()
2180 // Actors can be removed (in a callback), before the on-stage stage is reported.
2181 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2182 if( OnStage() && !mOnStageSignalled )
2184 // Notification for external (CustomActor) derived classes
2185 OnStageConnectionExternal( mDepth );
2187 if( !mOnStageSignal.Empty() )
2189 Dali::Actor handle( this );
2190 mOnStageSignal.Emit( handle );
2193 // Guard against Remove during callbacks
2196 mOnStageSignalled = true; // signal required next time Actor is removed
2201 void Actor::DisconnectFromStage()
2203 // This container is used instead of walking the Actor hierachy.
2204 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2205 ActorContainer disconnectionList;
2209 mScene->RequestRebuildDepthTree();
2212 // This stage is atomic i.e. not interrupted by user callbacks
2213 RecursiveDisconnectFromStage( disconnectionList );
2215 // Notify applications about the newly disconnected actors.
2216 const ActorIter endIter = disconnectionList.end();
2217 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2219 (*iter)->NotifyStageDisconnection();
2223 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2225 // need to change state first so that internals relying on IsOnStage() inside OnStageDisconnectionInternal() get the correct value
2228 // Recursively disconnect children
2231 ActorConstIter endIter = mChildren->end();
2232 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2234 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2238 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2239 disconnectionList.push_back( ActorPtr( this ) );
2241 // Notification for internal derived classes
2242 OnStageDisconnectionInternal();
2244 DisconnectFromSceneGraph();
2248 * This method is called by an actor or its parent, before a node removal message is sent.
2249 * This is recursive; the child calls DisconnectFromStage() for its children.
2251 void Actor::DisconnectFromSceneGraph()
2253 // Notification for Object::Observers
2254 OnSceneObjectRemove();
2257 void Actor::NotifyStageDisconnection()
2259 // Actors can be added (in a callback), before the off-stage state is reported.
2260 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2261 // only do this step if there is a stage, i.e. Core is not being shut down
2262 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2264 // Notification for external (CustomeActor) derived classes
2265 OnStageDisconnectionExternal();
2267 if( !mOffStageSignal.Empty() )
2269 Dali::Actor handle( this );
2270 mOffStageSignal.Emit( handle );
2273 // Guard against Add during callbacks
2276 mOnStageSignalled = false; // signal required next time Actor is added
2281 bool Actor::IsNodeConnected() const
2283 bool connected( false );
2287 if( IsRoot() || GetNode().GetParent() )
2296 // This method initiates traversal of the actor tree using depth-first
2297 // traversal to set a depth index based on traversal order. It sends a
2298 // single message to update manager to update all the actor's nodes in
2299 // this tree with the depth index. The sceneGraphNodeDepths vector's
2300 // elements are ordered by depth, and could be used to reduce sorting
2301 // in the update thread.
2302 void Actor::RebuildDepthTree()
2304 DALI_LOG_TIMER_START(depthTimer);
2306 // Vector of scene-graph nodes and their depths to send to UpdateManager
2307 // in a single message
2308 OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths( new SceneGraph::NodeDepths() );
2310 int32_t depthIndex = 1;
2311 DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
2313 SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths );
2314 DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
2317 void Actor::DepthTraverseActorTree( OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths, int32_t& depthIndex )
2319 mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
2320 sceneGraphNodeDepths->Add( const_cast<SceneGraph::Node*>( &GetNode() ), mSortedDepth );
2322 // Create/add to children of this node
2325 for( ActorContainer::iterator it = mChildren->begin(); it != mChildren->end(); ++it )
2327 Actor* childActor = (*it).Get();
2329 childActor->DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
2334 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2338 case Dali::Actor::Property::PARENT_ORIGIN:
2340 Property::Type type = property.GetType();
2341 if( type == Property::VECTOR3 )
2343 SetParentOrigin( property.Get< Vector3 >() );
2345 else if ( type == Property::STRING )
2347 std::string parentOriginString;
2348 property.Get( parentOriginString );
2349 Vector3 parentOrigin;
2350 if( GetParentOriginConstant( parentOriginString, parentOrigin ) )
2352 SetParentOrigin( parentOrigin );
2358 case Dali::Actor::Property::PARENT_ORIGIN_X:
2360 SetParentOriginX( property.Get< float >() );
2364 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2366 SetParentOriginY( property.Get< float >() );
2370 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2372 SetParentOriginZ( property.Get< float >() );
2376 case Dali::Actor::Property::ANCHOR_POINT:
2378 Property::Type type = property.GetType();
2379 if( type == Property::VECTOR3 )
2381 SetAnchorPoint( property.Get< Vector3 >() );
2383 else if ( type == Property::STRING )
2385 std::string anchorPointString;
2386 property.Get( anchorPointString );
2388 if( GetAnchorPointConstant( anchorPointString, anchor ) )
2390 SetAnchorPoint( anchor );
2396 case Dali::Actor::Property::ANCHOR_POINT_X:
2398 SetAnchorPointX( property.Get< float >() );
2402 case Dali::Actor::Property::ANCHOR_POINT_Y:
2404 SetAnchorPointY( property.Get< float >() );
2408 case Dali::Actor::Property::ANCHOR_POINT_Z:
2410 SetAnchorPointZ( property.Get< float >() );
2414 case Dali::Actor::Property::SIZE:
2416 SetSize( property.Get< Vector3 >() );
2420 case Dali::Actor::Property::SIZE_WIDTH:
2422 SetWidth( property.Get< float >() );
2426 case Dali::Actor::Property::SIZE_HEIGHT:
2428 SetHeight( property.Get< float >() );
2432 case Dali::Actor::Property::SIZE_DEPTH:
2434 SetDepth( property.Get< float >() );
2438 case Dali::Actor::Property::POSITION:
2440 SetPosition( property.Get< Vector3 >() );
2444 case Dali::Actor::Property::POSITION_X:
2446 SetX( property.Get< float >() );
2450 case Dali::Actor::Property::POSITION_Y:
2452 SetY( property.Get< float >() );
2456 case Dali::Actor::Property::POSITION_Z:
2458 SetZ( property.Get< float >() );
2462 case Dali::Actor::Property::ORIENTATION:
2464 SetOrientation( property.Get< Quaternion >() );
2468 case Dali::Actor::Property::SCALE:
2470 SetScale( property.Get< Vector3 >() );
2474 case Dali::Actor::Property::SCALE_X:
2476 SetScaleX( property.Get< float >() );
2480 case Dali::Actor::Property::SCALE_Y:
2482 SetScaleY( property.Get< float >() );
2486 case Dali::Actor::Property::SCALE_Z:
2488 SetScaleZ( property.Get< float >() );
2492 case Dali::Actor::Property::VISIBLE:
2494 SetVisible( property.Get< bool >() );
2498 case Dali::Actor::Property::COLOR:
2500 SetColor( property.Get< Vector4 >() );
2504 case Dali::Actor::Property::COLOR_RED:
2506 SetColorRed( property.Get< float >() );
2510 case Dali::Actor::Property::COLOR_GREEN:
2512 SetColorGreen( property.Get< float >() );
2516 case Dali::Actor::Property::COLOR_BLUE:
2518 SetColorBlue( property.Get< float >() );
2522 case Dali::Actor::Property::COLOR_ALPHA:
2523 case Dali::DevelActor::Property::OPACITY:
2526 if( property.Get( value ) )
2528 SetOpacity( value );
2533 case Dali::Actor::Property::NAME:
2535 SetName( property.Get< std::string >() );
2539 case Dali::Actor::Property::SENSITIVE:
2541 SetSensitive( property.Get< bool >() );
2545 case Dali::Actor::Property::LEAVE_REQUIRED:
2547 SetLeaveRequired( property.Get< bool >() );
2551 case Dali::Actor::Property::INHERIT_POSITION:
2553 SetInheritPosition( property.Get< bool >() );
2557 case Dali::Actor::Property::INHERIT_ORIENTATION:
2559 SetInheritOrientation( property.Get< bool >() );
2563 case Dali::Actor::Property::INHERIT_SCALE:
2565 SetInheritScale( property.Get< bool >() );
2569 case Dali::Actor::Property::COLOR_MODE:
2571 ColorMode mode = mColorMode;
2572 if ( Scripting::GetEnumerationProperty< ColorMode >( property, COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT, mode ) )
2574 SetColorMode( mode );
2579 case Dali::Actor::Property::DRAW_MODE:
2581 DrawMode::Type mode = mDrawMode;
2582 if( Scripting::GetEnumerationProperty< DrawMode::Type >( property, DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT, mode ) )
2584 SetDrawMode( mode );
2589 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2591 SetSizeModeFactor( property.Get< Vector3 >() );
2595 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2597 ResizePolicy::Type type = GetResizePolicy( Dimension::WIDTH );
2598 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2600 SetResizePolicy( type, Dimension::WIDTH );
2605 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2607 ResizePolicy::Type type = GetResizePolicy( Dimension::HEIGHT );
2608 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2610 SetResizePolicy( type, Dimension::HEIGHT );
2615 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2617 SizeScalePolicy::Type type = GetSizeScalePolicy();
2618 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT, type ) )
2620 SetSizeScalePolicy( type );
2625 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2627 if( property.Get< bool >() )
2629 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2634 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2636 if( property.Get< bool >() )
2638 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2643 case Dali::Actor::Property::PADDING:
2645 Vector4 padding = property.Get< Vector4 >();
2646 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2647 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2651 case Dali::Actor::Property::MINIMUM_SIZE:
2653 Vector2 size = property.Get< Vector2 >();
2654 SetMinimumSize( size.x, Dimension::WIDTH );
2655 SetMinimumSize( size.y, Dimension::HEIGHT );
2659 case Dali::Actor::Property::MAXIMUM_SIZE:
2661 Vector2 size = property.Get< Vector2 >();
2662 SetMaximumSize( size.x, Dimension::WIDTH );
2663 SetMaximumSize( size.y, Dimension::HEIGHT );
2667 case Dali::DevelActor::Property::SIBLING_ORDER:
2671 if( property.Get( value ) )
2673 SetSiblingOrder( value );
2678 case Dali::Actor::Property::CLIPPING_MODE:
2680 ClippingMode::Type convertedValue = mClippingMode;
2681 if( Scripting::GetEnumerationProperty< ClippingMode::Type >( property, CLIPPING_MODE_TABLE, CLIPPING_MODE_TABLE_COUNT, convertedValue ) )
2683 mClippingMode = convertedValue;
2684 SetClippingModeMessage( GetEventThreadServices(), GetNode(), mClippingMode );
2689 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
2692 if( property.Get( value ) && value != mPositionUsesAnchorPoint )
2694 mPositionUsesAnchorPoint = value;
2695 SetPositionUsesAnchorPointMessage( GetEventThreadServices(), GetNode(), mPositionUsesAnchorPoint );
2700 case Dali::Actor::Property::LAYOUT_DIRECTION:
2702 Dali::LayoutDirection::Type direction = mLayoutDirection;
2703 mInheritLayoutDirection = false;
2705 if( Scripting::GetEnumerationProperty< LayoutDirection::Type >( property, LAYOUT_DIRECTION_TABLE, LAYOUT_DIRECTION_TABLE_COUNT, direction ) )
2707 InheritLayoutDirectionRecursively( this, direction, true );
2712 case Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION:
2715 if( property.Get( value ) )
2717 SetInheritLayoutDirection( value );
2722 case Dali::DevelActor::Property::UPDATE_SIZE_HINT:
2724 SetUpdateSizeHint( property.Get< Vector2 >() );
2730 // this can happen in the case of a non-animatable default property so just do nothing
2736 // TODO: This method needs to be removed
2737 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2739 switch( entry.GetType() )
2741 case Property::BOOLEAN:
2743 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2744 DALI_ASSERT_DEBUG( NULL != property );
2746 // property is being used in a separate thread; queue a message to set the property
2747 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2752 case Property::INTEGER:
2754 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2755 DALI_ASSERT_DEBUG( NULL != property );
2757 // property is being used in a separate thread; queue a message to set the property
2758 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2763 case Property::FLOAT:
2765 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2766 DALI_ASSERT_DEBUG( NULL != property );
2768 // property is being used in a separate thread; queue a message to set the property
2769 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2774 case Property::VECTOR2:
2776 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2777 DALI_ASSERT_DEBUG( NULL != property );
2779 // property is being used in a separate thread; queue a message to set the property
2780 if(entry.componentIndex == 0)
2782 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2784 else if(entry.componentIndex == 1)
2786 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2790 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2796 case Property::VECTOR3:
2798 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2799 DALI_ASSERT_DEBUG( NULL != property );
2801 // property is being used in a separate thread; queue a message to set the property
2802 if(entry.componentIndex == 0)
2804 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2806 else if(entry.componentIndex == 1)
2808 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2810 else if(entry.componentIndex == 2)
2812 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2816 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2822 case Property::VECTOR4:
2824 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2825 DALI_ASSERT_DEBUG( NULL != property );
2827 // property is being used in a separate thread; queue a message to set the property
2828 if(entry.componentIndex == 0)
2830 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
2832 else if(entry.componentIndex == 1)
2834 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
2836 else if(entry.componentIndex == 2)
2838 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
2840 else if(entry.componentIndex == 3)
2842 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
2846 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2852 case Property::ROTATION:
2854 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
2855 DALI_ASSERT_DEBUG( NULL != property );
2857 // property is being used in a separate thread; queue a message to set the property
2858 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
2863 case Property::MATRIX:
2865 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
2866 DALI_ASSERT_DEBUG( NULL != property );
2868 // property is being used in a separate thread; queue a message to set the property
2869 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), &GetNode(), property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
2874 case Property::MATRIX3:
2876 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
2877 DALI_ASSERT_DEBUG( NULL != property );
2879 // property is being used in a separate thread; queue a message to set the property
2880 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), &GetNode(), property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
2887 // nothing to do for other types
2892 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
2894 Property::Value value;
2896 if( ! GetCachedPropertyValue( index, value ) )
2898 // If property value is not stored in the event-side, then it must be a scene-graph only property
2899 GetCurrentPropertyValue( index, value );
2905 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
2907 Property::Value value;
2909 if( ! GetCurrentPropertyValue( index, value ) )
2911 // If unable to retrieve scene-graph property value, then it must be an event-side only property
2912 GetCachedPropertyValue( index, value );
2918 void Actor::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
2920 switch( animationType )
2923 case Animation::BETWEEN:
2927 case Dali::Actor::Property::SIZE:
2929 if( value.Get( mTargetSize ) )
2931 // Notify deriving classes
2932 OnSizeAnimation( animation, mTargetSize );
2937 case Dali::Actor::Property::SIZE_WIDTH:
2939 if( value.Get( mTargetSize.width ) )
2941 // Notify deriving classes
2942 OnSizeAnimation( animation, mTargetSize );
2947 case Dali::Actor::Property::SIZE_HEIGHT:
2949 if( value.Get( mTargetSize.height ) )
2951 // Notify deriving classes
2952 OnSizeAnimation( animation, mTargetSize );
2957 case Dali::Actor::Property::SIZE_DEPTH:
2959 if( value.Get( mTargetSize.depth ) )
2961 // Notify deriving classes
2962 OnSizeAnimation( animation, mTargetSize );
2967 case Dali::Actor::Property::POSITION:
2969 value.Get( mTargetPosition );
2973 case Dali::Actor::Property::POSITION_X:
2975 value.Get( mTargetPosition.x );
2979 case Dali::Actor::Property::POSITION_Y:
2981 value.Get( mTargetPosition.y );
2985 case Dali::Actor::Property::POSITION_Z:
2987 value.Get( mTargetPosition.z );
2991 case Dali::Actor::Property::ORIENTATION:
2993 value.Get( mTargetOrientation );
2997 case Dali::Actor::Property::SCALE:
2999 value.Get( mTargetScale );
3003 case Dali::Actor::Property::SCALE_X:
3005 value.Get( mTargetScale.x );
3009 case Dali::Actor::Property::SCALE_Y:
3011 value.Get( mTargetScale.y );
3015 case Dali::Actor::Property::SCALE_Z:
3017 value.Get( mTargetScale.z );
3021 case Dali::Actor::Property::VISIBLE:
3023 SetVisibleInternal( value.Get< bool >(), SendMessage::FALSE );
3027 case Dali::Actor::Property::COLOR:
3029 value.Get( mTargetColor );
3033 case Dali::Actor::Property::COLOR_RED:
3035 value.Get( mTargetColor.r );
3039 case Dali::Actor::Property::COLOR_GREEN:
3041 value.Get( mTargetColor.g );
3045 case Dali::Actor::Property::COLOR_BLUE:
3047 value.Get( mTargetColor.b );
3051 case Dali::Actor::Property::COLOR_ALPHA:
3052 case Dali::DevelActor::Property::OPACITY:
3054 value.Get( mTargetColor.a );
3060 // Not an animatable property. Do nothing.
3071 case Dali::Actor::Property::SIZE:
3073 if( AdjustValue< Vector3 >( mTargetSize, value ) )
3075 // Notify deriving classes
3076 OnSizeAnimation( animation, mTargetSize );
3081 case Dali::Actor::Property::SIZE_WIDTH:
3083 if( AdjustValue< float >( mTargetSize.width, value ) )
3085 // Notify deriving classes
3086 OnSizeAnimation( animation, mTargetSize );
3091 case Dali::Actor::Property::SIZE_HEIGHT:
3093 if( AdjustValue< float >( mTargetSize.height, value ) )
3095 // Notify deriving classes
3096 OnSizeAnimation( animation, mTargetSize );
3101 case Dali::Actor::Property::SIZE_DEPTH:
3103 if( AdjustValue< float >( mTargetSize.depth, value ) )
3105 // Notify deriving classes
3106 OnSizeAnimation( animation, mTargetSize );
3111 case Dali::Actor::Property::POSITION:
3113 AdjustValue< Vector3 >( mTargetPosition, value );
3117 case Dali::Actor::Property::POSITION_X:
3119 AdjustValue< float >( mTargetPosition.x, value );
3123 case Dali::Actor::Property::POSITION_Y:
3125 AdjustValue< float >( mTargetPosition.y, value );
3129 case Dali::Actor::Property::POSITION_Z:
3131 AdjustValue< float >( mTargetPosition.z, value );
3135 case Dali::Actor::Property::ORIENTATION:
3137 Quaternion relativeValue;
3138 if( value.Get( relativeValue ) )
3140 mTargetOrientation *= relativeValue;
3145 case Dali::Actor::Property::SCALE:
3147 AdjustValue< Vector3 >( mTargetScale, value );
3151 case Dali::Actor::Property::SCALE_X:
3153 AdjustValue< float >( mTargetScale.x, value );
3157 case Dali::Actor::Property::SCALE_Y:
3159 AdjustValue< float >( mTargetScale.y, value );
3163 case Dali::Actor::Property::SCALE_Z:
3165 AdjustValue< float >( mTargetScale.z, value );
3169 case Dali::Actor::Property::VISIBLE:
3171 bool relativeValue = false;
3172 if( value.Get( relativeValue ) )
3174 bool visible = mVisible || relativeValue;
3175 SetVisibleInternal( visible, SendMessage::FALSE );
3180 case Dali::Actor::Property::COLOR:
3182 AdjustValue< Vector4 >( mTargetColor, value );
3186 case Dali::Actor::Property::COLOR_RED:
3188 AdjustValue< float >( mTargetColor.r, value );
3192 case Dali::Actor::Property::COLOR_GREEN:
3194 AdjustValue< float >( mTargetColor.g, value );
3198 case Dali::Actor::Property::COLOR_BLUE:
3200 AdjustValue< float >( mTargetColor.b, value );
3204 case Dali::Actor::Property::COLOR_ALPHA:
3205 case Dali::DevelActor::Property::OPACITY:
3207 AdjustValue< float >( mTargetColor.a, value );
3213 // Not an animatable property. Do nothing.
3222 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3224 const PropertyBase* property( NULL );
3228 case Dali::Actor::Property::SIZE: // FALLTHROUGH
3229 case Dali::Actor::Property::SIZE_WIDTH: // FALLTHROUGH
3230 case Dali::Actor::Property::SIZE_HEIGHT: // FALLTHROUGH
3231 case Dali::Actor::Property::SIZE_DEPTH:
3233 property = &GetNode().mSize;
3236 case Dali::Actor::Property::POSITION: // FALLTHROUGH
3237 case Dali::Actor::Property::POSITION_X: // FALLTHROUGH
3238 case Dali::Actor::Property::POSITION_Y: // FALLTHROUGH
3239 case Dali::Actor::Property::POSITION_Z:
3241 property = &GetNode().mPosition;
3244 case Dali::Actor::Property::ORIENTATION:
3246 property = &GetNode().mOrientation;
3249 case Dali::Actor::Property::SCALE: // FALLTHROUGH
3250 case Dali::Actor::Property::SCALE_X: // FALLTHROUGH
3251 case Dali::Actor::Property::SCALE_Y: // FALLTHROUGH
3252 case Dali::Actor::Property::SCALE_Z:
3254 property = &GetNode().mScale;
3257 case Dali::Actor::Property::VISIBLE:
3259 property = &GetNode().mVisible;
3262 case Dali::Actor::Property::COLOR: // FALLTHROUGH
3263 case Dali::Actor::Property::COLOR_RED: // FALLTHROUGH
3264 case Dali::Actor::Property::COLOR_GREEN: // FALLTHROUGH
3265 case Dali::Actor::Property::COLOR_BLUE: // FALLTHROUGH
3266 case Dali::Actor::Property::COLOR_ALPHA: // FALLTHROUGH
3267 case Dali::DevelActor::Property::OPACITY:
3269 property = &GetNode().mColor;
3279 // not our property, ask base
3280 property = Object::GetSceneObjectAnimatableProperty( index );
3286 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3288 const PropertyInputImpl* property( NULL );
3292 case Dali::Actor::Property::PARENT_ORIGIN: // FALLTHROUGH
3293 case Dali::Actor::Property::PARENT_ORIGIN_X: // FALLTHROUGH
3294 case Dali::Actor::Property::PARENT_ORIGIN_Y: // FALLTHROUGH
3295 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3297 property = &GetNode().mParentOrigin;
3300 case Dali::Actor::Property::ANCHOR_POINT: // FALLTHROUGH
3301 case Dali::Actor::Property::ANCHOR_POINT_X: // FALLTHROUGH
3302 case Dali::Actor::Property::ANCHOR_POINT_Y: // FALLTHROUGH
3303 case Dali::Actor::Property::ANCHOR_POINT_Z:
3305 property = &GetNode().mAnchorPoint;
3308 case Dali::Actor::Property::WORLD_POSITION: // FALLTHROUGH
3309 case Dali::Actor::Property::WORLD_POSITION_X: // FALLTHROUGH
3310 case Dali::Actor::Property::WORLD_POSITION_Y: // FALLTHROUGH
3311 case Dali::Actor::Property::WORLD_POSITION_Z:
3313 property = &GetNode().mWorldPosition;
3316 case Dali::Actor::Property::WORLD_ORIENTATION:
3318 property = &GetNode().mWorldOrientation;
3321 case Dali::Actor::Property::WORLD_SCALE:
3323 property = &GetNode().mWorldScale;
3326 case Dali::Actor::Property::WORLD_COLOR:
3328 property = &GetNode().mWorldColor;
3331 case Dali::Actor::Property::WORLD_MATRIX:
3333 property = &GetNode().mWorldMatrix;
3336 case Dali::DevelActor::Property::CULLED:
3338 property = &GetNode().mCulled;
3348 // reuse animatable property getter as animatable properties are inputs as well
3349 // animatable property chains back to Object::GetSceneObjectInputProperty() so all properties get covered
3350 property = GetSceneObjectAnimatableProperty( index );
3356 int32_t Actor::GetPropertyComponentIndex( Property::Index index ) const
3358 int32_t componentIndex = Property::INVALID_COMPONENT_INDEX;
3362 case Dali::Actor::Property::PARENT_ORIGIN_X:
3363 case Dali::Actor::Property::ANCHOR_POINT_X:
3364 case Dali::Actor::Property::SIZE_WIDTH:
3365 case Dali::Actor::Property::POSITION_X:
3366 case Dali::Actor::Property::WORLD_POSITION_X:
3367 case Dali::Actor::Property::SCALE_X:
3368 case Dali::Actor::Property::COLOR_RED:
3374 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3375 case Dali::Actor::Property::ANCHOR_POINT_Y:
3376 case Dali::Actor::Property::SIZE_HEIGHT:
3377 case Dali::Actor::Property::POSITION_Y:
3378 case Dali::Actor::Property::WORLD_POSITION_Y:
3379 case Dali::Actor::Property::SCALE_Y:
3380 case Dali::Actor::Property::COLOR_GREEN:
3386 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3387 case Dali::Actor::Property::ANCHOR_POINT_Z:
3388 case Dali::Actor::Property::SIZE_DEPTH:
3389 case Dali::Actor::Property::POSITION_Z:
3390 case Dali::Actor::Property::WORLD_POSITION_Z:
3391 case Dali::Actor::Property::SCALE_Z:
3392 case Dali::Actor::Property::COLOR_BLUE:
3398 case Dali::Actor::Property::COLOR_ALPHA:
3399 case Dali::DevelActor::Property::OPACITY:
3411 if( Property::INVALID_COMPONENT_INDEX == componentIndex )
3414 componentIndex = Object::GetPropertyComponentIndex( index );
3417 return componentIndex;
3420 void Actor::SetParent( Actor* parent )
3424 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3428 mScene = parent->mScene;
3430 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3433 // Instruct each actor to create a corresponding node in the scene graph
3434 ConnectToStage( parent->GetHierarchyDepth() );
3437 // Resolve the name and index for the child properties if any
3438 ResolveChildProperties();
3440 else // parent being set to NULL
3442 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3446 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3449 // Disconnect the Node & its children from the scene-graph.
3450 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
3452 // Instruct each actor to discard pointers to the scene-graph
3453 DisconnectFromStage();
3460 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3463 Actor* actor = dynamic_cast< Actor* >( object );
3467 if( 0 == actionName.compare( ACTION_SHOW ) )
3469 actor->SetVisible( true );
3472 else if( 0 == actionName.compare( ACTION_HIDE ) )
3474 actor->SetVisible( false );
3482 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
3484 bool valueSet = true;
3488 case Dali::Actor::Property::PARENT_ORIGIN:
3490 value = GetCurrentParentOrigin();
3494 case Dali::Actor::Property::PARENT_ORIGIN_X:
3496 value = GetCurrentParentOrigin().x;
3500 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3502 value = GetCurrentParentOrigin().y;
3506 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3508 value = GetCurrentParentOrigin().z;
3512 case Dali::Actor::Property::ANCHOR_POINT:
3514 value = GetCurrentAnchorPoint();
3518 case Dali::Actor::Property::ANCHOR_POINT_X:
3520 value = GetCurrentAnchorPoint().x;
3524 case Dali::Actor::Property::ANCHOR_POINT_Y:
3526 value = GetCurrentAnchorPoint().y;
3530 case Dali::Actor::Property::ANCHOR_POINT_Z:
3532 value = GetCurrentAnchorPoint().z;
3536 case Dali::Actor::Property::SIZE:
3538 value = GetTargetSize();
3542 case Dali::Actor::Property::SIZE_WIDTH:
3544 value = GetTargetSize().width;
3548 case Dali::Actor::Property::SIZE_HEIGHT:
3550 value = GetTargetSize().height;
3554 case Dali::Actor::Property::SIZE_DEPTH:
3556 value = GetTargetSize().depth;
3560 case Dali::Actor::Property::POSITION:
3562 value = GetTargetPosition();
3566 case Dali::Actor::Property::POSITION_X:
3568 value = GetTargetPosition().x;
3572 case Dali::Actor::Property::POSITION_Y:
3574 value = GetTargetPosition().y;
3578 case Dali::Actor::Property::POSITION_Z:
3580 value = GetTargetPosition().z;
3584 case Dali::Actor::Property::ORIENTATION:
3586 value = mTargetOrientation;
3590 case Dali::Actor::Property::SCALE:
3592 value = mTargetScale;
3596 case Dali::Actor::Property::SCALE_X:
3598 value = mTargetScale.x;
3602 case Dali::Actor::Property::SCALE_Y:
3604 value = mTargetScale.y;
3608 case Dali::Actor::Property::SCALE_Z:
3610 value = mTargetScale.z;
3614 case Dali::Actor::Property::VISIBLE:
3620 case Dali::Actor::Property::COLOR:
3622 value = mTargetColor;
3626 case Dali::Actor::Property::COLOR_RED:
3628 value = mTargetColor.r;
3632 case Dali::Actor::Property::COLOR_GREEN:
3634 value = mTargetColor.g;
3638 case Dali::Actor::Property::COLOR_BLUE:
3640 value = mTargetColor.b;
3644 case Dali::Actor::Property::COLOR_ALPHA:
3645 case Dali::DevelActor::Property::OPACITY:
3647 value = mTargetColor.a;
3651 case Dali::Actor::Property::NAME:
3657 case Dali::Actor::Property::SENSITIVE:
3659 value = IsSensitive();
3663 case Dali::Actor::Property::LEAVE_REQUIRED:
3665 value = GetLeaveRequired();
3669 case Dali::Actor::Property::INHERIT_POSITION:
3671 value = IsPositionInherited();
3675 case Dali::Actor::Property::INHERIT_ORIENTATION:
3677 value = IsOrientationInherited();
3681 case Dali::Actor::Property::INHERIT_SCALE:
3683 value = IsScaleInherited();
3687 case Dali::Actor::Property::COLOR_MODE:
3689 value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
3693 case Dali::Actor::Property::DRAW_MODE:
3695 value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
3699 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3701 value = GetSizeModeFactor();
3705 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3707 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3711 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3713 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3717 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3719 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT );
3723 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3725 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3729 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3731 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3735 case Dali::Actor::Property::PADDING:
3737 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3738 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3739 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3743 case Dali::Actor::Property::MINIMUM_SIZE:
3745 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3749 case Dali::Actor::Property::MAXIMUM_SIZE:
3751 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3755 case Dali::Actor::Property::CLIPPING_MODE:
3757 value = mClippingMode;
3761 case Dali::DevelActor::Property::SIBLING_ORDER:
3763 value = static_cast<int>( GetSiblingOrder() );
3767 case Dali::DevelActor::Property::SCREEN_POSITION:
3769 value = GetCurrentScreenPosition();
3773 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
3775 value = mPositionUsesAnchorPoint;
3779 case Dali::Actor::Property::LAYOUT_DIRECTION:
3781 value = mLayoutDirection;
3785 case Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION:
3787 value = IsLayoutDirectionInherited();
3793 // Must be a scene-graph only property
3802 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
3804 bool valueSet = true;
3808 case Dali::Actor::Property::SIZE:
3810 value = GetCurrentSize();
3814 case Dali::Actor::Property::SIZE_WIDTH:
3816 value = GetCurrentSize().width;
3820 case Dali::Actor::Property::SIZE_HEIGHT:
3822 value = GetCurrentSize().height;
3826 case Dali::Actor::Property::SIZE_DEPTH:
3828 value = GetCurrentSize().depth;
3832 case Dali::Actor::Property::POSITION:
3834 value = GetCurrentPosition();
3838 case Dali::Actor::Property::POSITION_X:
3840 value = GetCurrentPosition().x;
3844 case Dali::Actor::Property::POSITION_Y:
3846 value = GetCurrentPosition().y;
3850 case Dali::Actor::Property::POSITION_Z:
3852 value = GetCurrentPosition().z;
3856 case Dali::Actor::Property::WORLD_POSITION:
3858 value = GetCurrentWorldPosition();
3862 case Dali::Actor::Property::WORLD_POSITION_X:
3864 value = GetCurrentWorldPosition().x;
3868 case Dali::Actor::Property::WORLD_POSITION_Y:
3870 value = GetCurrentWorldPosition().y;
3874 case Dali::Actor::Property::WORLD_POSITION_Z:
3876 value = GetCurrentWorldPosition().z;
3880 case Dali::Actor::Property::ORIENTATION:
3882 value = GetCurrentOrientation();
3886 case Dali::Actor::Property::WORLD_ORIENTATION:
3888 value = GetCurrentWorldOrientation();
3892 case Dali::Actor::Property::SCALE:
3894 value = GetCurrentScale();
3898 case Dali::Actor::Property::SCALE_X:
3900 value = GetCurrentScale().x;
3904 case Dali::Actor::Property::SCALE_Y:
3906 value = GetCurrentScale().y;
3910 case Dali::Actor::Property::SCALE_Z:
3912 value = GetCurrentScale().z;
3916 case Dali::Actor::Property::WORLD_SCALE:
3918 value = GetCurrentWorldScale();
3922 case Dali::Actor::Property::COLOR:
3924 value = GetCurrentColor();
3928 case Dali::Actor::Property::COLOR_RED:
3930 value = GetCurrentColor().r;
3934 case Dali::Actor::Property::COLOR_GREEN:
3936 value = GetCurrentColor().g;
3940 case Dali::Actor::Property::COLOR_BLUE:
3942 value = GetCurrentColor().b;
3946 case Dali::Actor::Property::COLOR_ALPHA:
3947 case Dali::DevelActor::Property::OPACITY:
3949 value = GetCurrentColor().a;
3953 case Dali::Actor::Property::WORLD_COLOR:
3955 value = GetCurrentWorldColor();
3959 case Dali::Actor::Property::WORLD_MATRIX:
3961 value = GetCurrentWorldMatrix();
3965 case Dali::Actor::Property::VISIBLE:
3967 value = IsVisible();
3971 case DevelActor::Property::CULLED:
3973 value = GetNode().IsCulled( GetEventThreadServices().GetEventBufferIndex() );
3977 case Dali::DevelActor::Property::UPDATE_SIZE_HINT:
3979 value = GetUpdateSizeHint();
3985 // Must be an event-side only property
3994 void Actor::EnsureRelayoutData()
3996 // Assign relayout data.
3997 if( !mRelayoutData )
3999 mRelayoutData = new RelayoutData();
4003 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
4005 // Check if actor is dependent on parent
4006 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4008 if( ( dimension & ( 1 << i ) ) )
4010 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4011 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
4021 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
4023 // Check if actor is dependent on children
4024 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4026 if( ( dimension & ( 1 << i ) ) )
4028 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4029 switch( resizePolicy )
4031 case ResizePolicy::FIT_TO_CHILDREN:
4032 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
4048 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
4050 return Actor::RelayoutDependentOnChildren( dimension );
4053 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
4055 // Check each possible dimension and see if it is dependent on the input one
4056 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4058 if( dimension & ( 1 << i ) )
4060 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
4067 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
4069 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4071 if( dimension & ( 1 << i ) )
4073 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
4078 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
4080 // If more than one dimension is requested, just return the first one found
4081 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4083 if( ( dimension & ( 1 << i ) ) )
4085 return mRelayoutData->negotiatedDimensions[ i ];
4089 return 0.0f; // Default
4092 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
4094 EnsureRelayoutData();
4096 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4098 if( dimension & ( 1 << i ) )
4100 mRelayoutData->dimensionPadding[ i ] = padding;
4105 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4107 if ( mRelayoutData )
4109 // If more than one dimension is requested, just return the first one found
4110 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4112 if( ( dimension & ( 1 << i ) ) )
4114 return mRelayoutData->dimensionPadding[ i ];
4119 return GetDefaultDimensionPadding();
4122 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4124 EnsureRelayoutData();
4126 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4128 if( dimension & ( 1 << i ) )
4130 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4135 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4137 if ( mRelayoutData )
4139 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4141 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4151 float Actor::GetHeightForWidthBase( float width )
4153 float height = 0.0f;
4155 const Vector3 naturalSize = GetNaturalSize();
4156 if( naturalSize.width > 0.0f )
4158 height = naturalSize.height * width / naturalSize.width;
4160 else // we treat 0 as 1:1 aspect ratio
4168 float Actor::GetWidthForHeightBase( float height )
4172 const Vector3 naturalSize = GetNaturalSize();
4173 if( naturalSize.height > 0.0f )
4175 width = naturalSize.width * height / naturalSize.height;
4177 else // we treat 0 as 1:1 aspect ratio
4185 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4187 // Fill to parent, taking size mode factor into account
4188 switch( child.GetResizePolicy( dimension ) )
4190 case ResizePolicy::FILL_TO_PARENT:
4192 return GetLatestSize( dimension );
4195 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4197 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4200 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4202 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4207 return GetLatestSize( dimension );
4212 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4214 // Can be overridden in derived class
4215 return CalculateChildSizeBase( child, dimension );
4218 float Actor::GetHeightForWidth( float width )
4220 // Can be overridden in derived class
4221 return GetHeightForWidthBase( width );
4224 float Actor::GetWidthForHeight( float height )
4226 // Can be overridden in derived class
4227 return GetWidthForHeightBase( height );
4230 float Actor::GetLatestSize( Dimension::Type dimension ) const
4232 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4235 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4237 Vector2 padding = GetPadding( dimension );
4239 return GetLatestSize( dimension ) + padding.x + padding.y;
4242 float Actor::NegotiateFromParent( Dimension::Type dimension )
4244 Actor* parent = GetParent();
4247 Vector2 padding( GetPadding( dimension ) );
4248 Vector2 parentPadding( parent->GetPadding( dimension ) );
4249 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4255 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4257 float maxDimensionPoint = 0.0f;
4259 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4261 ActorPtr child = GetChildAt( i );
4263 if( !child->RelayoutDependentOnParent( dimension ) )
4265 // Calculate the min and max points that the children range across
4266 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
4267 float dimensionSize = child->GetRelayoutSize( dimension );
4268 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4272 return maxDimensionPoint;
4275 float Actor::GetSize( Dimension::Type dimension ) const
4277 return GetDimensionValue( mTargetSize, dimension );
4280 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4282 return GetDimensionValue( GetNaturalSize(), dimension );
4285 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4287 switch( GetResizePolicy( dimension ) )
4289 case ResizePolicy::USE_NATURAL_SIZE:
4291 return GetNaturalSize( dimension );
4294 case ResizePolicy::FIXED:
4296 return GetDimensionValue( GetPreferredSize(), dimension );
4299 case ResizePolicy::USE_ASSIGNED_SIZE:
4301 return GetDimensionValue( maximumSize, dimension );
4304 case ResizePolicy::FILL_TO_PARENT:
4305 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4306 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4308 return NegotiateFromParent( dimension );
4311 case ResizePolicy::FIT_TO_CHILDREN:
4313 return NegotiateFromChildren( dimension );
4316 case ResizePolicy::DIMENSION_DEPENDENCY:
4318 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4321 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4323 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4326 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4328 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4340 return 0.0f; // Default
4343 float Actor::ClampDimension( float size, Dimension::Type dimension )
4345 const float minSize = GetMinimumSize( dimension );
4346 const float maxSize = GetMaximumSize( dimension );
4348 return std::max( minSize, std::min( size, maxSize ) );
4351 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4353 // Check if it needs to be negotiated
4354 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4356 // Check that we havn't gotten into an infinite loop
4357 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4358 bool recursionFound = false;
4359 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4361 if( *it == searchActor )
4363 recursionFound = true;
4368 if( !recursionFound )
4370 // Record the path that we have taken
4371 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4373 // Dimension dependency check
4374 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4376 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4378 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4380 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4384 // Parent dependency check
4385 Actor* parent = GetParent();
4386 if( parent && RelayoutDependentOnParent( dimension ) )
4388 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4391 // Children dependency check
4392 if( RelayoutDependentOnChildren( dimension ) )
4394 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4396 ActorPtr child = GetChildAt( i );
4398 // Only relayout child first if it is not dependent on this actor
4399 if( !child->RelayoutDependentOnParent( dimension ) )
4401 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
4406 // For deriving classes
4407 OnCalculateRelayoutSize( dimension );
4409 // All dependencies checked, calculate the size and set negotiated flag
4410 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4412 SetNegotiatedDimension( newSize, dimension );
4413 SetLayoutNegotiated( true, dimension );
4415 // For deriving classes
4416 OnLayoutNegotiated( newSize, dimension );
4418 // This actor has been successfully processed, pop it off the recursion stack
4419 recursionStack.pop_back();
4423 // TODO: Break infinite loop
4424 SetLayoutNegotiated( true, dimension );
4429 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4431 // Negotiate all dimensions that require it
4432 ActorDimensionStack recursionStack;
4434 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4436 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4439 NegotiateDimension( dimension, allocatedSize, recursionStack );
4443 Vector2 Actor::ApplySizeSetPolicy( const Vector2& size )
4445 switch( mRelayoutData->sizeSetPolicy )
4447 case SizeScalePolicy::USE_SIZE_SET:
4452 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4454 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4455 const Vector3 naturalSize = GetNaturalSize();
4456 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4458 const float sizeRatio = size.width / size.height;
4459 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4461 if( naturalSizeRatio < sizeRatio )
4463 return Vector2( naturalSizeRatio * size.height, size.height );
4465 else if( naturalSizeRatio > sizeRatio )
4467 return Vector2( size.width, size.width / naturalSizeRatio );
4478 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4480 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4481 const Vector3 naturalSize = GetNaturalSize();
4482 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4484 const float sizeRatio = size.width / size.height;
4485 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4487 if( naturalSizeRatio < sizeRatio )
4489 return Vector2( size.width, size.width / naturalSizeRatio );
4491 else if( naturalSizeRatio > sizeRatio )
4493 return Vector2( naturalSizeRatio * size.height, size.height );
4512 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4514 // Do the set actor size
4515 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4517 // Adjust for size set policy
4518 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4520 // Lock the flag to stop recursive relayouts on set size
4521 mRelayoutData->insideRelayout = true;
4522 SetSize( negotiatedSize );
4523 mRelayoutData->insideRelayout = false;
4525 // Clear flags for all dimensions
4526 SetLayoutDirty( false );
4528 // Give deriving classes a chance to respond
4529 OnRelayout( negotiatedSize, container );
4531 if( !mOnRelayoutSignal.Empty() )
4533 Dali::Actor handle( this );
4534 mOnRelayoutSignal.Emit( handle );
4538 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4540 // Force a size negotiation for actors that has assigned size during relayout
4541 // This is required as otherwise the flags that force a relayout will not
4542 // necessarilly be set. This will occur if the actor has already been laid out.
4543 // The dirty flags are then cleared. Then if the actor is added back into the
4544 // relayout container afterwards, the dirty flags would still be clear...
4545 // causing a relayout to be skipped. Here we force any actors added to the
4546 // container to be relayed out.
4547 DALI_LOG_TIMER_START( NegSizeTimer1 );
4549 if( GetUseAssignedSize(Dimension::WIDTH ) )
4551 SetLayoutNegotiated( false, Dimension::WIDTH );
4553 if( GetUseAssignedSize( Dimension::HEIGHT ) )
4555 SetLayoutNegotiated( false, Dimension::HEIGHT );
4558 // Do the negotiation
4559 NegotiateDimensions( allocatedSize );
4561 // Set the actor size
4562 SetNegotiatedSize( container );
4564 // Negotiate down to children
4565 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4567 ActorPtr child = GetChildAt( i );
4569 // Forces children that have already been laid out to be relayed out
4570 // if they have assigned size during relayout.
4571 if( child->GetUseAssignedSize(Dimension::WIDTH) )
4573 child->SetLayoutNegotiated(false, Dimension::WIDTH);
4574 child->SetLayoutDirty(true, Dimension::WIDTH);
4577 if( child->GetUseAssignedSize(Dimension::HEIGHT) )
4579 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
4580 child->SetLayoutDirty(true, Dimension::HEIGHT);
4583 // Only relayout if required
4584 if( child->RelayoutRequired() )
4586 container.Add( Dali::Actor( child.Get() ), mTargetSize.GetVectorXY() );
4589 DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
4592 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
4596 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4598 if( dimension & ( 1 << i ) )
4600 mRelayoutData->useAssignedSize[ i ] = use;
4606 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
4608 if ( mRelayoutData )
4610 // If more than one dimension is requested, just return the first one found
4611 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4613 if( dimension & ( 1 << i ) )
4615 return mRelayoutData->useAssignedSize[ i ];
4623 void Actor::RelayoutRequest( Dimension::Type dimension )
4625 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4626 if( relayoutController )
4628 Dali::Actor self( this );
4629 relayoutController->RequestRelayout( self, dimension );
4633 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4637 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4641 void Actor::SetPreferredSize( const Vector2& size )
4643 EnsureRelayoutData();
4645 if( size.width > 0.0f )
4647 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4650 if( size.height > 0.0f )
4652 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4655 mRelayoutData->preferredSize = size;
4660 Vector2 Actor::GetPreferredSize() const
4662 if ( mRelayoutData )
4664 return Vector2( mRelayoutData->preferredSize );
4667 return GetDefaultPreferredSize();
4670 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4672 EnsureRelayoutData();
4674 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4676 if( dimension & ( 1 << i ) )
4678 mRelayoutData->minimumSize[ i ] = size;
4685 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4687 if ( mRelayoutData )
4689 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4691 if( dimension & ( 1 << i ) )
4693 return mRelayoutData->minimumSize[ i ];
4698 return 0.0f; // Default
4701 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4703 EnsureRelayoutData();
4705 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4707 if( dimension & ( 1 << i ) )
4709 mRelayoutData->maximumSize[ i ] = size;
4716 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4718 if ( mRelayoutData )
4720 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4722 if( dimension & ( 1 << i ) )
4724 return mRelayoutData->maximumSize[ i ];
4729 return FLT_MAX; // Default
4732 void Actor::SetUpdateSizeHint( const Vector2& updateSizeHint )
4734 // node is being used in a separate thread; queue a message to set the value & base value
4735 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mUpdateSizeHint, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, Vector3(updateSizeHint.width, updateSizeHint.height, 0.f ) );
4738 const Vector2 Actor::GetUpdateSizeHint() const
4740 // node is being used in a separate thread; copy the value from the previous update
4741 Vector3 updateSizeHint = GetNode().GetUpdateSizeHint( GetEventThreadServices().GetEventBufferIndex() );
4742 return Vector2( updateSizeHint.width, updateSizeHint.height );
4745 Object* Actor::GetParentObject() const
4750 void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
4752 if( mVisible != visible )
4754 if( sendMessage == SendMessage::TRUE )
4756 // node is being used in a separate thread; queue a message to set the value & base value
4757 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible );
4762 // Emit the signal on this actor and all its children
4763 EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
4767 void Actor::SetSiblingOrder( uint32_t order )
4771 ActorContainer& siblings = *(mParent->mChildren);
4772 uint32_t currentOrder = GetSiblingOrder();
4774 if( order != currentOrder )
4780 else if( order < siblings.size() -1 )
4782 if( order > currentOrder )
4784 RaiseAbove( *siblings[order] );
4788 LowerBelow( *siblings[order] );
4799 uint32_t Actor::GetSiblingOrder() const
4805 ActorContainer& siblings = *(mParent->mChildren);
4806 for( std::size_t i = 0; i < siblings.size(); ++i )
4808 if( siblings[i] == this )
4810 order = static_cast<uint32_t>( i );
4819 void Actor::RequestRebuildDepthTree()
4825 mScene->RequestRebuildDepthTree();
4834 ActorContainer& siblings = *(mParent->mChildren);
4835 if( siblings.back() != this ) // If not already at end
4837 for( std::size_t i=0; i<siblings.size(); ++i )
4839 if( siblings[i] == this )
4842 ActorPtr next = siblings[i+1];
4843 siblings[i+1] = this;
4850 Dali::Actor handle( this );
4851 mParent->mChildOrderChangedSignal.Emit( handle );
4853 RequestRebuildDepthTree();
4857 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4865 ActorContainer& siblings = *(mParent->mChildren);
4866 if( siblings.front() != this ) // If not already at beginning
4868 for( std::size_t i=1; i<siblings.size(); ++i )
4870 if( siblings[i] == this )
4872 // Swap with previous
4873 ActorPtr previous = siblings[i-1];
4874 siblings[i-1] = this;
4875 siblings[i] = previous;
4881 Dali::Actor handle( this );
4882 mParent->mChildOrderChangedSignal.Emit( handle );
4884 RequestRebuildDepthTree();
4888 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4892 void Actor::RaiseToTop()
4896 ActorContainer& siblings = *(mParent->mChildren);
4897 if( siblings.back() != this ) // If not already at end
4899 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
4900 if( iter != siblings.end() )
4902 siblings.erase(iter);
4903 siblings.push_back(ActorPtr(this));
4907 Dali::Actor handle( this );
4908 mParent->mChildOrderChangedSignal.Emit( handle );
4910 RequestRebuildDepthTree();
4914 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4918 void Actor::LowerToBottom()
4922 ActorContainer& siblings = *(mParent->mChildren);
4923 if( siblings.front() != this ) // If not already at bottom,
4925 ActorPtr thisPtr(this); // ensure this actor remains referenced.
4927 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
4928 if( iter != siblings.end() )
4930 siblings.erase(iter);
4931 siblings.insert(siblings.begin(), thisPtr);
4935 Dali::Actor handle( this );
4936 mParent->mChildOrderChangedSignal.Emit( handle );
4938 RequestRebuildDepthTree();
4942 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4946 void Actor::RaiseAbove( Internal::Actor& target )
4950 ActorContainer& siblings = *(mParent->mChildren);
4951 if( siblings.back() != this && target.mParent == mParent ) // If not already at top
4953 ActorPtr thisPtr(this); // ensure this actor remains referenced.
4955 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
4956 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
4957 if( thisIter < targetIter )
4959 siblings.erase(thisIter);
4960 // Erasing early invalidates the targetIter. (Conversely, inserting first may also
4961 // invalidate thisIter)
4962 targetIter = std::find( siblings.begin(), siblings.end(), &target );
4964 siblings.insert(targetIter, thisPtr);
4967 Dali::Actor handle( this );
4968 mParent->mChildOrderChangedSignal.Emit( handle );
4970 RequestRebuildDepthTree();
4975 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4979 void Actor::LowerBelow( Internal::Actor& target )
4983 ActorContainer& siblings = *(mParent->mChildren);
4984 if( siblings.front() != this && target.mParent == mParent ) // If not already at bottom
4986 ActorPtr thisPtr(this); // ensure this actor remains referenced.
4988 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
4989 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
4991 if( thisIter > targetIter )
4993 siblings.erase(thisIter); // this only invalidates iterators at or after this point.
4994 siblings.insert(targetIter, thisPtr);
4997 Dali::Actor handle( this );
4998 mParent->mChildOrderChangedSignal.Emit( handle );
5000 RequestRebuildDepthTree();
5005 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5009 void Actor::SetScene( Scene& scene )
5014 Scene& Actor::GetScene() const
5019 void Actor::SetInheritLayoutDirection( bool inherit )
5021 if( mInheritLayoutDirection != inherit )
5023 mInheritLayoutDirection = inherit;
5025 if( inherit && mParent )
5027 InheritLayoutDirectionRecursively( this, mParent->mLayoutDirection );
5032 bool Actor::IsLayoutDirectionInherited() const
5034 return mInheritLayoutDirection;
5037 void Actor::InheritLayoutDirectionRecursively( ActorPtr actor, Dali::LayoutDirection::Type direction, bool set )
5039 if( actor && ( actor->mInheritLayoutDirection || set ) )
5041 if( actor->mLayoutDirection != direction )
5043 actor->mLayoutDirection = direction;
5044 actor->EmitLayoutDirectionChangedSignal( direction );
5045 actor->RelayoutRequest();
5048 if( actor->GetChildCount() > 0 )
5050 ActorContainer& children = actor->GetChildrenInternal();
5051 for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter )
5053 InheritLayoutDirectionRecursively( *iter, direction );
5059 } // namespace Internal