2 * Copyright (c) 2020 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_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperties )
221 const char* const SIGNAL_TOUCHED = "touched";
222 const char* const SIGNAL_HOVERED = "hovered";
223 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
224 const char* const SIGNAL_ON_STAGE = "onStage";
225 const char* const SIGNAL_OFF_STAGE = "offStage";
226 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
227 const char* const SIGNAL_TOUCH = "touch";
228 const char* const SIGNAL_VISIBILITY_CHANGED = "visibilityChanged";
229 const char* const SIGNAL_LAYOUT_DIRECTION_CHANGED = "layoutDirectionChanged";
230 const char* const SIGNAL_CHILD_ADDED = "childAdded";
231 const char* const SIGNAL_CHILD_REMOVED = "childRemoved";
235 const char* const ACTION_SHOW = "show";
236 const char* const ACTION_HIDE = "hide";
238 BaseHandle CreateActor()
240 return Dali::Actor::New();
243 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor, ActorDefaultProperties );
245 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
246 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
247 SignalConnectorType signalConnector3( mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal );
248 SignalConnectorType signalConnector4( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
249 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
250 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
251 SignalConnectorType signalConnector7( mType, SIGNAL_TOUCH, &Actor::DoConnectSignal );
252 SignalConnectorType signalConnector8( mType, SIGNAL_VISIBILITY_CHANGED, &Actor::DoConnectSignal );
253 SignalConnectorType signalConnector9( mType, SIGNAL_LAYOUT_DIRECTION_CHANGED, &Actor::DoConnectSignal );
254 SignalConnectorType signalConnector10( mType, SIGNAL_CHILD_ADDED, &Actor::DoConnectSignal );
255 SignalConnectorType signalConnector11( mType, SIGNAL_CHILD_REMOVED, &Actor::DoConnectSignal );
257 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
258 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
263 const Vector3& value;
266 DALI_ENUM_TO_STRING_TABLE_BEGIN_WITH_TYPE( AnchorValue, ANCHOR_CONSTANT )
267 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_LEFT )
268 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_CENTER )
269 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_RIGHT )
270 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_LEFT )
271 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER )
272 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_RIGHT )
273 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_LEFT )
274 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_CENTER )
275 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_RIGHT )
276 DALI_ENUM_TO_STRING_TABLE_END( ANCHOR_CONSTANT )
278 DALI_ENUM_TO_STRING_TABLE_BEGIN( COLOR_MODE )
279 DALI_ENUM_TO_STRING( USE_OWN_COLOR )
280 DALI_ENUM_TO_STRING( USE_PARENT_COLOR )
281 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_COLOR )
282 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_ALPHA )
283 DALI_ENUM_TO_STRING_TABLE_END( COLOR_MODE )
285 DALI_ENUM_TO_STRING_TABLE_BEGIN( DRAW_MODE )
286 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, NORMAL )
287 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, OVERLAY_2D )
288 DALI_ENUM_TO_STRING_TABLE_END( DRAW_MODE )
290 DALI_ENUM_TO_STRING_TABLE_BEGIN( RESIZE_POLICY )
291 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIXED )
292 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_NATURAL_SIZE )
293 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FILL_TO_PARENT )
294 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_RELATIVE_TO_PARENT )
295 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_FIXED_OFFSET_FROM_PARENT )
296 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIT_TO_CHILDREN )
297 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, DIMENSION_DEPENDENCY )
298 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_ASSIGNED_SIZE )
299 DALI_ENUM_TO_STRING_TABLE_END( RESIZE_POLICY )
301 DALI_ENUM_TO_STRING_TABLE_BEGIN( SIZE_SCALE_POLICY )
302 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, USE_SIZE_SET )
303 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FIT_WITH_ASPECT_RATIO )
304 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FILL_WITH_ASPECT_RATIO )
305 DALI_ENUM_TO_STRING_TABLE_END( SIZE_SCALE_POLICY )
307 DALI_ENUM_TO_STRING_TABLE_BEGIN( CLIPPING_MODE )
308 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, DISABLED )
309 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, CLIP_CHILDREN )
310 DALI_ENUM_TO_STRING_TABLE_END( CLIPPING_MODE )
312 DALI_ENUM_TO_STRING_TABLE_BEGIN( LAYOUT_DIRECTION )
313 DALI_ENUM_TO_STRING_WITH_SCOPE( LayoutDirection, LEFT_TO_RIGHT )
314 DALI_ENUM_TO_STRING_WITH_SCOPE( LayoutDirection, RIGHT_TO_LEFT )
315 DALI_ENUM_TO_STRING_TABLE_END( LAYOUT_DIRECTION )
317 bool GetAnchorPointConstant( const std::string& value, Vector3& anchor )
319 for( uint32_t i = 0; i < ANCHOR_CONSTANT_TABLE_COUNT; ++i )
321 uint32_t sizeIgnored = 0;
322 if( CompareTokens( value.c_str(), ANCHOR_CONSTANT_TABLE[ i ].name, sizeIgnored ) )
324 anchor = ANCHOR_CONSTANT_TABLE[ i ].value;
331 inline bool GetParentOriginConstant( const std::string& value, Vector3& parentOrigin )
333 // Values are the same so just use the same table as anchor-point
334 return GetAnchorPointConstant( value, parentOrigin );
338 * @brief Extract a given dimension from a Vector2
340 * @param[in] values The values to extract from
341 * @param[in] dimension The dimension to extract
342 * @return Return the value for the dimension
344 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
348 case Dimension::WIDTH:
352 case Dimension::HEIGHT:
354 return values.height;
365 * @brief Extract a given dimension from a Vector3
367 * @param[in] values The values to extract from
368 * @param[in] dimension The dimension to extract
369 * @return Return the value for the dimension
371 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
373 return GetDimensionValue( values.GetVectorXY(), dimension );
377 * @brief Recursively emits the visibility-changed-signal on the actor tree.
378 * @param[in] actor The actor to emit the signal on
379 * @param[in] visible The new visibility of the actor
380 * @param[in] type Whether the actor's visible property has changed or a parent's
382 void EmitVisibilityChangedSignalRecursively( ActorPtr actor, bool visible, DevelActor::VisibilityChange::Type type )
386 actor->EmitVisibilityChangedSignal( visible, type );
388 if( actor->GetChildCount() > 0 )
390 ActorContainer& children = actor->GetChildrenInternal();
391 for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter )
393 EmitVisibilityChangedSignalRecursively( *iter, visible, DevelActor::VisibilityChange::PARENT );
399 } // unnamed namespace
401 ActorPtr Actor::New()
403 // pass a reference to actor, actor does not own its node
404 ActorPtr actor( new Actor( BASIC, *CreateNode() ) );
406 // Second-phase construction
412 const SceneGraph::Node* Actor::CreateNode()
414 // create node. Nodes are owned by the update manager
415 SceneGraph::Node* node = SceneGraph::Node::New();
416 OwnerPointer< SceneGraph::Node > transferOwnership( node );
417 Internal::ThreadLocalStorage* tls = Internal::ThreadLocalStorage::GetInternal();
418 AddNodeMessage( tls->GetUpdateManager(), transferOwnership );
423 const std::string& Actor::GetName() const
428 void Actor::SetName( const std::string& name )
432 // ATTENTION: string for debug purposes is not thread safe.
433 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( &GetNode() ), name );
436 uint32_t Actor::GetId() const
438 return GetNode().GetId();
441 bool Actor::OnStage() const
446 Dali::Layer Actor::GetLayer()
450 // Short-circuit for Layer derived actors
453 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
456 // Find the immediate Layer parent
457 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
459 if( parent->IsLayer() )
461 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
468 void Actor::Add( Actor& child )
470 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
471 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
475 mChildren = new ActorContainer;
478 Actor* const oldParent( child.mParent );
480 // child might already be ours
481 if( this != oldParent )
483 // if we already have parent, unparent us first
486 oldParent->Remove( child ); // This causes OnChildRemove callback & ChildRemoved signal
488 // Old parent may need to readjust to missing child
489 if( oldParent->RelayoutDependentOnChildren() )
491 oldParent->RelayoutRequest();
495 // Guard against Add() during previous OnChildRemove callback
498 // Do this first, since user callbacks from within SetParent() may need to remove child
499 mChildren->push_back( ActorPtr( &child ) );
501 // SetParent asserts that child can be added
502 child.SetParent( this );
504 // Notification for derived classes
506 EmitChildAddedSignal( child );
508 InheritLayoutDirectionRecursively( ActorPtr( &child ), mLayoutDirection );
510 // Only put in a relayout request if there is a suitable dependency
511 if( RelayoutDependentOnChildren() )
519 void Actor::Remove( Actor& child )
521 if( (this == &child) || (!mChildren) )
523 // no children or removing itself
529 // Find the child in mChildren, and unparent it
530 ActorIter end = mChildren->end();
531 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
533 ActorPtr actor = (*iter);
535 if( actor.Get() == &child )
537 // Keep handle for OnChildRemove notification
540 // Do this first, since user callbacks from within SetParent() may need to add the child
541 mChildren->erase( iter );
543 DALI_ASSERT_DEBUG( actor->GetParent() == this );
544 actor->SetParent( NULL );
552 // Only put in a relayout request if there is a suitable dependency
553 if( RelayoutDependentOnChildren() )
559 // Notification for derived classes
560 OnChildRemove( child );
561 EmitChildRemovedSignal( child );
564 void Actor::Unparent()
568 // Remove this actor from the parent. The remove will put a relayout request in for
569 // the parent if required
570 mParent->Remove( *this );
571 // mParent is now NULL!
575 uint32_t Actor::GetChildCount() const
577 return ( NULL != mChildren ) ? static_cast<uint32_t>( mChildren->size() ) : 0; // only 4,294,967,295 children per actor
580 ActorPtr Actor::GetChildAt( uint32_t index ) const
582 DALI_ASSERT_ALWAYS( index < GetChildCount() );
584 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
587 ActorPtr Actor::FindChildByName( const std::string& actorName )
590 if( actorName == mName )
596 ActorIter end = mChildren->end();
597 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
599 child = (*iter)->FindChildByName( actorName );
610 ActorPtr Actor::FindChildById( const uint32_t id )
619 ActorIter end = mChildren->end();
620 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
622 child = (*iter)->FindChildById( id );
633 void Actor::SetParentOrigin( const Vector3& origin )
635 // node is being used in a separate thread; queue a message to set the value & base value
636 SetParentOriginMessage( GetEventThreadServices(), GetNode(), origin );
638 // Cache for event-thread access
641 // not allocated, check if different from default
642 if( ParentOrigin::DEFAULT != origin )
644 mParentOrigin = new Vector3( origin );
649 // check if different from current costs more than just set
650 *mParentOrigin = origin;
654 void Actor::SetParentOriginX( float x )
656 const Vector3& current = GetCurrentParentOrigin();
658 SetParentOrigin( Vector3( x, current.y, current.z ) );
661 void Actor::SetParentOriginY( float y )
663 const Vector3& current = GetCurrentParentOrigin();
665 SetParentOrigin( Vector3( current.x, y, current.z ) );
668 void Actor::SetParentOriginZ( float z )
670 const Vector3& current = GetCurrentParentOrigin();
672 SetParentOrigin( Vector3( current.x, current.y, z ) );
675 const Vector3& Actor::GetCurrentParentOrigin() const
677 // Cached for event-thread access
678 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
681 void Actor::SetAnchorPoint( const Vector3& anchor )
683 // node is being used in a separate thread; queue a message to set the value & base value
684 SetAnchorPointMessage( GetEventThreadServices(), GetNode(), anchor );
686 // Cache for event-thread access
689 // not allocated, check if different from default
690 if( AnchorPoint::DEFAULT != anchor )
692 mAnchorPoint = new Vector3( anchor );
697 // check if different from current costs more than just set
698 *mAnchorPoint = anchor;
702 void Actor::SetAnchorPointX( float x )
704 const Vector3& current = GetCurrentAnchorPoint();
706 SetAnchorPoint( Vector3( x, current.y, current.z ) );
709 void Actor::SetAnchorPointY( float y )
711 const Vector3& current = GetCurrentAnchorPoint();
713 SetAnchorPoint( Vector3( current.x, y, current.z ) );
716 void Actor::SetAnchorPointZ( float z )
718 const Vector3& current = GetCurrentAnchorPoint();
720 SetAnchorPoint( Vector3( current.x, current.y, z ) );
723 const Vector3& Actor::GetCurrentAnchorPoint() const
725 // Cached for event-thread access
726 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
729 void Actor::SetPosition( float x, float y )
731 SetPosition( Vector3( x, y, 0.0f ) );
734 void Actor::SetPosition( float x, float y, float z )
736 SetPosition( Vector3( x, y, z ) );
739 void Actor::SetPosition( const Vector3& position )
741 mTargetPosition = position;
743 // node is being used in a separate thread; queue a message to set the value & base value
744 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
747 void Actor::SetX( float x )
749 mTargetPosition.x = x;
751 // node is being used in a separate thread; queue a message to set the value & base value
752 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
755 void Actor::SetY( float y )
757 mTargetPosition.y = y;
759 // node is being used in a separate thread; queue a message to set the value & base value
760 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
763 void Actor::SetZ( float z )
765 mTargetPosition.z = z;
767 // node is being used in a separate thread; queue a message to set the value & base value
768 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
771 void Actor::TranslateBy( const Vector3& distance )
773 mTargetPosition += distance;
775 // node is being used in a separate thread; queue a message to set the value & base value
776 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
779 const Vector3& Actor::GetCurrentPosition() const
781 // node is being used in a separate thread; copy the value from the previous update
782 return GetNode().GetPosition(GetEventThreadServices().GetEventBufferIndex());
785 const Vector3& Actor::GetTargetPosition() const
787 return mTargetPosition;
790 const Vector3& Actor::GetCurrentWorldPosition() const
792 // node is being used in a separate thread; copy the value from the previous update
793 return GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
796 const Vector2 Actor::GetCurrentScreenPosition() const
798 if( mScene && OnStage() )
800 Vector3 worldPosition = GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
801 Vector3 cameraPosition = mScene->GetDefaultCameraActor().GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
802 worldPosition -= cameraPosition;
804 Vector3 actorSize = GetCurrentSize() * GetCurrentWorldScale();
805 Vector2 halfSceneSize( mScene->GetSize() * 0.5f ); // World position origin is center of scene
806 Vector3 halfActorSize( actorSize * 0.5f );
807 Vector3 anchorPointOffSet = halfActorSize - actorSize * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
809 return Vector2( halfSceneSize.width + worldPosition.x - anchorPointOffSet.x,
810 halfSceneSize.height + worldPosition.y - anchorPointOffSet.y );
813 return Vector2::ZERO;
816 void Actor::SetInheritPosition( bool inherit )
818 if( mInheritPosition != inherit )
820 // non animatable so keep local copy
821 mInheritPosition = inherit;
822 SetInheritPositionMessage( GetEventThreadServices(), GetNode(), inherit );
826 bool Actor::IsPositionInherited() const
828 return mInheritPosition;
831 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
833 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
834 normalizedAxis.Normalize();
836 Quaternion orientation( angle, normalizedAxis );
838 SetOrientation( orientation );
841 void Actor::SetOrientation( const Quaternion& orientation )
843 mTargetOrientation = orientation;
845 // node is being used in a separate thread; queue a message to set the value & base value
846 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation );
849 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
851 RotateBy( Quaternion(angle, axis) );
854 void Actor::RotateBy( const Quaternion& relativeRotation )
856 mTargetOrientation *= Quaternion( relativeRotation );
858 // node is being used in a separate thread; queue a message to set the value & base value
859 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
862 const Quaternion& Actor::GetCurrentOrientation() const
864 // node is being used in a separate thread; copy the value from the previous update
865 return GetNode().GetOrientation(GetEventThreadServices().GetEventBufferIndex());
868 const Quaternion& Actor::GetCurrentWorldOrientation() const
870 // node is being used in a separate thread; copy the value from the previous update
871 return GetNode().GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
874 void Actor::SetScale( float scale )
876 SetScale( Vector3( scale, scale, scale ) );
879 void Actor::SetScale( float x, float y, float z )
881 SetScale( Vector3( x, y, z ) );
884 void Actor::SetScale( const Vector3& scale )
886 mTargetScale = scale;
888 // node is being used in a separate thread; queue a message to set the value & base value
889 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
892 void Actor::SetScaleX( float x )
896 // node is being used in a separate thread; queue a message to set the value & base value
897 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
900 void Actor::SetScaleY( float y )
904 // node is being used in a separate thread; queue a message to set the value & base value
905 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
908 void Actor::SetScaleZ( float z )
912 // node is being used in a separate thread; queue a message to set the value & base value
913 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
916 void Actor::ScaleBy(const Vector3& relativeScale)
918 mTargetScale *= relativeScale;
920 // node is being used in a separate thread; queue a message to set the value & base value
921 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
924 const Vector3& Actor::GetCurrentScale() const
926 // node is being used in a separate thread; copy the value from the previous update
927 return GetNode().GetScale(GetEventThreadServices().GetEventBufferIndex());
930 const Vector3& Actor::GetCurrentWorldScale() const
932 // node is being used in a separate thread; copy the value from the previous update
933 return GetNode().GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
936 void Actor::SetInheritScale( bool inherit )
938 if( mInheritScale != inherit )
940 // non animatable so keep local copy
941 mInheritScale = inherit;
942 // node is being used in a separate thread; queue a message to set the value
943 SetInheritScaleMessage( GetEventThreadServices(), GetNode(), inherit );
947 bool Actor::IsScaleInherited() const
949 return mInheritScale;
952 Matrix Actor::GetCurrentWorldMatrix() const
954 return GetNode().GetWorldMatrix(0);
957 void Actor::SetVisible( bool visible )
959 SetVisibleInternal( visible, SendMessage::TRUE );
962 bool Actor::IsVisible() const
964 // node is being used in a separate thread; copy the value from the previous update
965 return GetNode().IsVisible( GetEventThreadServices().GetEventBufferIndex() );
968 void Actor::SetOpacity( float opacity )
970 mTargetColor.a = opacity;
972 // node is being used in a separate thread; queue a message to set the value & base value
973 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
976 float Actor::GetCurrentOpacity() const
978 // node is being used in a separate thread; copy the value from the previous update
979 return GetNode().GetOpacity(GetEventThreadServices().GetEventBufferIndex());
982 ClippingMode::Type Actor::GetClippingMode() const
984 return mClippingMode;
987 uint32_t Actor::GetSortingDepth()
992 const Vector4& Actor::GetCurrentWorldColor() const
994 return GetNode().GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
997 void Actor::SetColor( const Vector4& color )
999 mTargetColor = color;
1001 // node is being used in a separate thread; queue a message to set the value & base value
1002 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::Bake, color );
1005 void Actor::SetColorRed( float red )
1007 mTargetColor.r = red;
1009 // node is being used in a separate thread; queue a message to set the value & base value
1010 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeX, red );
1013 void Actor::SetColorGreen( float green )
1015 mTargetColor.g = green;
1017 // node is being used in a separate thread; queue a message to set the value & base value
1018 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeY, green );
1021 void Actor::SetColorBlue( float blue )
1023 mTargetColor.b = blue;
1025 // node is being used in a separate thread; queue a message to set the value & base value
1026 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1029 const Vector4& Actor::GetCurrentColor() const
1031 // node is being used in a separate thread; copy the value from the previous update
1032 return GetNode().GetColor(GetEventThreadServices().GetEventBufferIndex());
1035 void Actor::SetInheritOrientation( bool inherit )
1037 if( mInheritOrientation != inherit )
1039 // non animatable so keep local copy
1040 mInheritOrientation = inherit;
1041 // node is being used in a separate thread; queue a message to set the value
1042 SetInheritOrientationMessage( GetEventThreadServices(), GetNode(), inherit );
1046 bool Actor::IsOrientationInherited() const
1048 return mInheritOrientation;
1051 void Actor::SetSizeModeFactor( const Vector3& factor )
1053 EnsureRelayoutData();
1055 mRelayoutData->sizeModeFactor = factor;
1058 const Vector3& Actor::GetSizeModeFactor() const
1060 if ( mRelayoutData )
1062 return mRelayoutData->sizeModeFactor;
1065 return GetDefaultSizeModeFactor();
1068 void Actor::SetColorMode( ColorMode colorMode )
1070 // non animatable so keep local copy
1071 mColorMode = colorMode;
1072 // node is being used in a separate thread; queue a message to set the value
1073 SetColorModeMessage( GetEventThreadServices(), GetNode(), colorMode );
1076 ColorMode Actor::GetColorMode() const
1078 // we have cached copy
1082 void Actor::SetSize( float width, float height )
1084 SetSize( Vector2( width, height ) );
1087 void Actor::SetSize( float width, float height, float depth )
1089 SetSize( Vector3( width, height, depth ) );
1092 void Actor::SetSize( const Vector2& size )
1094 SetSize( Vector3( size.width, size.height, 0.f ) );
1097 void Actor::SetSizeInternal( const Vector2& size )
1099 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1102 void Actor::SetSize( const Vector3& size )
1104 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1106 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1107 SetPreferredSize( size.GetVectorXY() );
1111 SetSizeInternal( size );
1115 void Actor::SetSizeInternal( const Vector3& size )
1117 // dont allow recursive loop
1118 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1119 // 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
1120 if( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1121 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1122 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) )
1126 // node is being used in a separate thread; queue a message to set the value & base value
1127 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
1129 // Notification for derived classes
1130 mInsideOnSizeSet = true;
1131 OnSizeSet( mTargetSize );
1132 mInsideOnSizeSet = false;
1134 // Raise a relayout request if the flag is not locked
1135 if( mRelayoutData && !mRelayoutData->insideRelayout )
1142 void Actor::SetWidth( float width )
1144 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1146 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
1147 mRelayoutData->preferredSize.width = width;
1151 mTargetSize.width = width;
1153 // node is being used in a separate thread; queue a message to set the value & base value
1154 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1160 void Actor::SetHeight( float height )
1162 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1164 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
1165 mRelayoutData->preferredSize.height = height;
1169 mTargetSize.height = height;
1171 // node is being used in a separate thread; queue a message to set the value & base value
1172 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1178 void Actor::SetDepth( float depth )
1180 mTargetSize.depth = depth;
1182 // node is being used in a separate thread; queue a message to set the value & base value
1183 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1186 Vector3 Actor::GetTargetSize() const
1188 Vector3 size = mTargetSize;
1190 // Should return preferred size if size is fixed as set by SetSize
1191 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
1193 size.width = GetPreferredSize().width;
1195 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
1197 size.height = GetPreferredSize().height;
1203 const Vector3& Actor::GetCurrentSize() const
1205 // node is being used in a separate thread; copy the value from the previous update
1206 return GetNode().GetSize( GetEventThreadServices().GetEventBufferIndex() );
1209 Vector3 Actor::GetNaturalSize() const
1211 // It is up to deriving classes to return the appropriate natural size
1212 return Vector3( 0.0f, 0.0f, 0.0f );
1215 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1217 EnsureRelayoutData();
1219 ResizePolicy::Type originalWidthPolicy = GetResizePolicy(Dimension::WIDTH);
1220 ResizePolicy::Type originalHeightPolicy = GetResizePolicy(Dimension::HEIGHT);
1222 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1224 if( dimension & ( 1 << i ) )
1226 if ( policy == ResizePolicy::USE_ASSIGNED_SIZE )
1228 mRelayoutData->useAssignedSize[ i ] = true;
1232 mRelayoutData->resizePolicies[ i ] = policy;
1233 mRelayoutData->useAssignedSize[ i ] = false;
1238 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1240 if( dimension & Dimension::WIDTH )
1242 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1245 if( dimension & Dimension::HEIGHT )
1247 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1251 // If calling SetResizePolicy, assume we want relayout enabled
1252 SetRelayoutEnabled( true );
1254 // If the resize policy is set to be FIXED, the preferred size
1255 // should be overrided by the target size. Otherwise the target
1256 // size should be overrided by the preferred size.
1258 if( dimension & Dimension::WIDTH )
1260 if( originalWidthPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1262 mRelayoutData->preferredSize.width = mTargetSize.width;
1264 else if( originalWidthPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1266 mTargetSize.width = mRelayoutData->preferredSize.width;
1270 if( dimension & Dimension::HEIGHT )
1272 if( originalHeightPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1274 mRelayoutData->preferredSize.height = mTargetSize.height;
1276 else if( originalHeightPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1278 mTargetSize.height = mRelayoutData->preferredSize.height;
1282 OnSetResizePolicy( policy, dimension );
1284 // Trigger relayout on this control
1288 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1290 if ( mRelayoutData )
1292 // If more than one dimension is requested, just return the first one found
1293 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1295 if( ( dimension & ( 1 << i ) ) )
1297 if( mRelayoutData->useAssignedSize[ i ] )
1299 return ResizePolicy::USE_ASSIGNED_SIZE;
1303 return mRelayoutData->resizePolicies[ i ];
1309 return ResizePolicy::DEFAULT;
1312 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1314 EnsureRelayoutData();
1316 mRelayoutData->sizeSetPolicy = policy;
1318 // Trigger relayout on this control
1322 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1324 if ( mRelayoutData )
1326 return mRelayoutData->sizeSetPolicy;
1329 return DEFAULT_SIZE_SCALE_POLICY;
1332 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1334 EnsureRelayoutData();
1336 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1338 if( dimension & ( 1 << i ) )
1340 mRelayoutData->dimensionDependencies[ i ] = dependency;
1345 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1347 if ( mRelayoutData )
1349 // If more than one dimension is requested, just return the first one found
1350 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1352 if( ( dimension & ( 1 << i ) ) )
1354 return mRelayoutData->dimensionDependencies[ i ];
1359 return Dimension::ALL_DIMENSIONS; // Default
1362 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1364 // If relayout data has not been allocated yet and the client is requesting
1365 // to disable it, do nothing
1366 if( mRelayoutData || relayoutEnabled )
1368 EnsureRelayoutData();
1370 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1372 mRelayoutData->relayoutEnabled = relayoutEnabled;
1376 bool Actor::IsRelayoutEnabled() const
1378 // Assume that if relayout data has not been allocated yet then
1379 // relayout is disabled
1380 return mRelayoutData && mRelayoutData->relayoutEnabled;
1383 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1385 EnsureRelayoutData();
1387 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1389 if( dimension & ( 1 << i ) )
1391 mRelayoutData->dimensionDirty[ i ] = dirty;
1396 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1398 if ( mRelayoutData )
1400 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1402 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1412 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1414 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1417 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1419 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1422 uint32_t Actor::AddRenderer( Renderer& renderer )
1426 mRenderers = new RendererContainer;
1429 uint32_t index = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1430 RendererPtr rendererPtr = RendererPtr( &renderer );
1431 mRenderers->push_back( rendererPtr );
1432 AttachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1436 uint32_t Actor::GetRendererCount() const
1438 uint32_t rendererCount(0);
1441 rendererCount = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1444 return rendererCount;
1447 RendererPtr Actor::GetRendererAt( uint32_t index )
1449 RendererPtr renderer;
1450 if( index < GetRendererCount() )
1452 renderer = ( *mRenderers )[ index ];
1458 void Actor::RemoveRenderer( Renderer& renderer )
1462 RendererIter end = mRenderers->end();
1463 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1465 if( (*iter).Get() == &renderer )
1467 mRenderers->erase( iter );
1468 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1475 void Actor::RemoveRenderer( uint32_t index )
1477 if( index < GetRendererCount() )
1479 RendererPtr renderer = ( *mRenderers )[ index ];
1480 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.Get()->GetRendererSceneObject() );
1481 mRenderers->erase( mRenderers->begin()+index );
1485 bool Actor::IsOverlay() const
1487 return ( DrawMode::OVERLAY_2D == mDrawMode );
1490 void Actor::SetDrawMode( DrawMode::Type drawMode )
1492 // this flag is not animatable so keep the value
1493 mDrawMode = drawMode;
1495 // node is being used in a separate thread; queue a message to set the value
1496 SetDrawModeMessage( GetEventThreadServices(), GetNode(), drawMode );
1499 DrawMode::Type Actor::GetDrawMode() const
1504 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1506 // only valid when on-stage
1507 if( mScene && OnStage() )
1509 const RenderTaskList& taskList = mScene->GetRenderTaskList();
1511 Vector2 converted( screenX, screenY );
1513 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1514 uint32_t taskCount = taskList.GetTaskCount();
1515 for( uint32_t i = taskCount; i > 0; --i )
1517 RenderTaskPtr task = taskList.GetTask( i - 1 );
1518 if( ScreenToLocal( *task, localX, localY, screenX, screenY ) )
1520 // found a task where this conversion was ok so return
1528 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1530 bool retval = false;
1531 // only valid when on-stage
1534 CameraActor* camera = renderTask.GetCameraActor();
1538 renderTask.GetViewport( viewport );
1540 // need to translate coordinates to render tasks coordinate space
1541 Vector2 converted( screenX, screenY );
1542 if( renderTask.TranslateCoordinates( converted ) )
1544 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1551 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1553 // Early-out if not on stage
1559 // Get the ModelView matrix
1561 Matrix::Multiply( modelView, GetNode().GetWorldMatrix(0), viewMatrix );
1563 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1564 Matrix invertedMvp( false/*don't init*/);
1565 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1566 bool success = invertedMvp.Invert();
1568 // Convert to GL coordinates
1569 Vector4 screenPos( screenX - static_cast<float>( viewport.x ), static_cast<float>( viewport.height ) - screenY - static_cast<float>( viewport.y ), 0.f, 1.f );
1574 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), nearPos );
1581 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), farPos );
1587 if( XyPlaneIntersect( nearPos, farPos, local ) )
1589 Vector3 size = GetCurrentSize();
1590 localX = local.x + size.x * 0.5f;
1591 localY = local.y + size.y * 0.5f;
1602 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1605 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1607 Mathematical Formulation
1609 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1611 ( p - c ) dot ( p - c ) = r^2
1613 Given a ray with a point of origin 'o', and a direction vector 'd':
1615 ray(t) = o + td, t >= 0
1617 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1619 (o + td - c ) dot ( o + td - c ) = r^2
1621 To solve for t we first expand the above into a more recognisable quadratic equation form
1623 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1632 B = 2( o - c ) dot d
1633 C = ( o - c ) dot ( o - c ) - r^2
1635 which can be solved using a standard quadratic formula.
1637 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1639 Practical Simplification
1641 In a renderer, we often differentiate between world space and object space. In the object space
1642 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1643 into object space, the mathematical solution presented above can be simplified significantly.
1645 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1649 and we can find the t at which the (transformed) ray intersects the sphere by
1651 ( o + td ) dot ( o + td ) = r^2
1653 According to the reasoning above, we expand the above quadratic equation into the general form
1657 which now has coefficients:
1664 // Early-out if not on stage
1670 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1672 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1673 const Vector3& translation( GetNode().GetWorldPosition( bufferIndex ) );
1674 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1676 // Compute the radius is not needed, square radius it's enough.
1677 const Vector3& size( GetNode().GetSize( bufferIndex ) );
1679 // Scale the sphere.
1680 const Vector3& scale( GetNode().GetWorldScale( bufferIndex ) );
1682 const float width = size.width * scale.width;
1683 const float height = size.height * scale.height;
1685 float squareSphereRadius = 0.5f * ( width * width + height * height );
1687 float a = rayDir.Dot( rayDir ); // a
1688 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1689 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1691 return ( b2 * b2 - a * c ) >= 0.f;
1694 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector2& hitPointLocal, float& distance ) const
1700 // Transforms the ray to the local reference system.
1701 // Calculate the inverse of Model matrix
1702 Matrix invModelMatrix( false/*don't init*/);
1704 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1705 invModelMatrix = GetNode().GetWorldMatrix(0);
1706 invModelMatrix.Invert();
1708 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1709 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1711 // Test with the actor's XY plane (Normal = 0 0 1 1).
1713 float a = -rayOriginLocal.z;
1714 float b = rayDirLocal.z;
1716 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1718 // Ray travels distance * rayDirLocal to intersect with plane.
1721 const Vector3& size = GetNode().GetSize( bufferIndex );
1723 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1724 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1726 // Test with the actor's geometry.
1727 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1734 void Actor::SetLeaveRequired( bool required )
1736 mLeaveRequired = required;
1739 bool Actor::GetLeaveRequired() const
1741 return mLeaveRequired;
1744 void Actor::SetKeyboardFocusable( bool focusable )
1746 mKeyboardFocusable = focusable;
1749 bool Actor::IsKeyboardFocusable() const
1751 return mKeyboardFocusable;
1754 bool Actor::GetTouchRequired() const
1756 return !mTouchedSignal.Empty() || !mTouchSignal.Empty() || mDerivedRequiresTouch;
1759 bool Actor::GetHoverRequired() const
1761 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1764 bool Actor::GetWheelEventRequired() const
1766 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1769 bool Actor::IsHittable() const
1771 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1774 ActorGestureData& Actor::GetGestureData()
1776 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1777 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1778 if( NULL == mGestureData )
1780 mGestureData = new ActorGestureData;
1782 return *mGestureData;
1785 bool Actor::IsGestureRequred( DevelGesture::Type type ) const
1787 return mGestureData && mGestureData->IsGestureRequred( type );
1790 bool Actor::EmitTouchEventSignal( const TouchEvent& event, const Dali::TouchData& touch )
1792 bool consumed = false;
1794 if( !mTouchSignal.Empty() )
1796 Dali::Actor handle( this );
1797 consumed = mTouchSignal.Emit( handle, touch );
1800 if( !mTouchedSignal.Empty() )
1802 Dali::Actor handle( this );
1803 consumed |= mTouchedSignal.Emit( handle, event );
1808 // Notification for derived classes
1809 consumed = OnTouchEvent( event ); // TODO
1815 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1817 bool consumed = false;
1819 if( !mHoveredSignal.Empty() )
1821 Dali::Actor handle( this );
1822 consumed = mHoveredSignal.Emit( handle, event );
1827 // Notification for derived classes
1828 consumed = OnHoverEvent( event );
1834 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1836 bool consumed = false;
1838 if( !mWheelEventSignal.Empty() )
1840 Dali::Actor handle( this );
1841 consumed = mWheelEventSignal.Emit( handle, event );
1846 // Notification for derived classes
1847 consumed = OnWheelEvent( event );
1853 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
1855 if( ! mVisibilityChangedSignal.Empty() )
1857 Dali::Actor handle( this );
1858 mVisibilityChangedSignal.Emit( handle, visible, type );
1862 void Actor::EmitLayoutDirectionChangedSignal( LayoutDirection::Type type )
1864 if( ! mLayoutDirectionChangedSignal.Empty() )
1866 Dali::Actor handle( this );
1867 mLayoutDirectionChangedSignal.Emit( handle, type );
1871 void Actor::EmitChildAddedSignal( Actor& child )
1873 if( ! mChildAddedSignal.Empty() )
1875 Dali::Actor handle( &child );
1876 mChildAddedSignal.Emit( handle );
1880 void Actor::EmitChildRemovedSignal( Actor& child )
1882 if( ! mChildRemovedSignal.Empty() )
1884 Dali::Actor handle( &child );
1885 mChildRemovedSignal.Emit( handle );
1889 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
1891 return mTouchedSignal;
1894 Dali::Actor::TouchDataSignalType& Actor::TouchSignal()
1896 return mTouchSignal;
1899 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
1901 return mHoveredSignal;
1904 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
1906 return mWheelEventSignal;
1909 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
1911 return mOnStageSignal;
1914 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
1916 return mOffStageSignal;
1919 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
1921 return mOnRelayoutSignal;
1924 DevelActor::VisibilityChangedSignalType& Actor::VisibilityChangedSignal()
1926 return mVisibilityChangedSignal;
1929 Dali::Actor::LayoutDirectionChangedSignalType& Actor::LayoutDirectionChangedSignal()
1931 return mLayoutDirectionChangedSignal;
1934 DevelActor::ChildChangedSignalType& Actor::ChildAddedSignal()
1936 return mChildAddedSignal;
1939 DevelActor::ChildChangedSignalType& Actor::ChildRemovedSignal()
1941 return mChildRemovedSignal;
1944 DevelActor::ChildOrderChangedSignalType& Actor::ChildOrderChangedSignal()
1946 return mChildOrderChangedSignal;
1949 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1951 bool connected( true );
1952 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
1954 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1956 actor->TouchedSignal().Connect( tracker, functor );
1958 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1960 actor->HoveredSignal().Connect( tracker, functor );
1962 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1964 actor->WheelEventSignal().Connect( tracker, functor );
1966 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
1968 actor->OnStageSignal().Connect( tracker, functor );
1970 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
1972 actor->OffStageSignal().Connect( tracker, functor );
1974 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
1976 actor->OnRelayoutSignal().Connect( tracker, functor );
1978 else if( 0 == signalName.compare( SIGNAL_TOUCH ) )
1980 actor->TouchSignal().Connect( tracker, functor );
1982 else if( 0 == signalName.compare( SIGNAL_VISIBILITY_CHANGED ) )
1984 actor->VisibilityChangedSignal().Connect( tracker, functor );
1986 else if( 0 == signalName.compare( SIGNAL_LAYOUT_DIRECTION_CHANGED ) )
1988 actor->LayoutDirectionChangedSignal().Connect( tracker, functor );
1990 else if( 0 == signalName.compare( SIGNAL_CHILD_ADDED ) )
1992 actor->ChildAddedSignal().Connect( tracker, functor );
1994 else if( 0 == signalName.compare( SIGNAL_CHILD_REMOVED ) )
1996 actor->ChildRemovedSignal().Connect( tracker, functor );
2000 // signalName does not match any signal
2007 Actor::Actor( DerivedType derivedType, const SceneGraph::Node& node )
2013 mParentOrigin( NULL ),
2014 mAnchorPoint( NULL ),
2015 mRelayoutData( NULL ),
2016 mGestureData( NULL ),
2020 mWheelEventSignal(),
2023 mOnRelayoutSignal(),
2024 mVisibilityChangedSignal(),
2025 mLayoutDirectionChangedSignal(),
2026 mChildAddedSignal(),
2027 mChildRemovedSignal(),
2028 mChildOrderChangedSignal(),
2029 mTargetOrientation( Quaternion::IDENTITY ),
2030 mTargetColor( Color::WHITE ),
2031 mTargetSize( Vector3::ZERO ),
2032 mTargetPosition( Vector3::ZERO ),
2033 mTargetScale( Vector3::ONE ),
2037 mIsRoot( ROOT_LAYER == derivedType ),
2038 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2039 mIsOnStage( false ),
2041 mLeaveRequired( false ),
2042 mKeyboardFocusable( false ),
2043 mDerivedRequiresTouch( false ),
2044 mDerivedRequiresHover( false ),
2045 mDerivedRequiresWheelEvent( false ),
2046 mOnStageSignalled( false ),
2047 mInsideOnSizeSet( false ),
2048 mInheritPosition( true ),
2049 mInheritOrientation( true ),
2050 mInheritScale( true ),
2051 mPositionUsesAnchorPoint( true ),
2053 mInheritLayoutDirection( true ),
2054 mLayoutDirection( LayoutDirection::LEFT_TO_RIGHT ),
2055 mDrawMode( DrawMode::NORMAL ),
2056 mColorMode( Node::DEFAULT_COLOR_MODE ),
2057 mClippingMode( ClippingMode::DISABLED )
2061 void Actor::Initialize()
2065 GetEventThreadServices().RegisterObject( this );
2070 // Remove mParent pointers from children even if we're destroying core,
2071 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2074 ActorConstIter endIter = mChildren->end();
2075 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2077 (*iter)->SetParent( NULL );
2083 // Guard to allow handle destruction after Core has been destroyed
2084 if( EventThreadServices::IsCoreRunning() )
2086 // Root layer will destroy its node in its own destructor
2089 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
2091 GetEventThreadServices().UnregisterObject( this );
2095 // Cleanup optional gesture data
2096 delete mGestureData;
2098 // Cleanup optional parent origin and anchor
2099 delete mParentOrigin;
2100 delete mAnchorPoint;
2102 // Delete optional relayout data
2103 delete mRelayoutData;
2106 void Actor::ConnectToStage( uint32_t parentDepth )
2108 // This container is used instead of walking the Actor hierarchy.
2109 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
2110 ActorContainer connectionList;
2114 mScene->RequestRebuildDepthTree();
2117 // This stage is atomic i.e. not interrupted by user callbacks.
2118 RecursiveConnectToStage( connectionList, parentDepth + 1 );
2120 // Notify applications about the newly connected actors.
2121 const ActorIter endIter = connectionList.end();
2122 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2124 (*iter)->NotifyStageConnection();
2130 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, uint32_t depth )
2132 DALI_ASSERT_ALWAYS( !OnStage() );
2135 mDepth = static_cast< uint16_t >( depth ); // overflow ignored, not expected in practice
2137 ConnectToSceneGraph();
2139 // Notification for internal derived classes
2140 OnStageConnectionInternal();
2142 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2143 connectionList.push_back( ActorPtr( this ) );
2145 // Recursively connect children
2148 ActorConstIter endIter = mChildren->end();
2149 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2151 (*iter)->SetScene( *mScene );
2152 (*iter)->RecursiveConnectToStage( connectionList, depth + 1 );
2158 * This method is called when the Actor is connected to the Stage.
2159 * The parent must have added its Node to the scene-graph.
2160 * The child must connect its Node to the parent's Node.
2161 * This is recursive; the child calls ConnectToStage() for its children.
2163 void Actor::ConnectToSceneGraph()
2165 DALI_ASSERT_DEBUG( mParent != NULL);
2167 // Reparent Node in next Update
2168 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), mParent->GetNode(), GetNode() );
2170 // Request relayout on all actors that are added to the scenegraph
2173 // Notification for Object::Observers
2177 void Actor::NotifyStageConnection()
2179 // Actors can be removed (in a callback), before the on-stage stage is reported.
2180 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2181 if( OnStage() && !mOnStageSignalled )
2183 // Notification for external (CustomActor) derived classes
2184 OnStageConnectionExternal( mDepth );
2186 if( !mOnStageSignal.Empty() )
2188 Dali::Actor handle( this );
2189 mOnStageSignal.Emit( handle );
2192 // Guard against Remove during callbacks
2195 mOnStageSignalled = true; // signal required next time Actor is removed
2200 void Actor::DisconnectFromStage()
2202 // This container is used instead of walking the Actor hierachy.
2203 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2204 ActorContainer disconnectionList;
2208 mScene->RequestRebuildDepthTree();
2211 // This stage is atomic i.e. not interrupted by user callbacks
2212 RecursiveDisconnectFromStage( disconnectionList );
2214 // Notify applications about the newly disconnected actors.
2215 const ActorIter endIter = disconnectionList.end();
2216 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2218 (*iter)->NotifyStageDisconnection();
2222 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2224 // need to change state first so that internals relying on IsOnStage() inside OnStageDisconnectionInternal() get the correct value
2227 // Recursively disconnect children
2230 ActorConstIter endIter = mChildren->end();
2231 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2233 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2237 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2238 disconnectionList.push_back( ActorPtr( this ) );
2240 // Notification for internal derived classes
2241 OnStageDisconnectionInternal();
2243 DisconnectFromSceneGraph();
2247 * This method is called by an actor or its parent, before a node removal message is sent.
2248 * This is recursive; the child calls DisconnectFromStage() for its children.
2250 void Actor::DisconnectFromSceneGraph()
2252 // Notification for Object::Observers
2253 OnSceneObjectRemove();
2256 void Actor::NotifyStageDisconnection()
2258 // Actors can be added (in a callback), before the off-stage state is reported.
2259 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2260 // only do this step if there is a stage, i.e. Core is not being shut down
2261 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2263 // Notification for external (CustomeActor) derived classes
2264 OnStageDisconnectionExternal();
2266 if( !mOffStageSignal.Empty() )
2268 Dali::Actor handle( this );
2269 mOffStageSignal.Emit( handle );
2272 // Guard against Add during callbacks
2275 mOnStageSignalled = false; // signal required next time Actor is added
2280 bool Actor::IsNodeConnected() const
2282 bool connected( false );
2286 if( IsRoot() || GetNode().GetParent() )
2295 // This method initiates traversal of the actor tree using depth-first
2296 // traversal to set a depth index based on traversal order. It sends a
2297 // single message to update manager to update all the actor's nodes in
2298 // this tree with the depth index. The sceneGraphNodeDepths vector's
2299 // elements are ordered by depth, and could be used to reduce sorting
2300 // in the update thread.
2301 void Actor::RebuildDepthTree()
2303 DALI_LOG_TIMER_START(depthTimer);
2305 // Vector of scene-graph nodes and their depths to send to UpdateManager
2306 // in a single message
2307 OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths( new SceneGraph::NodeDepths() );
2309 int32_t depthIndex = 1;
2310 DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
2312 SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths );
2313 DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
2316 void Actor::DepthTraverseActorTree( OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths, int32_t& depthIndex )
2318 mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
2319 sceneGraphNodeDepths->Add( const_cast<SceneGraph::Node*>( &GetNode() ), mSortedDepth );
2321 // Create/add to children of this node
2324 for( ActorContainer::iterator it = mChildren->begin(); it != mChildren->end(); ++it )
2326 Actor* childActor = (*it).Get();
2328 childActor->DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
2333 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2337 case Dali::Actor::Property::PARENT_ORIGIN:
2339 Property::Type type = property.GetType();
2340 if( type == Property::VECTOR3 )
2342 SetParentOrigin( property.Get< Vector3 >() );
2344 else if ( type == Property::STRING )
2346 std::string parentOriginString;
2347 property.Get( parentOriginString );
2348 Vector3 parentOrigin;
2349 if( GetParentOriginConstant( parentOriginString, parentOrigin ) )
2351 SetParentOrigin( parentOrigin );
2357 case Dali::Actor::Property::PARENT_ORIGIN_X:
2359 SetParentOriginX( property.Get< float >() );
2363 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2365 SetParentOriginY( property.Get< float >() );
2369 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2371 SetParentOriginZ( property.Get< float >() );
2375 case Dali::Actor::Property::ANCHOR_POINT:
2377 Property::Type type = property.GetType();
2378 if( type == Property::VECTOR3 )
2380 SetAnchorPoint( property.Get< Vector3 >() );
2382 else if ( type == Property::STRING )
2384 std::string anchorPointString;
2385 property.Get( anchorPointString );
2387 if( GetAnchorPointConstant( anchorPointString, anchor ) )
2389 SetAnchorPoint( anchor );
2395 case Dali::Actor::Property::ANCHOR_POINT_X:
2397 SetAnchorPointX( property.Get< float >() );
2401 case Dali::Actor::Property::ANCHOR_POINT_Y:
2403 SetAnchorPointY( property.Get< float >() );
2407 case Dali::Actor::Property::ANCHOR_POINT_Z:
2409 SetAnchorPointZ( property.Get< float >() );
2413 case Dali::Actor::Property::SIZE:
2415 SetSize( property.Get< Vector3 >() );
2419 case Dali::Actor::Property::SIZE_WIDTH:
2421 SetWidth( property.Get< float >() );
2425 case Dali::Actor::Property::SIZE_HEIGHT:
2427 SetHeight( property.Get< float >() );
2431 case Dali::Actor::Property::SIZE_DEPTH:
2433 SetDepth( property.Get< float >() );
2437 case Dali::Actor::Property::POSITION:
2439 SetPosition( property.Get< Vector3 >() );
2443 case Dali::Actor::Property::POSITION_X:
2445 SetX( property.Get< float >() );
2449 case Dali::Actor::Property::POSITION_Y:
2451 SetY( property.Get< float >() );
2455 case Dali::Actor::Property::POSITION_Z:
2457 SetZ( property.Get< float >() );
2461 case Dali::Actor::Property::ORIENTATION:
2463 SetOrientation( property.Get< Quaternion >() );
2467 case Dali::Actor::Property::SCALE:
2469 SetScale( property.Get< Vector3 >() );
2473 case Dali::Actor::Property::SCALE_X:
2475 SetScaleX( property.Get< float >() );
2479 case Dali::Actor::Property::SCALE_Y:
2481 SetScaleY( property.Get< float >() );
2485 case Dali::Actor::Property::SCALE_Z:
2487 SetScaleZ( property.Get< float >() );
2491 case Dali::Actor::Property::VISIBLE:
2493 SetVisible( property.Get< bool >() );
2497 case Dali::Actor::Property::COLOR:
2499 Property::Type type = property.GetType();
2500 if( type == Property::VECTOR3 )
2502 Vector3 color = property.Get< Vector3 >();
2503 SetColor( Vector4( color.r, color.g, color.b, 1.0f ) );
2505 else if( type == Property::VECTOR4 )
2507 SetColor( property.Get< Vector4 >() );
2512 case Dali::Actor::Property::COLOR_RED:
2514 SetColorRed( property.Get< float >() );
2518 case Dali::Actor::Property::COLOR_GREEN:
2520 SetColorGreen( property.Get< float >() );
2524 case Dali::Actor::Property::COLOR_BLUE:
2526 SetColorBlue( property.Get< float >() );
2530 case Dali::Actor::Property::COLOR_ALPHA:
2531 case Dali::DevelActor::Property::OPACITY:
2534 if( property.Get( value ) )
2536 SetOpacity( value );
2541 case Dali::Actor::Property::NAME:
2543 SetName( property.Get< std::string >() );
2547 case Dali::Actor::Property::SENSITIVE:
2549 SetSensitive( property.Get< bool >() );
2553 case Dali::Actor::Property::LEAVE_REQUIRED:
2555 SetLeaveRequired( property.Get< bool >() );
2559 case Dali::Actor::Property::INHERIT_POSITION:
2561 SetInheritPosition( property.Get< bool >() );
2565 case Dali::Actor::Property::INHERIT_ORIENTATION:
2567 SetInheritOrientation( property.Get< bool >() );
2571 case Dali::Actor::Property::INHERIT_SCALE:
2573 SetInheritScale( property.Get< bool >() );
2577 case Dali::Actor::Property::COLOR_MODE:
2579 ColorMode mode = mColorMode;
2580 if ( Scripting::GetEnumerationProperty< ColorMode >( property, COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT, mode ) )
2582 SetColorMode( mode );
2587 case Dali::Actor::Property::DRAW_MODE:
2589 DrawMode::Type mode = mDrawMode;
2590 if( Scripting::GetEnumerationProperty< DrawMode::Type >( property, DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT, mode ) )
2592 SetDrawMode( mode );
2597 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2599 SetSizeModeFactor( property.Get< Vector3 >() );
2603 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2605 ResizePolicy::Type type = GetResizePolicy( Dimension::WIDTH );
2606 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2608 SetResizePolicy( type, Dimension::WIDTH );
2613 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2615 ResizePolicy::Type type = GetResizePolicy( Dimension::HEIGHT );
2616 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2618 SetResizePolicy( type, Dimension::HEIGHT );
2623 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2625 SizeScalePolicy::Type type = GetSizeScalePolicy();
2626 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT, type ) )
2628 SetSizeScalePolicy( type );
2633 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2635 if( property.Get< bool >() )
2637 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2642 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2644 if( property.Get< bool >() )
2646 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2651 case Dali::Actor::Property::PADDING:
2653 Vector4 padding = property.Get< Vector4 >();
2654 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2655 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2659 case Dali::Actor::Property::MINIMUM_SIZE:
2661 Vector2 size = property.Get< Vector2 >();
2662 SetMinimumSize( size.x, Dimension::WIDTH );
2663 SetMinimumSize( size.y, Dimension::HEIGHT );
2667 case Dali::Actor::Property::MAXIMUM_SIZE:
2669 Vector2 size = property.Get< Vector2 >();
2670 SetMaximumSize( size.x, Dimension::WIDTH );
2671 SetMaximumSize( size.y, Dimension::HEIGHT );
2675 case Dali::DevelActor::Property::SIBLING_ORDER:
2679 if( property.Get( value ) )
2681 SetSiblingOrder( value );
2686 case Dali::Actor::Property::CLIPPING_MODE:
2688 ClippingMode::Type convertedValue = mClippingMode;
2689 if( Scripting::GetEnumerationProperty< ClippingMode::Type >( property, CLIPPING_MODE_TABLE, CLIPPING_MODE_TABLE_COUNT, convertedValue ) )
2691 mClippingMode = convertedValue;
2692 SetClippingModeMessage( GetEventThreadServices(), GetNode(), mClippingMode );
2697 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
2700 if( property.Get( value ) && value != mPositionUsesAnchorPoint )
2702 mPositionUsesAnchorPoint = value;
2703 SetPositionUsesAnchorPointMessage( GetEventThreadServices(), GetNode(), mPositionUsesAnchorPoint );
2708 case Dali::Actor::Property::LAYOUT_DIRECTION:
2710 Dali::LayoutDirection::Type direction = mLayoutDirection;
2711 mInheritLayoutDirection = false;
2713 if( Scripting::GetEnumerationProperty< LayoutDirection::Type >( property, LAYOUT_DIRECTION_TABLE, LAYOUT_DIRECTION_TABLE_COUNT, direction ) )
2715 InheritLayoutDirectionRecursively( this, direction, true );
2720 case Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION:
2723 if( property.Get( value ) )
2725 SetInheritLayoutDirection( value );
2732 // this can happen in the case of a non-animatable default property so just do nothing
2738 // TODO: This method needs to be removed
2739 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2741 switch( entry.GetType() )
2743 case Property::BOOLEAN:
2745 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2746 DALI_ASSERT_DEBUG( NULL != property );
2748 // property is being used in a separate thread; queue a message to set the property
2749 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2754 case Property::INTEGER:
2756 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2757 DALI_ASSERT_DEBUG( NULL != property );
2759 // property is being used in a separate thread; queue a message to set the property
2760 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2765 case Property::FLOAT:
2767 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2768 DALI_ASSERT_DEBUG( NULL != property );
2770 // property is being used in a separate thread; queue a message to set the property
2771 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2776 case Property::VECTOR2:
2778 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2779 DALI_ASSERT_DEBUG( NULL != property );
2781 // property is being used in a separate thread; queue a message to set the property
2782 if(entry.componentIndex == 0)
2784 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2786 else if(entry.componentIndex == 1)
2788 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2792 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2798 case Property::VECTOR3:
2800 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2801 DALI_ASSERT_DEBUG( NULL != property );
2803 // property is being used in a separate thread; queue a message to set the property
2804 if(entry.componentIndex == 0)
2806 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2808 else if(entry.componentIndex == 1)
2810 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2812 else if(entry.componentIndex == 2)
2814 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2818 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2824 case Property::VECTOR4:
2826 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2827 DALI_ASSERT_DEBUG( NULL != property );
2829 // property is being used in a separate thread; queue a message to set the property
2830 if(entry.componentIndex == 0)
2832 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
2834 else if(entry.componentIndex == 1)
2836 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
2838 else if(entry.componentIndex == 2)
2840 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
2842 else if(entry.componentIndex == 3)
2844 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
2848 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2854 case Property::ROTATION:
2856 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
2857 DALI_ASSERT_DEBUG( NULL != property );
2859 // property is being used in a separate thread; queue a message to set the property
2860 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
2865 case Property::MATRIX:
2867 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
2868 DALI_ASSERT_DEBUG( NULL != property );
2870 // property is being used in a separate thread; queue a message to set the property
2871 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), &GetNode(), property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
2876 case Property::MATRIX3:
2878 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
2879 DALI_ASSERT_DEBUG( NULL != property );
2881 // property is being used in a separate thread; queue a message to set the property
2882 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), &GetNode(), property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
2889 // nothing to do for other types
2894 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
2896 Property::Value value;
2898 if( ! GetCachedPropertyValue( index, value ) )
2900 // If property value is not stored in the event-side, then it must be a scene-graph only property
2901 GetCurrentPropertyValue( index, value );
2907 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
2909 Property::Value value;
2911 if( ! GetCurrentPropertyValue( index, value ) )
2913 // If unable to retrieve scene-graph property value, then it must be an event-side only property
2914 GetCachedPropertyValue( index, value );
2920 void Actor::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
2922 switch( animationType )
2925 case Animation::BETWEEN:
2929 case Dali::Actor::Property::SIZE:
2931 if( value.Get( mTargetSize ) )
2935 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
2937 mRelayoutData->preferredSize.width = mTargetSize.width;
2940 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
2942 mRelayoutData->preferredSize.height = mTargetSize.height;
2946 // Notify deriving classes
2947 OnSizeAnimation( animation, mTargetSize );
2952 case Dali::Actor::Property::SIZE_WIDTH:
2954 if( value.Get( mTargetSize.width ) )
2956 if( mRelayoutData && GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
2958 mRelayoutData->preferredSize.width = mTargetSize.width;
2961 // Notify deriving classes
2962 OnSizeAnimation( animation, mTargetSize );
2967 case Dali::Actor::Property::SIZE_HEIGHT:
2969 if( value.Get( mTargetSize.height ) )
2971 if( mRelayoutData && GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
2973 mRelayoutData->preferredSize.height = mTargetSize.height;
2976 // Notify deriving classes
2977 OnSizeAnimation( animation, mTargetSize );
2982 case Dali::Actor::Property::SIZE_DEPTH:
2984 if( value.Get( mTargetSize.depth ) )
2986 // Notify deriving classes
2987 OnSizeAnimation( animation, mTargetSize );
2992 case Dali::Actor::Property::POSITION:
2994 value.Get( mTargetPosition );
2998 case Dali::Actor::Property::POSITION_X:
3000 value.Get( mTargetPosition.x );
3004 case Dali::Actor::Property::POSITION_Y:
3006 value.Get( mTargetPosition.y );
3010 case Dali::Actor::Property::POSITION_Z:
3012 value.Get( mTargetPosition.z );
3016 case Dali::Actor::Property::ORIENTATION:
3018 value.Get( mTargetOrientation );
3022 case Dali::Actor::Property::SCALE:
3024 value.Get( mTargetScale );
3028 case Dali::Actor::Property::SCALE_X:
3030 value.Get( mTargetScale.x );
3034 case Dali::Actor::Property::SCALE_Y:
3036 value.Get( mTargetScale.y );
3040 case Dali::Actor::Property::SCALE_Z:
3042 value.Get( mTargetScale.z );
3046 case Dali::Actor::Property::VISIBLE:
3048 SetVisibleInternal( value.Get< bool >(), SendMessage::FALSE );
3052 case Dali::Actor::Property::COLOR:
3054 value.Get( mTargetColor );
3058 case Dali::Actor::Property::COLOR_RED:
3060 value.Get( mTargetColor.r );
3064 case Dali::Actor::Property::COLOR_GREEN:
3066 value.Get( mTargetColor.g );
3070 case Dali::Actor::Property::COLOR_BLUE:
3072 value.Get( mTargetColor.b );
3076 case Dali::Actor::Property::COLOR_ALPHA:
3077 case Dali::DevelActor::Property::OPACITY:
3079 value.Get( mTargetColor.a );
3085 // Not an animatable property. Do nothing.
3096 case Dali::Actor::Property::SIZE:
3098 if( AdjustValue< Vector3 >( mTargetSize, value ) )
3102 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
3104 mRelayoutData->preferredSize.width = mTargetSize.width;
3107 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
3109 mRelayoutData->preferredSize.height = mTargetSize.height;
3113 // Notify deriving classes
3114 OnSizeAnimation( animation, mTargetSize );
3119 case Dali::Actor::Property::SIZE_WIDTH:
3121 if( AdjustValue< float >( mTargetSize.width, value ) )
3123 if( mRelayoutData && GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
3125 mRelayoutData->preferredSize.width = mTargetSize.width;
3128 // Notify deriving classes
3129 OnSizeAnimation( animation, mTargetSize );
3134 case Dali::Actor::Property::SIZE_HEIGHT:
3136 if( AdjustValue< float >( mTargetSize.height, value ) )
3138 if( mRelayoutData && GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
3140 mRelayoutData->preferredSize.height = mTargetSize.height;
3143 // Notify deriving classes
3144 OnSizeAnimation( animation, mTargetSize );
3149 case Dali::Actor::Property::SIZE_DEPTH:
3151 if( AdjustValue< float >( mTargetSize.depth, value ) )
3153 // Notify deriving classes
3154 OnSizeAnimation( animation, mTargetSize );
3159 case Dali::Actor::Property::POSITION:
3161 AdjustValue< Vector3 >( mTargetPosition, value );
3165 case Dali::Actor::Property::POSITION_X:
3167 AdjustValue< float >( mTargetPosition.x, value );
3171 case Dali::Actor::Property::POSITION_Y:
3173 AdjustValue< float >( mTargetPosition.y, value );
3177 case Dali::Actor::Property::POSITION_Z:
3179 AdjustValue< float >( mTargetPosition.z, value );
3183 case Dali::Actor::Property::ORIENTATION:
3185 Quaternion relativeValue;
3186 if( value.Get( relativeValue ) )
3188 mTargetOrientation *= relativeValue;
3193 case Dali::Actor::Property::SCALE:
3195 AdjustValue< Vector3 >( mTargetScale, value );
3199 case Dali::Actor::Property::SCALE_X:
3201 AdjustValue< float >( mTargetScale.x, value );
3205 case Dali::Actor::Property::SCALE_Y:
3207 AdjustValue< float >( mTargetScale.y, value );
3211 case Dali::Actor::Property::SCALE_Z:
3213 AdjustValue< float >( mTargetScale.z, value );
3217 case Dali::Actor::Property::VISIBLE:
3219 bool relativeValue = false;
3220 if( value.Get( relativeValue ) )
3222 bool visible = mVisible || relativeValue;
3223 SetVisibleInternal( visible, SendMessage::FALSE );
3228 case Dali::Actor::Property::COLOR:
3230 AdjustValue< Vector4 >( mTargetColor, value );
3234 case Dali::Actor::Property::COLOR_RED:
3236 AdjustValue< float >( mTargetColor.r, value );
3240 case Dali::Actor::Property::COLOR_GREEN:
3242 AdjustValue< float >( mTargetColor.g, value );
3246 case Dali::Actor::Property::COLOR_BLUE:
3248 AdjustValue< float >( mTargetColor.b, value );
3252 case Dali::Actor::Property::COLOR_ALPHA:
3253 case Dali::DevelActor::Property::OPACITY:
3255 AdjustValue< float >( mTargetColor.a, value );
3261 // Not an animatable property. Do nothing.
3270 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3272 const PropertyBase* property( NULL );
3276 case Dali::Actor::Property::SIZE: // FALLTHROUGH
3277 case Dali::Actor::Property::SIZE_WIDTH: // FALLTHROUGH
3278 case Dali::Actor::Property::SIZE_HEIGHT: // FALLTHROUGH
3279 case Dali::Actor::Property::SIZE_DEPTH:
3281 property = &GetNode().mSize;
3284 case Dali::Actor::Property::POSITION: // FALLTHROUGH
3285 case Dali::Actor::Property::POSITION_X: // FALLTHROUGH
3286 case Dali::Actor::Property::POSITION_Y: // FALLTHROUGH
3287 case Dali::Actor::Property::POSITION_Z:
3289 property = &GetNode().mPosition;
3292 case Dali::Actor::Property::ORIENTATION:
3294 property = &GetNode().mOrientation;
3297 case Dali::Actor::Property::SCALE: // FALLTHROUGH
3298 case Dali::Actor::Property::SCALE_X: // FALLTHROUGH
3299 case Dali::Actor::Property::SCALE_Y: // FALLTHROUGH
3300 case Dali::Actor::Property::SCALE_Z:
3302 property = &GetNode().mScale;
3305 case Dali::Actor::Property::VISIBLE:
3307 property = &GetNode().mVisible;
3310 case Dali::Actor::Property::COLOR: // FALLTHROUGH
3311 case Dali::Actor::Property::COLOR_RED: // FALLTHROUGH
3312 case Dali::Actor::Property::COLOR_GREEN: // FALLTHROUGH
3313 case Dali::Actor::Property::COLOR_BLUE: // FALLTHROUGH
3314 case Dali::Actor::Property::COLOR_ALPHA: // FALLTHROUGH
3315 case Dali::DevelActor::Property::OPACITY:
3317 property = &GetNode().mColor;
3327 // not our property, ask base
3328 property = Object::GetSceneObjectAnimatableProperty( index );
3334 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3336 const PropertyInputImpl* property( NULL );
3340 case Dali::Actor::Property::PARENT_ORIGIN: // FALLTHROUGH
3341 case Dali::Actor::Property::PARENT_ORIGIN_X: // FALLTHROUGH
3342 case Dali::Actor::Property::PARENT_ORIGIN_Y: // FALLTHROUGH
3343 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3345 property = &GetNode().mParentOrigin;
3348 case Dali::Actor::Property::ANCHOR_POINT: // FALLTHROUGH
3349 case Dali::Actor::Property::ANCHOR_POINT_X: // FALLTHROUGH
3350 case Dali::Actor::Property::ANCHOR_POINT_Y: // FALLTHROUGH
3351 case Dali::Actor::Property::ANCHOR_POINT_Z:
3353 property = &GetNode().mAnchorPoint;
3356 case Dali::Actor::Property::WORLD_POSITION: // FALLTHROUGH
3357 case Dali::Actor::Property::WORLD_POSITION_X: // FALLTHROUGH
3358 case Dali::Actor::Property::WORLD_POSITION_Y: // FALLTHROUGH
3359 case Dali::Actor::Property::WORLD_POSITION_Z:
3361 property = &GetNode().mWorldPosition;
3364 case Dali::Actor::Property::WORLD_ORIENTATION:
3366 property = &GetNode().mWorldOrientation;
3369 case Dali::Actor::Property::WORLD_SCALE:
3371 property = &GetNode().mWorldScale;
3374 case Dali::Actor::Property::WORLD_COLOR:
3376 property = &GetNode().mWorldColor;
3379 case Dali::Actor::Property::WORLD_MATRIX:
3381 property = &GetNode().mWorldMatrix;
3384 case Dali::DevelActor::Property::CULLED:
3386 property = &GetNode().mCulled;
3396 // reuse animatable property getter as animatable properties are inputs as well
3397 // animatable property chains back to Object::GetSceneObjectInputProperty() so all properties get covered
3398 property = GetSceneObjectAnimatableProperty( index );
3404 int32_t Actor::GetPropertyComponentIndex( Property::Index index ) const
3406 int32_t componentIndex = Property::INVALID_COMPONENT_INDEX;
3410 case Dali::Actor::Property::PARENT_ORIGIN_X:
3411 case Dali::Actor::Property::ANCHOR_POINT_X:
3412 case Dali::Actor::Property::SIZE_WIDTH:
3413 case Dali::Actor::Property::POSITION_X:
3414 case Dali::Actor::Property::WORLD_POSITION_X:
3415 case Dali::Actor::Property::SCALE_X:
3416 case Dali::Actor::Property::COLOR_RED:
3422 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3423 case Dali::Actor::Property::ANCHOR_POINT_Y:
3424 case Dali::Actor::Property::SIZE_HEIGHT:
3425 case Dali::Actor::Property::POSITION_Y:
3426 case Dali::Actor::Property::WORLD_POSITION_Y:
3427 case Dali::Actor::Property::SCALE_Y:
3428 case Dali::Actor::Property::COLOR_GREEN:
3434 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3435 case Dali::Actor::Property::ANCHOR_POINT_Z:
3436 case Dali::Actor::Property::SIZE_DEPTH:
3437 case Dali::Actor::Property::POSITION_Z:
3438 case Dali::Actor::Property::WORLD_POSITION_Z:
3439 case Dali::Actor::Property::SCALE_Z:
3440 case Dali::Actor::Property::COLOR_BLUE:
3446 case Dali::Actor::Property::COLOR_ALPHA:
3447 case Dali::DevelActor::Property::OPACITY:
3459 if( Property::INVALID_COMPONENT_INDEX == componentIndex )
3462 componentIndex = Object::GetPropertyComponentIndex( index );
3465 return componentIndex;
3468 void Actor::SetParent( Actor* parent )
3472 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3476 mScene = parent->mScene;
3478 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3481 // Instruct each actor to create a corresponding node in the scene graph
3482 ConnectToStage( parent->GetHierarchyDepth() );
3485 // Resolve the name and index for the child properties if any
3486 ResolveChildProperties();
3488 else // parent being set to NULL
3490 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3494 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3497 // Disconnect the Node & its children from the scene-graph.
3498 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
3500 // Instruct each actor to discard pointers to the scene-graph
3501 DisconnectFromStage();
3508 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3511 Actor* actor = dynamic_cast< Actor* >( object );
3515 if( 0 == actionName.compare( ACTION_SHOW ) )
3517 actor->SetVisible( true );
3520 else if( 0 == actionName.compare( ACTION_HIDE ) )
3522 actor->SetVisible( false );
3530 Rect<> Actor::CalculateScreenExtents( ) const
3532 auto screenPosition = GetCurrentScreenPosition();
3533 Vector3 size = GetCurrentSize() * GetCurrentWorldScale();
3534 Vector3 anchorPointOffSet = size * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
3535 Vector2 position = Vector2( screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y );
3536 return { position.x, position.y, size.x, size.y };
3539 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
3541 bool valueSet = true;
3545 case Dali::Actor::Property::PARENT_ORIGIN:
3547 value = GetCurrentParentOrigin();
3551 case Dali::Actor::Property::PARENT_ORIGIN_X:
3553 value = GetCurrentParentOrigin().x;
3557 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3559 value = GetCurrentParentOrigin().y;
3563 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3565 value = GetCurrentParentOrigin().z;
3569 case Dali::Actor::Property::ANCHOR_POINT:
3571 value = GetCurrentAnchorPoint();
3575 case Dali::Actor::Property::ANCHOR_POINT_X:
3577 value = GetCurrentAnchorPoint().x;
3581 case Dali::Actor::Property::ANCHOR_POINT_Y:
3583 value = GetCurrentAnchorPoint().y;
3587 case Dali::Actor::Property::ANCHOR_POINT_Z:
3589 value = GetCurrentAnchorPoint().z;
3593 case Dali::Actor::Property::SIZE:
3595 value = GetTargetSize();
3599 case Dali::Actor::Property::SIZE_WIDTH:
3601 value = GetTargetSize().width;
3605 case Dali::Actor::Property::SIZE_HEIGHT:
3607 value = GetTargetSize().height;
3611 case Dali::Actor::Property::SIZE_DEPTH:
3613 value = GetTargetSize().depth;
3617 case Dali::Actor::Property::POSITION:
3619 value = GetTargetPosition();
3623 case Dali::Actor::Property::POSITION_X:
3625 value = GetTargetPosition().x;
3629 case Dali::Actor::Property::POSITION_Y:
3631 value = GetTargetPosition().y;
3635 case Dali::Actor::Property::POSITION_Z:
3637 value = GetTargetPosition().z;
3641 case Dali::Actor::Property::ORIENTATION:
3643 value = mTargetOrientation;
3647 case Dali::Actor::Property::SCALE:
3649 value = mTargetScale;
3653 case Dali::Actor::Property::SCALE_X:
3655 value = mTargetScale.x;
3659 case Dali::Actor::Property::SCALE_Y:
3661 value = mTargetScale.y;
3665 case Dali::Actor::Property::SCALE_Z:
3667 value = mTargetScale.z;
3671 case Dali::Actor::Property::VISIBLE:
3677 case Dali::Actor::Property::COLOR:
3679 value = mTargetColor;
3683 case Dali::Actor::Property::COLOR_RED:
3685 value = mTargetColor.r;
3689 case Dali::Actor::Property::COLOR_GREEN:
3691 value = mTargetColor.g;
3695 case Dali::Actor::Property::COLOR_BLUE:
3697 value = mTargetColor.b;
3701 case Dali::Actor::Property::COLOR_ALPHA:
3702 case Dali::DevelActor::Property::OPACITY:
3704 value = mTargetColor.a;
3708 case Dali::Actor::Property::NAME:
3714 case Dali::Actor::Property::SENSITIVE:
3716 value = IsSensitive();
3720 case Dali::Actor::Property::LEAVE_REQUIRED:
3722 value = GetLeaveRequired();
3726 case Dali::Actor::Property::INHERIT_POSITION:
3728 value = IsPositionInherited();
3732 case Dali::Actor::Property::INHERIT_ORIENTATION:
3734 value = IsOrientationInherited();
3738 case Dali::Actor::Property::INHERIT_SCALE:
3740 value = IsScaleInherited();
3744 case Dali::Actor::Property::COLOR_MODE:
3746 value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
3750 case Dali::Actor::Property::DRAW_MODE:
3752 value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
3756 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3758 value = GetSizeModeFactor();
3762 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3764 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3768 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3770 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3774 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3776 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT );
3780 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3782 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3786 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3788 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3792 case Dali::Actor::Property::PADDING:
3794 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3795 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3796 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3800 case Dali::Actor::Property::MINIMUM_SIZE:
3802 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3806 case Dali::Actor::Property::MAXIMUM_SIZE:
3808 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3812 case Dali::Actor::Property::CLIPPING_MODE:
3814 value = mClippingMode;
3818 case Dali::DevelActor::Property::SIBLING_ORDER:
3820 value = static_cast<int>( GetSiblingOrder() );
3824 case Dali::DevelActor::Property::SCREEN_POSITION:
3826 value = GetCurrentScreenPosition();
3830 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
3832 value = mPositionUsesAnchorPoint;
3836 case Dali::Actor::Property::LAYOUT_DIRECTION:
3838 value = mLayoutDirection;
3842 case Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION:
3844 value = IsLayoutDirectionInherited();
3850 // Must be a scene-graph only property
3859 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
3861 bool valueSet = true;
3865 case Dali::Actor::Property::SIZE:
3867 value = GetCurrentSize();
3871 case Dali::Actor::Property::SIZE_WIDTH:
3873 value = GetCurrentSize().width;
3877 case Dali::Actor::Property::SIZE_HEIGHT:
3879 value = GetCurrentSize().height;
3883 case Dali::Actor::Property::SIZE_DEPTH:
3885 value = GetCurrentSize().depth;
3889 case Dali::Actor::Property::POSITION:
3891 value = GetCurrentPosition();
3895 case Dali::Actor::Property::POSITION_X:
3897 value = GetCurrentPosition().x;
3901 case Dali::Actor::Property::POSITION_Y:
3903 value = GetCurrentPosition().y;
3907 case Dali::Actor::Property::POSITION_Z:
3909 value = GetCurrentPosition().z;
3913 case Dali::Actor::Property::WORLD_POSITION:
3915 value = GetCurrentWorldPosition();
3919 case Dali::Actor::Property::WORLD_POSITION_X:
3921 value = GetCurrentWorldPosition().x;
3925 case Dali::Actor::Property::WORLD_POSITION_Y:
3927 value = GetCurrentWorldPosition().y;
3931 case Dali::Actor::Property::WORLD_POSITION_Z:
3933 value = GetCurrentWorldPosition().z;
3937 case Dali::Actor::Property::ORIENTATION:
3939 value = GetCurrentOrientation();
3943 case Dali::Actor::Property::WORLD_ORIENTATION:
3945 value = GetCurrentWorldOrientation();
3949 case Dali::Actor::Property::SCALE:
3951 value = GetCurrentScale();
3955 case Dali::Actor::Property::SCALE_X:
3957 value = GetCurrentScale().x;
3961 case Dali::Actor::Property::SCALE_Y:
3963 value = GetCurrentScale().y;
3967 case Dali::Actor::Property::SCALE_Z:
3969 value = GetCurrentScale().z;
3973 case Dali::Actor::Property::WORLD_SCALE:
3975 value = GetCurrentWorldScale();
3979 case Dali::Actor::Property::COLOR:
3981 value = GetCurrentColor();
3985 case Dali::Actor::Property::COLOR_RED:
3987 value = GetCurrentColor().r;
3991 case Dali::Actor::Property::COLOR_GREEN:
3993 value = GetCurrentColor().g;
3997 case Dali::Actor::Property::COLOR_BLUE:
3999 value = GetCurrentColor().b;
4003 case Dali::Actor::Property::COLOR_ALPHA:
4004 case Dali::DevelActor::Property::OPACITY:
4006 value = GetCurrentColor().a;
4010 case Dali::Actor::Property::WORLD_COLOR:
4012 value = GetCurrentWorldColor();
4016 case Dali::Actor::Property::WORLD_MATRIX:
4018 value = GetCurrentWorldMatrix();
4022 case Dali::Actor::Property::VISIBLE:
4024 value = IsVisible();
4028 case DevelActor::Property::CULLED:
4030 value = GetNode().IsCulled( GetEventThreadServices().GetEventBufferIndex() );
4036 // Must be an event-side only property
4045 void Actor::EnsureRelayoutData()
4047 // Assign relayout data.
4048 if( !mRelayoutData )
4050 mRelayoutData = new RelayoutData();
4054 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
4056 // Check if actor is dependent on parent
4057 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4059 if( ( dimension & ( 1 << i ) ) )
4061 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4062 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
4072 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
4074 // Check if actor is dependent on children
4075 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4077 if( ( dimension & ( 1 << i ) ) )
4079 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4080 switch( resizePolicy )
4082 case ResizePolicy::FIT_TO_CHILDREN:
4083 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
4099 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
4101 return Actor::RelayoutDependentOnChildren( dimension );
4104 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
4106 // Check each possible dimension and see if it is dependent on the input one
4107 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4109 if( dimension & ( 1 << i ) )
4111 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
4118 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
4120 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4122 if( dimension & ( 1 << i ) )
4124 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
4129 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
4131 // If more than one dimension is requested, just return the first one found
4132 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4134 if( ( dimension & ( 1 << i ) ) )
4136 return mRelayoutData->negotiatedDimensions[ i ];
4140 return 0.0f; // Default
4143 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
4145 EnsureRelayoutData();
4147 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4149 if( dimension & ( 1 << i ) )
4151 mRelayoutData->dimensionPadding[ i ] = padding;
4156 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4158 if ( mRelayoutData )
4160 // If more than one dimension is requested, just return the first one found
4161 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4163 if( ( dimension & ( 1 << i ) ) )
4165 return mRelayoutData->dimensionPadding[ i ];
4170 return GetDefaultDimensionPadding();
4173 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4175 EnsureRelayoutData();
4177 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4179 if( dimension & ( 1 << i ) )
4181 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4186 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4188 if ( mRelayoutData )
4190 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4192 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4202 float Actor::GetHeightForWidthBase( float width )
4204 float height = 0.0f;
4206 const Vector3 naturalSize = GetNaturalSize();
4207 if( naturalSize.width > 0.0f )
4209 height = naturalSize.height * width / naturalSize.width;
4211 else // we treat 0 as 1:1 aspect ratio
4219 float Actor::GetWidthForHeightBase( float height )
4223 const Vector3 naturalSize = GetNaturalSize();
4224 if( naturalSize.height > 0.0f )
4226 width = naturalSize.width * height / naturalSize.height;
4228 else // we treat 0 as 1:1 aspect ratio
4236 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4238 // Fill to parent, taking size mode factor into account
4239 switch( child.GetResizePolicy( dimension ) )
4241 case ResizePolicy::FILL_TO_PARENT:
4243 return GetLatestSize( dimension );
4246 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4248 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4251 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4253 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4258 return GetLatestSize( dimension );
4263 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4265 // Can be overridden in derived class
4266 return CalculateChildSizeBase( child, dimension );
4269 float Actor::GetHeightForWidth( float width )
4271 // Can be overridden in derived class
4272 return GetHeightForWidthBase( width );
4275 float Actor::GetWidthForHeight( float height )
4277 // Can be overridden in derived class
4278 return GetWidthForHeightBase( height );
4281 float Actor::GetLatestSize( Dimension::Type dimension ) const
4283 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4286 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4288 Vector2 padding = GetPadding( dimension );
4290 return GetLatestSize( dimension ) + padding.x + padding.y;
4293 float Actor::NegotiateFromParent( Dimension::Type dimension )
4295 Actor* parent = GetParent();
4298 Vector2 padding( GetPadding( dimension ) );
4299 Vector2 parentPadding( parent->GetPadding( dimension ) );
4300 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4306 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4308 float maxDimensionPoint = 0.0f;
4310 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4312 ActorPtr child = GetChildAt( i );
4314 if( !child->RelayoutDependentOnParent( dimension ) )
4316 // Calculate the min and max points that the children range across
4317 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
4318 float dimensionSize = child->GetRelayoutSize( dimension );
4319 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4323 return maxDimensionPoint;
4326 float Actor::GetSize( Dimension::Type dimension ) const
4328 return GetDimensionValue( mTargetSize, dimension );
4331 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4333 return GetDimensionValue( GetNaturalSize(), dimension );
4336 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4338 switch( GetResizePolicy( dimension ) )
4340 case ResizePolicy::USE_NATURAL_SIZE:
4342 return GetNaturalSize( dimension );
4345 case ResizePolicy::FIXED:
4347 return GetDimensionValue( GetPreferredSize(), dimension );
4350 case ResizePolicy::USE_ASSIGNED_SIZE:
4352 return GetDimensionValue( maximumSize, dimension );
4355 case ResizePolicy::FILL_TO_PARENT:
4356 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4357 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4359 return NegotiateFromParent( dimension );
4362 case ResizePolicy::FIT_TO_CHILDREN:
4364 return NegotiateFromChildren( dimension );
4367 case ResizePolicy::DIMENSION_DEPENDENCY:
4369 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4372 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4374 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4377 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4379 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4391 return 0.0f; // Default
4394 float Actor::ClampDimension( float size, Dimension::Type dimension )
4396 const float minSize = GetMinimumSize( dimension );
4397 const float maxSize = GetMaximumSize( dimension );
4399 return std::max( minSize, std::min( size, maxSize ) );
4402 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4404 // Check if it needs to be negotiated
4405 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4407 // Check that we havn't gotten into an infinite loop
4408 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4409 bool recursionFound = false;
4410 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4412 if( *it == searchActor )
4414 recursionFound = true;
4419 if( !recursionFound )
4421 // Record the path that we have taken
4422 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4424 // Dimension dependency check
4425 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4427 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4429 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4431 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4435 // Parent dependency check
4436 Actor* parent = GetParent();
4437 if( parent && RelayoutDependentOnParent( dimension ) )
4439 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4442 // Children dependency check
4443 if( RelayoutDependentOnChildren( dimension ) )
4445 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4447 ActorPtr child = GetChildAt( i );
4449 // Only relayout child first if it is not dependent on this actor
4450 if( !child->RelayoutDependentOnParent( dimension ) )
4452 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
4457 // For deriving classes
4458 OnCalculateRelayoutSize( dimension );
4460 // All dependencies checked, calculate the size and set negotiated flag
4461 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4463 SetNegotiatedDimension( newSize, dimension );
4464 SetLayoutNegotiated( true, dimension );
4466 // For deriving classes
4467 OnLayoutNegotiated( newSize, dimension );
4469 // This actor has been successfully processed, pop it off the recursion stack
4470 recursionStack.pop_back();
4474 // TODO: Break infinite loop
4475 SetLayoutNegotiated( true, dimension );
4480 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4482 // Negotiate all dimensions that require it
4483 ActorDimensionStack recursionStack;
4485 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4487 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4490 NegotiateDimension( dimension, allocatedSize, recursionStack );
4494 Vector2 Actor::ApplySizeSetPolicy( const Vector2& size )
4496 switch( mRelayoutData->sizeSetPolicy )
4498 case SizeScalePolicy::USE_SIZE_SET:
4503 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4505 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4506 const Vector3 naturalSize = GetNaturalSize();
4507 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4509 const float sizeRatio = size.width / size.height;
4510 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4512 if( naturalSizeRatio < sizeRatio )
4514 return Vector2( naturalSizeRatio * size.height, size.height );
4516 else if( naturalSizeRatio > sizeRatio )
4518 return Vector2( size.width, size.width / naturalSizeRatio );
4529 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4531 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4532 const Vector3 naturalSize = GetNaturalSize();
4533 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4535 const float sizeRatio = size.width / size.height;
4536 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4538 if( naturalSizeRatio < sizeRatio )
4540 return Vector2( size.width, size.width / naturalSizeRatio );
4542 else if( naturalSizeRatio > sizeRatio )
4544 return Vector2( naturalSizeRatio * size.height, size.height );
4563 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4565 // Do the set actor size
4566 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4568 // Adjust for size set policy
4569 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4571 // Lock the flag to stop recursive relayouts on set size
4572 mRelayoutData->insideRelayout = true;
4573 SetSize( negotiatedSize );
4574 mRelayoutData->insideRelayout = false;
4576 // Clear flags for all dimensions
4577 SetLayoutDirty( false );
4579 // Give deriving classes a chance to respond
4580 OnRelayout( negotiatedSize, container );
4582 if( !mOnRelayoutSignal.Empty() )
4584 Dali::Actor handle( this );
4585 mOnRelayoutSignal.Emit( handle );
4589 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4591 // Force a size negotiation for actors that has assigned size during relayout
4592 // This is required as otherwise the flags that force a relayout will not
4593 // necessarilly be set. This will occur if the actor has already been laid out.
4594 // The dirty flags are then cleared. Then if the actor is added back into the
4595 // relayout container afterwards, the dirty flags would still be clear...
4596 // causing a relayout to be skipped. Here we force any actors added to the
4597 // container to be relayed out.
4598 DALI_LOG_TIMER_START( NegSizeTimer1 );
4600 if( GetUseAssignedSize(Dimension::WIDTH ) )
4602 SetLayoutNegotiated( false, Dimension::WIDTH );
4604 if( GetUseAssignedSize( Dimension::HEIGHT ) )
4606 SetLayoutNegotiated( false, Dimension::HEIGHT );
4609 // Do the negotiation
4610 NegotiateDimensions( allocatedSize );
4612 // Set the actor size
4613 SetNegotiatedSize( container );
4615 // Negotiate down to children
4616 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4618 ActorPtr child = GetChildAt( i );
4620 // Forces children that have already been laid out to be relayed out
4621 // if they have assigned size during relayout.
4622 if( child->GetUseAssignedSize(Dimension::WIDTH) )
4624 child->SetLayoutNegotiated(false, Dimension::WIDTH);
4625 child->SetLayoutDirty(true, Dimension::WIDTH);
4628 if( child->GetUseAssignedSize(Dimension::HEIGHT) )
4630 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
4631 child->SetLayoutDirty(true, Dimension::HEIGHT);
4634 // Only relayout if required
4635 if( child->RelayoutRequired() )
4637 container.Add( Dali::Actor( child.Get() ), mTargetSize.GetVectorXY() );
4640 DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
4643 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
4647 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4649 if( dimension & ( 1 << i ) )
4651 mRelayoutData->useAssignedSize[ i ] = use;
4657 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
4659 if ( mRelayoutData )
4661 // If more than one dimension is requested, just return the first one found
4662 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4664 if( dimension & ( 1 << i ) )
4666 return mRelayoutData->useAssignedSize[ i ];
4674 void Actor::RelayoutRequest( Dimension::Type dimension )
4676 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4677 if( relayoutController )
4679 Dali::Actor self( this );
4680 relayoutController->RequestRelayout( self, dimension );
4684 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4688 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4692 void Actor::SetPreferredSize( const Vector2& size )
4694 EnsureRelayoutData();
4696 // If valid width or height, then set the resize policy to FIXED
4697 // A 0 width or height may also be required so if the resize policy has not been changed, i.e. is still set to DEFAULT,
4698 // then change to FIXED as well
4700 if( size.width > 0.0f || GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DEFAULT )
4702 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4705 if( size.height > 0.0f || GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DEFAULT )
4707 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4710 mRelayoutData->preferredSize = size;
4715 Vector2 Actor::GetPreferredSize() const
4717 if ( mRelayoutData )
4719 return Vector2( mRelayoutData->preferredSize );
4722 return GetDefaultPreferredSize();
4725 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4727 EnsureRelayoutData();
4729 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4731 if( dimension & ( 1 << i ) )
4733 mRelayoutData->minimumSize[ i ] = size;
4740 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4742 if ( mRelayoutData )
4744 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4746 if( dimension & ( 1 << i ) )
4748 return mRelayoutData->minimumSize[ i ];
4753 return 0.0f; // Default
4756 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4758 EnsureRelayoutData();
4760 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4762 if( dimension & ( 1 << i ) )
4764 mRelayoutData->maximumSize[ i ] = size;
4771 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4773 if ( mRelayoutData )
4775 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4777 if( dimension & ( 1 << i ) )
4779 return mRelayoutData->maximumSize[ i ];
4784 return FLT_MAX; // Default
4787 Object* Actor::GetParentObject() const
4792 void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
4794 if( mVisible != visible )
4796 if( sendMessage == SendMessage::TRUE )
4798 // node is being used in a separate thread; queue a message to set the value & base value
4799 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible );
4804 // Emit the signal on this actor and all its children
4805 EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
4809 void Actor::SetSiblingOrder( uint32_t order )
4813 ActorContainer& siblings = *(mParent->mChildren);
4814 uint32_t currentOrder = GetSiblingOrder();
4816 if( order != currentOrder )
4822 else if( order < siblings.size() -1 )
4824 if( order > currentOrder )
4826 RaiseAbove( *siblings[order] );
4830 LowerBelow( *siblings[order] );
4841 uint32_t Actor::GetSiblingOrder() const
4847 ActorContainer& siblings = *(mParent->mChildren);
4848 for( std::size_t i = 0; i < siblings.size(); ++i )
4850 if( siblings[i] == this )
4852 order = static_cast<uint32_t>( i );
4861 void Actor::RequestRebuildDepthTree()
4867 mScene->RequestRebuildDepthTree();
4876 ActorContainer& siblings = *(mParent->mChildren);
4877 if( siblings.back() != this ) // If not already at end
4879 for( std::size_t i=0; i<siblings.size(); ++i )
4881 if( siblings[i] == this )
4884 ActorPtr next = siblings[i+1];
4885 siblings[i+1] = this;
4892 Dali::Actor handle( this );
4893 mParent->mChildOrderChangedSignal.Emit( handle );
4895 RequestRebuildDepthTree();
4899 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4907 ActorContainer& siblings = *(mParent->mChildren);
4908 if( siblings.front() != this ) // If not already at beginning
4910 for( std::size_t i=1; i<siblings.size(); ++i )
4912 if( siblings[i] == this )
4914 // Swap with previous
4915 ActorPtr previous = siblings[i-1];
4916 siblings[i-1] = this;
4917 siblings[i] = previous;
4923 Dali::Actor handle( this );
4924 mParent->mChildOrderChangedSignal.Emit( handle );
4926 RequestRebuildDepthTree();
4930 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4934 void Actor::RaiseToTop()
4938 ActorContainer& siblings = *(mParent->mChildren);
4939 if( siblings.back() != this ) // If not already at end
4941 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
4942 if( iter != siblings.end() )
4944 siblings.erase(iter);
4945 siblings.push_back(ActorPtr(this));
4949 Dali::Actor handle( this );
4950 mParent->mChildOrderChangedSignal.Emit( handle );
4952 RequestRebuildDepthTree();
4956 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4960 void Actor::LowerToBottom()
4964 ActorContainer& siblings = *(mParent->mChildren);
4965 if( siblings.front() != this ) // If not already at bottom,
4967 ActorPtr thisPtr(this); // ensure this actor remains referenced.
4969 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
4970 if( iter != siblings.end() )
4972 siblings.erase(iter);
4973 siblings.insert(siblings.begin(), thisPtr);
4977 Dali::Actor handle( this );
4978 mParent->mChildOrderChangedSignal.Emit( handle );
4980 RequestRebuildDepthTree();
4984 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4988 void Actor::RaiseAbove( Internal::Actor& target )
4992 ActorContainer& siblings = *(mParent->mChildren);
4993 if( siblings.back() != this && target.mParent == mParent ) // If not already at top
4995 ActorPtr thisPtr(this); // ensure this actor remains referenced.
4997 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
4998 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
4999 if( thisIter < targetIter )
5001 siblings.erase(thisIter);
5002 // Erasing early invalidates the targetIter. (Conversely, inserting first may also
5003 // invalidate thisIter)
5004 targetIter = std::find( siblings.begin(), siblings.end(), &target );
5006 siblings.insert(targetIter, thisPtr);
5009 Dali::Actor handle( this );
5010 mParent->mChildOrderChangedSignal.Emit( handle );
5012 RequestRebuildDepthTree();
5017 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5021 void Actor::LowerBelow( Internal::Actor& target )
5025 ActorContainer& siblings = *(mParent->mChildren);
5026 if( siblings.front() != this && target.mParent == mParent ) // If not already at bottom
5028 ActorPtr thisPtr(this); // ensure this actor remains referenced.
5030 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
5031 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
5033 if( thisIter > targetIter )
5035 siblings.erase(thisIter); // this only invalidates iterators at or after this point.
5036 siblings.insert(targetIter, thisPtr);
5039 Dali::Actor handle( this );
5040 mParent->mChildOrderChangedSignal.Emit( handle );
5042 RequestRebuildDepthTree();
5047 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5051 void Actor::SetScene( Scene& scene )
5056 Scene& Actor::GetScene() const
5061 void Actor::SetInheritLayoutDirection( bool inherit )
5063 if( mInheritLayoutDirection != inherit )
5065 mInheritLayoutDirection = inherit;
5067 if( inherit && mParent )
5069 InheritLayoutDirectionRecursively( this, mParent->mLayoutDirection );
5074 bool Actor::IsLayoutDirectionInherited() const
5076 return mInheritLayoutDirection;
5079 void Actor::InheritLayoutDirectionRecursively( ActorPtr actor, Dali::LayoutDirection::Type direction, bool set )
5081 if( actor && ( actor->mInheritLayoutDirection || set ) )
5083 if( actor->mLayoutDirection != direction )
5085 actor->mLayoutDirection = direction;
5086 actor->EmitLayoutDirectionChangedSignal( direction );
5087 actor->RelayoutRequest();
5090 if( actor->GetChildCount() > 0 )
5092 ActorContainer& children = actor->GetChildrenInternal();
5093 for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter )
5095 InheritLayoutDirectionRecursively( *iter, direction );
5101 } // namespace Internal