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/animation/constraint-impl.h>
46 #include <dali/internal/event/common/projection.h>
47 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
48 #include <dali/internal/update/common/animatable-property.h>
49 #include <dali/internal/update/nodes/node-messages.h>
50 #include <dali/internal/update/nodes/node-declarations.h>
51 #include <dali/internal/update/animation/scene-graph-constraint.h>
52 #include <dali/internal/event/events/actor-gesture-data.h>
53 #include <dali/internal/common/message.h>
54 #include <dali/integration-api/debug.h>
56 using Dali::Internal::SceneGraph::Node;
57 using Dali::Internal::SceneGraph::AnimatableProperty;
58 using Dali::Internal::SceneGraph::PropertyBase;
60 #if defined(DEBUG_ENABLED)
61 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_DEPTH_TIMER" );
62 Debug::Filter* gLogRelayoutFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_TIMER" );
73 /// Using a function because of library initialisation order. Vector3::ONE may not have been initialised yet.
74 inline const Vector3& GetDefaultSizeModeFactor()
79 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
80 inline const Vector2& GetDefaultPreferredSize()
85 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
86 inline const Vector2& GetDefaultDimensionPadding()
91 const SizeScalePolicy::Type DEFAULT_SIZE_SCALE_POLICY = SizeScalePolicy::USE_SIZE_SET;
93 } // unnamed namespace
96 * Struct to collect relayout variables
98 struct Actor::RelayoutData
101 : sizeModeFactor( GetDefaultSizeModeFactor() ), preferredSize( GetDefaultPreferredSize() ), sizeSetPolicy( DEFAULT_SIZE_SCALE_POLICY ), relayoutEnabled( false ), insideRelayout( false )
103 // Set size negotiation defaults
104 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
106 resizePolicies[ i ] = ResizePolicy::DEFAULT;
107 useAssignedSize[ i ] = false;
108 negotiatedDimensions[ i ] = 0.0f;
109 dimensionNegotiated[ i ] = false;
110 dimensionDirty[ i ] = false;
111 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
112 dimensionPadding[ i ] = GetDefaultDimensionPadding();
113 minimumSize[ i ] = 0.0f;
114 maximumSize[ i ] = FLT_MAX;
118 ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies
119 bool useAssignedSize[ Dimension::DIMENSION_COUNT ]; ///< The flag to specify whether the size should be assigned to the actor
121 Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies
123 Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
125 float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
127 float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be
128 float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be
130 bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated
131 bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
133 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
135 Vector2 preferredSize; ///< The preferred size of the actor
137 SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
139 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
140 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
143 namespace // unnamed namespace
149 * We want to discourage the use of property strings (minimize string comparisons),
150 * particularly for the default properties.
151 * Name Type writable animatable constraint-input enum for index-checking
153 DALI_PROPERTY_TABLE_BEGIN
154 DALI_PROPERTY( "parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
155 DALI_PROPERTY( "parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
156 DALI_PROPERTY( "parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
157 DALI_PROPERTY( "parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
158 DALI_PROPERTY( "anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
159 DALI_PROPERTY( "anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
160 DALI_PROPERTY( "anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
161 DALI_PROPERTY( "anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
162 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
163 DALI_PROPERTY( "sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
164 DALI_PROPERTY( "sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
165 DALI_PROPERTY( "sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
166 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
167 DALI_PROPERTY( "positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
168 DALI_PROPERTY( "positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
169 DALI_PROPERTY( "positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
170 DALI_PROPERTY( "worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
171 DALI_PROPERTY( "worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
172 DALI_PROPERTY( "worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
173 DALI_PROPERTY( "worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
174 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
175 DALI_PROPERTY( "worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
176 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
177 DALI_PROPERTY( "scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
178 DALI_PROPERTY( "scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
179 DALI_PROPERTY( "scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
180 DALI_PROPERTY( "worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
181 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
182 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
183 DALI_PROPERTY( "colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
184 DALI_PROPERTY( "colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
185 DALI_PROPERTY( "colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
186 DALI_PROPERTY( "colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
187 DALI_PROPERTY( "worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
188 DALI_PROPERTY( "worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
189 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
190 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
191 DALI_PROPERTY( "leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
192 DALI_PROPERTY( "inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
193 DALI_PROPERTY( "inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
194 DALI_PROPERTY( "colorMode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
195 DALI_PROPERTY( "positionInheritance", STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE )
196 DALI_PROPERTY( "drawMode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
197 DALI_PROPERTY( "sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
198 DALI_PROPERTY( "widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
199 DALI_PROPERTY( "heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
200 DALI_PROPERTY( "sizeScalePolicy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
201 DALI_PROPERTY( "widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
202 DALI_PROPERTY( "heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
203 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
204 DALI_PROPERTY( "minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
205 DALI_PROPERTY( "maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
206 DALI_PROPERTY( "inheritPosition", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_POSITION )
207 DALI_PROPERTY( "clippingMode", STRING, true, false, false, Dali::Actor::Property::CLIPPING_MODE )
208 DALI_PROPERTY( "layoutDirection", STRING, true, false, false, Dali::Actor::Property::LAYOUT_DIRECTION )
209 DALI_PROPERTY( "inheritLayoutDirection", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION )
210 DALI_PROPERTY( "siblingOrder", INTEGER, true, false, false, Dali::DevelActor::Property::SIBLING_ORDER )
211 DALI_PROPERTY( "opacity", FLOAT, true, true, true, Dali::DevelActor::Property::OPACITY )
212 DALI_PROPERTY( "screenPosition", VECTOR2, false, false, false, Dali::DevelActor::Property::SCREEN_POSITION )
213 DALI_PROPERTY( "positionUsesAnchorPoint", BOOLEAN, true, false, false, Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT )
214 DALI_PROPERTY( "culled", BOOLEAN, false, false, true, Dali::DevelActor::Property::CULLED )
215 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperties )
219 const char* const SIGNAL_TOUCHED = "touched";
220 const char* const SIGNAL_HOVERED = "hovered";
221 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
222 const char* const SIGNAL_ON_STAGE = "onStage";
223 const char* const SIGNAL_OFF_STAGE = "offStage";
224 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
225 const char* const SIGNAL_TOUCH = "touch";
226 const char* const SIGNAL_VISIBILITY_CHANGED = "visibilityChanged";
227 const char* const SIGNAL_LAYOUT_DIRECTION_CHANGED = "layoutDirectionChanged";
228 const char* const SIGNAL_CHILD_ADDED = "childAdded";
229 const char* const SIGNAL_CHILD_REMOVED = "childRemoved";
233 const char* const ACTION_SHOW = "show";
234 const char* const ACTION_HIDE = "hide";
236 BaseHandle CreateActor()
238 return Dali::Actor::New();
241 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor, ActorDefaultProperties );
243 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
244 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
245 SignalConnectorType signalConnector3( mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal );
246 SignalConnectorType signalConnector4( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
247 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
248 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
249 SignalConnectorType signalConnector7( mType, SIGNAL_TOUCH, &Actor::DoConnectSignal );
250 SignalConnectorType signalConnector8( mType, SIGNAL_VISIBILITY_CHANGED, &Actor::DoConnectSignal );
251 SignalConnectorType signalConnector9( mType, SIGNAL_LAYOUT_DIRECTION_CHANGED, &Actor::DoConnectSignal );
252 SignalConnectorType signalConnector10( mType, SIGNAL_CHILD_ADDED, &Actor::DoConnectSignal );
253 SignalConnectorType signalConnector11( mType, SIGNAL_CHILD_REMOVED, &Actor::DoConnectSignal );
255 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
256 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
261 const Vector3& value;
264 DALI_ENUM_TO_STRING_TABLE_BEGIN_WITH_TYPE( AnchorValue, ANCHOR_CONSTANT )
265 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_LEFT )
266 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_CENTER )
267 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_RIGHT )
268 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_LEFT )
269 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER )
270 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_RIGHT )
271 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_LEFT )
272 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_CENTER )
273 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_RIGHT )
274 DALI_ENUM_TO_STRING_TABLE_END( ANCHOR_CONSTANT )
276 DALI_ENUM_TO_STRING_TABLE_BEGIN( COLOR_MODE )
277 DALI_ENUM_TO_STRING( USE_OWN_COLOR )
278 DALI_ENUM_TO_STRING( USE_PARENT_COLOR )
279 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_COLOR )
280 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_ALPHA )
281 DALI_ENUM_TO_STRING_TABLE_END( COLOR_MODE )
283 DALI_ENUM_TO_STRING_TABLE_BEGIN( POSITION_INHERITANCE_MODE )
284 DALI_ENUM_TO_STRING( INHERIT_PARENT_POSITION )
285 DALI_ENUM_TO_STRING( USE_PARENT_POSITION )
286 DALI_ENUM_TO_STRING( USE_PARENT_POSITION_PLUS_LOCAL_POSITION )
287 DALI_ENUM_TO_STRING( DONT_INHERIT_POSITION )
288 DALI_ENUM_TO_STRING_TABLE_END( POSITION_INHERITANCE_MODE )
290 DALI_ENUM_TO_STRING_TABLE_BEGIN( DRAW_MODE )
291 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, NORMAL )
292 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, OVERLAY_2D )
293 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, STENCIL )
294 DALI_ENUM_TO_STRING_TABLE_END( DRAW_MODE )
296 DALI_ENUM_TO_STRING_TABLE_BEGIN( RESIZE_POLICY )
297 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIXED )
298 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_NATURAL_SIZE )
299 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FILL_TO_PARENT )
300 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_RELATIVE_TO_PARENT )
301 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_FIXED_OFFSET_FROM_PARENT )
302 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIT_TO_CHILDREN )
303 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, DIMENSION_DEPENDENCY )
304 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_ASSIGNED_SIZE )
305 DALI_ENUM_TO_STRING_TABLE_END( RESIZE_POLICY )
307 DALI_ENUM_TO_STRING_TABLE_BEGIN( SIZE_SCALE_POLICY )
308 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, USE_SIZE_SET )
309 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FIT_WITH_ASPECT_RATIO )
310 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FILL_WITH_ASPECT_RATIO )
311 DALI_ENUM_TO_STRING_TABLE_END( SIZE_SCALE_POLICY )
313 DALI_ENUM_TO_STRING_TABLE_BEGIN( CLIPPING_MODE )
314 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, DISABLED )
315 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, CLIP_CHILDREN )
316 DALI_ENUM_TO_STRING_TABLE_END( CLIPPING_MODE )
318 DALI_ENUM_TO_STRING_TABLE_BEGIN( LAYOUT_DIRECTION )
319 DALI_ENUM_TO_STRING_WITH_SCOPE( LayoutDirection, LEFT_TO_RIGHT )
320 DALI_ENUM_TO_STRING_WITH_SCOPE( LayoutDirection, RIGHT_TO_LEFT )
321 DALI_ENUM_TO_STRING_TABLE_END( LAYOUT_DIRECTION )
323 bool GetAnchorPointConstant( const std::string& value, Vector3& anchor )
325 for( uint32_t i = 0; i < ANCHOR_CONSTANT_TABLE_COUNT; ++i )
327 uint32_t sizeIgnored = 0;
328 if( CompareTokens( value.c_str(), ANCHOR_CONSTANT_TABLE[ i ].name, sizeIgnored ) )
330 anchor = ANCHOR_CONSTANT_TABLE[ i ].value;
337 inline bool GetParentOriginConstant( const std::string& value, Vector3& parentOrigin )
339 // Values are the same so just use the same table as anchor-point
340 return GetAnchorPointConstant( value, parentOrigin );
344 * @brief Extract a given dimension from a Vector2
346 * @param[in] values The values to extract from
347 * @param[in] dimension The dimension to extract
348 * @return Return the value for the dimension
350 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
354 case Dimension::WIDTH:
358 case Dimension::HEIGHT:
360 return values.height;
371 * @brief Extract a given dimension from a Vector3
373 * @param[in] values The values to extract from
374 * @param[in] dimension The dimension to extract
375 * @return Return the value for the dimension
377 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
379 return GetDimensionValue( values.GetVectorXY(), dimension );
383 * @brief Recursively emits the visibility-changed-signal on the actor tree.
384 * @param[in] actor The actor to emit the signal on
385 * @param[in] visible The new visibility of the actor
386 * @param[in] type Whether the actor's visible property has changed or a parent's
388 void EmitVisibilityChangedSignalRecursively( ActorPtr actor, bool visible, DevelActor::VisibilityChange::Type type )
392 actor->EmitVisibilityChangedSignal( visible, type );
394 if( actor->GetChildCount() > 0 )
396 ActorContainer& children = actor->GetChildrenInternal();
397 for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter )
399 EmitVisibilityChangedSignalRecursively( *iter, visible, DevelActor::VisibilityChange::PARENT );
405 } // unnamed namespace
407 ActorPtr Actor::New()
409 // pass a reference to actor, actor does not own its node
410 ActorPtr actor( new Actor( BASIC, *CreateNode() ) );
412 // Second-phase construction
418 const SceneGraph::Node* Actor::CreateNode()
420 // create node. Nodes are owned by the update manager
421 SceneGraph::Node* node = SceneGraph::Node::New();
422 OwnerPointer< SceneGraph::Node > transferOwnership( node );
423 AddNodeMessage( Stage::GetCurrent()->GetUpdateManager(), transferOwnership );
428 const std::string& Actor::GetName() const
433 void Actor::SetName( const std::string& name )
437 // ATTENTION: string for debug purposes is not thread safe.
438 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( &GetNode() ), name );
441 uint32_t Actor::GetId() const
443 return GetNode().GetId();
446 bool Actor::OnStage() const
451 Dali::Layer Actor::GetLayer()
455 // Short-circuit for Layer derived actors
458 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
461 // Find the immediate Layer parent
462 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
464 if( parent->IsLayer() )
466 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
473 void Actor::Add( Actor& child )
475 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
476 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
480 mChildren = new ActorContainer;
483 Actor* const oldParent( child.mParent );
485 // child might already be ours
486 if( this != oldParent )
488 // if we already have parent, unparent us first
491 oldParent->Remove( child ); // This causes OnChildRemove callback & ChildRemoved signal
493 // Old parent may need to readjust to missing child
494 if( oldParent->RelayoutDependentOnChildren() )
496 oldParent->RelayoutRequest();
500 // Guard against Add() during previous OnChildRemove callback
503 // Do this first, since user callbacks from within SetParent() may need to remove child
504 mChildren->push_back( ActorPtr( &child ) );
506 // SetParent asserts that child can be added
507 child.SetParent( this );
509 // Notification for derived classes
511 EmitChildAddedSignal( child );
513 InheritLayoutDirectionRecursively( ActorPtr( &child ), mLayoutDirection );
515 // Only put in a relayout request if there is a suitable dependency
516 if( RelayoutDependentOnChildren() )
524 void Actor::Remove( Actor& child )
526 if( (this == &child) || (!mChildren) )
528 // no children or removing itself
534 // Find the child in mChildren, and unparent it
535 ActorIter end = mChildren->end();
536 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
538 ActorPtr actor = (*iter);
540 if( actor.Get() == &child )
542 // Keep handle for OnChildRemove notification
545 // Do this first, since user callbacks from within SetParent() may need to add the child
546 mChildren->erase( iter );
548 DALI_ASSERT_DEBUG( actor->GetParent() == this );
549 actor->SetParent( NULL );
557 // Only put in a relayout request if there is a suitable dependency
558 if( RelayoutDependentOnChildren() )
564 // Notification for derived classes
565 OnChildRemove( child );
566 EmitChildRemovedSignal( child );
569 void Actor::Unparent()
573 // Remove this actor from the parent. The remove will put a relayout request in for
574 // the parent if required
575 mParent->Remove( *this );
576 // mParent is now NULL!
580 uint32_t Actor::GetChildCount() const
582 return ( NULL != mChildren ) ? static_cast<uint32_t>( mChildren->size() ) : 0; // only 4,294,967,295 children per actor
585 ActorPtr Actor::GetChildAt( uint32_t index ) const
587 DALI_ASSERT_ALWAYS( index < GetChildCount() );
589 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
592 ActorPtr Actor::FindChildByName( const std::string& actorName )
595 if( actorName == mName )
601 ActorIter end = mChildren->end();
602 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
604 child = (*iter)->FindChildByName( actorName );
615 ActorPtr Actor::FindChildById( const uint32_t id )
624 ActorIter end = mChildren->end();
625 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
627 child = (*iter)->FindChildById( id );
638 void Actor::SetParentOrigin( const Vector3& origin )
640 // node is being used in a separate thread; queue a message to set the value & base value
641 SetParentOriginMessage( GetEventThreadServices(), GetNode(), origin );
643 // Cache for event-thread access
646 // not allocated, check if different from default
647 if( ParentOrigin::DEFAULT != origin )
649 mParentOrigin = new Vector3( origin );
654 // check if different from current costs more than just set
655 *mParentOrigin = origin;
659 void Actor::SetParentOriginX( float x )
661 const Vector3& current = GetCurrentParentOrigin();
663 SetParentOrigin( Vector3( x, current.y, current.z ) );
666 void Actor::SetParentOriginY( float y )
668 const Vector3& current = GetCurrentParentOrigin();
670 SetParentOrigin( Vector3( current.x, y, current.z ) );
673 void Actor::SetParentOriginZ( float z )
675 const Vector3& current = GetCurrentParentOrigin();
677 SetParentOrigin( Vector3( current.x, current.y, z ) );
680 const Vector3& Actor::GetCurrentParentOrigin() const
682 // Cached for event-thread access
683 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
686 void Actor::SetAnchorPoint( const Vector3& anchor )
688 // node is being used in a separate thread; queue a message to set the value & base value
689 SetAnchorPointMessage( GetEventThreadServices(), GetNode(), anchor );
691 // Cache for event-thread access
694 // not allocated, check if different from default
695 if( AnchorPoint::DEFAULT != anchor )
697 mAnchorPoint = new Vector3( anchor );
702 // check if different from current costs more than just set
703 *mAnchorPoint = anchor;
707 void Actor::SetAnchorPointX( float x )
709 const Vector3& current = GetCurrentAnchorPoint();
711 SetAnchorPoint( Vector3( x, current.y, current.z ) );
714 void Actor::SetAnchorPointY( float y )
716 const Vector3& current = GetCurrentAnchorPoint();
718 SetAnchorPoint( Vector3( current.x, y, current.z ) );
721 void Actor::SetAnchorPointZ( float z )
723 const Vector3& current = GetCurrentAnchorPoint();
725 SetAnchorPoint( Vector3( current.x, current.y, z ) );
728 const Vector3& Actor::GetCurrentAnchorPoint() const
730 // Cached for event-thread access
731 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
734 void Actor::SetPosition( float x, float y )
736 SetPosition( Vector3( x, y, 0.0f ) );
739 void Actor::SetPosition( float x, float y, float z )
741 SetPosition( Vector3( x, y, z ) );
744 void Actor::SetPosition( const Vector3& position )
746 mTargetPosition = position;
748 // node is being used in a separate thread; queue a message to set the value & base value
749 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
752 void Actor::SetX( float x )
754 mTargetPosition.x = x;
756 // node is being used in a separate thread; queue a message to set the value & base value
757 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
760 void Actor::SetY( float y )
762 mTargetPosition.y = y;
764 // node is being used in a separate thread; queue a message to set the value & base value
765 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
768 void Actor::SetZ( float z )
770 mTargetPosition.z = z;
772 // node is being used in a separate thread; queue a message to set the value & base value
773 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
776 void Actor::TranslateBy( const Vector3& distance )
778 mTargetPosition += distance;
780 // node is being used in a separate thread; queue a message to set the value & base value
781 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
784 const Vector3& Actor::GetCurrentPosition() const
786 // node is being used in a separate thread; copy the value from the previous update
787 return GetNode().GetPosition(GetEventThreadServices().GetEventBufferIndex());
790 const Vector3& Actor::GetTargetPosition() const
792 return mTargetPosition;
795 const Vector3& Actor::GetCurrentWorldPosition() const
797 // node is being used in a separate thread; copy the value from the previous update
798 return GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
801 const Vector2 Actor::GetCurrentScreenPosition() const
803 StagePtr stage = Stage::GetCurrent();
804 if( stage && OnStage() )
806 Vector3 worldPosition = GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
807 Vector3 cameraPosition = stage->GetDefaultCameraActor().GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
808 worldPosition -= cameraPosition;
810 Vector3 actorSize = GetCurrentSize() * GetCurrentWorldScale();
811 Vector2 halfStageSize( stage->GetSize() * 0.5f ); // World position origin is center of stage
812 Vector3 halfActorSize( actorSize * 0.5f );
813 Vector3 anchorPointOffSet = halfActorSize - actorSize * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
815 return Vector2( halfStageSize.width + worldPosition.x - anchorPointOffSet.x,
816 halfStageSize.height + worldPosition.y - anchorPointOffSet.y );
819 return Vector2::ZERO;
822 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
824 // this flag is not animatable so keep the value
825 mPositionInheritanceMode = mode;
826 // node is being used in a separate thread; queue a message to set the value
827 SetInheritPositionMessage( GetEventThreadServices(), GetNode(), mode == INHERIT_PARENT_POSITION );
830 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
832 // Cached for event-thread access
833 return mPositionInheritanceMode;
836 void Actor::SetInheritPosition( bool inherit )
838 if( mInheritPosition != inherit )
840 // non animatable so keep local copy
841 mInheritPosition = inherit;
842 SetInheritPositionMessage( GetEventThreadServices(), GetNode(), inherit );
846 bool Actor::IsPositionInherited() const
848 return mInheritPosition;
851 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
853 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
854 normalizedAxis.Normalize();
856 Quaternion orientation( angle, normalizedAxis );
858 SetOrientation( orientation );
861 void Actor::SetOrientation( const Quaternion& orientation )
863 mTargetOrientation = orientation;
865 // node is being used in a separate thread; queue a message to set the value & base value
866 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation );
869 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
871 RotateBy( Quaternion(angle, axis) );
874 void Actor::RotateBy( const Quaternion& relativeRotation )
876 mTargetOrientation *= Quaternion( relativeRotation );
878 // node is being used in a separate thread; queue a message to set the value & base value
879 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
882 const Quaternion& Actor::GetCurrentOrientation() const
884 // node is being used in a separate thread; copy the value from the previous update
885 return GetNode().GetOrientation(GetEventThreadServices().GetEventBufferIndex());
888 const Quaternion& Actor::GetCurrentWorldOrientation() const
890 // node is being used in a separate thread; copy the value from the previous update
891 return GetNode().GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
894 void Actor::SetScale( float scale )
896 SetScale( Vector3( scale, scale, scale ) );
899 void Actor::SetScale( float x, float y, float z )
901 SetScale( Vector3( x, y, z ) );
904 void Actor::SetScale( const Vector3& scale )
906 mTargetScale = scale;
908 // node is being used in a separate thread; queue a message to set the value & base value
909 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
912 void Actor::SetScaleX( float x )
916 // node is being used in a separate thread; queue a message to set the value & base value
917 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
920 void Actor::SetScaleY( float y )
924 // node is being used in a separate thread; queue a message to set the value & base value
925 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
928 void Actor::SetScaleZ( float z )
932 // node is being used in a separate thread; queue a message to set the value & base value
933 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
936 void Actor::ScaleBy(const Vector3& relativeScale)
938 mTargetScale *= relativeScale;
940 // node is being used in a separate thread; queue a message to set the value & base value
941 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
944 const Vector3& Actor::GetCurrentScale() const
946 // node is being used in a separate thread; copy the value from the previous update
947 return GetNode().GetScale(GetEventThreadServices().GetEventBufferIndex());
950 const Vector3& Actor::GetCurrentWorldScale() const
952 // node is being used in a separate thread; copy the value from the previous update
953 return GetNode().GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
956 void Actor::SetInheritScale( bool inherit )
958 if( mInheritScale != inherit )
960 // non animatable so keep local copy
961 mInheritScale = inherit;
962 // node is being used in a separate thread; queue a message to set the value
963 SetInheritScaleMessage( GetEventThreadServices(), GetNode(), inherit );
967 bool Actor::IsScaleInherited() const
969 return mInheritScale;
972 Matrix Actor::GetCurrentWorldMatrix() const
974 return GetNode().GetWorldMatrix(0);
977 void Actor::SetVisible( bool visible )
979 SetVisibleInternal( visible, SendMessage::TRUE );
982 bool Actor::IsVisible() const
984 // node is being used in a separate thread; copy the value from the previous update
985 return GetNode().IsVisible( GetEventThreadServices().GetEventBufferIndex() );
988 void Actor::SetOpacity( float opacity )
990 mTargetColor.a = opacity;
992 // node is being used in a separate thread; queue a message to set the value & base value
993 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
996 float Actor::GetCurrentOpacity() const
998 // node is being used in a separate thread; copy the value from the previous update
999 return GetNode().GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1002 ClippingMode::Type Actor::GetClippingMode() const
1004 return mClippingMode;
1007 uint32_t Actor::GetSortingDepth()
1009 return mSortedDepth;
1012 const Vector4& Actor::GetCurrentWorldColor() const
1014 return GetNode().GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1017 void Actor::SetColor( const Vector4& color )
1019 mTargetColor = color;
1021 // node is being used in a separate thread; queue a message to set the value & base value
1022 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::Bake, color );
1025 void Actor::SetColorRed( float red )
1027 mTargetColor.r = red;
1029 // node is being used in a separate thread; queue a message to set the value & base value
1030 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeX, red );
1033 void Actor::SetColorGreen( float green )
1035 mTargetColor.g = green;
1037 // node is being used in a separate thread; queue a message to set the value & base value
1038 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeY, green );
1041 void Actor::SetColorBlue( float blue )
1043 mTargetColor.b = blue;
1045 // node is being used in a separate thread; queue a message to set the value & base value
1046 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1049 const Vector4& Actor::GetCurrentColor() const
1051 // node is being used in a separate thread; copy the value from the previous update
1052 return GetNode().GetColor(GetEventThreadServices().GetEventBufferIndex());
1055 void Actor::SetInheritOrientation( bool inherit )
1057 if( mInheritOrientation != inherit )
1059 // non animatable so keep local copy
1060 mInheritOrientation = inherit;
1061 // node is being used in a separate thread; queue a message to set the value
1062 SetInheritOrientationMessage( GetEventThreadServices(), GetNode(), inherit );
1066 bool Actor::IsOrientationInherited() const
1068 return mInheritOrientation;
1071 void Actor::SetSizeModeFactor( const Vector3& factor )
1073 EnsureRelayoutData();
1075 mRelayoutData->sizeModeFactor = factor;
1078 const Vector3& Actor::GetSizeModeFactor() const
1080 if ( mRelayoutData )
1082 return mRelayoutData->sizeModeFactor;
1085 return GetDefaultSizeModeFactor();
1088 void Actor::SetColorMode( ColorMode colorMode )
1090 // non animatable so keep local copy
1091 mColorMode = colorMode;
1092 // node is being used in a separate thread; queue a message to set the value
1093 SetColorModeMessage( GetEventThreadServices(), GetNode(), colorMode );
1096 ColorMode Actor::GetColorMode() const
1098 // we have cached copy
1102 void Actor::SetSize( float width, float height )
1104 SetSize( Vector2( width, height ) );
1107 void Actor::SetSize( float width, float height, float depth )
1109 SetSize( Vector3( width, height, depth ) );
1112 void Actor::SetSize( const Vector2& size )
1114 SetSize( Vector3( size.width, size.height, 0.f ) );
1117 void Actor::SetSizeInternal( const Vector2& size )
1119 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1122 void Actor::SetSize( const Vector3& size )
1124 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1126 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1127 SetPreferredSize( size.GetVectorXY() );
1131 SetSizeInternal( size );
1135 void Actor::SetSizeInternal( const Vector3& size )
1137 // dont allow recursive loop
1138 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1139 // 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
1140 if( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1141 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1142 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) )
1146 // node is being used in a separate thread; queue a message to set the value & base value
1147 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
1149 // Notification for derived classes
1150 mInsideOnSizeSet = true;
1151 OnSizeSet( mTargetSize );
1152 mInsideOnSizeSet = false;
1154 // Raise a relayout request if the flag is not locked
1155 if( mRelayoutData && !mRelayoutData->insideRelayout )
1162 void Actor::SetWidth( float width )
1164 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1166 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
1167 mRelayoutData->preferredSize.width = width;
1171 mTargetSize.width = width;
1173 // node is being used in a separate thread; queue a message to set the value & base value
1174 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1180 void Actor::SetHeight( float height )
1182 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1184 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
1185 mRelayoutData->preferredSize.height = height;
1189 mTargetSize.height = height;
1191 // node is being used in a separate thread; queue a message to set the value & base value
1192 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1198 void Actor::SetDepth( float depth )
1200 mTargetSize.depth = depth;
1202 // node is being used in a separate thread; queue a message to set the value & base value
1203 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1206 Vector3 Actor::GetTargetSize() const
1208 Vector3 size = mTargetSize;
1210 // Should return preferred size if size is fixed as set by SetSize
1211 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
1213 size.width = GetPreferredSize().width;
1215 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
1217 size.height = GetPreferredSize().height;
1223 const Vector3& Actor::GetCurrentSize() const
1225 // node is being used in a separate thread; copy the value from the previous update
1226 return GetNode().GetSize( GetEventThreadServices().GetEventBufferIndex() );
1229 Vector3 Actor::GetNaturalSize() const
1231 // It is up to deriving classes to return the appropriate natural size
1232 return Vector3( 0.0f, 0.0f, 0.0f );
1235 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1237 EnsureRelayoutData();
1239 ResizePolicy::Type originalWidthPolicy = GetResizePolicy(Dimension::WIDTH);
1240 ResizePolicy::Type originalHeightPolicy = GetResizePolicy(Dimension::HEIGHT);
1242 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1244 if( dimension & ( 1 << i ) )
1246 if ( policy == ResizePolicy::USE_ASSIGNED_SIZE )
1248 mRelayoutData->useAssignedSize[ i ] = true;
1252 mRelayoutData->resizePolicies[ i ] = policy;
1253 mRelayoutData->useAssignedSize[ i ] = false;
1258 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1260 if( dimension & Dimension::WIDTH )
1262 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1265 if( dimension & Dimension::HEIGHT )
1267 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1271 // If calling SetResizePolicy, assume we want relayout enabled
1272 SetRelayoutEnabled( true );
1274 // If the resize policy is set to be FIXED, the preferred size
1275 // should be overrided by the target size. Otherwise the target
1276 // size should be overrided by the preferred size.
1278 if( dimension & Dimension::WIDTH )
1280 if( originalWidthPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1282 mRelayoutData->preferredSize.width = mTargetSize.width;
1284 else if( originalWidthPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1286 mTargetSize.width = mRelayoutData->preferredSize.width;
1290 if( dimension & Dimension::HEIGHT )
1292 if( originalHeightPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1294 mRelayoutData->preferredSize.height = mTargetSize.height;
1296 else if( originalHeightPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1298 mTargetSize.height = mRelayoutData->preferredSize.height;
1302 OnSetResizePolicy( policy, dimension );
1304 // Trigger relayout on this control
1308 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1310 if ( mRelayoutData )
1312 // If more than one dimension is requested, just return the first one found
1313 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1315 if( ( dimension & ( 1 << i ) ) )
1317 if( mRelayoutData->useAssignedSize[ i ] )
1319 return ResizePolicy::USE_ASSIGNED_SIZE;
1323 return mRelayoutData->resizePolicies[ i ];
1329 return ResizePolicy::DEFAULT;
1332 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1334 EnsureRelayoutData();
1336 mRelayoutData->sizeSetPolicy = policy;
1339 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1341 if ( mRelayoutData )
1343 return mRelayoutData->sizeSetPolicy;
1346 return DEFAULT_SIZE_SCALE_POLICY;
1349 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1351 EnsureRelayoutData();
1353 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1355 if( dimension & ( 1 << i ) )
1357 mRelayoutData->dimensionDependencies[ i ] = dependency;
1362 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1364 if ( mRelayoutData )
1366 // If more than one dimension is requested, just return the first one found
1367 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1369 if( ( dimension & ( 1 << i ) ) )
1371 return mRelayoutData->dimensionDependencies[ i ];
1376 return Dimension::ALL_DIMENSIONS; // Default
1379 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1381 // If relayout data has not been allocated yet and the client is requesting
1382 // to disable it, do nothing
1383 if( mRelayoutData || relayoutEnabled )
1385 EnsureRelayoutData();
1387 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1389 mRelayoutData->relayoutEnabled = relayoutEnabled;
1393 bool Actor::IsRelayoutEnabled() const
1395 // Assume that if relayout data has not been allocated yet then
1396 // relayout is disabled
1397 return mRelayoutData && mRelayoutData->relayoutEnabled;
1400 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1402 EnsureRelayoutData();
1404 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1406 if( dimension & ( 1 << i ) )
1408 mRelayoutData->dimensionDirty[ i ] = dirty;
1413 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1415 if ( mRelayoutData )
1417 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1419 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1429 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1431 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1434 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1436 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1439 uint32_t Actor::AddRenderer( Renderer& renderer )
1443 mRenderers = new RendererContainer;
1446 uint32_t index = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1447 RendererPtr rendererPtr = RendererPtr( &renderer );
1448 mRenderers->push_back( rendererPtr );
1449 AttachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1453 uint32_t Actor::GetRendererCount() const
1455 uint32_t rendererCount(0);
1458 rendererCount = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1461 return rendererCount;
1464 RendererPtr Actor::GetRendererAt( uint32_t index )
1466 RendererPtr renderer;
1467 if( index < GetRendererCount() )
1469 renderer = ( *mRenderers )[ index ];
1475 void Actor::RemoveRenderer( Renderer& renderer )
1479 RendererIter end = mRenderers->end();
1480 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1482 if( (*iter).Get() == &renderer )
1484 mRenderers->erase( iter );
1485 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1492 void Actor::RemoveRenderer( uint32_t index )
1494 if( index < GetRendererCount() )
1496 RendererPtr renderer = ( *mRenderers )[ index ];
1497 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.Get()->GetRendererSceneObject() );
1498 mRenderers->erase( mRenderers->begin()+index );
1502 bool Actor::IsOverlay() const
1504 return ( DrawMode::OVERLAY_2D == mDrawMode );
1507 void Actor::SetDrawMode( DrawMode::Type drawMode )
1509 // this flag is not animatable so keep the value
1510 mDrawMode = drawMode;
1511 if( drawMode != DrawMode::STENCIL )
1513 // node is being used in a separate thread; queue a message to set the value
1514 SetDrawModeMessage( GetEventThreadServices(), GetNode(), drawMode );
1518 DrawMode::Type Actor::GetDrawMode() const
1523 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1525 // only valid when on-stage
1526 StagePtr stage = Stage::GetCurrent();
1527 if( stage && OnStage() )
1529 const RenderTaskList& taskList = stage->GetRenderTaskList();
1531 Vector2 converted( screenX, screenY );
1533 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1534 uint32_t taskCount = taskList.GetTaskCount();
1535 for( uint32_t i = taskCount; i > 0; --i )
1537 RenderTaskPtr task = taskList.GetTask( i - 1 );
1538 if( ScreenToLocal( *task, localX, localY, screenX, screenY ) )
1540 // found a task where this conversion was ok so return
1548 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1550 bool retval = false;
1551 // only valid when on-stage
1554 CameraActor* camera = renderTask.GetCameraActor();
1558 renderTask.GetViewport( viewport );
1560 // need to translate coordinates to render tasks coordinate space
1561 Vector2 converted( screenX, screenY );
1562 if( renderTask.TranslateCoordinates( converted ) )
1564 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1571 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1573 // Early-out if not on stage
1579 // Get the ModelView matrix
1581 Matrix::Multiply( modelView, GetNode().GetWorldMatrix(0), viewMatrix );
1583 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1584 Matrix invertedMvp( false/*don't init*/);
1585 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1586 bool success = invertedMvp.Invert();
1588 // Convert to GL coordinates
1589 Vector4 screenPos( screenX - static_cast<float>( viewport.x ), static_cast<float>( viewport.height ) - screenY - static_cast<float>( viewport.y ), 0.f, 1.f );
1594 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), nearPos );
1601 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), farPos );
1607 if( XyPlaneIntersect( nearPos, farPos, local ) )
1609 Vector3 size = GetCurrentSize();
1610 localX = local.x + size.x * 0.5f;
1611 localY = local.y + size.y * 0.5f;
1622 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1625 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1627 Mathematical Formulation
1629 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1631 ( p - c ) dot ( p - c ) = r^2
1633 Given a ray with a point of origin 'o', and a direction vector 'd':
1635 ray(t) = o + td, t >= 0
1637 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1639 (o + td - c ) dot ( o + td - c ) = r^2
1641 To solve for t we first expand the above into a more recognisable quadratic equation form
1643 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1652 B = 2( o - c ) dot d
1653 C = ( o - c ) dot ( o - c ) - r^2
1655 which can be solved using a standard quadratic formula.
1657 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1659 Practical Simplification
1661 In a renderer, we often differentiate between world space and object space. In the object space
1662 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1663 into object space, the mathematical solution presented above can be simplified significantly.
1665 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1669 and we can find the t at which the (transformed) ray intersects the sphere by
1671 ( o + td ) dot ( o + td ) = r^2
1673 According to the reasoning above, we expand the above quadratic equation into the general form
1677 which now has coefficients:
1684 // Early-out if not on stage
1690 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1692 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1693 const Vector3& translation( GetNode().GetWorldPosition( bufferIndex ) );
1694 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1696 // Compute the radius is not needed, square radius it's enough.
1697 const Vector3& size( GetNode().GetSize( bufferIndex ) );
1699 // Scale the sphere.
1700 const Vector3& scale( GetNode().GetWorldScale( bufferIndex ) );
1702 const float width = size.width * scale.width;
1703 const float height = size.height * scale.height;
1705 float squareSphereRadius = 0.5f * ( width * width + height * height );
1707 float a = rayDir.Dot( rayDir ); // a
1708 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1709 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1711 return ( b2 * b2 - a * c ) >= 0.f;
1714 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector2& hitPointLocal, float& distance ) const
1720 // Transforms the ray to the local reference system.
1721 // Calculate the inverse of Model matrix
1722 Matrix invModelMatrix( false/*don't init*/);
1724 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1725 invModelMatrix = GetNode().GetWorldMatrix(0);
1726 invModelMatrix.Invert();
1728 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1729 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1731 // Test with the actor's XY plane (Normal = 0 0 1 1).
1733 float a = -rayOriginLocal.z;
1734 float b = rayDirLocal.z;
1736 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1738 // Ray travels distance * rayDirLocal to intersect with plane.
1741 const Vector3& size = GetNode().GetSize( bufferIndex );
1743 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1744 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1746 // Test with the actor's geometry.
1747 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1754 void Actor::SetLeaveRequired( bool required )
1756 mLeaveRequired = required;
1759 bool Actor::GetLeaveRequired() const
1761 return mLeaveRequired;
1764 void Actor::SetKeyboardFocusable( bool focusable )
1766 mKeyboardFocusable = focusable;
1769 bool Actor::IsKeyboardFocusable() const
1771 return mKeyboardFocusable;
1774 bool Actor::GetTouchRequired() const
1776 return !mTouchedSignal.Empty() || !mTouchSignal.Empty() || mDerivedRequiresTouch;
1779 bool Actor::GetHoverRequired() const
1781 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1784 bool Actor::GetWheelEventRequired() const
1786 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1789 bool Actor::IsHittable() const
1791 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1794 ActorGestureData& Actor::GetGestureData()
1796 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1797 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1798 if( NULL == mGestureData )
1800 mGestureData = new ActorGestureData;
1802 return *mGestureData;
1805 bool Actor::IsGestureRequred( Gesture::Type type ) const
1807 return mGestureData && mGestureData->IsGestureRequred( type );
1810 bool Actor::EmitTouchEventSignal( const TouchEvent& event, const Dali::TouchData& touch )
1812 bool consumed = false;
1814 if( !mTouchSignal.Empty() )
1816 Dali::Actor handle( this );
1817 consumed = mTouchSignal.Emit( handle, touch );
1820 if( !mTouchedSignal.Empty() )
1822 Dali::Actor handle( this );
1823 consumed |= mTouchedSignal.Emit( handle, event );
1828 // Notification for derived classes
1829 consumed = OnTouchEvent( event ); // TODO
1835 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1837 bool consumed = false;
1839 if( !mHoveredSignal.Empty() )
1841 Dali::Actor handle( this );
1842 consumed = mHoveredSignal.Emit( handle, event );
1847 // Notification for derived classes
1848 consumed = OnHoverEvent( event );
1854 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1856 bool consumed = false;
1858 if( !mWheelEventSignal.Empty() )
1860 Dali::Actor handle( this );
1861 consumed = mWheelEventSignal.Emit( handle, event );
1866 // Notification for derived classes
1867 consumed = OnWheelEvent( event );
1873 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
1875 if( ! mVisibilityChangedSignal.Empty() )
1877 Dali::Actor handle( this );
1878 mVisibilityChangedSignal.Emit( handle, visible, type );
1882 void Actor::EmitLayoutDirectionChangedSignal( LayoutDirection::Type type )
1884 if( ! mLayoutDirectionChangedSignal.Empty() )
1886 Dali::Actor handle( this );
1887 mLayoutDirectionChangedSignal.Emit( handle, type );
1891 void Actor::EmitChildAddedSignal( Actor& child )
1893 if( ! mChildAddedSignal.Empty() )
1895 Dali::Actor handle( &child );
1896 mChildAddedSignal.Emit( handle );
1900 void Actor::EmitChildRemovedSignal( Actor& child )
1902 if( ! mChildRemovedSignal.Empty() )
1904 Dali::Actor handle( &child );
1905 mChildRemovedSignal.Emit( handle );
1909 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
1911 return mTouchedSignal;
1914 Dali::Actor::TouchDataSignalType& Actor::TouchSignal()
1916 return mTouchSignal;
1919 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
1921 return mHoveredSignal;
1924 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
1926 return mWheelEventSignal;
1929 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
1931 return mOnStageSignal;
1934 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
1936 return mOffStageSignal;
1939 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
1941 return mOnRelayoutSignal;
1944 DevelActor::VisibilityChangedSignalType& Actor::VisibilityChangedSignal()
1946 return mVisibilityChangedSignal;
1949 Dali::Actor::LayoutDirectionChangedSignalType& Actor::LayoutDirectionChangedSignal()
1951 return mLayoutDirectionChangedSignal;
1954 DevelActor::ChildChangedSignalType& Actor::ChildAddedSignal()
1956 return mChildAddedSignal;
1959 DevelActor::ChildChangedSignalType& Actor::ChildRemovedSignal()
1961 return mChildRemovedSignal;
1964 DevelActor::ChildOrderChangedSignalType& Actor::ChildOrderChangedSignal()
1966 return mChildOrderChangedSignal;
1969 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1971 bool connected( true );
1972 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
1974 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1976 actor->TouchedSignal().Connect( tracker, functor );
1978 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1980 actor->HoveredSignal().Connect( tracker, functor );
1982 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1984 actor->WheelEventSignal().Connect( tracker, functor );
1986 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
1988 actor->OnStageSignal().Connect( tracker, functor );
1990 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
1992 actor->OffStageSignal().Connect( tracker, functor );
1994 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
1996 actor->OnRelayoutSignal().Connect( tracker, functor );
1998 else if( 0 == signalName.compare( SIGNAL_TOUCH ) )
2000 actor->TouchSignal().Connect( tracker, functor );
2002 else if( 0 == signalName.compare( SIGNAL_VISIBILITY_CHANGED ) )
2004 actor->VisibilityChangedSignal().Connect( tracker, functor );
2006 else if( 0 == signalName.compare( SIGNAL_LAYOUT_DIRECTION_CHANGED ) )
2008 actor->LayoutDirectionChangedSignal().Connect( tracker, functor );
2010 else if( 0 == signalName.compare( SIGNAL_CHILD_ADDED ) )
2012 actor->ChildAddedSignal().Connect( tracker, functor );
2014 else if( 0 == signalName.compare( SIGNAL_CHILD_REMOVED ) )
2016 actor->ChildRemovedSignal().Connect( tracker, functor );
2020 // signalName does not match any signal
2027 Actor::Actor( DerivedType derivedType, const SceneGraph::Node& node )
2032 mParentOrigin( NULL ),
2033 mAnchorPoint( NULL ),
2034 mRelayoutData( NULL ),
2035 mGestureData( NULL ),
2039 mWheelEventSignal(),
2042 mOnRelayoutSignal(),
2043 mVisibilityChangedSignal(),
2044 mLayoutDirectionChangedSignal(),
2045 mChildAddedSignal(),
2046 mChildRemovedSignal(),
2047 mChildOrderChangedSignal(),
2048 mTargetOrientation( Quaternion::IDENTITY ),
2049 mTargetColor( Color::WHITE ),
2050 mTargetSize( Vector3::ZERO ),
2051 mTargetPosition( Vector3::ZERO ),
2052 mTargetScale( Vector3::ONE ),
2056 mIsRoot( ROOT_LAYER == derivedType ),
2057 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2058 mIsOnStage( false ),
2060 mLeaveRequired( false ),
2061 mKeyboardFocusable( false ),
2062 mDerivedRequiresTouch( false ),
2063 mDerivedRequiresHover( false ),
2064 mDerivedRequiresWheelEvent( false ),
2065 mOnStageSignalled( false ),
2066 mInsideOnSizeSet( false ),
2067 mInheritPosition( true ),
2068 mInheritOrientation( true ),
2069 mInheritScale( true ),
2070 mPositionUsesAnchorPoint( true ),
2072 mInheritLayoutDirection( true ),
2073 mLayoutDirection( LayoutDirection::LEFT_TO_RIGHT ),
2074 mDrawMode( DrawMode::NORMAL ),
2075 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2076 mColorMode( Node::DEFAULT_COLOR_MODE ),
2077 mClippingMode( ClippingMode::DISABLED )
2081 void Actor::Initialize()
2085 GetEventThreadServices().RegisterObject( this );
2090 // Remove mParent pointers from children even if we're destroying core,
2091 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2094 ActorConstIter endIter = mChildren->end();
2095 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2097 (*iter)->SetParent( NULL );
2103 // Guard to allow handle destruction after Core has been destroyed
2104 if( EventThreadServices::IsCoreRunning() )
2106 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
2108 GetEventThreadServices().UnregisterObject( this );
2111 // Cleanup optional gesture data
2112 delete mGestureData;
2114 // Cleanup optional parent origin and anchor
2115 delete mParentOrigin;
2116 delete mAnchorPoint;
2118 // Delete optional relayout data
2119 delete mRelayoutData;
2122 void Actor::ConnectToStage( uint32_t parentDepth )
2124 // This container is used instead of walking the Actor hierarchy.
2125 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
2126 ActorContainer connectionList;
2128 StagePtr stage = Stage::GetCurrent();
2131 stage->RequestRebuildDepthTree();
2134 // This stage is atomic i.e. not interrupted by user callbacks.
2135 RecursiveConnectToStage( connectionList, parentDepth + 1 );
2137 // Notify applications about the newly connected actors.
2138 const ActorIter endIter = connectionList.end();
2139 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2141 (*iter)->NotifyStageConnection();
2147 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, uint32_t depth )
2149 DALI_ASSERT_ALWAYS( !OnStage() );
2152 mDepth = static_cast< uint16_t >( depth ); // overflow ignored, not expected in practice
2154 ConnectToSceneGraph();
2156 // Notification for internal derived classes
2157 OnStageConnectionInternal();
2159 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2160 connectionList.push_back( ActorPtr( this ) );
2162 // Recursively connect children
2165 ActorConstIter endIter = mChildren->end();
2166 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2168 (*iter)->RecursiveConnectToStage( connectionList, depth + 1 );
2174 * This method is called when the Actor is connected to the Stage.
2175 * The parent must have added its Node to the scene-graph.
2176 * The child must connect its Node to the parent's Node.
2177 * This is recursive; the child calls ConnectToStage() for its children.
2179 void Actor::ConnectToSceneGraph()
2181 DALI_ASSERT_DEBUG( mParent != NULL);
2183 // Reparent Node in next Update
2184 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), mParent->GetNode(), GetNode() );
2186 // Request relayout on all actors that are added to the scenegraph
2189 // Notification for Object::Observers
2193 void Actor::NotifyStageConnection()
2195 // Actors can be removed (in a callback), before the on-stage stage is reported.
2196 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2197 if( OnStage() && !mOnStageSignalled )
2199 // Notification for external (CustomActor) derived classes
2200 OnStageConnectionExternal( mDepth );
2202 if( !mOnStageSignal.Empty() )
2204 Dali::Actor handle( this );
2205 mOnStageSignal.Emit( handle );
2208 // Guard against Remove during callbacks
2211 mOnStageSignalled = true; // signal required next time Actor is removed
2216 void Actor::DisconnectFromStage()
2218 // This container is used instead of walking the Actor hierachy.
2219 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2220 ActorContainer disconnectionList;
2222 StagePtr stage = Stage::GetCurrent();
2225 stage->RequestRebuildDepthTree();
2228 // This stage is atomic i.e. not interrupted by user callbacks
2229 RecursiveDisconnectFromStage( disconnectionList );
2231 // Notify applications about the newly disconnected actors.
2232 const ActorIter endIter = disconnectionList.end();
2233 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2235 (*iter)->NotifyStageDisconnection();
2239 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2241 // need to change state first so that internals relying on IsOnStage() inside OnStageDisconnectionInternal() get the correct value
2244 // Recursively disconnect children
2247 ActorConstIter endIter = mChildren->end();
2248 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2250 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2254 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2255 disconnectionList.push_back( ActorPtr( this ) );
2257 // Notification for internal derived classes
2258 OnStageDisconnectionInternal();
2260 DisconnectFromSceneGraph();
2264 * This method is called by an actor or its parent, before a node removal message is sent.
2265 * This is recursive; the child calls DisconnectFromStage() for its children.
2267 void Actor::DisconnectFromSceneGraph()
2269 // Notification for Object::Observers
2270 OnSceneObjectRemove();
2273 void Actor::NotifyStageDisconnection()
2275 // Actors can be added (in a callback), before the off-stage state is reported.
2276 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2277 // only do this step if there is a stage, i.e. Core is not being shut down
2278 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2280 // Notification for external (CustomeActor) derived classes
2281 OnStageDisconnectionExternal();
2283 if( !mOffStageSignal.Empty() )
2285 Dali::Actor handle( this );
2286 mOffStageSignal.Emit( handle );
2289 // Guard against Add during callbacks
2292 mOnStageSignalled = false; // signal required next time Actor is added
2297 bool Actor::IsNodeConnected() const
2299 bool connected( false );
2303 if( IsRoot() || GetNode().GetParent() )
2312 // This method initiates traversal of the actor tree using depth-first
2313 // traversal to set a depth index based on traversal order. It sends a
2314 // single message to update manager to update all the actor's nodes in
2315 // this tree with the depth index. The sceneGraphNodeDepths vector's
2316 // elements are ordered by depth, and could be used to reduce sorting
2317 // in the update thread.
2318 void Actor::RebuildDepthTree()
2320 DALI_LOG_TIMER_START(depthTimer);
2322 // Vector of scene-graph nodes and their depths to send to UpdateManager
2323 // in a single message
2324 OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths( new SceneGraph::NodeDepths() );
2326 int32_t depthIndex = 1;
2327 DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
2329 SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths );
2330 DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
2333 void Actor::DepthTraverseActorTree( OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths, int32_t& depthIndex )
2335 mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
2336 sceneGraphNodeDepths->Add( const_cast<SceneGraph::Node*>( &GetNode() ), mSortedDepth );
2338 // Create/add to children of this node
2341 for( ActorContainer::iterator it = mChildren->begin(); it != mChildren->end(); ++it )
2343 Actor* childActor = (*it).Get();
2345 childActor->DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
2350 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2354 case Dali::Actor::Property::PARENT_ORIGIN:
2356 Property::Type type = property.GetType();
2357 if( type == Property::VECTOR3 )
2359 SetParentOrigin( property.Get< Vector3 >() );
2361 else if ( type == Property::STRING )
2363 std::string parentOriginString;
2364 property.Get( parentOriginString );
2365 Vector3 parentOrigin;
2366 if( GetParentOriginConstant( parentOriginString, parentOrigin ) )
2368 SetParentOrigin( parentOrigin );
2374 case Dali::Actor::Property::PARENT_ORIGIN_X:
2376 SetParentOriginX( property.Get< float >() );
2380 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2382 SetParentOriginY( property.Get< float >() );
2386 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2388 SetParentOriginZ( property.Get< float >() );
2392 case Dali::Actor::Property::ANCHOR_POINT:
2394 Property::Type type = property.GetType();
2395 if( type == Property::VECTOR3 )
2397 SetAnchorPoint( property.Get< Vector3 >() );
2399 else if ( type == Property::STRING )
2401 std::string anchorPointString;
2402 property.Get( anchorPointString );
2404 if( GetAnchorPointConstant( anchorPointString, anchor ) )
2406 SetAnchorPoint( anchor );
2412 case Dali::Actor::Property::ANCHOR_POINT_X:
2414 SetAnchorPointX( property.Get< float >() );
2418 case Dali::Actor::Property::ANCHOR_POINT_Y:
2420 SetAnchorPointY( property.Get< float >() );
2424 case Dali::Actor::Property::ANCHOR_POINT_Z:
2426 SetAnchorPointZ( property.Get< float >() );
2430 case Dali::Actor::Property::SIZE:
2432 SetSize( property.Get< Vector3 >() );
2436 case Dali::Actor::Property::SIZE_WIDTH:
2438 SetWidth( property.Get< float >() );
2442 case Dali::Actor::Property::SIZE_HEIGHT:
2444 SetHeight( property.Get< float >() );
2448 case Dali::Actor::Property::SIZE_DEPTH:
2450 SetDepth( property.Get< float >() );
2454 case Dali::Actor::Property::POSITION:
2456 SetPosition( property.Get< Vector3 >() );
2460 case Dali::Actor::Property::POSITION_X:
2462 SetX( property.Get< float >() );
2466 case Dali::Actor::Property::POSITION_Y:
2468 SetY( property.Get< float >() );
2472 case Dali::Actor::Property::POSITION_Z:
2474 SetZ( property.Get< float >() );
2478 case Dali::Actor::Property::ORIENTATION:
2480 SetOrientation( property.Get< Quaternion >() );
2484 case Dali::Actor::Property::SCALE:
2486 SetScale( property.Get< Vector3 >() );
2490 case Dali::Actor::Property::SCALE_X:
2492 SetScaleX( property.Get< float >() );
2496 case Dali::Actor::Property::SCALE_Y:
2498 SetScaleY( property.Get< float >() );
2502 case Dali::Actor::Property::SCALE_Z:
2504 SetScaleZ( property.Get< float >() );
2508 case Dali::Actor::Property::VISIBLE:
2510 SetVisible( property.Get< bool >() );
2514 case Dali::Actor::Property::COLOR:
2516 SetColor( property.Get< Vector4 >() );
2520 case Dali::Actor::Property::COLOR_RED:
2522 SetColorRed( property.Get< float >() );
2526 case Dali::Actor::Property::COLOR_GREEN:
2528 SetColorGreen( property.Get< float >() );
2532 case Dali::Actor::Property::COLOR_BLUE:
2534 SetColorBlue( property.Get< float >() );
2538 case Dali::Actor::Property::COLOR_ALPHA:
2539 case Dali::DevelActor::Property::OPACITY:
2542 if( property.Get( value ) )
2544 SetOpacity( value );
2549 case Dali::Actor::Property::NAME:
2551 SetName( property.Get< std::string >() );
2555 case Dali::Actor::Property::SENSITIVE:
2557 SetSensitive( property.Get< bool >() );
2561 case Dali::Actor::Property::LEAVE_REQUIRED:
2563 SetLeaveRequired( property.Get< bool >() );
2567 case Dali::Actor::Property::INHERIT_POSITION:
2569 SetInheritPosition( property.Get< bool >() );
2573 case Dali::Actor::Property::INHERIT_ORIENTATION:
2575 SetInheritOrientation( property.Get< bool >() );
2579 case Dali::Actor::Property::INHERIT_SCALE:
2581 SetInheritScale( property.Get< bool >() );
2585 case Dali::Actor::Property::COLOR_MODE:
2587 ColorMode mode = mColorMode;
2588 if ( Scripting::GetEnumerationProperty< ColorMode >( property, COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT, mode ) )
2590 SetColorMode( mode );
2595 case Dali::Actor::Property::POSITION_INHERITANCE:
2597 PositionInheritanceMode mode = mPositionInheritanceMode;
2598 if( Scripting::GetEnumerationProperty< PositionInheritanceMode >( property, POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT, mode ) )
2600 SetPositionInheritanceMode( mode );
2605 case Dali::Actor::Property::DRAW_MODE:
2607 DrawMode::Type mode = mDrawMode;
2608 if( Scripting::GetEnumerationProperty< DrawMode::Type >( property, DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT, mode ) )
2610 SetDrawMode( mode );
2615 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2617 SetSizeModeFactor( property.Get< Vector3 >() );
2621 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2623 ResizePolicy::Type type = GetResizePolicy( Dimension::WIDTH );
2624 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2626 SetResizePolicy( type, Dimension::WIDTH );
2631 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2633 ResizePolicy::Type type = GetResizePolicy( Dimension::HEIGHT );
2634 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2636 SetResizePolicy( type, Dimension::HEIGHT );
2641 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2643 SizeScalePolicy::Type type = GetSizeScalePolicy();
2644 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT, type ) )
2646 SetSizeScalePolicy( type );
2651 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2653 if( property.Get< bool >() )
2655 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2660 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2662 if( property.Get< bool >() )
2664 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2669 case Dali::Actor::Property::PADDING:
2671 Vector4 padding = property.Get< Vector4 >();
2672 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2673 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2677 case Dali::Actor::Property::MINIMUM_SIZE:
2679 Vector2 size = property.Get< Vector2 >();
2680 SetMinimumSize( size.x, Dimension::WIDTH );
2681 SetMinimumSize( size.y, Dimension::HEIGHT );
2685 case Dali::Actor::Property::MAXIMUM_SIZE:
2687 Vector2 size = property.Get< Vector2 >();
2688 SetMaximumSize( size.x, Dimension::WIDTH );
2689 SetMaximumSize( size.y, Dimension::HEIGHT );
2693 case Dali::DevelActor::Property::SIBLING_ORDER:
2697 if( property.Get( value ) )
2699 SetSiblingOrder( value );
2704 case Dali::Actor::Property::CLIPPING_MODE:
2706 ClippingMode::Type convertedValue = mClippingMode;
2707 if( Scripting::GetEnumerationProperty< ClippingMode::Type >( property, CLIPPING_MODE_TABLE, CLIPPING_MODE_TABLE_COUNT, convertedValue ) )
2709 mClippingMode = convertedValue;
2710 SetClippingModeMessage( GetEventThreadServices(), GetNode(), mClippingMode );
2715 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
2718 if( property.Get( value ) && value != mPositionUsesAnchorPoint )
2720 mPositionUsesAnchorPoint = value;
2721 SetPositionUsesAnchorPointMessage( GetEventThreadServices(), GetNode(), mPositionUsesAnchorPoint );
2726 case Dali::Actor::Property::LAYOUT_DIRECTION:
2728 Dali::LayoutDirection::Type direction = mLayoutDirection;
2729 mInheritLayoutDirection = false;
2731 if( Scripting::GetEnumerationProperty< LayoutDirection::Type >( property, LAYOUT_DIRECTION_TABLE, LAYOUT_DIRECTION_TABLE_COUNT, direction ) )
2733 InheritLayoutDirectionRecursively( this, direction, true );
2738 case Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION:
2741 if( property.Get( value ) )
2743 SetInheritLayoutDirection( value );
2750 // this can happen in the case of a non-animatable default property so just do nothing
2756 // TODO: This method needs to be removed
2757 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2759 switch( entry.GetType() )
2761 case Property::BOOLEAN:
2763 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2764 DALI_ASSERT_DEBUG( NULL != property );
2766 // property is being used in a separate thread; queue a message to set the property
2767 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2772 case Property::INTEGER:
2774 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2775 DALI_ASSERT_DEBUG( NULL != property );
2777 // property is being used in a separate thread; queue a message to set the property
2778 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2783 case Property::FLOAT:
2785 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2786 DALI_ASSERT_DEBUG( NULL != property );
2788 // property is being used in a separate thread; queue a message to set the property
2789 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2794 case Property::VECTOR2:
2796 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2797 DALI_ASSERT_DEBUG( NULL != property );
2799 // property is being used in a separate thread; queue a message to set the property
2800 if(entry.componentIndex == 0)
2802 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2804 else if(entry.componentIndex == 1)
2806 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2810 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2816 case Property::VECTOR3:
2818 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2819 DALI_ASSERT_DEBUG( NULL != property );
2821 // property is being used in a separate thread; queue a message to set the property
2822 if(entry.componentIndex == 0)
2824 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2826 else if(entry.componentIndex == 1)
2828 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2830 else if(entry.componentIndex == 2)
2832 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2836 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2842 case Property::VECTOR4:
2844 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2845 DALI_ASSERT_DEBUG( NULL != property );
2847 // property is being used in a separate thread; queue a message to set the property
2848 if(entry.componentIndex == 0)
2850 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
2852 else if(entry.componentIndex == 1)
2854 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
2856 else if(entry.componentIndex == 2)
2858 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
2860 else if(entry.componentIndex == 3)
2862 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
2866 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2872 case Property::ROTATION:
2874 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
2875 DALI_ASSERT_DEBUG( NULL != property );
2877 // property is being used in a separate thread; queue a message to set the property
2878 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
2883 case Property::MATRIX:
2885 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
2886 DALI_ASSERT_DEBUG( NULL != property );
2888 // property is being used in a separate thread; queue a message to set the property
2889 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), &GetNode(), property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
2894 case Property::MATRIX3:
2896 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
2897 DALI_ASSERT_DEBUG( NULL != property );
2899 // property is being used in a separate thread; queue a message to set the property
2900 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), &GetNode(), property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
2907 // nothing to do for other types
2912 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
2914 Property::Value value;
2916 if( ! GetCachedPropertyValue( index, value ) )
2918 // If property value is not stored in the event-side, then it must be a scene-graph only property
2919 GetCurrentPropertyValue( index, value );
2925 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
2927 Property::Value value;
2929 if( ! GetCurrentPropertyValue( index, value ) )
2931 // If unable to retrieve scene-graph property value, then it must be an event-side only property
2932 GetCachedPropertyValue( index, value );
2938 void Actor::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
2940 switch( animationType )
2943 case Animation::BETWEEN:
2947 case Dali::Actor::Property::SIZE:
2949 if( value.Get( mTargetSize ) )
2951 // Notify deriving classes
2952 OnSizeAnimation( animation, mTargetSize );
2957 case Dali::Actor::Property::SIZE_WIDTH:
2959 if( value.Get( mTargetSize.width ) )
2961 // Notify deriving classes
2962 OnSizeAnimation( animation, mTargetSize );
2967 case Dali::Actor::Property::SIZE_HEIGHT:
2969 if( value.Get( mTargetSize.height ) )
2971 // Notify deriving classes
2972 OnSizeAnimation( animation, mTargetSize );
2977 case Dali::Actor::Property::SIZE_DEPTH:
2979 if( value.Get( mTargetSize.depth ) )
2981 // Notify deriving classes
2982 OnSizeAnimation( animation, mTargetSize );
2987 case Dali::Actor::Property::POSITION:
2989 value.Get( mTargetPosition );
2993 case Dali::Actor::Property::POSITION_X:
2995 value.Get( mTargetPosition.x );
2999 case Dali::Actor::Property::POSITION_Y:
3001 value.Get( mTargetPosition.y );
3005 case Dali::Actor::Property::POSITION_Z:
3007 value.Get( mTargetPosition.z );
3011 case Dali::Actor::Property::ORIENTATION:
3013 value.Get( mTargetOrientation );
3017 case Dali::Actor::Property::SCALE:
3019 value.Get( mTargetScale );
3023 case Dali::Actor::Property::SCALE_X:
3025 value.Get( mTargetScale.x );
3029 case Dali::Actor::Property::SCALE_Y:
3031 value.Get( mTargetScale.y );
3035 case Dali::Actor::Property::SCALE_Z:
3037 value.Get( mTargetScale.z );
3041 case Dali::Actor::Property::VISIBLE:
3043 SetVisibleInternal( value.Get< bool >(), SendMessage::FALSE );
3047 case Dali::Actor::Property::COLOR:
3049 value.Get( mTargetColor );
3053 case Dali::Actor::Property::COLOR_RED:
3055 value.Get( mTargetColor.r );
3059 case Dali::Actor::Property::COLOR_GREEN:
3061 value.Get( mTargetColor.g );
3065 case Dali::Actor::Property::COLOR_BLUE:
3067 value.Get( mTargetColor.b );
3071 case Dali::Actor::Property::COLOR_ALPHA:
3072 case Dali::DevelActor::Property::OPACITY:
3074 value.Get( mTargetColor.a );
3080 // Not an animatable property. Do nothing.
3091 case Dali::Actor::Property::SIZE:
3093 if( AdjustValue< Vector3 >( mTargetSize, value ) )
3095 // Notify deriving classes
3096 OnSizeAnimation( animation, mTargetSize );
3101 case Dali::Actor::Property::SIZE_WIDTH:
3103 if( AdjustValue< float >( mTargetSize.width, value ) )
3105 // Notify deriving classes
3106 OnSizeAnimation( animation, mTargetSize );
3111 case Dali::Actor::Property::SIZE_HEIGHT:
3113 if( AdjustValue< float >( mTargetSize.height, value ) )
3115 // Notify deriving classes
3116 OnSizeAnimation( animation, mTargetSize );
3121 case Dali::Actor::Property::SIZE_DEPTH:
3123 if( AdjustValue< float >( mTargetSize.depth, value ) )
3125 // Notify deriving classes
3126 OnSizeAnimation( animation, mTargetSize );
3131 case Dali::Actor::Property::POSITION:
3133 AdjustValue< Vector3 >( mTargetPosition, value );
3137 case Dali::Actor::Property::POSITION_X:
3139 AdjustValue< float >( mTargetPosition.x, value );
3143 case Dali::Actor::Property::POSITION_Y:
3145 AdjustValue< float >( mTargetPosition.y, value );
3149 case Dali::Actor::Property::POSITION_Z:
3151 AdjustValue< float >( mTargetPosition.z, value );
3155 case Dali::Actor::Property::ORIENTATION:
3157 Quaternion relativeValue;
3158 if( value.Get( relativeValue ) )
3160 mTargetOrientation *= relativeValue;
3165 case Dali::Actor::Property::SCALE:
3167 AdjustValue< Vector3 >( mTargetScale, value );
3171 case Dali::Actor::Property::SCALE_X:
3173 AdjustValue< float >( mTargetScale.x, value );
3177 case Dali::Actor::Property::SCALE_Y:
3179 AdjustValue< float >( mTargetScale.y, value );
3183 case Dali::Actor::Property::SCALE_Z:
3185 AdjustValue< float >( mTargetScale.z, value );
3189 case Dali::Actor::Property::VISIBLE:
3191 bool relativeValue = false;
3192 if( value.Get( relativeValue ) )
3194 bool visible = mVisible || relativeValue;
3195 SetVisibleInternal( visible, SendMessage::FALSE );
3200 case Dali::Actor::Property::COLOR:
3202 AdjustValue< Vector4 >( mTargetColor, value );
3206 case Dali::Actor::Property::COLOR_RED:
3208 AdjustValue< float >( mTargetColor.r, value );
3212 case Dali::Actor::Property::COLOR_GREEN:
3214 AdjustValue< float >( mTargetColor.g, value );
3218 case Dali::Actor::Property::COLOR_BLUE:
3220 AdjustValue< float >( mTargetColor.b, value );
3224 case Dali::Actor::Property::COLOR_ALPHA:
3225 case Dali::DevelActor::Property::OPACITY:
3227 AdjustValue< float >( mTargetColor.a, value );
3233 // Not an animatable property. Do nothing.
3242 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3244 const PropertyBase* property( NULL );
3248 case Dali::Actor::Property::SIZE: // FALLTHROUGH
3249 case Dali::Actor::Property::SIZE_WIDTH: // FALLTHROUGH
3250 case Dali::Actor::Property::SIZE_HEIGHT: // FALLTHROUGH
3251 case Dali::Actor::Property::SIZE_DEPTH:
3253 property = &GetNode().mSize;
3256 case Dali::Actor::Property::POSITION: // FALLTHROUGH
3257 case Dali::Actor::Property::POSITION_X: // FALLTHROUGH
3258 case Dali::Actor::Property::POSITION_Y: // FALLTHROUGH
3259 case Dali::Actor::Property::POSITION_Z:
3261 property = &GetNode().mPosition;
3264 case Dali::Actor::Property::ORIENTATION:
3266 property = &GetNode().mOrientation;
3269 case Dali::Actor::Property::SCALE: // FALLTHROUGH
3270 case Dali::Actor::Property::SCALE_X: // FALLTHROUGH
3271 case Dali::Actor::Property::SCALE_Y: // FALLTHROUGH
3272 case Dali::Actor::Property::SCALE_Z:
3274 property = &GetNode().mScale;
3277 case Dali::Actor::Property::VISIBLE:
3279 property = &GetNode().mVisible;
3282 case Dali::Actor::Property::COLOR: // FALLTHROUGH
3283 case Dali::Actor::Property::COLOR_RED: // FALLTHROUGH
3284 case Dali::Actor::Property::COLOR_GREEN: // FALLTHROUGH
3285 case Dali::Actor::Property::COLOR_BLUE: // FALLTHROUGH
3286 case Dali::Actor::Property::COLOR_ALPHA: // FALLTHROUGH
3287 case Dali::DevelActor::Property::OPACITY:
3289 property = &GetNode().mColor;
3299 // not our property, ask base
3300 property = Object::GetSceneObjectAnimatableProperty( index );
3306 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3308 const PropertyInputImpl* property( NULL );
3312 case Dali::Actor::Property::PARENT_ORIGIN: // FALLTHROUGH
3313 case Dali::Actor::Property::PARENT_ORIGIN_X: // FALLTHROUGH
3314 case Dali::Actor::Property::PARENT_ORIGIN_Y: // FALLTHROUGH
3315 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3317 property = &GetNode().mParentOrigin;
3320 case Dali::Actor::Property::ANCHOR_POINT: // FALLTHROUGH
3321 case Dali::Actor::Property::ANCHOR_POINT_X: // FALLTHROUGH
3322 case Dali::Actor::Property::ANCHOR_POINT_Y: // FALLTHROUGH
3323 case Dali::Actor::Property::ANCHOR_POINT_Z:
3325 property = &GetNode().mAnchorPoint;
3328 case Dali::Actor::Property::WORLD_POSITION: // FALLTHROUGH
3329 case Dali::Actor::Property::WORLD_POSITION_X: // FALLTHROUGH
3330 case Dali::Actor::Property::WORLD_POSITION_Y: // FALLTHROUGH
3331 case Dali::Actor::Property::WORLD_POSITION_Z:
3333 property = &GetNode().mWorldPosition;
3336 case Dali::Actor::Property::WORLD_ORIENTATION:
3338 property = &GetNode().mWorldOrientation;
3341 case Dali::Actor::Property::WORLD_SCALE:
3343 property = &GetNode().mWorldScale;
3346 case Dali::Actor::Property::WORLD_COLOR:
3348 property = &GetNode().mWorldColor;
3351 case Dali::Actor::Property::WORLD_MATRIX:
3353 property = &GetNode().mWorldMatrix;
3356 case Dali::DevelActor::Property::CULLED:
3358 property = &GetNode().mCulled;
3368 // reuse animatable property getter as animatable properties are inputs as well
3369 // animatable property chains back to Object::GetSceneObjectInputProperty() so all properties get covered
3370 property = GetSceneObjectAnimatableProperty( index );
3376 int32_t Actor::GetPropertyComponentIndex( Property::Index index ) const
3378 int32_t componentIndex = Property::INVALID_COMPONENT_INDEX;
3382 case Dali::Actor::Property::PARENT_ORIGIN_X:
3383 case Dali::Actor::Property::ANCHOR_POINT_X:
3384 case Dali::Actor::Property::SIZE_WIDTH:
3385 case Dali::Actor::Property::POSITION_X:
3386 case Dali::Actor::Property::WORLD_POSITION_X:
3387 case Dali::Actor::Property::SCALE_X:
3388 case Dali::Actor::Property::COLOR_RED:
3394 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3395 case Dali::Actor::Property::ANCHOR_POINT_Y:
3396 case Dali::Actor::Property::SIZE_HEIGHT:
3397 case Dali::Actor::Property::POSITION_Y:
3398 case Dali::Actor::Property::WORLD_POSITION_Y:
3399 case Dali::Actor::Property::SCALE_Y:
3400 case Dali::Actor::Property::COLOR_GREEN:
3406 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3407 case Dali::Actor::Property::ANCHOR_POINT_Z:
3408 case Dali::Actor::Property::SIZE_DEPTH:
3409 case Dali::Actor::Property::POSITION_Z:
3410 case Dali::Actor::Property::WORLD_POSITION_Z:
3411 case Dali::Actor::Property::SCALE_Z:
3412 case Dali::Actor::Property::COLOR_BLUE:
3418 case Dali::Actor::Property::COLOR_ALPHA:
3419 case Dali::DevelActor::Property::OPACITY:
3431 if( Property::INVALID_COMPONENT_INDEX == componentIndex )
3434 componentIndex = Object::GetPropertyComponentIndex( index );
3437 return componentIndex;
3440 void Actor::SetParent( Actor* parent )
3444 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3448 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3451 // Instruct each actor to create a corresponding node in the scene graph
3452 ConnectToStage( parent->GetHierarchyDepth() );
3455 // Resolve the name and index for the child properties if any
3456 ResolveChildProperties();
3458 else // parent being set to NULL
3460 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3464 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3467 // Disconnect the Node & its children from the scene-graph.
3468 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
3470 // Instruct each actor to discard pointers to the scene-graph
3471 DisconnectFromStage();
3476 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3479 Actor* actor = dynamic_cast< Actor* >( object );
3483 if( 0 == actionName.compare( ACTION_SHOW ) )
3485 actor->SetVisible( true );
3488 else if( 0 == actionName.compare( ACTION_HIDE ) )
3490 actor->SetVisible( false );
3498 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
3500 bool valueSet = true;
3504 case Dali::Actor::Property::PARENT_ORIGIN:
3506 value = GetCurrentParentOrigin();
3510 case Dali::Actor::Property::PARENT_ORIGIN_X:
3512 value = GetCurrentParentOrigin().x;
3516 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3518 value = GetCurrentParentOrigin().y;
3522 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3524 value = GetCurrentParentOrigin().z;
3528 case Dali::Actor::Property::ANCHOR_POINT:
3530 value = GetCurrentAnchorPoint();
3534 case Dali::Actor::Property::ANCHOR_POINT_X:
3536 value = GetCurrentAnchorPoint().x;
3540 case Dali::Actor::Property::ANCHOR_POINT_Y:
3542 value = GetCurrentAnchorPoint().y;
3546 case Dali::Actor::Property::ANCHOR_POINT_Z:
3548 value = GetCurrentAnchorPoint().z;
3552 case Dali::Actor::Property::SIZE:
3554 value = GetTargetSize();
3558 case Dali::Actor::Property::SIZE_WIDTH:
3560 value = GetTargetSize().width;
3564 case Dali::Actor::Property::SIZE_HEIGHT:
3566 value = GetTargetSize().height;
3570 case Dali::Actor::Property::SIZE_DEPTH:
3572 value = GetTargetSize().depth;
3576 case Dali::Actor::Property::POSITION:
3578 value = GetTargetPosition();
3582 case Dali::Actor::Property::POSITION_X:
3584 value = GetTargetPosition().x;
3588 case Dali::Actor::Property::POSITION_Y:
3590 value = GetTargetPosition().y;
3594 case Dali::Actor::Property::POSITION_Z:
3596 value = GetTargetPosition().z;
3600 case Dali::Actor::Property::ORIENTATION:
3602 value = mTargetOrientation;
3606 case Dali::Actor::Property::SCALE:
3608 value = mTargetScale;
3612 case Dali::Actor::Property::SCALE_X:
3614 value = mTargetScale.x;
3618 case Dali::Actor::Property::SCALE_Y:
3620 value = mTargetScale.y;
3624 case Dali::Actor::Property::SCALE_Z:
3626 value = mTargetScale.z;
3630 case Dali::Actor::Property::VISIBLE:
3636 case Dali::Actor::Property::COLOR:
3638 value = mTargetColor;
3642 case Dali::Actor::Property::COLOR_RED:
3644 value = mTargetColor.r;
3648 case Dali::Actor::Property::COLOR_GREEN:
3650 value = mTargetColor.g;
3654 case Dali::Actor::Property::COLOR_BLUE:
3656 value = mTargetColor.b;
3660 case Dali::Actor::Property::COLOR_ALPHA:
3661 case Dali::DevelActor::Property::OPACITY:
3663 value = mTargetColor.a;
3667 case Dali::Actor::Property::NAME:
3673 case Dali::Actor::Property::SENSITIVE:
3675 value = IsSensitive();
3679 case Dali::Actor::Property::LEAVE_REQUIRED:
3681 value = GetLeaveRequired();
3685 case Dali::Actor::Property::INHERIT_POSITION:
3687 value = IsPositionInherited();
3691 case Dali::Actor::Property::INHERIT_ORIENTATION:
3693 value = IsOrientationInherited();
3697 case Dali::Actor::Property::INHERIT_SCALE:
3699 value = IsScaleInherited();
3703 case Dali::Actor::Property::COLOR_MODE:
3705 value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
3709 case Dali::Actor::Property::POSITION_INHERITANCE:
3711 value = Scripting::GetLinearEnumerationName< PositionInheritanceMode >( GetPositionInheritanceMode(), POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT );
3715 case Dali::Actor::Property::DRAW_MODE:
3717 value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
3721 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3723 value = GetSizeModeFactor();
3727 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3729 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3733 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3735 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3739 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3741 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT );
3745 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3747 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3751 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3753 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3757 case Dali::Actor::Property::PADDING:
3759 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3760 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3761 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3765 case Dali::Actor::Property::MINIMUM_SIZE:
3767 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3771 case Dali::Actor::Property::MAXIMUM_SIZE:
3773 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3777 case Dali::Actor::Property::CLIPPING_MODE:
3779 value = mClippingMode;
3783 case Dali::DevelActor::Property::SIBLING_ORDER:
3785 value = static_cast<int>( GetSiblingOrder() );
3789 case Dali::DevelActor::Property::SCREEN_POSITION:
3791 value = GetCurrentScreenPosition();
3795 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
3797 value = mPositionUsesAnchorPoint;
3801 case Dali::Actor::Property::LAYOUT_DIRECTION:
3803 value = mLayoutDirection;
3807 case Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION:
3809 value = IsLayoutDirectionInherited();
3815 // Must be a scene-graph only property
3824 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
3826 bool valueSet = true;
3830 case Dali::Actor::Property::SIZE:
3832 value = GetCurrentSize();
3836 case Dali::Actor::Property::SIZE_WIDTH:
3838 value = GetCurrentSize().width;
3842 case Dali::Actor::Property::SIZE_HEIGHT:
3844 value = GetCurrentSize().height;
3848 case Dali::Actor::Property::SIZE_DEPTH:
3850 value = GetCurrentSize().depth;
3854 case Dali::Actor::Property::POSITION:
3856 value = GetCurrentPosition();
3860 case Dali::Actor::Property::POSITION_X:
3862 value = GetCurrentPosition().x;
3866 case Dali::Actor::Property::POSITION_Y:
3868 value = GetCurrentPosition().y;
3872 case Dali::Actor::Property::POSITION_Z:
3874 value = GetCurrentPosition().z;
3878 case Dali::Actor::Property::WORLD_POSITION:
3880 value = GetCurrentWorldPosition();
3884 case Dali::Actor::Property::WORLD_POSITION_X:
3886 value = GetCurrentWorldPosition().x;
3890 case Dali::Actor::Property::WORLD_POSITION_Y:
3892 value = GetCurrentWorldPosition().y;
3896 case Dali::Actor::Property::WORLD_POSITION_Z:
3898 value = GetCurrentWorldPosition().z;
3902 case Dali::Actor::Property::ORIENTATION:
3904 value = GetCurrentOrientation();
3908 case Dali::Actor::Property::WORLD_ORIENTATION:
3910 value = GetCurrentWorldOrientation();
3914 case Dali::Actor::Property::SCALE:
3916 value = GetCurrentScale();
3920 case Dali::Actor::Property::SCALE_X:
3922 value = GetCurrentScale().x;
3926 case Dali::Actor::Property::SCALE_Y:
3928 value = GetCurrentScale().y;
3932 case Dali::Actor::Property::SCALE_Z:
3934 value = GetCurrentScale().z;
3938 case Dali::Actor::Property::WORLD_SCALE:
3940 value = GetCurrentWorldScale();
3944 case Dali::Actor::Property::COLOR:
3946 value = GetCurrentColor();
3950 case Dali::Actor::Property::COLOR_RED:
3952 value = GetCurrentColor().r;
3956 case Dali::Actor::Property::COLOR_GREEN:
3958 value = GetCurrentColor().g;
3962 case Dali::Actor::Property::COLOR_BLUE:
3964 value = GetCurrentColor().b;
3968 case Dali::Actor::Property::COLOR_ALPHA:
3969 case Dali::DevelActor::Property::OPACITY:
3971 value = GetCurrentColor().a;
3975 case Dali::Actor::Property::WORLD_COLOR:
3977 value = GetCurrentWorldColor();
3981 case Dali::Actor::Property::WORLD_MATRIX:
3983 value = GetCurrentWorldMatrix();
3987 case Dali::Actor::Property::VISIBLE:
3989 value = IsVisible();
3993 case DevelActor::Property::CULLED:
3995 value = GetNode().IsCulled( GetEventThreadServices().GetEventBufferIndex() );
4001 // Must be an event-side only property
4010 void Actor::EnsureRelayoutData()
4012 // Assign relayout data.
4013 if( !mRelayoutData )
4015 mRelayoutData = new RelayoutData();
4019 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
4021 // Check if actor is dependent on parent
4022 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4024 if( ( dimension & ( 1 << i ) ) )
4026 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4027 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
4037 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
4039 // Check if actor is dependent on children
4040 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4042 if( ( dimension & ( 1 << i ) ) )
4044 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4045 switch( resizePolicy )
4047 case ResizePolicy::FIT_TO_CHILDREN:
4048 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
4064 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
4066 return Actor::RelayoutDependentOnChildren( dimension );
4069 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
4071 // Check each possible dimension and see if it is dependent on the input one
4072 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4074 if( dimension & ( 1 << i ) )
4076 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
4083 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
4085 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4087 if( dimension & ( 1 << i ) )
4089 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
4094 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
4096 // If more than one dimension is requested, just return the first one found
4097 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4099 if( ( dimension & ( 1 << i ) ) )
4101 return mRelayoutData->negotiatedDimensions[ i ];
4105 return 0.0f; // Default
4108 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
4110 EnsureRelayoutData();
4112 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4114 if( dimension & ( 1 << i ) )
4116 mRelayoutData->dimensionPadding[ i ] = padding;
4121 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4123 if ( mRelayoutData )
4125 // If more than one dimension is requested, just return the first one found
4126 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4128 if( ( dimension & ( 1 << i ) ) )
4130 return mRelayoutData->dimensionPadding[ i ];
4135 return GetDefaultDimensionPadding();
4138 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4140 EnsureRelayoutData();
4142 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4144 if( dimension & ( 1 << i ) )
4146 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4151 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4153 if ( mRelayoutData )
4155 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4157 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4167 float Actor::GetHeightForWidthBase( float width )
4169 float height = 0.0f;
4171 const Vector3 naturalSize = GetNaturalSize();
4172 if( naturalSize.width > 0.0f )
4174 height = naturalSize.height * width / naturalSize.width;
4176 else // we treat 0 as 1:1 aspect ratio
4184 float Actor::GetWidthForHeightBase( float height )
4188 const Vector3 naturalSize = GetNaturalSize();
4189 if( naturalSize.height > 0.0f )
4191 width = naturalSize.width * height / naturalSize.height;
4193 else // we treat 0 as 1:1 aspect ratio
4201 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4203 // Fill to parent, taking size mode factor into account
4204 switch( child.GetResizePolicy( dimension ) )
4206 case ResizePolicy::FILL_TO_PARENT:
4208 return GetLatestSize( dimension );
4211 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4213 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4216 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4218 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4223 return GetLatestSize( dimension );
4228 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4230 // Can be overridden in derived class
4231 return CalculateChildSizeBase( child, dimension );
4234 float Actor::GetHeightForWidth( float width )
4236 // Can be overridden in derived class
4237 return GetHeightForWidthBase( width );
4240 float Actor::GetWidthForHeight( float height )
4242 // Can be overridden in derived class
4243 return GetWidthForHeightBase( height );
4246 float Actor::GetLatestSize( Dimension::Type dimension ) const
4248 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4251 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4253 Vector2 padding = GetPadding( dimension );
4255 return GetLatestSize( dimension ) + padding.x + padding.y;
4258 float Actor::NegotiateFromParent( Dimension::Type dimension )
4260 Actor* parent = GetParent();
4263 Vector2 padding( GetPadding( dimension ) );
4264 Vector2 parentPadding( parent->GetPadding( dimension ) );
4265 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4271 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4273 float maxDimensionPoint = 0.0f;
4275 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4277 ActorPtr child = GetChildAt( i );
4279 if( !child->RelayoutDependentOnParent( dimension ) )
4281 // Calculate the min and max points that the children range across
4282 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
4283 float dimensionSize = child->GetRelayoutSize( dimension );
4284 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4288 return maxDimensionPoint;
4291 float Actor::GetSize( Dimension::Type dimension ) const
4293 return GetDimensionValue( mTargetSize, dimension );
4296 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4298 return GetDimensionValue( GetNaturalSize(), dimension );
4301 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4303 switch( GetResizePolicy( dimension ) )
4305 case ResizePolicy::USE_NATURAL_SIZE:
4307 return GetNaturalSize( dimension );
4310 case ResizePolicy::FIXED:
4312 return GetDimensionValue( GetPreferredSize(), dimension );
4315 case ResizePolicy::USE_ASSIGNED_SIZE:
4317 return GetDimensionValue( maximumSize, dimension );
4320 case ResizePolicy::FILL_TO_PARENT:
4321 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4322 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4324 return NegotiateFromParent( dimension );
4327 case ResizePolicy::FIT_TO_CHILDREN:
4329 return NegotiateFromChildren( dimension );
4332 case ResizePolicy::DIMENSION_DEPENDENCY:
4334 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4337 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4339 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4342 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4344 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4356 return 0.0f; // Default
4359 float Actor::ClampDimension( float size, Dimension::Type dimension )
4361 const float minSize = GetMinimumSize( dimension );
4362 const float maxSize = GetMaximumSize( dimension );
4364 return std::max( minSize, std::min( size, maxSize ) );
4367 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4369 // Check if it needs to be negotiated
4370 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4372 // Check that we havn't gotten into an infinite loop
4373 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4374 bool recursionFound = false;
4375 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4377 if( *it == searchActor )
4379 recursionFound = true;
4384 if( !recursionFound )
4386 // Record the path that we have taken
4387 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4389 // Dimension dependency check
4390 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4392 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4394 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4396 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4400 // Parent dependency check
4401 Actor* parent = GetParent();
4402 if( parent && RelayoutDependentOnParent( dimension ) )
4404 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4407 // Children dependency check
4408 if( RelayoutDependentOnChildren( dimension ) )
4410 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4412 ActorPtr child = GetChildAt( i );
4414 // Only relayout child first if it is not dependent on this actor
4415 if( !child->RelayoutDependentOnParent( dimension ) )
4417 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
4422 // For deriving classes
4423 OnCalculateRelayoutSize( dimension );
4425 // All dependencies checked, calculate the size and set negotiated flag
4426 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4428 SetNegotiatedDimension( newSize, dimension );
4429 SetLayoutNegotiated( true, dimension );
4431 // For deriving classes
4432 OnLayoutNegotiated( newSize, dimension );
4434 // This actor has been successfully processed, pop it off the recursion stack
4435 recursionStack.pop_back();
4439 // TODO: Break infinite loop
4440 SetLayoutNegotiated( true, dimension );
4445 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4447 // Negotiate all dimensions that require it
4448 ActorDimensionStack recursionStack;
4450 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4452 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4455 NegotiateDimension( dimension, allocatedSize, recursionStack );
4459 Vector2 Actor::ApplySizeSetPolicy( const Vector2& size )
4461 switch( mRelayoutData->sizeSetPolicy )
4463 case SizeScalePolicy::USE_SIZE_SET:
4468 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4470 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4471 const Vector3 naturalSize = GetNaturalSize();
4472 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4474 const float sizeRatio = size.width / size.height;
4475 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4477 if( naturalSizeRatio < sizeRatio )
4479 return Vector2( naturalSizeRatio * size.height, size.height );
4481 else if( naturalSizeRatio > sizeRatio )
4483 return Vector2( size.width, size.width / naturalSizeRatio );
4494 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4496 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4497 const Vector3 naturalSize = GetNaturalSize();
4498 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4500 const float sizeRatio = size.width / size.height;
4501 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4503 if( naturalSizeRatio < sizeRatio )
4505 return Vector2( size.width, size.width / naturalSizeRatio );
4507 else if( naturalSizeRatio > sizeRatio )
4509 return Vector2( naturalSizeRatio * size.height, size.height );
4528 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4530 // Do the set actor size
4531 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4533 // Adjust for size set policy
4534 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4536 // Lock the flag to stop recursive relayouts on set size
4537 mRelayoutData->insideRelayout = true;
4538 SetSize( negotiatedSize );
4539 mRelayoutData->insideRelayout = false;
4541 // Clear flags for all dimensions
4542 SetLayoutDirty( false );
4544 // Give deriving classes a chance to respond
4545 OnRelayout( negotiatedSize, container );
4547 if( !mOnRelayoutSignal.Empty() )
4549 Dali::Actor handle( this );
4550 mOnRelayoutSignal.Emit( handle );
4554 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4556 // Force a size negotiation for actors that has assigned size during relayout
4557 // This is required as otherwise the flags that force a relayout will not
4558 // necessarilly be set. This will occur if the actor has already been laid out.
4559 // The dirty flags are then cleared. Then if the actor is added back into the
4560 // relayout container afterwards, the dirty flags would still be clear...
4561 // causing a relayout to be skipped. Here we force any actors added to the
4562 // container to be relayed out.
4563 DALI_LOG_TIMER_START( NegSizeTimer1 );
4565 if( GetUseAssignedSize(Dimension::WIDTH ) )
4567 SetLayoutNegotiated( false, Dimension::WIDTH );
4569 if( GetUseAssignedSize( Dimension::HEIGHT ) )
4571 SetLayoutNegotiated( false, Dimension::HEIGHT );
4574 // Do the negotiation
4575 NegotiateDimensions( allocatedSize );
4577 // Set the actor size
4578 SetNegotiatedSize( container );
4580 // Negotiate down to children
4581 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4583 ActorPtr child = GetChildAt( i );
4585 // Forces children that have already been laid out to be relayed out
4586 // if they have assigned size during relayout.
4587 if( child->GetUseAssignedSize(Dimension::WIDTH) )
4589 child->SetLayoutNegotiated(false, Dimension::WIDTH);
4590 child->SetLayoutDirty(true, Dimension::WIDTH);
4593 if( child->GetUseAssignedSize(Dimension::HEIGHT) )
4595 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
4596 child->SetLayoutDirty(true, Dimension::HEIGHT);
4599 // Only relayout if required
4600 if( child->RelayoutRequired() )
4602 container.Add( Dali::Actor( child.Get() ), mTargetSize.GetVectorXY() );
4605 DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
4608 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
4612 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4614 if( dimension & ( 1 << i ) )
4616 mRelayoutData->useAssignedSize[ i ] = use;
4622 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
4624 if ( mRelayoutData )
4626 // If more than one dimension is requested, just return the first one found
4627 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4629 if( dimension & ( 1 << i ) )
4631 return mRelayoutData->useAssignedSize[ i ];
4639 void Actor::RelayoutRequest( Dimension::Type dimension )
4641 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4642 if( relayoutController )
4644 Dali::Actor self( this );
4645 relayoutController->RequestRelayout( self, dimension );
4649 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4653 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4657 void Actor::SetPreferredSize( const Vector2& size )
4659 EnsureRelayoutData();
4661 if( size.width > 0.0f )
4663 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4666 if( size.height > 0.0f )
4668 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4671 mRelayoutData->preferredSize = size;
4676 Vector2 Actor::GetPreferredSize() const
4678 if ( mRelayoutData )
4680 return Vector2( mRelayoutData->preferredSize );
4683 return GetDefaultPreferredSize();
4686 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4688 EnsureRelayoutData();
4690 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4692 if( dimension & ( 1 << i ) )
4694 mRelayoutData->minimumSize[ i ] = size;
4701 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4703 if ( mRelayoutData )
4705 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4707 if( dimension & ( 1 << i ) )
4709 return mRelayoutData->minimumSize[ i ];
4714 return 0.0f; // Default
4717 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4719 EnsureRelayoutData();
4721 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4723 if( dimension & ( 1 << i ) )
4725 mRelayoutData->maximumSize[ i ] = size;
4732 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4734 if ( mRelayoutData )
4736 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4738 if( dimension & ( 1 << i ) )
4740 return mRelayoutData->maximumSize[ i ];
4745 return FLT_MAX; // Default
4748 Object* Actor::GetParentObject() const
4753 void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
4755 if( mVisible != visible )
4757 if( sendMessage == SendMessage::TRUE )
4759 // node is being used in a separate thread; queue a message to set the value & base value
4760 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible );
4765 // Emit the signal on this actor and all its children
4766 EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
4770 void Actor::SetSiblingOrder( uint32_t order )
4774 ActorContainer& siblings = *(mParent->mChildren);
4775 uint32_t currentOrder = GetSiblingOrder();
4777 if( order != currentOrder )
4783 else if( order < siblings.size() -1 )
4785 if( order > currentOrder )
4787 RaiseAbove( *siblings[order] );
4791 LowerBelow( *siblings[order] );
4802 uint32_t Actor::GetSiblingOrder() const
4808 ActorContainer& siblings = *(mParent->mChildren);
4809 for( std::size_t i = 0; i < siblings.size(); ++i )
4811 if( siblings[i] == this )
4813 order = static_cast<uint32_t>( i );
4822 void Actor::RequestRebuildDepthTree()
4826 StagePtr stage = Stage::GetCurrent();
4829 stage->RequestRebuildDepthTree();
4838 ActorContainer& siblings = *(mParent->mChildren);
4839 if( siblings.back() != this ) // If not already at end
4841 for( std::size_t i=0; i<siblings.size(); ++i )
4843 if( siblings[i] == this )
4846 ActorPtr next = siblings[i+1];
4847 siblings[i+1] = this;
4854 Dali::Actor handle( this );
4855 mParent->mChildOrderChangedSignal.Emit( handle );
4857 RequestRebuildDepthTree();
4861 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4869 ActorContainer& siblings = *(mParent->mChildren);
4870 if( siblings.front() != this ) // If not already at beginning
4872 for( std::size_t i=1; i<siblings.size(); ++i )
4874 if( siblings[i] == this )
4876 // Swap with previous
4877 ActorPtr previous = siblings[i-1];
4878 siblings[i-1] = this;
4879 siblings[i] = previous;
4885 Dali::Actor handle( this );
4886 mParent->mChildOrderChangedSignal.Emit( handle );
4888 RequestRebuildDepthTree();
4892 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4896 void Actor::RaiseToTop()
4900 ActorContainer& siblings = *(mParent->mChildren);
4901 if( siblings.back() != this ) // If not already at end
4903 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
4904 if( iter != siblings.end() )
4906 siblings.erase(iter);
4907 siblings.push_back(ActorPtr(this));
4911 Dali::Actor handle( this );
4912 mParent->mChildOrderChangedSignal.Emit( handle );
4914 RequestRebuildDepthTree();
4918 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4922 void Actor::LowerToBottom()
4926 ActorContainer& siblings = *(mParent->mChildren);
4927 if( siblings.front() != this ) // If not already at bottom,
4929 ActorPtr thisPtr(this); // ensure this actor remains referenced.
4931 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
4932 if( iter != siblings.end() )
4934 siblings.erase(iter);
4935 siblings.insert(siblings.begin(), thisPtr);
4939 Dali::Actor handle( this );
4940 mParent->mChildOrderChangedSignal.Emit( handle );
4942 RequestRebuildDepthTree();
4946 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4950 void Actor::RaiseAbove( Internal::Actor& target )
4954 ActorContainer& siblings = *(mParent->mChildren);
4955 if( siblings.back() != this && target.mParent == mParent ) // If not already at top
4957 ActorPtr thisPtr(this); // ensure this actor remains referenced.
4959 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
4960 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
4961 if( thisIter < targetIter )
4963 siblings.erase(thisIter);
4964 // Erasing early invalidates the targetIter. (Conversely, inserting first may also
4965 // invalidate thisIter)
4966 targetIter = std::find( siblings.begin(), siblings.end(), &target );
4968 siblings.insert(targetIter, thisPtr);
4971 Dali::Actor handle( this );
4972 mParent->mChildOrderChangedSignal.Emit( handle );
4974 RequestRebuildDepthTree();
4979 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4983 void Actor::LowerBelow( Internal::Actor& target )
4987 ActorContainer& siblings = *(mParent->mChildren);
4988 if( siblings.front() != this && target.mParent == mParent ) // If not already at bottom
4990 ActorPtr thisPtr(this); // ensure this actor remains referenced.
4992 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
4993 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
4995 if( thisIter > targetIter )
4997 siblings.erase(thisIter); // this only invalidates iterators at or after this point.
4998 siblings.insert(targetIter, thisPtr);
5001 Dali::Actor handle( this );
5002 mParent->mChildOrderChangedSignal.Emit( handle );
5004 RequestRebuildDepthTree();
5009 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5013 void Actor::SetInheritLayoutDirection( bool inherit )
5015 if( mInheritLayoutDirection != inherit )
5017 mInheritLayoutDirection = inherit;
5019 if( inherit && mParent )
5021 InheritLayoutDirectionRecursively( this, mParent->mLayoutDirection );
5026 bool Actor::IsLayoutDirectionInherited() const
5028 return mInheritLayoutDirection;
5031 void Actor::InheritLayoutDirectionRecursively( ActorPtr actor, Dali::LayoutDirection::Type direction, bool set )
5033 if( actor && ( actor->mInheritLayoutDirection || set ) )
5035 if( actor->mLayoutDirection != direction )
5037 actor->mLayoutDirection = direction;
5038 actor->EmitLayoutDirectionChangedSignal( direction );
5039 actor->RelayoutRequest();
5042 if( actor->GetChildCount() > 0 )
5044 ActorContainer& children = actor->GetChildrenInternal();
5045 for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter )
5047 InheritLayoutDirectionRecursively( *iter, direction );
5053 } // namespace Internal