2 * Copyright (c) 2019 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/event/actors/actor-impl.h>
27 #include <dali/devel-api/actors/layer-devel.h>
28 #include <dali/public-api/common/dali-common.h>
29 #include <dali/public-api/common/constants.h>
30 #include <dali/public-api/events/touch-data.h>
31 #include <dali/public-api/math/vector2.h>
32 #include <dali/public-api/math/vector3.h>
33 #include <dali/public-api/math/radian.h>
34 #include <dali/public-api/object/type-registry.h>
35 #include <dali/devel-api/actors/actor-devel.h>
36 #include <dali/devel-api/scripting/scripting.h>
37 #include <dali/internal/common/internal-constants.h>
38 #include <dali/internal/event/common/event-thread-services.h>
39 #include <dali/internal/event/render-tasks/render-task-impl.h>
40 #include <dali/internal/event/actors/camera-actor-impl.h>
41 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
42 #include <dali/internal/event/common/property-helper.h>
43 #include <dali/internal/event/common/stage-impl.h>
44 #include <dali/internal/event/common/type-info-impl.h>
45 #include <dali/internal/event/common/scene-impl.h>
46 #include <dali/internal/event/common/thread-local-storage.h>
47 #include <dali/internal/event/animation/constraint-impl.h>
48 #include <dali/internal/event/common/projection.h>
49 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
50 #include <dali/internal/update/common/animatable-property.h>
51 #include <dali/internal/update/nodes/node-messages.h>
52 #include <dali/internal/update/nodes/node-declarations.h>
53 #include <dali/internal/update/animation/scene-graph-constraint.h>
54 #include <dali/internal/event/events/actor-gesture-data.h>
55 #include <dali/internal/common/message.h>
56 #include <dali/integration-api/debug.h>
58 using Dali::Internal::SceneGraph::Node;
59 using Dali::Internal::SceneGraph::AnimatableProperty;
60 using Dali::Internal::SceneGraph::PropertyBase;
62 #if defined(DEBUG_ENABLED)
63 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_DEPTH_TIMER" );
64 Debug::Filter* gLogRelayoutFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_TIMER" );
75 /// Using a function because of library initialisation order. Vector3::ONE may not have been initialised yet.
76 inline const Vector3& GetDefaultSizeModeFactor()
81 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
82 inline const Vector2& GetDefaultPreferredSize()
87 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
88 inline const Vector2& GetDefaultDimensionPadding()
93 const SizeScalePolicy::Type DEFAULT_SIZE_SCALE_POLICY = SizeScalePolicy::USE_SIZE_SET;
95 } // unnamed namespace
98 * Struct to collect relayout variables
100 struct Actor::RelayoutData
103 : sizeModeFactor( GetDefaultSizeModeFactor() ), preferredSize( GetDefaultPreferredSize() ), sizeSetPolicy( DEFAULT_SIZE_SCALE_POLICY ), relayoutEnabled( false ), insideRelayout( false )
105 // Set size negotiation defaults
106 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
108 resizePolicies[ i ] = ResizePolicy::DEFAULT;
109 useAssignedSize[ i ] = false;
110 negotiatedDimensions[ i ] = 0.0f;
111 dimensionNegotiated[ i ] = false;
112 dimensionDirty[ i ] = false;
113 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
114 dimensionPadding[ i ] = GetDefaultDimensionPadding();
115 minimumSize[ i ] = 0.0f;
116 maximumSize[ i ] = FLT_MAX;
120 ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies
121 bool useAssignedSize[ Dimension::DIMENSION_COUNT ]; ///< The flag to specify whether the size should be assigned to the actor
123 Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies
125 Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
127 float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
129 float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be
130 float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be
132 bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated
133 bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
135 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
137 Vector2 preferredSize; ///< The preferred size of the actor
139 SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
141 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
142 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
145 namespace // unnamed namespace
151 * We want to discourage the use of property strings (minimize string comparisons),
152 * particularly for the default properties.
153 * Name Type writable animatable constraint-input enum for index-checking
155 DALI_PROPERTY_TABLE_BEGIN
156 DALI_PROPERTY( "parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
157 DALI_PROPERTY( "parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
158 DALI_PROPERTY( "parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
159 DALI_PROPERTY( "parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
160 DALI_PROPERTY( "anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
161 DALI_PROPERTY( "anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
162 DALI_PROPERTY( "anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
163 DALI_PROPERTY( "anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
164 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
165 DALI_PROPERTY( "sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
166 DALI_PROPERTY( "sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
167 DALI_PROPERTY( "sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
168 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
169 DALI_PROPERTY( "positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
170 DALI_PROPERTY( "positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
171 DALI_PROPERTY( "positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
172 DALI_PROPERTY( "worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
173 DALI_PROPERTY( "worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
174 DALI_PROPERTY( "worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
175 DALI_PROPERTY( "worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
176 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
177 DALI_PROPERTY( "worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
178 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
179 DALI_PROPERTY( "scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
180 DALI_PROPERTY( "scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
181 DALI_PROPERTY( "scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
182 DALI_PROPERTY( "worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
183 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
184 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
185 DALI_PROPERTY( "colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
186 DALI_PROPERTY( "colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
187 DALI_PROPERTY( "colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
188 DALI_PROPERTY( "colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
189 DALI_PROPERTY( "worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
190 DALI_PROPERTY( "worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
191 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
192 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
193 DALI_PROPERTY( "leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
194 DALI_PROPERTY( "inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
195 DALI_PROPERTY( "inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
196 DALI_PROPERTY( "colorMode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
197 DALI_PROPERTY( "reservedProperty01", STRING, true, false, false, Dali::Actor::Property::RESERVED_PROPERTY_01 ) // This property was removed, but to keep binary compatibility and TypeRegister test app, remain it here.
198 DALI_PROPERTY( "drawMode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
199 DALI_PROPERTY( "sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
200 DALI_PROPERTY( "widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
201 DALI_PROPERTY( "heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
202 DALI_PROPERTY( "sizeScalePolicy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
203 DALI_PROPERTY( "widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
204 DALI_PROPERTY( "heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
205 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
206 DALI_PROPERTY( "minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
207 DALI_PROPERTY( "maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
208 DALI_PROPERTY( "inheritPosition", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_POSITION )
209 DALI_PROPERTY( "clippingMode", STRING, true, false, false, Dali::Actor::Property::CLIPPING_MODE )
210 DALI_PROPERTY( "layoutDirection", STRING, true, false, false, Dali::Actor::Property::LAYOUT_DIRECTION )
211 DALI_PROPERTY( "inheritLayoutDirection", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION )
212 DALI_PROPERTY( "siblingOrder", INTEGER, true, false, false, Dali::DevelActor::Property::SIBLING_ORDER )
213 DALI_PROPERTY( "opacity", FLOAT, true, true, true, Dali::DevelActor::Property::OPACITY )
214 DALI_PROPERTY( "screenPosition", VECTOR2, false, false, false, Dali::DevelActor::Property::SCREEN_POSITION )
215 DALI_PROPERTY( "positionUsesAnchorPoint", BOOLEAN, true, false, false, Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT )
216 DALI_PROPERTY( "culled", BOOLEAN, false, false, true, Dali::DevelActor::Property::CULLED )
217 DALI_PROPERTY( "updateSizeHint", VECTOR2, true, false, true, Dali::DevelActor::Property::UPDATE_SIZE_HINT )
218 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperties )
222 const char* const SIGNAL_TOUCHED = "touched";
223 const char* const SIGNAL_HOVERED = "hovered";
224 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
225 const char* const SIGNAL_ON_STAGE = "onStage";
226 const char* const SIGNAL_OFF_STAGE = "offStage";
227 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
228 const char* const SIGNAL_TOUCH = "touch";
229 const char* const SIGNAL_VISIBILITY_CHANGED = "visibilityChanged";
230 const char* const SIGNAL_LAYOUT_DIRECTION_CHANGED = "layoutDirectionChanged";
231 const char* const SIGNAL_CHILD_ADDED = "childAdded";
232 const char* const SIGNAL_CHILD_REMOVED = "childRemoved";
236 const char* const ACTION_SHOW = "show";
237 const char* const ACTION_HIDE = "hide";
239 BaseHandle CreateActor()
241 return Dali::Actor::New();
244 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor, ActorDefaultProperties );
246 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
247 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
248 SignalConnectorType signalConnector3( mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal );
249 SignalConnectorType signalConnector4( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
250 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
251 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
252 SignalConnectorType signalConnector7( mType, SIGNAL_TOUCH, &Actor::DoConnectSignal );
253 SignalConnectorType signalConnector8( mType, SIGNAL_VISIBILITY_CHANGED, &Actor::DoConnectSignal );
254 SignalConnectorType signalConnector9( mType, SIGNAL_LAYOUT_DIRECTION_CHANGED, &Actor::DoConnectSignal );
255 SignalConnectorType signalConnector10( mType, SIGNAL_CHILD_ADDED, &Actor::DoConnectSignal );
256 SignalConnectorType signalConnector11( mType, SIGNAL_CHILD_REMOVED, &Actor::DoConnectSignal );
258 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
259 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
264 const Vector3& value;
267 DALI_ENUM_TO_STRING_TABLE_BEGIN_WITH_TYPE( AnchorValue, ANCHOR_CONSTANT )
268 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_LEFT )
269 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_CENTER )
270 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_RIGHT )
271 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_LEFT )
272 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER )
273 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_RIGHT )
274 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_LEFT )
275 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_CENTER )
276 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_RIGHT )
277 DALI_ENUM_TO_STRING_TABLE_END( ANCHOR_CONSTANT )
279 DALI_ENUM_TO_STRING_TABLE_BEGIN( COLOR_MODE )
280 DALI_ENUM_TO_STRING( USE_OWN_COLOR )
281 DALI_ENUM_TO_STRING( USE_PARENT_COLOR )
282 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_COLOR )
283 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_ALPHA )
284 DALI_ENUM_TO_STRING_TABLE_END( COLOR_MODE )
286 DALI_ENUM_TO_STRING_TABLE_BEGIN( DRAW_MODE )
287 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, NORMAL )
288 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, OVERLAY_2D )
289 DALI_ENUM_TO_STRING_TABLE_END( DRAW_MODE )
291 DALI_ENUM_TO_STRING_TABLE_BEGIN( RESIZE_POLICY )
292 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIXED )
293 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_NATURAL_SIZE )
294 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FILL_TO_PARENT )
295 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_RELATIVE_TO_PARENT )
296 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_FIXED_OFFSET_FROM_PARENT )
297 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIT_TO_CHILDREN )
298 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, DIMENSION_DEPENDENCY )
299 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_ASSIGNED_SIZE )
300 DALI_ENUM_TO_STRING_TABLE_END( RESIZE_POLICY )
302 DALI_ENUM_TO_STRING_TABLE_BEGIN( SIZE_SCALE_POLICY )
303 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, USE_SIZE_SET )
304 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FIT_WITH_ASPECT_RATIO )
305 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FILL_WITH_ASPECT_RATIO )
306 DALI_ENUM_TO_STRING_TABLE_END( SIZE_SCALE_POLICY )
308 DALI_ENUM_TO_STRING_TABLE_BEGIN( CLIPPING_MODE )
309 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, DISABLED )
310 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, CLIP_CHILDREN )
311 DALI_ENUM_TO_STRING_TABLE_END( CLIPPING_MODE )
313 DALI_ENUM_TO_STRING_TABLE_BEGIN( LAYOUT_DIRECTION )
314 DALI_ENUM_TO_STRING_WITH_SCOPE( LayoutDirection, LEFT_TO_RIGHT )
315 DALI_ENUM_TO_STRING_WITH_SCOPE( LayoutDirection, RIGHT_TO_LEFT )
316 DALI_ENUM_TO_STRING_TABLE_END( LAYOUT_DIRECTION )
318 bool GetAnchorPointConstant( const std::string& value, Vector3& anchor )
320 for( uint32_t i = 0; i < ANCHOR_CONSTANT_TABLE_COUNT; ++i )
322 uint32_t sizeIgnored = 0;
323 if( CompareTokens( value.c_str(), ANCHOR_CONSTANT_TABLE[ i ].name, sizeIgnored ) )
325 anchor = ANCHOR_CONSTANT_TABLE[ i ].value;
332 inline bool GetParentOriginConstant( const std::string& value, Vector3& parentOrigin )
334 // Values are the same so just use the same table as anchor-point
335 return GetAnchorPointConstant( value, parentOrigin );
339 * @brief Extract a given dimension from a Vector2
341 * @param[in] values The values to extract from
342 * @param[in] dimension The dimension to extract
343 * @return Return the value for the dimension
345 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
349 case Dimension::WIDTH:
353 case Dimension::HEIGHT:
355 return values.height;
366 * @brief Extract a given dimension from a Vector3
368 * @param[in] values The values to extract from
369 * @param[in] dimension The dimension to extract
370 * @return Return the value for the dimension
372 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
374 return GetDimensionValue( values.GetVectorXY(), dimension );
378 * @brief Recursively emits the visibility-changed-signal on the actor tree.
379 * @param[in] actor The actor to emit the signal on
380 * @param[in] visible The new visibility of the actor
381 * @param[in] type Whether the actor's visible property has changed or a parent's
383 void EmitVisibilityChangedSignalRecursively( ActorPtr actor, bool visible, DevelActor::VisibilityChange::Type type )
387 actor->EmitVisibilityChangedSignal( visible, type );
389 if( actor->GetChildCount() > 0 )
391 ActorContainer& children = actor->GetChildrenInternal();
392 for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter )
394 EmitVisibilityChangedSignalRecursively( *iter, visible, DevelActor::VisibilityChange::PARENT );
400 } // unnamed namespace
402 ActorPtr Actor::New()
404 // pass a reference to actor, actor does not own its node
405 ActorPtr actor( new Actor( BASIC, *CreateNode() ) );
407 // Second-phase construction
413 const SceneGraph::Node* Actor::CreateNode()
415 // create node. Nodes are owned by the update manager
416 SceneGraph::Node* node = SceneGraph::Node::New();
417 OwnerPointer< SceneGraph::Node > transferOwnership( node );
418 Internal::ThreadLocalStorage* tls = Internal::ThreadLocalStorage::GetInternal();
419 AddNodeMessage( tls->GetUpdateManager(), transferOwnership );
424 const std::string& Actor::GetName() const
429 void Actor::SetName( const std::string& name )
433 // ATTENTION: string for debug purposes is not thread safe.
434 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( &GetNode() ), name );
437 uint32_t Actor::GetId() const
439 return GetNode().GetId();
442 bool Actor::OnStage() const
447 Dali::Layer Actor::GetLayer()
451 // Short-circuit for Layer derived actors
454 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
457 // Find the immediate Layer parent
458 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
460 if( parent->IsLayer() )
462 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
469 void Actor::Add( Actor& child )
471 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
472 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
476 mChildren = new ActorContainer;
479 Actor* const oldParent( child.mParent );
481 // child might already be ours
482 if( this != oldParent )
484 // if we already have parent, unparent us first
487 oldParent->Remove( child ); // This causes OnChildRemove callback & ChildRemoved signal
489 // Old parent may need to readjust to missing child
490 if( oldParent->RelayoutDependentOnChildren() )
492 oldParent->RelayoutRequest();
496 // Guard against Add() during previous OnChildRemove callback
499 // Do this first, since user callbacks from within SetParent() may need to remove child
500 mChildren->push_back( ActorPtr( &child ) );
502 // SetParent asserts that child can be added
503 child.SetParent( this );
505 // Notification for derived classes
507 EmitChildAddedSignal( child );
509 InheritLayoutDirectionRecursively( ActorPtr( &child ), mLayoutDirection );
511 // Only put in a relayout request if there is a suitable dependency
512 if( RelayoutDependentOnChildren() )
520 void Actor::Remove( Actor& child )
522 if( (this == &child) || (!mChildren) )
524 // no children or removing itself
530 // Find the child in mChildren, and unparent it
531 ActorIter end = mChildren->end();
532 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
534 ActorPtr actor = (*iter);
536 if( actor.Get() == &child )
538 // Keep handle for OnChildRemove notification
541 // Do this first, since user callbacks from within SetParent() may need to add the child
542 mChildren->erase( iter );
544 DALI_ASSERT_DEBUG( actor->GetParent() == this );
545 actor->SetParent( NULL );
553 // Only put in a relayout request if there is a suitable dependency
554 if( RelayoutDependentOnChildren() )
560 // Notification for derived classes
561 OnChildRemove( child );
562 EmitChildRemovedSignal( child );
565 void Actor::Unparent()
569 // Remove this actor from the parent. The remove will put a relayout request in for
570 // the parent if required
571 mParent->Remove( *this );
572 // mParent is now NULL!
576 uint32_t Actor::GetChildCount() const
578 return ( NULL != mChildren ) ? static_cast<uint32_t>( mChildren->size() ) : 0; // only 4,294,967,295 children per actor
581 ActorPtr Actor::GetChildAt( uint32_t index ) const
583 DALI_ASSERT_ALWAYS( index < GetChildCount() );
585 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
588 ActorPtr Actor::FindChildByName( const std::string& actorName )
591 if( actorName == mName )
597 ActorIter end = mChildren->end();
598 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
600 child = (*iter)->FindChildByName( actorName );
611 ActorPtr Actor::FindChildById( const uint32_t id )
620 ActorIter end = mChildren->end();
621 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
623 child = (*iter)->FindChildById( id );
634 void Actor::SetParentOrigin( const Vector3& origin )
636 // node is being used in a separate thread; queue a message to set the value & base value
637 SetParentOriginMessage( GetEventThreadServices(), GetNode(), origin );
639 // Cache for event-thread access
642 // not allocated, check if different from default
643 if( ParentOrigin::DEFAULT != origin )
645 mParentOrigin = new Vector3( origin );
650 // check if different from current costs more than just set
651 *mParentOrigin = origin;
655 void Actor::SetParentOriginX( float x )
657 const Vector3& current = GetCurrentParentOrigin();
659 SetParentOrigin( Vector3( x, current.y, current.z ) );
662 void Actor::SetParentOriginY( float y )
664 const Vector3& current = GetCurrentParentOrigin();
666 SetParentOrigin( Vector3( current.x, y, current.z ) );
669 void Actor::SetParentOriginZ( float z )
671 const Vector3& current = GetCurrentParentOrigin();
673 SetParentOrigin( Vector3( current.x, current.y, z ) );
676 const Vector3& Actor::GetCurrentParentOrigin() const
678 // Cached for event-thread access
679 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
682 void Actor::SetAnchorPoint( const Vector3& anchor )
684 // node is being used in a separate thread; queue a message to set the value & base value
685 SetAnchorPointMessage( GetEventThreadServices(), GetNode(), anchor );
687 // Cache for event-thread access
690 // not allocated, check if different from default
691 if( AnchorPoint::DEFAULT != anchor )
693 mAnchorPoint = new Vector3( anchor );
698 // check if different from current costs more than just set
699 *mAnchorPoint = anchor;
703 void Actor::SetAnchorPointX( float x )
705 const Vector3& current = GetCurrentAnchorPoint();
707 SetAnchorPoint( Vector3( x, current.y, current.z ) );
710 void Actor::SetAnchorPointY( float y )
712 const Vector3& current = GetCurrentAnchorPoint();
714 SetAnchorPoint( Vector3( current.x, y, current.z ) );
717 void Actor::SetAnchorPointZ( float z )
719 const Vector3& current = GetCurrentAnchorPoint();
721 SetAnchorPoint( Vector3( current.x, current.y, z ) );
724 const Vector3& Actor::GetCurrentAnchorPoint() const
726 // Cached for event-thread access
727 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
730 void Actor::SetPosition( float x, float y )
732 SetPosition( Vector3( x, y, 0.0f ) );
735 void Actor::SetPosition( float x, float y, float z )
737 SetPosition( Vector3( x, y, z ) );
740 void Actor::SetPosition( const Vector3& position )
742 mTargetPosition = position;
744 // node is being used in a separate thread; queue a message to set the value & base value
745 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
748 void Actor::SetX( float x )
750 mTargetPosition.x = x;
752 // node is being used in a separate thread; queue a message to set the value & base value
753 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
756 void Actor::SetY( float y )
758 mTargetPosition.y = y;
760 // node is being used in a separate thread; queue a message to set the value & base value
761 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
764 void Actor::SetZ( float z )
766 mTargetPosition.z = z;
768 // node is being used in a separate thread; queue a message to set the value & base value
769 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
772 void Actor::TranslateBy( const Vector3& distance )
774 mTargetPosition += distance;
776 // node is being used in a separate thread; queue a message to set the value & base value
777 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
780 const Vector3& Actor::GetCurrentPosition() const
782 // node is being used in a separate thread; copy the value from the previous update
783 return GetNode().GetPosition(GetEventThreadServices().GetEventBufferIndex());
786 const Vector3& Actor::GetTargetPosition() const
788 return mTargetPosition;
791 const Vector3& Actor::GetCurrentWorldPosition() const
793 // node is being used in a separate thread; copy the value from the previous update
794 return GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
797 const Vector2 Actor::GetCurrentScreenPosition() const
799 if( mScene && OnStage() )
801 Vector3 worldPosition = GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
802 Vector3 cameraPosition = mScene->GetDefaultCameraActor().GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
803 worldPosition -= cameraPosition;
805 Vector3 actorSize = GetCurrentSize() * GetCurrentWorldScale();
806 Vector2 halfSceneSize( mScene->GetSize() * 0.5f ); // World position origin is center of scene
807 Vector3 halfActorSize( actorSize * 0.5f );
808 Vector3 anchorPointOffSet = halfActorSize - actorSize * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
810 return Vector2( halfSceneSize.width + worldPosition.x - anchorPointOffSet.x,
811 halfSceneSize.height + worldPosition.y - anchorPointOffSet.y );
814 return Vector2::ZERO;
817 void Actor::SetInheritPosition( bool inherit )
819 if( mInheritPosition != inherit )
821 // non animatable so keep local copy
822 mInheritPosition = inherit;
823 SetInheritPositionMessage( GetEventThreadServices(), GetNode(), inherit );
827 bool Actor::IsPositionInherited() const
829 return mInheritPosition;
832 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
834 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
835 normalizedAxis.Normalize();
837 Quaternion orientation( angle, normalizedAxis );
839 SetOrientation( orientation );
842 void Actor::SetOrientation( const Quaternion& orientation )
844 mTargetOrientation = orientation;
846 // node is being used in a separate thread; queue a message to set the value & base value
847 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation );
850 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
852 RotateBy( Quaternion(angle, axis) );
855 void Actor::RotateBy( const Quaternion& relativeRotation )
857 mTargetOrientation *= Quaternion( relativeRotation );
859 // node is being used in a separate thread; queue a message to set the value & base value
860 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
863 const Quaternion& Actor::GetCurrentOrientation() const
865 // node is being used in a separate thread; copy the value from the previous update
866 return GetNode().GetOrientation(GetEventThreadServices().GetEventBufferIndex());
869 const Quaternion& Actor::GetCurrentWorldOrientation() const
871 // node is being used in a separate thread; copy the value from the previous update
872 return GetNode().GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
875 void Actor::SetScale( float scale )
877 SetScale( Vector3( scale, scale, scale ) );
880 void Actor::SetScale( float x, float y, float z )
882 SetScale( Vector3( x, y, z ) );
885 void Actor::SetScale( const Vector3& scale )
887 mTargetScale = scale;
889 // node is being used in a separate thread; queue a message to set the value & base value
890 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
893 void Actor::SetScaleX( float x )
897 // node is being used in a separate thread; queue a message to set the value & base value
898 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
901 void Actor::SetScaleY( float y )
905 // node is being used in a separate thread; queue a message to set the value & base value
906 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
909 void Actor::SetScaleZ( float z )
913 // node is being used in a separate thread; queue a message to set the value & base value
914 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
917 void Actor::ScaleBy(const Vector3& relativeScale)
919 mTargetScale *= relativeScale;
921 // node is being used in a separate thread; queue a message to set the value & base value
922 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
925 const Vector3& Actor::GetCurrentScale() const
927 // node is being used in a separate thread; copy the value from the previous update
928 return GetNode().GetScale(GetEventThreadServices().GetEventBufferIndex());
931 const Vector3& Actor::GetCurrentWorldScale() const
933 // node is being used in a separate thread; copy the value from the previous update
934 return GetNode().GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
937 void Actor::SetInheritScale( bool inherit )
939 if( mInheritScale != inherit )
941 // non animatable so keep local copy
942 mInheritScale = inherit;
943 // node is being used in a separate thread; queue a message to set the value
944 SetInheritScaleMessage( GetEventThreadServices(), GetNode(), inherit );
948 bool Actor::IsScaleInherited() const
950 return mInheritScale;
953 Matrix Actor::GetCurrentWorldMatrix() const
955 return GetNode().GetWorldMatrix(0);
958 void Actor::SetVisible( bool visible )
960 SetVisibleInternal( visible, SendMessage::TRUE );
963 bool Actor::IsVisible() const
965 // node is being used in a separate thread; copy the value from the previous update
966 return GetNode().IsVisible( GetEventThreadServices().GetEventBufferIndex() );
969 void Actor::SetOpacity( float opacity )
971 mTargetColor.a = opacity;
973 // node is being used in a separate thread; queue a message to set the value & base value
974 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
977 float Actor::GetCurrentOpacity() const
979 // node is being used in a separate thread; copy the value from the previous update
980 return GetNode().GetOpacity(GetEventThreadServices().GetEventBufferIndex());
983 ClippingMode::Type Actor::GetClippingMode() const
985 return mClippingMode;
988 uint32_t Actor::GetSortingDepth()
993 const Vector4& Actor::GetCurrentWorldColor() const
995 return GetNode().GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
998 void Actor::SetColor( const Vector4& color )
1000 mTargetColor = color;
1002 // node is being used in a separate thread; queue a message to set the value & base value
1003 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::Bake, color );
1006 void Actor::SetColorRed( float red )
1008 mTargetColor.r = red;
1010 // node is being used in a separate thread; queue a message to set the value & base value
1011 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeX, red );
1014 void Actor::SetColorGreen( float green )
1016 mTargetColor.g = green;
1018 // node is being used in a separate thread; queue a message to set the value & base value
1019 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeY, green );
1022 void Actor::SetColorBlue( float blue )
1024 mTargetColor.b = blue;
1026 // node is being used in a separate thread; queue a message to set the value & base value
1027 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1030 const Vector4& Actor::GetCurrentColor() const
1032 // node is being used in a separate thread; copy the value from the previous update
1033 return GetNode().GetColor(GetEventThreadServices().GetEventBufferIndex());
1036 void Actor::SetInheritOrientation( bool inherit )
1038 if( mInheritOrientation != inherit )
1040 // non animatable so keep local copy
1041 mInheritOrientation = inherit;
1042 // node is being used in a separate thread; queue a message to set the value
1043 SetInheritOrientationMessage( GetEventThreadServices(), GetNode(), inherit );
1047 bool Actor::IsOrientationInherited() const
1049 return mInheritOrientation;
1052 void Actor::SetSizeModeFactor( const Vector3& factor )
1054 EnsureRelayoutData();
1056 mRelayoutData->sizeModeFactor = factor;
1059 const Vector3& Actor::GetSizeModeFactor() const
1061 if ( mRelayoutData )
1063 return mRelayoutData->sizeModeFactor;
1066 return GetDefaultSizeModeFactor();
1069 void Actor::SetColorMode( ColorMode colorMode )
1071 // non animatable so keep local copy
1072 mColorMode = colorMode;
1073 // node is being used in a separate thread; queue a message to set the value
1074 SetColorModeMessage( GetEventThreadServices(), GetNode(), colorMode );
1077 ColorMode Actor::GetColorMode() const
1079 // we have cached copy
1083 void Actor::SetSize( float width, float height )
1085 SetSize( Vector2( width, height ) );
1088 void Actor::SetSize( float width, float height, float depth )
1090 SetSize( Vector3( width, height, depth ) );
1093 void Actor::SetSize( const Vector2& size )
1095 SetSize( Vector3( size.width, size.height, 0.f ) );
1098 void Actor::SetSizeInternal( const Vector2& size )
1100 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1103 void Actor::SetSize( const Vector3& size )
1105 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1107 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1108 SetPreferredSize( size.GetVectorXY() );
1112 SetSizeInternal( size );
1116 void Actor::SetSizeInternal( const Vector3& size )
1118 // dont allow recursive loop
1119 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1120 // check that we have a node AND the new size width, height or depth is at least a little bit different from the old one
1121 if( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1122 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1123 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) )
1127 // node is being used in a separate thread; queue a message to set the value & base value
1128 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
1130 // Notification for derived classes
1131 mInsideOnSizeSet = true;
1132 OnSizeSet( mTargetSize );
1133 mInsideOnSizeSet = false;
1135 // Raise a relayout request if the flag is not locked
1136 if( mRelayoutData && !mRelayoutData->insideRelayout )
1143 void Actor::SetWidth( float width )
1145 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1147 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
1148 mRelayoutData->preferredSize.width = width;
1152 mTargetSize.width = width;
1154 // node is being used in a separate thread; queue a message to set the value & base value
1155 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1161 void Actor::SetHeight( float height )
1163 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1165 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
1166 mRelayoutData->preferredSize.height = height;
1170 mTargetSize.height = height;
1172 // node is being used in a separate thread; queue a message to set the value & base value
1173 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1179 void Actor::SetDepth( float depth )
1181 mTargetSize.depth = depth;
1183 // node is being used in a separate thread; queue a message to set the value & base value
1184 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1187 Vector3 Actor::GetTargetSize() const
1189 Vector3 size = mTargetSize;
1191 // Should return preferred size if size is fixed as set by SetSize
1192 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
1194 size.width = GetPreferredSize().width;
1196 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
1198 size.height = GetPreferredSize().height;
1204 const Vector3& Actor::GetCurrentSize() const
1206 // node is being used in a separate thread; copy the value from the previous update
1207 return GetNode().GetSize( GetEventThreadServices().GetEventBufferIndex() );
1210 Vector3 Actor::GetNaturalSize() const
1212 // It is up to deriving classes to return the appropriate natural size
1213 return Vector3( 0.0f, 0.0f, 0.0f );
1216 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1218 EnsureRelayoutData();
1220 ResizePolicy::Type originalWidthPolicy = GetResizePolicy(Dimension::WIDTH);
1221 ResizePolicy::Type originalHeightPolicy = GetResizePolicy(Dimension::HEIGHT);
1223 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1225 if( dimension & ( 1 << i ) )
1227 if ( policy == ResizePolicy::USE_ASSIGNED_SIZE )
1229 mRelayoutData->useAssignedSize[ i ] = true;
1233 mRelayoutData->resizePolicies[ i ] = policy;
1234 mRelayoutData->useAssignedSize[ i ] = false;
1239 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1241 if( dimension & Dimension::WIDTH )
1243 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1246 if( dimension & Dimension::HEIGHT )
1248 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1252 // If calling SetResizePolicy, assume we want relayout enabled
1253 SetRelayoutEnabled( true );
1255 // If the resize policy is set to be FIXED, the preferred size
1256 // should be overrided by the target size. Otherwise the target
1257 // size should be overrided by the preferred size.
1259 if( dimension & Dimension::WIDTH )
1261 if( originalWidthPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1263 mRelayoutData->preferredSize.width = mTargetSize.width;
1265 else if( originalWidthPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1267 mTargetSize.width = mRelayoutData->preferredSize.width;
1271 if( dimension & Dimension::HEIGHT )
1273 if( originalHeightPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1275 mRelayoutData->preferredSize.height = mTargetSize.height;
1277 else if( originalHeightPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1279 mTargetSize.height = mRelayoutData->preferredSize.height;
1283 OnSetResizePolicy( policy, dimension );
1285 // Trigger relayout on this control
1289 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1291 if ( mRelayoutData )
1293 // If more than one dimension is requested, just return the first one found
1294 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1296 if( ( dimension & ( 1 << i ) ) )
1298 if( mRelayoutData->useAssignedSize[ i ] )
1300 return ResizePolicy::USE_ASSIGNED_SIZE;
1304 return mRelayoutData->resizePolicies[ i ];
1310 return ResizePolicy::DEFAULT;
1313 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1315 EnsureRelayoutData();
1317 mRelayoutData->sizeSetPolicy = policy;
1319 // Trigger relayout on this control
1323 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1325 if ( mRelayoutData )
1327 return mRelayoutData->sizeSetPolicy;
1330 return DEFAULT_SIZE_SCALE_POLICY;
1333 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1335 EnsureRelayoutData();
1337 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1339 if( dimension & ( 1 << i ) )
1341 mRelayoutData->dimensionDependencies[ i ] = dependency;
1346 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1348 if ( mRelayoutData )
1350 // If more than one dimension is requested, just return the first one found
1351 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1353 if( ( dimension & ( 1 << i ) ) )
1355 return mRelayoutData->dimensionDependencies[ i ];
1360 return Dimension::ALL_DIMENSIONS; // Default
1363 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1365 // If relayout data has not been allocated yet and the client is requesting
1366 // to disable it, do nothing
1367 if( mRelayoutData || relayoutEnabled )
1369 EnsureRelayoutData();
1371 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1373 mRelayoutData->relayoutEnabled = relayoutEnabled;
1377 bool Actor::IsRelayoutEnabled() const
1379 // Assume that if relayout data has not been allocated yet then
1380 // relayout is disabled
1381 return mRelayoutData && mRelayoutData->relayoutEnabled;
1384 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1386 EnsureRelayoutData();
1388 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1390 if( dimension & ( 1 << i ) )
1392 mRelayoutData->dimensionDirty[ i ] = dirty;
1397 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1399 if ( mRelayoutData )
1401 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1403 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1413 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1415 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1418 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1420 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1423 uint32_t Actor::AddRenderer( Renderer& renderer )
1427 mRenderers = new RendererContainer;
1430 uint32_t index = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1431 RendererPtr rendererPtr = RendererPtr( &renderer );
1432 mRenderers->push_back( rendererPtr );
1433 AttachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1437 uint32_t Actor::GetRendererCount() const
1439 uint32_t rendererCount(0);
1442 rendererCount = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1445 return rendererCount;
1448 RendererPtr Actor::GetRendererAt( uint32_t index )
1450 RendererPtr renderer;
1451 if( index < GetRendererCount() )
1453 renderer = ( *mRenderers )[ index ];
1459 void Actor::RemoveRenderer( Renderer& renderer )
1463 RendererIter end = mRenderers->end();
1464 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1466 if( (*iter).Get() == &renderer )
1468 mRenderers->erase( iter );
1469 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1476 void Actor::RemoveRenderer( uint32_t index )
1478 if( index < GetRendererCount() )
1480 RendererPtr renderer = ( *mRenderers )[ index ];
1481 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.Get()->GetRendererSceneObject() );
1482 mRenderers->erase( mRenderers->begin()+index );
1486 bool Actor::IsOverlay() const
1488 return ( DrawMode::OVERLAY_2D == mDrawMode );
1491 void Actor::SetDrawMode( DrawMode::Type drawMode )
1493 // this flag is not animatable so keep the value
1494 mDrawMode = drawMode;
1496 // node is being used in a separate thread; queue a message to set the value
1497 SetDrawModeMessage( GetEventThreadServices(), GetNode(), drawMode );
1500 DrawMode::Type Actor::GetDrawMode() const
1505 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1507 // only valid when on-stage
1508 if( mScene && OnStage() )
1510 const RenderTaskList& taskList = mScene->GetRenderTaskList();
1512 Vector2 converted( screenX, screenY );
1514 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1515 uint32_t taskCount = taskList.GetTaskCount();
1516 for( uint32_t i = taskCount; i > 0; --i )
1518 RenderTaskPtr task = taskList.GetTask( i - 1 );
1519 if( ScreenToLocal( *task, localX, localY, screenX, screenY ) )
1521 // found a task where this conversion was ok so return
1529 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1531 bool retval = false;
1532 // only valid when on-stage
1535 CameraActor* camera = renderTask.GetCameraActor();
1539 renderTask.GetViewport( viewport );
1541 // need to translate coordinates to render tasks coordinate space
1542 Vector2 converted( screenX, screenY );
1543 if( renderTask.TranslateCoordinates( converted ) )
1545 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1552 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1554 // Early-out if not on stage
1560 // Get the ModelView matrix
1562 Matrix::Multiply( modelView, GetNode().GetWorldMatrix(0), viewMatrix );
1564 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1565 Matrix invertedMvp( false/*don't init*/);
1566 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1567 bool success = invertedMvp.Invert();
1569 // Convert to GL coordinates
1570 Vector4 screenPos( screenX - static_cast<float>( viewport.x ), static_cast<float>( viewport.height ) - screenY - static_cast<float>( viewport.y ), 0.f, 1.f );
1575 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), nearPos );
1582 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), farPos );
1588 if( XyPlaneIntersect( nearPos, farPos, local ) )
1590 Vector3 size = GetCurrentSize();
1591 localX = local.x + size.x * 0.5f;
1592 localY = local.y + size.y * 0.5f;
1603 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1606 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1608 Mathematical Formulation
1610 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1612 ( p - c ) dot ( p - c ) = r^2
1614 Given a ray with a point of origin 'o', and a direction vector 'd':
1616 ray(t) = o + td, t >= 0
1618 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1620 (o + td - c ) dot ( o + td - c ) = r^2
1622 To solve for t we first expand the above into a more recognisable quadratic equation form
1624 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1633 B = 2( o - c ) dot d
1634 C = ( o - c ) dot ( o - c ) - r^2
1636 which can be solved using a standard quadratic formula.
1638 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1640 Practical Simplification
1642 In a renderer, we often differentiate between world space and object space. In the object space
1643 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1644 into object space, the mathematical solution presented above can be simplified significantly.
1646 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1650 and we can find the t at which the (transformed) ray intersects the sphere by
1652 ( o + td ) dot ( o + td ) = r^2
1654 According to the reasoning above, we expand the above quadratic equation into the general form
1658 which now has coefficients:
1665 // Early-out if not on stage
1671 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1673 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1674 const Vector3& translation( GetNode().GetWorldPosition( bufferIndex ) );
1675 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1677 // Compute the radius is not needed, square radius it's enough.
1678 const Vector3& size( GetNode().GetSize( bufferIndex ) );
1680 // Scale the sphere.
1681 const Vector3& scale( GetNode().GetWorldScale( bufferIndex ) );
1683 const float width = size.width * scale.width;
1684 const float height = size.height * scale.height;
1686 float squareSphereRadius = 0.5f * ( width * width + height * height );
1688 float a = rayDir.Dot( rayDir ); // a
1689 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1690 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1692 return ( b2 * b2 - a * c ) >= 0.f;
1695 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector2& hitPointLocal, float& distance ) const
1701 // Transforms the ray to the local reference system.
1702 // Calculate the inverse of Model matrix
1703 Matrix invModelMatrix( false/*don't init*/);
1705 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1706 invModelMatrix = GetNode().GetWorldMatrix(0);
1707 invModelMatrix.Invert();
1709 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1710 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1712 // Test with the actor's XY plane (Normal = 0 0 1 1).
1714 float a = -rayOriginLocal.z;
1715 float b = rayDirLocal.z;
1717 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1719 // Ray travels distance * rayDirLocal to intersect with plane.
1722 const Vector3& size = GetNode().GetSize( bufferIndex );
1724 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1725 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1727 // Test with the actor's geometry.
1728 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1735 void Actor::SetLeaveRequired( bool required )
1737 mLeaveRequired = required;
1740 bool Actor::GetLeaveRequired() const
1742 return mLeaveRequired;
1745 void Actor::SetKeyboardFocusable( bool focusable )
1747 mKeyboardFocusable = focusable;
1750 bool Actor::IsKeyboardFocusable() const
1752 return mKeyboardFocusable;
1755 bool Actor::GetTouchRequired() const
1757 return !mTouchedSignal.Empty() || !mTouchSignal.Empty() || mDerivedRequiresTouch;
1760 bool Actor::GetHoverRequired() const
1762 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1765 bool Actor::GetWheelEventRequired() const
1767 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1770 bool Actor::IsHittable() const
1772 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1775 ActorGestureData& Actor::GetGestureData()
1777 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1778 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1779 if( NULL == mGestureData )
1781 mGestureData = new ActorGestureData;
1783 return *mGestureData;
1786 bool Actor::IsGestureRequred( DevelGesture::Type type ) const
1788 return mGestureData && mGestureData->IsGestureRequred( type );
1791 bool Actor::EmitTouchEventSignal( const TouchEvent& event, const Dali::TouchData& touch )
1793 bool consumed = false;
1795 if( !mTouchSignal.Empty() )
1797 Dali::Actor handle( this );
1798 consumed = mTouchSignal.Emit( handle, touch );
1801 if( !mTouchedSignal.Empty() )
1803 Dali::Actor handle( this );
1804 consumed |= mTouchedSignal.Emit( handle, event );
1809 // Notification for derived classes
1810 consumed = OnTouchEvent( event ); // TODO
1816 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1818 bool consumed = false;
1820 if( !mHoveredSignal.Empty() )
1822 Dali::Actor handle( this );
1823 consumed = mHoveredSignal.Emit( handle, event );
1828 // Notification for derived classes
1829 consumed = OnHoverEvent( event );
1835 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1837 bool consumed = false;
1839 if( !mWheelEventSignal.Empty() )
1841 Dali::Actor handle( this );
1842 consumed = mWheelEventSignal.Emit( handle, event );
1847 // Notification for derived classes
1848 consumed = OnWheelEvent( event );
1854 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
1856 if( ! mVisibilityChangedSignal.Empty() )
1858 Dali::Actor handle( this );
1859 mVisibilityChangedSignal.Emit( handle, visible, type );
1863 void Actor::EmitLayoutDirectionChangedSignal( LayoutDirection::Type type )
1865 if( ! mLayoutDirectionChangedSignal.Empty() )
1867 Dali::Actor handle( this );
1868 mLayoutDirectionChangedSignal.Emit( handle, type );
1872 void Actor::EmitChildAddedSignal( Actor& child )
1874 if( ! mChildAddedSignal.Empty() )
1876 Dali::Actor handle( &child );
1877 mChildAddedSignal.Emit( handle );
1881 void Actor::EmitChildRemovedSignal( Actor& child )
1883 if( ! mChildRemovedSignal.Empty() )
1885 Dali::Actor handle( &child );
1886 mChildRemovedSignal.Emit( handle );
1890 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
1892 return mTouchedSignal;
1895 Dali::Actor::TouchDataSignalType& Actor::TouchSignal()
1897 return mTouchSignal;
1900 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
1902 return mHoveredSignal;
1905 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
1907 return mWheelEventSignal;
1910 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
1912 return mOnStageSignal;
1915 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
1917 return mOffStageSignal;
1920 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
1922 return mOnRelayoutSignal;
1925 DevelActor::VisibilityChangedSignalType& Actor::VisibilityChangedSignal()
1927 return mVisibilityChangedSignal;
1930 Dali::Actor::LayoutDirectionChangedSignalType& Actor::LayoutDirectionChangedSignal()
1932 return mLayoutDirectionChangedSignal;
1935 DevelActor::ChildChangedSignalType& Actor::ChildAddedSignal()
1937 return mChildAddedSignal;
1940 DevelActor::ChildChangedSignalType& Actor::ChildRemovedSignal()
1942 return mChildRemovedSignal;
1945 DevelActor::ChildOrderChangedSignalType& Actor::ChildOrderChangedSignal()
1947 return mChildOrderChangedSignal;
1950 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1952 bool connected( true );
1953 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
1955 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1957 actor->TouchedSignal().Connect( tracker, functor );
1959 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1961 actor->HoveredSignal().Connect( tracker, functor );
1963 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1965 actor->WheelEventSignal().Connect( tracker, functor );
1967 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
1969 actor->OnStageSignal().Connect( tracker, functor );
1971 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
1973 actor->OffStageSignal().Connect( tracker, functor );
1975 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
1977 actor->OnRelayoutSignal().Connect( tracker, functor );
1979 else if( 0 == signalName.compare( SIGNAL_TOUCH ) )
1981 actor->TouchSignal().Connect( tracker, functor );
1983 else if( 0 == signalName.compare( SIGNAL_VISIBILITY_CHANGED ) )
1985 actor->VisibilityChangedSignal().Connect( tracker, functor );
1987 else if( 0 == signalName.compare( SIGNAL_LAYOUT_DIRECTION_CHANGED ) )
1989 actor->LayoutDirectionChangedSignal().Connect( tracker, functor );
1991 else if( 0 == signalName.compare( SIGNAL_CHILD_ADDED ) )
1993 actor->ChildAddedSignal().Connect( tracker, functor );
1995 else if( 0 == signalName.compare( SIGNAL_CHILD_REMOVED ) )
1997 actor->ChildRemovedSignal().Connect( tracker, functor );
2001 // signalName does not match any signal
2008 Actor::Actor( DerivedType derivedType, const SceneGraph::Node& node )
2014 mParentOrigin( NULL ),
2015 mAnchorPoint( NULL ),
2016 mRelayoutData( NULL ),
2017 mGestureData( NULL ),
2021 mWheelEventSignal(),
2024 mOnRelayoutSignal(),
2025 mVisibilityChangedSignal(),
2026 mLayoutDirectionChangedSignal(),
2027 mChildAddedSignal(),
2028 mChildRemovedSignal(),
2029 mChildOrderChangedSignal(),
2030 mTargetOrientation( Quaternion::IDENTITY ),
2031 mTargetColor( Color::WHITE ),
2032 mTargetSize( Vector3::ZERO ),
2033 mTargetPosition( Vector3::ZERO ),
2034 mTargetScale( Vector3::ONE ),
2038 mIsRoot( ROOT_LAYER == derivedType ),
2039 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2040 mIsOnStage( false ),
2042 mLeaveRequired( false ),
2043 mKeyboardFocusable( false ),
2044 mDerivedRequiresTouch( false ),
2045 mDerivedRequiresHover( false ),
2046 mDerivedRequiresWheelEvent( false ),
2047 mOnStageSignalled( false ),
2048 mInsideOnSizeSet( false ),
2049 mInheritPosition( true ),
2050 mInheritOrientation( true ),
2051 mInheritScale( true ),
2052 mPositionUsesAnchorPoint( true ),
2054 mInheritLayoutDirection( true ),
2055 mLayoutDirection( LayoutDirection::LEFT_TO_RIGHT ),
2056 mDrawMode( DrawMode::NORMAL ),
2057 mColorMode( Node::DEFAULT_COLOR_MODE ),
2058 mClippingMode( ClippingMode::DISABLED )
2062 void Actor::Initialize()
2066 GetEventThreadServices().RegisterObject( this );
2071 // Remove mParent pointers from children even if we're destroying core,
2072 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2075 ActorConstIter endIter = mChildren->end();
2076 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2078 (*iter)->SetParent( NULL );
2084 // Guard to allow handle destruction after Core has been destroyed
2085 if( EventThreadServices::IsCoreRunning() )
2087 // Root layer will destroy its node in its own destructor
2090 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
2092 GetEventThreadServices().UnregisterObject( this );
2096 // Cleanup optional gesture data
2097 delete mGestureData;
2099 // Cleanup optional parent origin and anchor
2100 delete mParentOrigin;
2101 delete mAnchorPoint;
2103 // Delete optional relayout data
2104 delete mRelayoutData;
2107 void Actor::ConnectToStage( uint32_t parentDepth )
2109 // This container is used instead of walking the Actor hierarchy.
2110 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
2111 ActorContainer connectionList;
2115 mScene->RequestRebuildDepthTree();
2118 // This stage is atomic i.e. not interrupted by user callbacks.
2119 RecursiveConnectToStage( connectionList, parentDepth + 1 );
2121 // Notify applications about the newly connected actors.
2122 const ActorIter endIter = connectionList.end();
2123 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2125 (*iter)->NotifyStageConnection();
2131 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, uint32_t depth )
2133 DALI_ASSERT_ALWAYS( !OnStage() );
2136 mDepth = static_cast< uint16_t >( depth ); // overflow ignored, not expected in practice
2138 ConnectToSceneGraph();
2140 // Notification for internal derived classes
2141 OnStageConnectionInternal();
2143 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2144 connectionList.push_back( ActorPtr( this ) );
2146 // Recursively connect children
2149 ActorConstIter endIter = mChildren->end();
2150 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2152 (*iter)->SetScene( *mScene );
2153 (*iter)->RecursiveConnectToStage( connectionList, depth + 1 );
2159 * This method is called when the Actor is connected to the Stage.
2160 * The parent must have added its Node to the scene-graph.
2161 * The child must connect its Node to the parent's Node.
2162 * This is recursive; the child calls ConnectToStage() for its children.
2164 void Actor::ConnectToSceneGraph()
2166 DALI_ASSERT_DEBUG( mParent != NULL);
2168 // Reparent Node in next Update
2169 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), mParent->GetNode(), GetNode() );
2171 // Request relayout on all actors that are added to the scenegraph
2174 // Notification for Object::Observers
2178 void Actor::NotifyStageConnection()
2180 // Actors can be removed (in a callback), before the on-stage stage is reported.
2181 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2182 if( OnStage() && !mOnStageSignalled )
2184 // Notification for external (CustomActor) derived classes
2185 OnStageConnectionExternal( mDepth );
2187 if( !mOnStageSignal.Empty() )
2189 Dali::Actor handle( this );
2190 mOnStageSignal.Emit( handle );
2193 // Guard against Remove during callbacks
2196 mOnStageSignalled = true; // signal required next time Actor is removed
2201 void Actor::DisconnectFromStage()
2203 // This container is used instead of walking the Actor hierachy.
2204 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2205 ActorContainer disconnectionList;
2209 mScene->RequestRebuildDepthTree();
2212 // This stage is atomic i.e. not interrupted by user callbacks
2213 RecursiveDisconnectFromStage( disconnectionList );
2215 // Notify applications about the newly disconnected actors.
2216 const ActorIter endIter = disconnectionList.end();
2217 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2219 (*iter)->NotifyStageDisconnection();
2223 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2225 // need to change state first so that internals relying on IsOnStage() inside OnStageDisconnectionInternal() get the correct value
2228 // Recursively disconnect children
2231 ActorConstIter endIter = mChildren->end();
2232 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2234 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2238 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2239 disconnectionList.push_back( ActorPtr( this ) );
2241 // Notification for internal derived classes
2242 OnStageDisconnectionInternal();
2244 DisconnectFromSceneGraph();
2248 * This method is called by an actor or its parent, before a node removal message is sent.
2249 * This is recursive; the child calls DisconnectFromStage() for its children.
2251 void Actor::DisconnectFromSceneGraph()
2253 // Notification for Object::Observers
2254 OnSceneObjectRemove();
2257 void Actor::NotifyStageDisconnection()
2259 // Actors can be added (in a callback), before the off-stage state is reported.
2260 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2261 // only do this step if there is a stage, i.e. Core is not being shut down
2262 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2264 // Notification for external (CustomeActor) derived classes
2265 OnStageDisconnectionExternal();
2267 if( !mOffStageSignal.Empty() )
2269 Dali::Actor handle( this );
2270 mOffStageSignal.Emit( handle );
2273 // Guard against Add during callbacks
2276 mOnStageSignalled = false; // signal required next time Actor is added
2281 bool Actor::IsNodeConnected() const
2283 bool connected( false );
2287 if( IsRoot() || GetNode().GetParent() )
2296 // This method initiates traversal of the actor tree using depth-first
2297 // traversal to set a depth index based on traversal order. It sends a
2298 // single message to update manager to update all the actor's nodes in
2299 // this tree with the depth index. The sceneGraphNodeDepths vector's
2300 // elements are ordered by depth, and could be used to reduce sorting
2301 // in the update thread.
2302 void Actor::RebuildDepthTree()
2304 DALI_LOG_TIMER_START(depthTimer);
2306 // Vector of scene-graph nodes and their depths to send to UpdateManager
2307 // in a single message
2308 OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths( new SceneGraph::NodeDepths() );
2310 int32_t depthIndex = 1;
2311 DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
2313 SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths );
2314 DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
2317 void Actor::DepthTraverseActorTree( OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths, int32_t& depthIndex )
2319 mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
2320 sceneGraphNodeDepths->Add( const_cast<SceneGraph::Node*>( &GetNode() ), mSortedDepth );
2322 // Create/add to children of this node
2325 for( ActorContainer::iterator it = mChildren->begin(); it != mChildren->end(); ++it )
2327 Actor* childActor = (*it).Get();
2329 childActor->DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
2334 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2338 case Dali::Actor::Property::PARENT_ORIGIN:
2340 Property::Type type = property.GetType();
2341 if( type == Property::VECTOR3 )
2343 SetParentOrigin( property.Get< Vector3 >() );
2345 else if ( type == Property::STRING )
2347 std::string parentOriginString;
2348 property.Get( parentOriginString );
2349 Vector3 parentOrigin;
2350 if( GetParentOriginConstant( parentOriginString, parentOrigin ) )
2352 SetParentOrigin( parentOrigin );
2358 case Dali::Actor::Property::PARENT_ORIGIN_X:
2360 SetParentOriginX( property.Get< float >() );
2364 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2366 SetParentOriginY( property.Get< float >() );
2370 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2372 SetParentOriginZ( property.Get< float >() );
2376 case Dali::Actor::Property::ANCHOR_POINT:
2378 Property::Type type = property.GetType();
2379 if( type == Property::VECTOR3 )
2381 SetAnchorPoint( property.Get< Vector3 >() );
2383 else if ( type == Property::STRING )
2385 std::string anchorPointString;
2386 property.Get( anchorPointString );
2388 if( GetAnchorPointConstant( anchorPointString, anchor ) )
2390 SetAnchorPoint( anchor );
2396 case Dali::Actor::Property::ANCHOR_POINT_X:
2398 SetAnchorPointX( property.Get< float >() );
2402 case Dali::Actor::Property::ANCHOR_POINT_Y:
2404 SetAnchorPointY( property.Get< float >() );
2408 case Dali::Actor::Property::ANCHOR_POINT_Z:
2410 SetAnchorPointZ( property.Get< float >() );
2414 case Dali::Actor::Property::SIZE:
2416 SetSize( property.Get< Vector3 >() );
2420 case Dali::Actor::Property::SIZE_WIDTH:
2422 SetWidth( property.Get< float >() );
2426 case Dali::Actor::Property::SIZE_HEIGHT:
2428 SetHeight( property.Get< float >() );
2432 case Dali::Actor::Property::SIZE_DEPTH:
2434 SetDepth( property.Get< float >() );
2438 case Dali::Actor::Property::POSITION:
2440 SetPosition( property.Get< Vector3 >() );
2444 case Dali::Actor::Property::POSITION_X:
2446 SetX( property.Get< float >() );
2450 case Dali::Actor::Property::POSITION_Y:
2452 SetY( property.Get< float >() );
2456 case Dali::Actor::Property::POSITION_Z:
2458 SetZ( property.Get< float >() );
2462 case Dali::Actor::Property::ORIENTATION:
2464 SetOrientation( property.Get< Quaternion >() );
2468 case Dali::Actor::Property::SCALE:
2470 SetScale( property.Get< Vector3 >() );
2474 case Dali::Actor::Property::SCALE_X:
2476 SetScaleX( property.Get< float >() );
2480 case Dali::Actor::Property::SCALE_Y:
2482 SetScaleY( property.Get< float >() );
2486 case Dali::Actor::Property::SCALE_Z:
2488 SetScaleZ( property.Get< float >() );
2492 case Dali::Actor::Property::VISIBLE:
2494 SetVisible( property.Get< bool >() );
2498 case Dali::Actor::Property::COLOR:
2500 SetColor( property.Get< Vector4 >() );
2504 case Dali::Actor::Property::COLOR_RED:
2506 SetColorRed( property.Get< float >() );
2510 case Dali::Actor::Property::COLOR_GREEN:
2512 SetColorGreen( property.Get< float >() );
2516 case Dali::Actor::Property::COLOR_BLUE:
2518 SetColorBlue( property.Get< float >() );
2522 case Dali::Actor::Property::COLOR_ALPHA:
2523 case Dali::DevelActor::Property::OPACITY:
2526 if( property.Get( value ) )
2528 SetOpacity( value );
2533 case Dali::Actor::Property::NAME:
2535 SetName( property.Get< std::string >() );
2539 case Dali::Actor::Property::SENSITIVE:
2541 SetSensitive( property.Get< bool >() );
2545 case Dali::Actor::Property::LEAVE_REQUIRED:
2547 SetLeaveRequired( property.Get< bool >() );
2551 case Dali::Actor::Property::INHERIT_POSITION:
2553 SetInheritPosition( property.Get< bool >() );
2557 case Dali::Actor::Property::INHERIT_ORIENTATION:
2559 SetInheritOrientation( property.Get< bool >() );
2563 case Dali::Actor::Property::INHERIT_SCALE:
2565 SetInheritScale( property.Get< bool >() );
2569 case Dali::Actor::Property::COLOR_MODE:
2571 ColorMode mode = mColorMode;
2572 if ( Scripting::GetEnumerationProperty< ColorMode >( property, COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT, mode ) )
2574 SetColorMode( mode );
2579 case Dali::Actor::Property::DRAW_MODE:
2581 DrawMode::Type mode = mDrawMode;
2582 if( Scripting::GetEnumerationProperty< DrawMode::Type >( property, DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT, mode ) )
2584 SetDrawMode( mode );
2589 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2591 SetSizeModeFactor( property.Get< Vector3 >() );
2595 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2597 ResizePolicy::Type type = GetResizePolicy( Dimension::WIDTH );
2598 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2600 SetResizePolicy( type, Dimension::WIDTH );
2605 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2607 ResizePolicy::Type type = GetResizePolicy( Dimension::HEIGHT );
2608 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2610 SetResizePolicy( type, Dimension::HEIGHT );
2615 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2617 SizeScalePolicy::Type type = GetSizeScalePolicy();
2618 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT, type ) )
2620 SetSizeScalePolicy( type );
2625 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2627 if( property.Get< bool >() )
2629 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2634 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2636 if( property.Get< bool >() )
2638 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2643 case Dali::Actor::Property::PADDING:
2645 Vector4 padding = property.Get< Vector4 >();
2646 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2647 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2651 case Dali::Actor::Property::MINIMUM_SIZE:
2653 Vector2 size = property.Get< Vector2 >();
2654 SetMinimumSize( size.x, Dimension::WIDTH );
2655 SetMinimumSize( size.y, Dimension::HEIGHT );
2659 case Dali::Actor::Property::MAXIMUM_SIZE:
2661 Vector2 size = property.Get< Vector2 >();
2662 SetMaximumSize( size.x, Dimension::WIDTH );
2663 SetMaximumSize( size.y, Dimension::HEIGHT );
2667 case Dali::DevelActor::Property::SIBLING_ORDER:
2671 if( property.Get( value ) )
2673 SetSiblingOrder( value );
2678 case Dali::Actor::Property::CLIPPING_MODE:
2680 ClippingMode::Type convertedValue = mClippingMode;
2681 if( Scripting::GetEnumerationProperty< ClippingMode::Type >( property, CLIPPING_MODE_TABLE, CLIPPING_MODE_TABLE_COUNT, convertedValue ) )
2683 mClippingMode = convertedValue;
2684 SetClippingModeMessage( GetEventThreadServices(), GetNode(), mClippingMode );
2689 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
2692 if( property.Get( value ) && value != mPositionUsesAnchorPoint )
2694 mPositionUsesAnchorPoint = value;
2695 SetPositionUsesAnchorPointMessage( GetEventThreadServices(), GetNode(), mPositionUsesAnchorPoint );
2700 case Dali::Actor::Property::LAYOUT_DIRECTION:
2702 Dali::LayoutDirection::Type direction = mLayoutDirection;
2703 mInheritLayoutDirection = false;
2705 if( Scripting::GetEnumerationProperty< LayoutDirection::Type >( property, LAYOUT_DIRECTION_TABLE, LAYOUT_DIRECTION_TABLE_COUNT, direction ) )
2707 InheritLayoutDirectionRecursively( this, direction, true );
2712 case Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION:
2715 if( property.Get( value ) )
2717 SetInheritLayoutDirection( value );
2722 case Dali::DevelActor::Property::UPDATE_SIZE_HINT:
2724 SetUpdateSizeHint( property.Get< Vector2 >() );
2730 // this can happen in the case of a non-animatable default property so just do nothing
2736 // TODO: This method needs to be removed
2737 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2739 switch( entry.GetType() )
2741 case Property::BOOLEAN:
2743 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2744 DALI_ASSERT_DEBUG( NULL != property );
2746 // property is being used in a separate thread; queue a message to set the property
2747 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2752 case Property::INTEGER:
2754 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2755 DALI_ASSERT_DEBUG( NULL != property );
2757 // property is being used in a separate thread; queue a message to set the property
2758 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2763 case Property::FLOAT:
2765 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2766 DALI_ASSERT_DEBUG( NULL != property );
2768 // property is being used in a separate thread; queue a message to set the property
2769 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2774 case Property::VECTOR2:
2776 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2777 DALI_ASSERT_DEBUG( NULL != property );
2779 // property is being used in a separate thread; queue a message to set the property
2780 if(entry.componentIndex == 0)
2782 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2784 else if(entry.componentIndex == 1)
2786 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2790 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2796 case Property::VECTOR3:
2798 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2799 DALI_ASSERT_DEBUG( NULL != property );
2801 // property is being used in a separate thread; queue a message to set the property
2802 if(entry.componentIndex == 0)
2804 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2806 else if(entry.componentIndex == 1)
2808 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2810 else if(entry.componentIndex == 2)
2812 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2816 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2822 case Property::VECTOR4:
2824 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2825 DALI_ASSERT_DEBUG( NULL != property );
2827 // property is being used in a separate thread; queue a message to set the property
2828 if(entry.componentIndex == 0)
2830 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
2832 else if(entry.componentIndex == 1)
2834 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
2836 else if(entry.componentIndex == 2)
2838 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
2840 else if(entry.componentIndex == 3)
2842 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
2846 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2852 case Property::ROTATION:
2854 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
2855 DALI_ASSERT_DEBUG( NULL != property );
2857 // property is being used in a separate thread; queue a message to set the property
2858 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
2863 case Property::MATRIX:
2865 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
2866 DALI_ASSERT_DEBUG( NULL != property );
2868 // property is being used in a separate thread; queue a message to set the property
2869 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), &GetNode(), property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
2874 case Property::MATRIX3:
2876 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
2877 DALI_ASSERT_DEBUG( NULL != property );
2879 // property is being used in a separate thread; queue a message to set the property
2880 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), &GetNode(), property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
2887 // nothing to do for other types
2892 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
2894 Property::Value value;
2896 if( ! GetCachedPropertyValue( index, value ) )
2898 // If property value is not stored in the event-side, then it must be a scene-graph only property
2899 GetCurrentPropertyValue( index, value );
2905 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
2907 Property::Value value;
2909 if( ! GetCurrentPropertyValue( index, value ) )
2911 // If unable to retrieve scene-graph property value, then it must be an event-side only property
2912 GetCachedPropertyValue( index, value );
2918 void Actor::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
2920 switch( animationType )
2923 case Animation::BETWEEN:
2927 case Dali::Actor::Property::SIZE:
2929 if( value.Get( mTargetSize ) )
2931 // Notify deriving classes
2932 OnSizeAnimation( animation, mTargetSize );
2937 case Dali::Actor::Property::SIZE_WIDTH:
2939 if( value.Get( mTargetSize.width ) )
2941 // Notify deriving classes
2942 OnSizeAnimation( animation, mTargetSize );
2947 case Dali::Actor::Property::SIZE_HEIGHT:
2949 if( value.Get( mTargetSize.height ) )
2951 // Notify deriving classes
2952 OnSizeAnimation( animation, mTargetSize );
2957 case Dali::Actor::Property::SIZE_DEPTH:
2959 if( value.Get( mTargetSize.depth ) )
2961 // Notify deriving classes
2962 OnSizeAnimation( animation, mTargetSize );
2967 case Dali::Actor::Property::POSITION:
2969 value.Get( mTargetPosition );
2973 case Dali::Actor::Property::POSITION_X:
2975 value.Get( mTargetPosition.x );
2979 case Dali::Actor::Property::POSITION_Y:
2981 value.Get( mTargetPosition.y );
2985 case Dali::Actor::Property::POSITION_Z:
2987 value.Get( mTargetPosition.z );
2991 case Dali::Actor::Property::ORIENTATION:
2993 value.Get( mTargetOrientation );
2997 case Dali::Actor::Property::SCALE:
2999 value.Get( mTargetScale );
3003 case Dali::Actor::Property::SCALE_X:
3005 value.Get( mTargetScale.x );
3009 case Dali::Actor::Property::SCALE_Y:
3011 value.Get( mTargetScale.y );
3015 case Dali::Actor::Property::SCALE_Z:
3017 value.Get( mTargetScale.z );
3021 case Dali::Actor::Property::VISIBLE:
3023 SetVisibleInternal( value.Get< bool >(), SendMessage::FALSE );
3027 case Dali::Actor::Property::COLOR:
3029 value.Get( mTargetColor );
3033 case Dali::Actor::Property::COLOR_RED:
3035 value.Get( mTargetColor.r );
3039 case Dali::Actor::Property::COLOR_GREEN:
3041 value.Get( mTargetColor.g );
3045 case Dali::Actor::Property::COLOR_BLUE:
3047 value.Get( mTargetColor.b );
3051 case Dali::Actor::Property::COLOR_ALPHA:
3052 case Dali::DevelActor::Property::OPACITY:
3054 value.Get( mTargetColor.a );
3060 // Not an animatable property. Do nothing.
3071 case Dali::Actor::Property::SIZE:
3073 if( AdjustValue< Vector3 >( mTargetSize, value ) )
3075 // Notify deriving classes
3076 OnSizeAnimation( animation, mTargetSize );
3081 case Dali::Actor::Property::SIZE_WIDTH:
3083 if( AdjustValue< float >( mTargetSize.width, value ) )
3085 // Notify deriving classes
3086 OnSizeAnimation( animation, mTargetSize );
3091 case Dali::Actor::Property::SIZE_HEIGHT:
3093 if( AdjustValue< float >( mTargetSize.height, value ) )
3095 // Notify deriving classes
3096 OnSizeAnimation( animation, mTargetSize );
3101 case Dali::Actor::Property::SIZE_DEPTH:
3103 if( AdjustValue< float >( mTargetSize.depth, value ) )
3105 // Notify deriving classes
3106 OnSizeAnimation( animation, mTargetSize );
3111 case Dali::Actor::Property::POSITION:
3113 AdjustValue< Vector3 >( mTargetPosition, value );
3117 case Dali::Actor::Property::POSITION_X:
3119 AdjustValue< float >( mTargetPosition.x, value );
3123 case Dali::Actor::Property::POSITION_Y:
3125 AdjustValue< float >( mTargetPosition.y, value );
3129 case Dali::Actor::Property::POSITION_Z:
3131 AdjustValue< float >( mTargetPosition.z, value );
3135 case Dali::Actor::Property::ORIENTATION:
3137 Quaternion relativeValue;
3138 if( value.Get( relativeValue ) )
3140 mTargetOrientation *= relativeValue;
3145 case Dali::Actor::Property::SCALE:
3147 AdjustValue< Vector3 >( mTargetScale, value );
3151 case Dali::Actor::Property::SCALE_X:
3153 AdjustValue< float >( mTargetScale.x, value );
3157 case Dali::Actor::Property::SCALE_Y:
3159 AdjustValue< float >( mTargetScale.y, value );
3163 case Dali::Actor::Property::SCALE_Z:
3165 AdjustValue< float >( mTargetScale.z, value );
3169 case Dali::Actor::Property::VISIBLE:
3171 bool relativeValue = false;
3172 if( value.Get( relativeValue ) )
3174 bool visible = mVisible || relativeValue;
3175 SetVisibleInternal( visible, SendMessage::FALSE );
3180 case Dali::Actor::Property::COLOR:
3182 AdjustValue< Vector4 >( mTargetColor, value );
3186 case Dali::Actor::Property::COLOR_RED:
3188 AdjustValue< float >( mTargetColor.r, value );
3192 case Dali::Actor::Property::COLOR_GREEN:
3194 AdjustValue< float >( mTargetColor.g, value );
3198 case Dali::Actor::Property::COLOR_BLUE:
3200 AdjustValue< float >( mTargetColor.b, value );
3204 case Dali::Actor::Property::COLOR_ALPHA:
3205 case Dali::DevelActor::Property::OPACITY:
3207 AdjustValue< float >( mTargetColor.a, value );
3213 // Not an animatable property. Do nothing.
3222 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3224 const PropertyBase* property( NULL );
3228 case Dali::Actor::Property::SIZE: // FALLTHROUGH
3229 case Dali::Actor::Property::SIZE_WIDTH: // FALLTHROUGH
3230 case Dali::Actor::Property::SIZE_HEIGHT: // FALLTHROUGH
3231 case Dali::Actor::Property::SIZE_DEPTH:
3233 property = &GetNode().mSize;
3236 case Dali::Actor::Property::POSITION: // FALLTHROUGH
3237 case Dali::Actor::Property::POSITION_X: // FALLTHROUGH
3238 case Dali::Actor::Property::POSITION_Y: // FALLTHROUGH
3239 case Dali::Actor::Property::POSITION_Z:
3241 property = &GetNode().mPosition;
3244 case Dali::Actor::Property::ORIENTATION:
3246 property = &GetNode().mOrientation;
3249 case Dali::Actor::Property::SCALE: // FALLTHROUGH
3250 case Dali::Actor::Property::SCALE_X: // FALLTHROUGH
3251 case Dali::Actor::Property::SCALE_Y: // FALLTHROUGH
3252 case Dali::Actor::Property::SCALE_Z:
3254 property = &GetNode().mScale;
3257 case Dali::Actor::Property::VISIBLE:
3259 property = &GetNode().mVisible;
3262 case Dali::Actor::Property::COLOR: // FALLTHROUGH
3263 case Dali::Actor::Property::COLOR_RED: // FALLTHROUGH
3264 case Dali::Actor::Property::COLOR_GREEN: // FALLTHROUGH
3265 case Dali::Actor::Property::COLOR_BLUE: // FALLTHROUGH
3266 case Dali::Actor::Property::COLOR_ALPHA: // FALLTHROUGH
3267 case Dali::DevelActor::Property::OPACITY:
3269 property = &GetNode().mColor;
3279 // not our property, ask base
3280 property = Object::GetSceneObjectAnimatableProperty( index );
3286 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3288 const PropertyInputImpl* property( NULL );
3292 case Dali::Actor::Property::PARENT_ORIGIN: // FALLTHROUGH
3293 case Dali::Actor::Property::PARENT_ORIGIN_X: // FALLTHROUGH
3294 case Dali::Actor::Property::PARENT_ORIGIN_Y: // FALLTHROUGH
3295 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3297 property = &GetNode().mParentOrigin;
3300 case Dali::Actor::Property::ANCHOR_POINT: // FALLTHROUGH
3301 case Dali::Actor::Property::ANCHOR_POINT_X: // FALLTHROUGH
3302 case Dali::Actor::Property::ANCHOR_POINT_Y: // FALLTHROUGH
3303 case Dali::Actor::Property::ANCHOR_POINT_Z:
3305 property = &GetNode().mAnchorPoint;
3308 case Dali::Actor::Property::WORLD_POSITION: // FALLTHROUGH
3309 case Dali::Actor::Property::WORLD_POSITION_X: // FALLTHROUGH
3310 case Dali::Actor::Property::WORLD_POSITION_Y: // FALLTHROUGH
3311 case Dali::Actor::Property::WORLD_POSITION_Z:
3313 property = &GetNode().mWorldPosition;
3316 case Dali::Actor::Property::WORLD_ORIENTATION:
3318 property = &GetNode().mWorldOrientation;
3321 case Dali::Actor::Property::WORLD_SCALE:
3323 property = &GetNode().mWorldScale;
3326 case Dali::Actor::Property::WORLD_COLOR:
3328 property = &GetNode().mWorldColor;
3331 case Dali::Actor::Property::WORLD_MATRIX:
3333 property = &GetNode().mWorldMatrix;
3336 case Dali::DevelActor::Property::CULLED:
3338 property = &GetNode().mCulled;
3348 // reuse animatable property getter as animatable properties are inputs as well
3349 // animatable property chains back to Object::GetSceneObjectInputProperty() so all properties get covered
3350 property = GetSceneObjectAnimatableProperty( index );
3356 int32_t Actor::GetPropertyComponentIndex( Property::Index index ) const
3358 int32_t componentIndex = Property::INVALID_COMPONENT_INDEX;
3362 case Dali::Actor::Property::PARENT_ORIGIN_X:
3363 case Dali::Actor::Property::ANCHOR_POINT_X:
3364 case Dali::Actor::Property::SIZE_WIDTH:
3365 case Dali::Actor::Property::POSITION_X:
3366 case Dali::Actor::Property::WORLD_POSITION_X:
3367 case Dali::Actor::Property::SCALE_X:
3368 case Dali::Actor::Property::COLOR_RED:
3374 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3375 case Dali::Actor::Property::ANCHOR_POINT_Y:
3376 case Dali::Actor::Property::SIZE_HEIGHT:
3377 case Dali::Actor::Property::POSITION_Y:
3378 case Dali::Actor::Property::WORLD_POSITION_Y:
3379 case Dali::Actor::Property::SCALE_Y:
3380 case Dali::Actor::Property::COLOR_GREEN:
3386 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3387 case Dali::Actor::Property::ANCHOR_POINT_Z:
3388 case Dali::Actor::Property::SIZE_DEPTH:
3389 case Dali::Actor::Property::POSITION_Z:
3390 case Dali::Actor::Property::WORLD_POSITION_Z:
3391 case Dali::Actor::Property::SCALE_Z:
3392 case Dali::Actor::Property::COLOR_BLUE:
3398 case Dali::Actor::Property::COLOR_ALPHA:
3399 case Dali::DevelActor::Property::OPACITY:
3411 if( Property::INVALID_COMPONENT_INDEX == componentIndex )
3414 componentIndex = Object::GetPropertyComponentIndex( index );
3417 return componentIndex;
3420 void Actor::SetParent( Actor* parent )
3424 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3428 mScene = parent->mScene;
3430 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3433 // Instruct each actor to create a corresponding node in the scene graph
3434 ConnectToStage( parent->GetHierarchyDepth() );
3437 // Resolve the name and index for the child properties if any
3438 ResolveChildProperties();
3440 else // parent being set to NULL
3442 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3446 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3449 // Disconnect the Node & its children from the scene-graph.
3450 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
3452 // Instruct each actor to discard pointers to the scene-graph
3453 DisconnectFromStage();
3460 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3463 Actor* actor = dynamic_cast< Actor* >( object );
3467 if( 0 == actionName.compare( ACTION_SHOW ) )
3469 actor->SetVisible( true );
3472 else if( 0 == actionName.compare( ACTION_HIDE ) )
3474 actor->SetVisible( false );
3482 Rect<> Actor::CalculateScreenExtents( ) const
3484 auto screenPosition = GetCurrentScreenPosition();
3485 Vector3 size = GetCurrentSize() * GetCurrentWorldScale();
3486 Vector3 anchorPointOffSet = size * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
3487 Vector2 position = Vector2( screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y );
3488 return { position.x, position.y, size.x, size.y };
3491 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
3493 bool valueSet = true;
3497 case Dali::Actor::Property::PARENT_ORIGIN:
3499 value = GetCurrentParentOrigin();
3503 case Dali::Actor::Property::PARENT_ORIGIN_X:
3505 value = GetCurrentParentOrigin().x;
3509 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3511 value = GetCurrentParentOrigin().y;
3515 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3517 value = GetCurrentParentOrigin().z;
3521 case Dali::Actor::Property::ANCHOR_POINT:
3523 value = GetCurrentAnchorPoint();
3527 case Dali::Actor::Property::ANCHOR_POINT_X:
3529 value = GetCurrentAnchorPoint().x;
3533 case Dali::Actor::Property::ANCHOR_POINT_Y:
3535 value = GetCurrentAnchorPoint().y;
3539 case Dali::Actor::Property::ANCHOR_POINT_Z:
3541 value = GetCurrentAnchorPoint().z;
3545 case Dali::Actor::Property::SIZE:
3547 value = GetTargetSize();
3551 case Dali::Actor::Property::SIZE_WIDTH:
3553 value = GetTargetSize().width;
3557 case Dali::Actor::Property::SIZE_HEIGHT:
3559 value = GetTargetSize().height;
3563 case Dali::Actor::Property::SIZE_DEPTH:
3565 value = GetTargetSize().depth;
3569 case Dali::Actor::Property::POSITION:
3571 value = GetTargetPosition();
3575 case Dali::Actor::Property::POSITION_X:
3577 value = GetTargetPosition().x;
3581 case Dali::Actor::Property::POSITION_Y:
3583 value = GetTargetPosition().y;
3587 case Dali::Actor::Property::POSITION_Z:
3589 value = GetTargetPosition().z;
3593 case Dali::Actor::Property::ORIENTATION:
3595 value = mTargetOrientation;
3599 case Dali::Actor::Property::SCALE:
3601 value = mTargetScale;
3605 case Dali::Actor::Property::SCALE_X:
3607 value = mTargetScale.x;
3611 case Dali::Actor::Property::SCALE_Y:
3613 value = mTargetScale.y;
3617 case Dali::Actor::Property::SCALE_Z:
3619 value = mTargetScale.z;
3623 case Dali::Actor::Property::VISIBLE:
3629 case Dali::Actor::Property::COLOR:
3631 value = mTargetColor;
3635 case Dali::Actor::Property::COLOR_RED:
3637 value = mTargetColor.r;
3641 case Dali::Actor::Property::COLOR_GREEN:
3643 value = mTargetColor.g;
3647 case Dali::Actor::Property::COLOR_BLUE:
3649 value = mTargetColor.b;
3653 case Dali::Actor::Property::COLOR_ALPHA:
3654 case Dali::DevelActor::Property::OPACITY:
3656 value = mTargetColor.a;
3660 case Dali::Actor::Property::NAME:
3666 case Dali::Actor::Property::SENSITIVE:
3668 value = IsSensitive();
3672 case Dali::Actor::Property::LEAVE_REQUIRED:
3674 value = GetLeaveRequired();
3678 case Dali::Actor::Property::INHERIT_POSITION:
3680 value = IsPositionInherited();
3684 case Dali::Actor::Property::INHERIT_ORIENTATION:
3686 value = IsOrientationInherited();
3690 case Dali::Actor::Property::INHERIT_SCALE:
3692 value = IsScaleInherited();
3696 case Dali::Actor::Property::COLOR_MODE:
3698 value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
3702 case Dali::Actor::Property::DRAW_MODE:
3704 value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
3708 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3710 value = GetSizeModeFactor();
3714 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3716 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3720 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3722 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3726 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3728 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT );
3732 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3734 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3738 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3740 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3744 case Dali::Actor::Property::PADDING:
3746 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3747 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3748 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3752 case Dali::Actor::Property::MINIMUM_SIZE:
3754 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3758 case Dali::Actor::Property::MAXIMUM_SIZE:
3760 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3764 case Dali::Actor::Property::CLIPPING_MODE:
3766 value = mClippingMode;
3770 case Dali::DevelActor::Property::SIBLING_ORDER:
3772 value = static_cast<int>( GetSiblingOrder() );
3776 case Dali::DevelActor::Property::SCREEN_POSITION:
3778 value = GetCurrentScreenPosition();
3782 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
3784 value = mPositionUsesAnchorPoint;
3788 case Dali::Actor::Property::LAYOUT_DIRECTION:
3790 value = mLayoutDirection;
3794 case Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION:
3796 value = IsLayoutDirectionInherited();
3802 // Must be a scene-graph only property
3811 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
3813 bool valueSet = true;
3817 case Dali::Actor::Property::SIZE:
3819 value = GetCurrentSize();
3823 case Dali::Actor::Property::SIZE_WIDTH:
3825 value = GetCurrentSize().width;
3829 case Dali::Actor::Property::SIZE_HEIGHT:
3831 value = GetCurrentSize().height;
3835 case Dali::Actor::Property::SIZE_DEPTH:
3837 value = GetCurrentSize().depth;
3841 case Dali::Actor::Property::POSITION:
3843 value = GetCurrentPosition();
3847 case Dali::Actor::Property::POSITION_X:
3849 value = GetCurrentPosition().x;
3853 case Dali::Actor::Property::POSITION_Y:
3855 value = GetCurrentPosition().y;
3859 case Dali::Actor::Property::POSITION_Z:
3861 value = GetCurrentPosition().z;
3865 case Dali::Actor::Property::WORLD_POSITION:
3867 value = GetCurrentWorldPosition();
3871 case Dali::Actor::Property::WORLD_POSITION_X:
3873 value = GetCurrentWorldPosition().x;
3877 case Dali::Actor::Property::WORLD_POSITION_Y:
3879 value = GetCurrentWorldPosition().y;
3883 case Dali::Actor::Property::WORLD_POSITION_Z:
3885 value = GetCurrentWorldPosition().z;
3889 case Dali::Actor::Property::ORIENTATION:
3891 value = GetCurrentOrientation();
3895 case Dali::Actor::Property::WORLD_ORIENTATION:
3897 value = GetCurrentWorldOrientation();
3901 case Dali::Actor::Property::SCALE:
3903 value = GetCurrentScale();
3907 case Dali::Actor::Property::SCALE_X:
3909 value = GetCurrentScale().x;
3913 case Dali::Actor::Property::SCALE_Y:
3915 value = GetCurrentScale().y;
3919 case Dali::Actor::Property::SCALE_Z:
3921 value = GetCurrentScale().z;
3925 case Dali::Actor::Property::WORLD_SCALE:
3927 value = GetCurrentWorldScale();
3931 case Dali::Actor::Property::COLOR:
3933 value = GetCurrentColor();
3937 case Dali::Actor::Property::COLOR_RED:
3939 value = GetCurrentColor().r;
3943 case Dali::Actor::Property::COLOR_GREEN:
3945 value = GetCurrentColor().g;
3949 case Dali::Actor::Property::COLOR_BLUE:
3951 value = GetCurrentColor().b;
3955 case Dali::Actor::Property::COLOR_ALPHA:
3956 case Dali::DevelActor::Property::OPACITY:
3958 value = GetCurrentColor().a;
3962 case Dali::Actor::Property::WORLD_COLOR:
3964 value = GetCurrentWorldColor();
3968 case Dali::Actor::Property::WORLD_MATRIX:
3970 value = GetCurrentWorldMatrix();
3974 case Dali::Actor::Property::VISIBLE:
3976 value = IsVisible();
3980 case DevelActor::Property::CULLED:
3982 value = GetNode().IsCulled( GetEventThreadServices().GetEventBufferIndex() );
3986 case Dali::DevelActor::Property::UPDATE_SIZE_HINT:
3988 value = GetUpdateSizeHint();
3994 // Must be an event-side only property
4003 void Actor::EnsureRelayoutData()
4005 // Assign relayout data.
4006 if( !mRelayoutData )
4008 mRelayoutData = new RelayoutData();
4012 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
4014 // Check if actor is dependent on parent
4015 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4017 if( ( dimension & ( 1 << i ) ) )
4019 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4020 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
4030 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
4032 // Check if actor is dependent on children
4033 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4035 if( ( dimension & ( 1 << i ) ) )
4037 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4038 switch( resizePolicy )
4040 case ResizePolicy::FIT_TO_CHILDREN:
4041 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
4057 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
4059 return Actor::RelayoutDependentOnChildren( dimension );
4062 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
4064 // Check each possible dimension and see if it is dependent on the input one
4065 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4067 if( dimension & ( 1 << i ) )
4069 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
4076 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
4078 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4080 if( dimension & ( 1 << i ) )
4082 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
4087 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
4089 // If more than one dimension is requested, just return the first one found
4090 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4092 if( ( dimension & ( 1 << i ) ) )
4094 return mRelayoutData->negotiatedDimensions[ i ];
4098 return 0.0f; // Default
4101 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
4103 EnsureRelayoutData();
4105 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4107 if( dimension & ( 1 << i ) )
4109 mRelayoutData->dimensionPadding[ i ] = padding;
4114 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4116 if ( mRelayoutData )
4118 // If more than one dimension is requested, just return the first one found
4119 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4121 if( ( dimension & ( 1 << i ) ) )
4123 return mRelayoutData->dimensionPadding[ i ];
4128 return GetDefaultDimensionPadding();
4131 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4133 EnsureRelayoutData();
4135 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4137 if( dimension & ( 1 << i ) )
4139 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4144 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4146 if ( mRelayoutData )
4148 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4150 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4160 float Actor::GetHeightForWidthBase( float width )
4162 float height = 0.0f;
4164 const Vector3 naturalSize = GetNaturalSize();
4165 if( naturalSize.width > 0.0f )
4167 height = naturalSize.height * width / naturalSize.width;
4169 else // we treat 0 as 1:1 aspect ratio
4177 float Actor::GetWidthForHeightBase( float height )
4181 const Vector3 naturalSize = GetNaturalSize();
4182 if( naturalSize.height > 0.0f )
4184 width = naturalSize.width * height / naturalSize.height;
4186 else // we treat 0 as 1:1 aspect ratio
4194 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4196 // Fill to parent, taking size mode factor into account
4197 switch( child.GetResizePolicy( dimension ) )
4199 case ResizePolicy::FILL_TO_PARENT:
4201 return GetLatestSize( dimension );
4204 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4206 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4209 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4211 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4216 return GetLatestSize( dimension );
4221 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4223 // Can be overridden in derived class
4224 return CalculateChildSizeBase( child, dimension );
4227 float Actor::GetHeightForWidth( float width )
4229 // Can be overridden in derived class
4230 return GetHeightForWidthBase( width );
4233 float Actor::GetWidthForHeight( float height )
4235 // Can be overridden in derived class
4236 return GetWidthForHeightBase( height );
4239 float Actor::GetLatestSize( Dimension::Type dimension ) const
4241 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4244 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4246 Vector2 padding = GetPadding( dimension );
4248 return GetLatestSize( dimension ) + padding.x + padding.y;
4251 float Actor::NegotiateFromParent( Dimension::Type dimension )
4253 Actor* parent = GetParent();
4256 Vector2 padding( GetPadding( dimension ) );
4257 Vector2 parentPadding( parent->GetPadding( dimension ) );
4258 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4264 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4266 float maxDimensionPoint = 0.0f;
4268 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4270 ActorPtr child = GetChildAt( i );
4272 if( !child->RelayoutDependentOnParent( dimension ) )
4274 // Calculate the min and max points that the children range across
4275 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
4276 float dimensionSize = child->GetRelayoutSize( dimension );
4277 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4281 return maxDimensionPoint;
4284 float Actor::GetSize( Dimension::Type dimension ) const
4286 return GetDimensionValue( mTargetSize, dimension );
4289 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4291 return GetDimensionValue( GetNaturalSize(), dimension );
4294 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4296 switch( GetResizePolicy( dimension ) )
4298 case ResizePolicy::USE_NATURAL_SIZE:
4300 return GetNaturalSize( dimension );
4303 case ResizePolicy::FIXED:
4305 return GetDimensionValue( GetPreferredSize(), dimension );
4308 case ResizePolicy::USE_ASSIGNED_SIZE:
4310 return GetDimensionValue( maximumSize, dimension );
4313 case ResizePolicy::FILL_TO_PARENT:
4314 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4315 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4317 return NegotiateFromParent( dimension );
4320 case ResizePolicy::FIT_TO_CHILDREN:
4322 return NegotiateFromChildren( dimension );
4325 case ResizePolicy::DIMENSION_DEPENDENCY:
4327 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4330 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4332 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4335 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4337 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4349 return 0.0f; // Default
4352 float Actor::ClampDimension( float size, Dimension::Type dimension )
4354 const float minSize = GetMinimumSize( dimension );
4355 const float maxSize = GetMaximumSize( dimension );
4357 return std::max( minSize, std::min( size, maxSize ) );
4360 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4362 // Check if it needs to be negotiated
4363 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4365 // Check that we havn't gotten into an infinite loop
4366 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4367 bool recursionFound = false;
4368 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4370 if( *it == searchActor )
4372 recursionFound = true;
4377 if( !recursionFound )
4379 // Record the path that we have taken
4380 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4382 // Dimension dependency check
4383 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4385 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4387 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4389 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4393 // Parent dependency check
4394 Actor* parent = GetParent();
4395 if( parent && RelayoutDependentOnParent( dimension ) )
4397 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4400 // Children dependency check
4401 if( RelayoutDependentOnChildren( dimension ) )
4403 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4405 ActorPtr child = GetChildAt( i );
4407 // Only relayout child first if it is not dependent on this actor
4408 if( !child->RelayoutDependentOnParent( dimension ) )
4410 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
4415 // For deriving classes
4416 OnCalculateRelayoutSize( dimension );
4418 // All dependencies checked, calculate the size and set negotiated flag
4419 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4421 SetNegotiatedDimension( newSize, dimension );
4422 SetLayoutNegotiated( true, dimension );
4424 // For deriving classes
4425 OnLayoutNegotiated( newSize, dimension );
4427 // This actor has been successfully processed, pop it off the recursion stack
4428 recursionStack.pop_back();
4432 // TODO: Break infinite loop
4433 SetLayoutNegotiated( true, dimension );
4438 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4440 // Negotiate all dimensions that require it
4441 ActorDimensionStack recursionStack;
4443 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4445 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4448 NegotiateDimension( dimension, allocatedSize, recursionStack );
4452 Vector2 Actor::ApplySizeSetPolicy( const Vector2& size )
4454 switch( mRelayoutData->sizeSetPolicy )
4456 case SizeScalePolicy::USE_SIZE_SET:
4461 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4463 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4464 const Vector3 naturalSize = GetNaturalSize();
4465 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4467 const float sizeRatio = size.width / size.height;
4468 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4470 if( naturalSizeRatio < sizeRatio )
4472 return Vector2( naturalSizeRatio * size.height, size.height );
4474 else if( naturalSizeRatio > sizeRatio )
4476 return Vector2( size.width, size.width / naturalSizeRatio );
4487 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4489 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4490 const Vector3 naturalSize = GetNaturalSize();
4491 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4493 const float sizeRatio = size.width / size.height;
4494 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4496 if( naturalSizeRatio < sizeRatio )
4498 return Vector2( size.width, size.width / naturalSizeRatio );
4500 else if( naturalSizeRatio > sizeRatio )
4502 return Vector2( naturalSizeRatio * size.height, size.height );
4521 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4523 // Do the set actor size
4524 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4526 // Adjust for size set policy
4527 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4529 // Lock the flag to stop recursive relayouts on set size
4530 mRelayoutData->insideRelayout = true;
4531 SetSize( negotiatedSize );
4532 mRelayoutData->insideRelayout = false;
4534 // Clear flags for all dimensions
4535 SetLayoutDirty( false );
4537 // Give deriving classes a chance to respond
4538 OnRelayout( negotiatedSize, container );
4540 if( !mOnRelayoutSignal.Empty() )
4542 Dali::Actor handle( this );
4543 mOnRelayoutSignal.Emit( handle );
4547 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4549 // Force a size negotiation for actors that has assigned size during relayout
4550 // This is required as otherwise the flags that force a relayout will not
4551 // necessarilly be set. This will occur if the actor has already been laid out.
4552 // The dirty flags are then cleared. Then if the actor is added back into the
4553 // relayout container afterwards, the dirty flags would still be clear...
4554 // causing a relayout to be skipped. Here we force any actors added to the
4555 // container to be relayed out.
4556 DALI_LOG_TIMER_START( NegSizeTimer1 );
4558 if( GetUseAssignedSize(Dimension::WIDTH ) )
4560 SetLayoutNegotiated( false, Dimension::WIDTH );
4562 if( GetUseAssignedSize( Dimension::HEIGHT ) )
4564 SetLayoutNegotiated( false, Dimension::HEIGHT );
4567 // Do the negotiation
4568 NegotiateDimensions( allocatedSize );
4570 // Set the actor size
4571 SetNegotiatedSize( container );
4573 // Negotiate down to children
4574 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4576 ActorPtr child = GetChildAt( i );
4578 // Forces children that have already been laid out to be relayed out
4579 // if they have assigned size during relayout.
4580 if( child->GetUseAssignedSize(Dimension::WIDTH) )
4582 child->SetLayoutNegotiated(false, Dimension::WIDTH);
4583 child->SetLayoutDirty(true, Dimension::WIDTH);
4586 if( child->GetUseAssignedSize(Dimension::HEIGHT) )
4588 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
4589 child->SetLayoutDirty(true, Dimension::HEIGHT);
4592 // Only relayout if required
4593 if( child->RelayoutRequired() )
4595 container.Add( Dali::Actor( child.Get() ), mTargetSize.GetVectorXY() );
4598 DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
4601 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
4605 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4607 if( dimension & ( 1 << i ) )
4609 mRelayoutData->useAssignedSize[ i ] = use;
4615 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
4617 if ( mRelayoutData )
4619 // If more than one dimension is requested, just return the first one found
4620 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4622 if( dimension & ( 1 << i ) )
4624 return mRelayoutData->useAssignedSize[ i ];
4632 void Actor::RelayoutRequest( Dimension::Type dimension )
4634 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4635 if( relayoutController )
4637 Dali::Actor self( this );
4638 relayoutController->RequestRelayout( self, dimension );
4642 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4646 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4650 void Actor::SetPreferredSize( const Vector2& size )
4652 EnsureRelayoutData();
4654 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4655 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4657 mRelayoutData->preferredSize = size;
4662 Vector2 Actor::GetPreferredSize() const
4664 if ( mRelayoutData )
4666 return Vector2( mRelayoutData->preferredSize );
4669 return GetDefaultPreferredSize();
4672 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4674 EnsureRelayoutData();
4676 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4678 if( dimension & ( 1 << i ) )
4680 mRelayoutData->minimumSize[ i ] = size;
4687 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4689 if ( mRelayoutData )
4691 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4693 if( dimension & ( 1 << i ) )
4695 return mRelayoutData->minimumSize[ i ];
4700 return 0.0f; // Default
4703 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4705 EnsureRelayoutData();
4707 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4709 if( dimension & ( 1 << i ) )
4711 mRelayoutData->maximumSize[ i ] = size;
4718 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4720 if ( mRelayoutData )
4722 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4724 if( dimension & ( 1 << i ) )
4726 return mRelayoutData->maximumSize[ i ];
4731 return FLT_MAX; // Default
4734 void Actor::SetUpdateSizeHint( const Vector2& updateSizeHint )
4736 // node is being used in a separate thread; queue a message to set the value & base value
4737 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mUpdateSizeHint, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, Vector3(updateSizeHint.width, updateSizeHint.height, 0.f ) );
4740 Vector2 Actor::GetUpdateSizeHint() const
4742 // node is being used in a separate thread; copy the value from the previous update
4743 Vector3 updateSizeHint = Vector3::ZERO;
4744 GetNode().GetUpdateSizeHint( GetEventThreadServices().GetEventBufferIndex(), updateSizeHint );
4745 return Vector2( updateSizeHint.width, updateSizeHint.height );
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()
4828 mScene->RequestRebuildDepthTree();
4837 ActorContainer& siblings = *(mParent->mChildren);
4838 if( siblings.back() != this ) // If not already at end
4840 for( std::size_t i=0; i<siblings.size(); ++i )
4842 if( siblings[i] == this )
4845 ActorPtr next = siblings[i+1];
4846 siblings[i+1] = this;
4853 Dali::Actor handle( this );
4854 mParent->mChildOrderChangedSignal.Emit( handle );
4856 RequestRebuildDepthTree();
4860 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4868 ActorContainer& siblings = *(mParent->mChildren);
4869 if( siblings.front() != this ) // If not already at beginning
4871 for( std::size_t i=1; i<siblings.size(); ++i )
4873 if( siblings[i] == this )
4875 // Swap with previous
4876 ActorPtr previous = siblings[i-1];
4877 siblings[i-1] = this;
4878 siblings[i] = previous;
4884 Dali::Actor handle( this );
4885 mParent->mChildOrderChangedSignal.Emit( handle );
4887 RequestRebuildDepthTree();
4891 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4895 void Actor::RaiseToTop()
4899 ActorContainer& siblings = *(mParent->mChildren);
4900 if( siblings.back() != this ) // If not already at end
4902 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
4903 if( iter != siblings.end() )
4905 siblings.erase(iter);
4906 siblings.push_back(ActorPtr(this));
4910 Dali::Actor handle( this );
4911 mParent->mChildOrderChangedSignal.Emit( handle );
4913 RequestRebuildDepthTree();
4917 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4921 void Actor::LowerToBottom()
4925 ActorContainer& siblings = *(mParent->mChildren);
4926 if( siblings.front() != this ) // If not already at bottom,
4928 ActorPtr thisPtr(this); // ensure this actor remains referenced.
4930 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
4931 if( iter != siblings.end() )
4933 siblings.erase(iter);
4934 siblings.insert(siblings.begin(), thisPtr);
4938 Dali::Actor handle( this );
4939 mParent->mChildOrderChangedSignal.Emit( handle );
4941 RequestRebuildDepthTree();
4945 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4949 void Actor::RaiseAbove( Internal::Actor& target )
4953 ActorContainer& siblings = *(mParent->mChildren);
4954 if( siblings.back() != this && target.mParent == mParent ) // If not already at top
4956 ActorPtr thisPtr(this); // ensure this actor remains referenced.
4958 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
4959 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
4960 if( thisIter < targetIter )
4962 siblings.erase(thisIter);
4963 // Erasing early invalidates the targetIter. (Conversely, inserting first may also
4964 // invalidate thisIter)
4965 targetIter = std::find( siblings.begin(), siblings.end(), &target );
4967 siblings.insert(targetIter, thisPtr);
4970 Dali::Actor handle( this );
4971 mParent->mChildOrderChangedSignal.Emit( handle );
4973 RequestRebuildDepthTree();
4978 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4982 void Actor::LowerBelow( Internal::Actor& target )
4986 ActorContainer& siblings = *(mParent->mChildren);
4987 if( siblings.front() != this && target.mParent == mParent ) // If not already at bottom
4989 ActorPtr thisPtr(this); // ensure this actor remains referenced.
4991 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
4992 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
4994 if( thisIter > targetIter )
4996 siblings.erase(thisIter); // this only invalidates iterators at or after this point.
4997 siblings.insert(targetIter, thisPtr);
5000 Dali::Actor handle( this );
5001 mParent->mChildOrderChangedSignal.Emit( handle );
5003 RequestRebuildDepthTree();
5008 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5012 void Actor::SetScene( Scene& scene )
5017 Scene& Actor::GetScene() const
5022 void Actor::SetInheritLayoutDirection( bool inherit )
5024 if( mInheritLayoutDirection != inherit )
5026 mInheritLayoutDirection = inherit;
5028 if( inherit && mParent )
5030 InheritLayoutDirectionRecursively( this, mParent->mLayoutDirection );
5035 bool Actor::IsLayoutDirectionInherited() const
5037 return mInheritLayoutDirection;
5040 void Actor::InheritLayoutDirectionRecursively( ActorPtr actor, Dali::LayoutDirection::Type direction, bool set )
5042 if( actor && ( actor->mInheritLayoutDirection || set ) )
5044 if( actor->mLayoutDirection != direction )
5046 actor->mLayoutDirection = direction;
5047 actor->EmitLayoutDirectionChangedSignal( direction );
5048 actor->RelayoutRequest();
5051 if( actor->GetChildCount() > 0 )
5053 ActorContainer& children = actor->GetChildrenInternal();
5054 for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter )
5056 InheritLayoutDirectionRecursively( *iter, direction );
5062 } // namespace Internal