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", INTEGER, true, false, false, Dali::Actor::Property::COLOR_MODE )
197 DALI_PROPERTY( "drawMode", INTEGER, true, false, false, Dali::Actor::Property::DRAW_MODE )
198 DALI_PROPERTY( "sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
199 DALI_PROPERTY( "widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
200 DALI_PROPERTY( "heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
201 DALI_PROPERTY( "sizeScalePolicy", INTEGER, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
202 DALI_PROPERTY( "widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
203 DALI_PROPERTY( "heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
204 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
205 DALI_PROPERTY( "minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
206 DALI_PROPERTY( "maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
207 DALI_PROPERTY( "inheritPosition", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_POSITION )
208 DALI_PROPERTY( "clippingMode", STRING, true, false, false, Dali::Actor::Property::CLIPPING_MODE )
209 DALI_PROPERTY( "layoutDirection", STRING, true, false, false, Dali::Actor::Property::LAYOUT_DIRECTION )
210 DALI_PROPERTY( "inheritLayoutDirection", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION )
211 DALI_PROPERTY( "opacity", FLOAT, true, true, true, Dali::Actor::Property::OPACITY )
212 DALI_PROPERTY( "screenPosition", VECTOR2, false, false, false, Dali::Actor::Property::SCREEN_POSITION )
213 DALI_PROPERTY( "positionUsesAnchorPoint", BOOLEAN, true, false, false, Dali::Actor::Property::POSITION_USES_ANCHOR_POINT )
214 DALI_PROPERTY( "culled", BOOLEAN, false, false, true, Dali::Actor::Property::CULLED )
215 DALI_PROPERTY( "id", INTEGER, false, false, false, Dali::Actor::Property::ID )
216 DALI_PROPERTY( "hierarchyDepth", INTEGER, false, false, false, Dali::Actor::Property::HIERARCHY_DEPTH )
217 DALI_PROPERTY( "isRoot", BOOLEAN, false, false, false, Dali::Actor::Property::IS_ROOT )
218 DALI_PROPERTY( "isLayer", BOOLEAN, false, false, false, Dali::Actor::Property::IS_LAYER )
219 DALI_PROPERTY( "connectedToScene", BOOLEAN, false, false, false, Dali::Actor::Property::CONNECTED_TO_SCENE )
220 DALI_PROPERTY( "keyboardFocusable", BOOLEAN, true, false, false, Dali::Actor::Property::KEYBOARD_FOCUSABLE )
221 DALI_PROPERTY( "siblingOrder", INTEGER, true, false, false, Dali::DevelActor::Property::SIBLING_ORDER )
222 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperties )
226 const char* const SIGNAL_TOUCHED = "touched";
227 const char* const SIGNAL_HOVERED = "hovered";
228 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
229 const char* const SIGNAL_ON_STAGE = "onStage";
230 const char* const SIGNAL_OFF_STAGE = "offStage";
231 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
232 const char* const SIGNAL_TOUCH = "touch";
233 const char* const SIGNAL_VISIBILITY_CHANGED = "visibilityChanged";
234 const char* const SIGNAL_LAYOUT_DIRECTION_CHANGED = "layoutDirectionChanged";
235 const char* const SIGNAL_CHILD_ADDED = "childAdded";
236 const char* const SIGNAL_CHILD_REMOVED = "childRemoved";
240 const char* const ACTION_SHOW = "show";
241 const char* const ACTION_HIDE = "hide";
243 BaseHandle CreateActor()
245 return Dali::Actor::New();
248 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor, ActorDefaultProperties );
250 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
251 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
252 SignalConnectorType signalConnector3( mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal );
253 SignalConnectorType signalConnector4( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
254 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
255 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
256 SignalConnectorType signalConnector7( mType, SIGNAL_TOUCH, &Actor::DoConnectSignal );
257 SignalConnectorType signalConnector8( mType, SIGNAL_VISIBILITY_CHANGED, &Actor::DoConnectSignal );
258 SignalConnectorType signalConnector9( mType, SIGNAL_LAYOUT_DIRECTION_CHANGED, &Actor::DoConnectSignal );
259 SignalConnectorType signalConnector10( mType, SIGNAL_CHILD_ADDED, &Actor::DoConnectSignal );
260 SignalConnectorType signalConnector11( mType, SIGNAL_CHILD_REMOVED, &Actor::DoConnectSignal );
262 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
263 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
268 const Vector3& value;
271 DALI_ENUM_TO_STRING_TABLE_BEGIN_WITH_TYPE( AnchorValue, ANCHOR_CONSTANT )
272 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_LEFT )
273 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_CENTER )
274 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_RIGHT )
275 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_LEFT )
276 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER )
277 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_RIGHT )
278 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_LEFT )
279 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_CENTER )
280 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_RIGHT )
281 DALI_ENUM_TO_STRING_TABLE_END( ANCHOR_CONSTANT )
283 DALI_ENUM_TO_STRING_TABLE_BEGIN( COLOR_MODE )
284 DALI_ENUM_TO_STRING( USE_OWN_COLOR )
285 DALI_ENUM_TO_STRING( USE_PARENT_COLOR )
286 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_COLOR )
287 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_ALPHA )
288 DALI_ENUM_TO_STRING_TABLE_END( COLOR_MODE )
290 DALI_ENUM_TO_STRING_TABLE_BEGIN( DRAW_MODE )
291 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, NORMAL )
292 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, OVERLAY_2D )
293 DALI_ENUM_TO_STRING_TABLE_END( DRAW_MODE )
295 DALI_ENUM_TO_STRING_TABLE_BEGIN( RESIZE_POLICY )
296 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIXED )
297 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_NATURAL_SIZE )
298 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FILL_TO_PARENT )
299 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_RELATIVE_TO_PARENT )
300 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_FIXED_OFFSET_FROM_PARENT )
301 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIT_TO_CHILDREN )
302 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, DIMENSION_DEPENDENCY )
303 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_ASSIGNED_SIZE )
304 DALI_ENUM_TO_STRING_TABLE_END( RESIZE_POLICY )
306 DALI_ENUM_TO_STRING_TABLE_BEGIN( SIZE_SCALE_POLICY )
307 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, USE_SIZE_SET )
308 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FIT_WITH_ASPECT_RATIO )
309 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FILL_WITH_ASPECT_RATIO )
310 DALI_ENUM_TO_STRING_TABLE_END( SIZE_SCALE_POLICY )
312 DALI_ENUM_TO_STRING_TABLE_BEGIN( CLIPPING_MODE )
313 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, DISABLED )
314 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, CLIP_CHILDREN )
315 DALI_ENUM_TO_STRING_TABLE_END( CLIPPING_MODE )
317 DALI_ENUM_TO_STRING_TABLE_BEGIN( LAYOUT_DIRECTION )
318 DALI_ENUM_TO_STRING_WITH_SCOPE( LayoutDirection, LEFT_TO_RIGHT )
319 DALI_ENUM_TO_STRING_WITH_SCOPE( LayoutDirection, RIGHT_TO_LEFT )
320 DALI_ENUM_TO_STRING_TABLE_END( LAYOUT_DIRECTION )
322 bool GetAnchorPointConstant( const std::string& value, Vector3& anchor )
324 for( uint32_t i = 0; i < ANCHOR_CONSTANT_TABLE_COUNT; ++i )
326 uint32_t sizeIgnored = 0;
327 if( CompareTokens( value.c_str(), ANCHOR_CONSTANT_TABLE[ i ].name, sizeIgnored ) )
329 anchor = ANCHOR_CONSTANT_TABLE[ i ].value;
336 inline bool GetParentOriginConstant( const std::string& value, Vector3& parentOrigin )
338 // Values are the same so just use the same table as anchor-point
339 return GetAnchorPointConstant( value, parentOrigin );
343 * @brief Extract a given dimension from a Vector2
345 * @param[in] values The values to extract from
346 * @param[in] dimension The dimension to extract
347 * @return Return the value for the dimension
349 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
353 case Dimension::WIDTH:
357 case Dimension::HEIGHT:
359 return values.height;
370 * @brief Extract a given dimension from a Vector3
372 * @param[in] values The values to extract from
373 * @param[in] dimension The dimension to extract
374 * @return Return the value for the dimension
376 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
378 return GetDimensionValue( values.GetVectorXY(), dimension );
382 * @brief Recursively emits the visibility-changed-signal on the actor tree.
383 * @param[in] actor The actor to emit the signal on
384 * @param[in] visible The new visibility of the actor
385 * @param[in] type Whether the actor's visible property has changed or a parent's
387 void EmitVisibilityChangedSignalRecursively( ActorPtr actor, bool visible, DevelActor::VisibilityChange::Type type )
391 actor->EmitVisibilityChangedSignal( visible, type );
393 if( actor->GetChildCount() > 0 )
395 ActorContainer& children = actor->GetChildrenInternal();
396 for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter )
398 EmitVisibilityChangedSignalRecursively( *iter, visible, DevelActor::VisibilityChange::PARENT );
404 } // unnamed namespace
406 ActorPtr Actor::New()
408 // pass a reference to actor, actor does not own its node
409 ActorPtr actor( new Actor( BASIC, *CreateNode() ) );
411 // Second-phase construction
417 const SceneGraph::Node* Actor::CreateNode()
419 // create node. Nodes are owned by the update manager
420 SceneGraph::Node* node = SceneGraph::Node::New();
421 OwnerPointer< SceneGraph::Node > transferOwnership( node );
422 Internal::ThreadLocalStorage* tls = Internal::ThreadLocalStorage::GetInternal();
424 DALI_ASSERT_ALWAYS( tls && "ThreadLocalStorage is null" );
426 AddNodeMessage( tls->GetUpdateManager(), transferOwnership );
431 const std::string& Actor::GetName() const
436 void Actor::SetName( const std::string& name )
440 // ATTENTION: string for debug purposes is not thread safe.
441 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( &GetNode() ), name );
444 uint32_t Actor::GetId() const
446 return GetNode().GetId();
449 bool Actor::OnStage() const
454 Dali::Layer Actor::GetLayer()
458 // Short-circuit for Layer derived actors
461 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
464 // Find the immediate Layer parent
465 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
467 if( parent->IsLayer() )
469 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
476 void Actor::Add( Actor& child )
478 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
479 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
483 mChildren = new ActorContainer;
486 Actor* const oldParent( child.mParent );
488 // child might already be ours
489 if( this != oldParent )
491 // if we already have parent, unparent us first
494 oldParent->Remove( child ); // This causes OnChildRemove callback & ChildRemoved signal
496 // Old parent may need to readjust to missing child
497 if( oldParent->RelayoutDependentOnChildren() )
499 oldParent->RelayoutRequest();
503 // Guard against Add() during previous OnChildRemove callback
506 // Do this first, since user callbacks from within SetParent() may need to remove child
507 mChildren->push_back( ActorPtr( &child ) );
509 // SetParent asserts that child can be added
510 child.SetParent( this );
512 // Notification for derived classes
514 EmitChildAddedSignal( child );
516 InheritLayoutDirectionRecursively( ActorPtr( &child ), mLayoutDirection );
518 // Only put in a relayout request if there is a suitable dependency
519 if( RelayoutDependentOnChildren() )
527 void Actor::Remove( Actor& child )
529 if( (this == &child) || (!mChildren) )
531 // no children or removing itself
537 // Find the child in mChildren, and unparent it
538 ActorIter end = mChildren->end();
539 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
541 ActorPtr actor = (*iter);
543 if( actor.Get() == &child )
545 // Keep handle for OnChildRemove notification
548 // Do this first, since user callbacks from within SetParent() may need to add the child
549 mChildren->erase( iter );
551 DALI_ASSERT_DEBUG( actor->GetParent() == this );
552 actor->SetParent( NULL );
560 // Only put in a relayout request if there is a suitable dependency
561 if( RelayoutDependentOnChildren() )
567 // Notification for derived classes
568 OnChildRemove( child );
569 EmitChildRemovedSignal( child );
572 void Actor::Unparent()
576 // Remove this actor from the parent. The remove will put a relayout request in for
577 // the parent if required
578 mParent->Remove( *this );
579 // mParent is now NULL!
583 uint32_t Actor::GetChildCount() const
585 return ( NULL != mChildren ) ? static_cast<uint32_t>( mChildren->size() ) : 0; // only 4,294,967,295 children per actor
588 ActorPtr Actor::GetChildAt( uint32_t index ) const
590 DALI_ASSERT_ALWAYS( index < GetChildCount() );
592 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
595 ActorPtr Actor::FindChildByName( const std::string& actorName )
598 if( actorName == mName )
604 ActorIter end = mChildren->end();
605 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
607 child = (*iter)->FindChildByName( actorName );
618 ActorPtr Actor::FindChildById( const uint32_t id )
627 ActorIter end = mChildren->end();
628 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
630 child = (*iter)->FindChildById( id );
641 void Actor::SetParentOrigin( const Vector3& origin )
643 // node is being used in a separate thread; queue a message to set the value & base value
644 SetParentOriginMessage( GetEventThreadServices(), GetNode(), origin );
646 // Cache for event-thread access
649 // not allocated, check if different from default
650 if( ParentOrigin::DEFAULT != origin )
652 mParentOrigin = new Vector3( origin );
657 // check if different from current costs more than just set
658 *mParentOrigin = origin;
662 void Actor::SetParentOriginX( float x )
664 const Vector3& current = GetCurrentParentOrigin();
666 SetParentOrigin( Vector3( x, current.y, current.z ) );
669 void Actor::SetParentOriginY( float y )
671 const Vector3& current = GetCurrentParentOrigin();
673 SetParentOrigin( Vector3( current.x, y, current.z ) );
676 void Actor::SetParentOriginZ( float z )
678 const Vector3& current = GetCurrentParentOrigin();
680 SetParentOrigin( Vector3( current.x, current.y, z ) );
683 const Vector3& Actor::GetCurrentParentOrigin() const
685 // Cached for event-thread access
686 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
689 void Actor::SetAnchorPoint( const Vector3& anchor )
691 // node is being used in a separate thread; queue a message to set the value & base value
692 SetAnchorPointMessage( GetEventThreadServices(), GetNode(), anchor );
694 // Cache for event-thread access
697 // not allocated, check if different from default
698 if( AnchorPoint::DEFAULT != anchor )
700 mAnchorPoint = new Vector3( anchor );
705 // check if different from current costs more than just set
706 *mAnchorPoint = anchor;
710 void Actor::SetAnchorPointX( float x )
712 const Vector3& current = GetCurrentAnchorPoint();
714 SetAnchorPoint( Vector3( x, current.y, current.z ) );
717 void Actor::SetAnchorPointY( float y )
719 const Vector3& current = GetCurrentAnchorPoint();
721 SetAnchorPoint( Vector3( current.x, y, current.z ) );
724 void Actor::SetAnchorPointZ( float z )
726 const Vector3& current = GetCurrentAnchorPoint();
728 SetAnchorPoint( Vector3( current.x, current.y, z ) );
731 const Vector3& Actor::GetCurrentAnchorPoint() const
733 // Cached for event-thread access
734 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
737 void Actor::SetPosition( float x, float y )
739 SetPosition( Vector3( x, y, 0.0f ) );
742 void Actor::SetPosition( float x, float y, float z )
744 SetPosition( Vector3( x, y, z ) );
747 void Actor::SetPosition( const Vector3& position )
749 mTargetPosition = position;
751 // node is being used in a separate thread; queue a message to set the value & base value
752 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
755 void Actor::SetX( float x )
757 mTargetPosition.x = x;
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>::BakeX, x );
763 void Actor::SetY( float y )
765 mTargetPosition.y = y;
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>::BakeY, y );
771 void Actor::SetZ( float z )
773 mTargetPosition.z = z;
775 // node is being used in a separate thread; queue a message to set the value & base value
776 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
779 void Actor::TranslateBy( const Vector3& distance )
781 mTargetPosition += distance;
783 // node is being used in a separate thread; queue a message to set the value & base value
784 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
787 const Vector3& Actor::GetCurrentPosition() const
789 // node is being used in a separate thread; copy the value from the previous update
790 return GetNode().GetPosition(GetEventThreadServices().GetEventBufferIndex());
793 const Vector3& Actor::GetTargetPosition() const
795 return mTargetPosition;
798 const Vector3& Actor::GetCurrentWorldPosition() const
800 // node is being used in a separate thread; copy the value from the previous update
801 return GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
804 const Vector2 Actor::GetCurrentScreenPosition() const
806 if( mScene && OnStage() )
808 Vector3 worldPosition = GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
809 Vector3 cameraPosition = mScene->GetDefaultCameraActor().GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
810 worldPosition -= cameraPosition;
812 Vector3 actorSize = GetCurrentSize() * GetCurrentWorldScale();
813 Vector2 halfSceneSize( mScene->GetSize() * 0.5f ); // World position origin is center of scene
814 Vector3 halfActorSize( actorSize * 0.5f );
815 Vector3 anchorPointOffSet = halfActorSize - actorSize * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
817 return Vector2( halfSceneSize.width + worldPosition.x - anchorPointOffSet.x,
818 halfSceneSize.height + worldPosition.y - anchorPointOffSet.y );
821 return Vector2::ZERO;
824 void Actor::SetInheritPosition( bool inherit )
826 if( mInheritPosition != inherit )
828 // non animatable so keep local copy
829 mInheritPosition = inherit;
830 SetInheritPositionMessage( GetEventThreadServices(), GetNode(), inherit );
834 bool Actor::IsPositionInherited() const
836 return mInheritPosition;
839 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
841 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
842 normalizedAxis.Normalize();
844 Quaternion orientation( angle, normalizedAxis );
846 SetOrientation( orientation );
849 void Actor::SetOrientation( const Quaternion& orientation )
851 mTargetOrientation = orientation;
853 // node is being used in a separate thread; queue a message to set the value & base value
854 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation );
857 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
859 RotateBy( Quaternion(angle, axis) );
862 void Actor::RotateBy( const Quaternion& relativeRotation )
864 mTargetOrientation *= Quaternion( relativeRotation );
866 // node is being used in a separate thread; queue a message to set the value & base value
867 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
870 const Quaternion& Actor::GetCurrentOrientation() const
872 // node is being used in a separate thread; copy the value from the previous update
873 return GetNode().GetOrientation(GetEventThreadServices().GetEventBufferIndex());
876 const Quaternion& Actor::GetCurrentWorldOrientation() const
878 // node is being used in a separate thread; copy the value from the previous update
879 return GetNode().GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
882 void Actor::SetScale( float scale )
884 SetScale( Vector3( scale, scale, scale ) );
887 void Actor::SetScale( float x, float y, float z )
889 SetScale( Vector3( x, y, z ) );
892 void Actor::SetScale( const Vector3& scale )
894 mTargetScale = scale;
896 // node is being used in a separate thread; queue a message to set the value & base value
897 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
900 void Actor::SetScaleX( float x )
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>::BakeX, x );
908 void Actor::SetScaleY( float y )
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>::BakeY, y );
916 void Actor::SetScaleZ( float z )
920 // node is being used in a separate thread; queue a message to set the value & base value
921 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
924 void Actor::ScaleBy(const Vector3& relativeScale)
926 mTargetScale *= relativeScale;
928 // node is being used in a separate thread; queue a message to set the value & base value
929 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
932 const Vector3& Actor::GetCurrentScale() const
934 // node is being used in a separate thread; copy the value from the previous update
935 return GetNode().GetScale(GetEventThreadServices().GetEventBufferIndex());
938 const Vector3& Actor::GetCurrentWorldScale() const
940 // node is being used in a separate thread; copy the value from the previous update
941 return GetNode().GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
944 void Actor::SetInheritScale( bool inherit )
946 if( mInheritScale != inherit )
948 // non animatable so keep local copy
949 mInheritScale = inherit;
950 // node is being used in a separate thread; queue a message to set the value
951 SetInheritScaleMessage( GetEventThreadServices(), GetNode(), inherit );
955 bool Actor::IsScaleInherited() const
957 return mInheritScale;
960 Matrix Actor::GetCurrentWorldMatrix() const
962 return GetNode().GetWorldMatrix(0);
965 void Actor::SetVisible( bool visible )
967 SetVisibleInternal( visible, SendMessage::TRUE );
970 bool Actor::IsVisible() const
972 // node is being used in a separate thread; copy the value from the previous update
973 return GetNode().IsVisible( GetEventThreadServices().GetEventBufferIndex() );
976 void Actor::SetOpacity( float opacity )
978 mTargetColor.a = opacity;
980 // node is being used in a separate thread; queue a message to set the value & base value
981 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
984 float Actor::GetCurrentOpacity() const
986 // node is being used in a separate thread; copy the value from the previous update
987 return GetNode().GetOpacity(GetEventThreadServices().GetEventBufferIndex());
990 ClippingMode::Type Actor::GetClippingMode() const
992 return mClippingMode;
995 uint32_t Actor::GetSortingDepth()
1000 const Vector4& Actor::GetCurrentWorldColor() const
1002 return GetNode().GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1005 void Actor::SetColor( const Vector4& color )
1007 mTargetColor = color;
1009 // node is being used in a separate thread; queue a message to set the value & base value
1010 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::Bake, color );
1013 void Actor::SetColorRed( float red )
1015 mTargetColor.r = red;
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>::BakeX, red );
1021 void Actor::SetColorGreen( float green )
1023 mTargetColor.g = green;
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>::BakeY, green );
1029 void Actor::SetColorBlue( float blue )
1031 mTargetColor.b = blue;
1033 // node is being used in a separate thread; queue a message to set the value & base value
1034 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1037 const Vector4& Actor::GetCurrentColor() const
1039 // node is being used in a separate thread; copy the value from the previous update
1040 return GetNode().GetColor(GetEventThreadServices().GetEventBufferIndex());
1043 void Actor::SetInheritOrientation( bool inherit )
1045 if( mInheritOrientation != inherit )
1047 // non animatable so keep local copy
1048 mInheritOrientation = inherit;
1049 // node is being used in a separate thread; queue a message to set the value
1050 SetInheritOrientationMessage( GetEventThreadServices(), GetNode(), inherit );
1054 bool Actor::IsOrientationInherited() const
1056 return mInheritOrientation;
1059 void Actor::SetSizeModeFactor( const Vector3& factor )
1061 EnsureRelayoutData();
1063 mRelayoutData->sizeModeFactor = factor;
1066 const Vector3& Actor::GetSizeModeFactor() const
1068 if ( mRelayoutData )
1070 return mRelayoutData->sizeModeFactor;
1073 return GetDefaultSizeModeFactor();
1076 void Actor::SetColorMode( ColorMode colorMode )
1078 // non animatable so keep local copy
1079 mColorMode = colorMode;
1080 // node is being used in a separate thread; queue a message to set the value
1081 SetColorModeMessage( GetEventThreadServices(), GetNode(), colorMode );
1084 ColorMode Actor::GetColorMode() const
1086 // we have cached copy
1090 void Actor::SetSize( float width, float height )
1092 SetSize( Vector2( width, height ) );
1095 void Actor::SetSize( float width, float height, float depth )
1097 SetSize( Vector3( width, height, depth ) );
1100 void Actor::SetSize( const Vector2& size )
1102 SetSize( Vector3( size.width, size.height, 0.f ) );
1105 void Actor::SetSizeInternal( const Vector2& size )
1107 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1110 void Actor::SetSize( const Vector3& size )
1112 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1114 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1115 SetPreferredSize( size.GetVectorXY() );
1119 SetSizeInternal( size );
1123 void Actor::SetSizeInternal( const Vector3& size )
1125 // dont allow recursive loop
1126 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1127 // 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
1128 if( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1129 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1130 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) )
1134 // node is being used in a separate thread; queue a message to set the value & base value
1135 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
1137 // Notification for derived classes
1138 mInsideOnSizeSet = true;
1139 OnSizeSet( mTargetSize );
1140 mInsideOnSizeSet = false;
1142 // Raise a relayout request if the flag is not locked
1143 if( mRelayoutData && !mRelayoutData->insideRelayout )
1150 void Actor::SetWidth( float width )
1152 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1154 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
1155 mRelayoutData->preferredSize.width = width;
1159 mTargetSize.width = width;
1161 // node is being used in a separate thread; queue a message to set the value & base value
1162 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1165 mUseAnimatedSize &= ~AnimatedSizeFlag::WIDTH;
1170 void Actor::SetHeight( float height )
1172 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1174 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
1175 mRelayoutData->preferredSize.height = height;
1179 mTargetSize.height = height;
1181 // node is being used in a separate thread; queue a message to set the value & base value
1182 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1185 mUseAnimatedSize &= ~AnimatedSizeFlag::HEIGHT;
1190 void Actor::SetDepth( float depth )
1192 mTargetSize.depth = depth;
1194 mUseAnimatedSize &= ~AnimatedSizeFlag::DEPTH;
1196 // node is being used in a separate thread; queue a message to set the value & base value
1197 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1200 Vector3 Actor::GetTargetSize() const
1202 Vector3 size = mTargetSize;
1204 if( mUseAnimatedSize & AnimatedSizeFlag::WIDTH )
1206 // Should return animated size if size is animated
1207 size.width = mAnimatedSize.width;
1211 // Should return preferred size if size is fixed as set by SetSize
1212 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
1214 size.width = GetPreferredSize().width;
1218 if( mUseAnimatedSize & AnimatedSizeFlag::HEIGHT )
1220 size.height = mAnimatedSize.height;
1224 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
1226 size.height = GetPreferredSize().height;
1230 if( mUseAnimatedSize & AnimatedSizeFlag::DEPTH )
1232 size.depth = mAnimatedSize.depth;
1238 const Vector3& Actor::GetCurrentSize() const
1240 // node is being used in a separate thread; copy the value from the previous update
1241 return GetNode().GetSize( GetEventThreadServices().GetEventBufferIndex() );
1244 Vector3 Actor::GetNaturalSize() const
1246 // It is up to deriving classes to return the appropriate natural size
1247 return Vector3( 0.0f, 0.0f, 0.0f );
1250 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1252 EnsureRelayoutData();
1254 ResizePolicy::Type originalWidthPolicy = GetResizePolicy(Dimension::WIDTH);
1255 ResizePolicy::Type originalHeightPolicy = GetResizePolicy(Dimension::HEIGHT);
1257 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1259 if( dimension & ( 1 << i ) )
1261 if ( policy == ResizePolicy::USE_ASSIGNED_SIZE )
1263 mRelayoutData->useAssignedSize[ i ] = true;
1267 mRelayoutData->resizePolicies[ i ] = policy;
1268 mRelayoutData->useAssignedSize[ i ] = false;
1273 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1275 if( dimension & Dimension::WIDTH )
1277 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1280 if( dimension & Dimension::HEIGHT )
1282 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1286 // If calling SetResizePolicy, assume we want relayout enabled
1287 SetRelayoutEnabled( true );
1289 // If the resize policy is set to be FIXED, the preferred size
1290 // should be overrided by the target size. Otherwise the target
1291 // size should be overrided by the preferred size.
1293 if( dimension & Dimension::WIDTH )
1295 if( originalWidthPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1297 mRelayoutData->preferredSize.width = mTargetSize.width;
1299 else if( originalWidthPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1301 mTargetSize.width = mRelayoutData->preferredSize.width;
1305 if( dimension & Dimension::HEIGHT )
1307 if( originalHeightPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1309 mRelayoutData->preferredSize.height = mTargetSize.height;
1311 else if( originalHeightPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1313 mTargetSize.height = mRelayoutData->preferredSize.height;
1317 OnSetResizePolicy( policy, dimension );
1319 // Trigger relayout on this control
1323 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1325 if ( mRelayoutData )
1327 // If more than one dimension is requested, just return the first one found
1328 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1330 if( ( dimension & ( 1 << i ) ) )
1332 if( mRelayoutData->useAssignedSize[ i ] )
1334 return ResizePolicy::USE_ASSIGNED_SIZE;
1338 return mRelayoutData->resizePolicies[ i ];
1344 return ResizePolicy::DEFAULT;
1347 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1349 EnsureRelayoutData();
1351 mRelayoutData->sizeSetPolicy = policy;
1353 // Trigger relayout on this control
1357 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1359 if ( mRelayoutData )
1361 return mRelayoutData->sizeSetPolicy;
1364 return DEFAULT_SIZE_SCALE_POLICY;
1367 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1369 EnsureRelayoutData();
1371 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1373 if( dimension & ( 1 << i ) )
1375 mRelayoutData->dimensionDependencies[ i ] = dependency;
1380 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1382 if ( mRelayoutData )
1384 // If more than one dimension is requested, just return the first one found
1385 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1387 if( ( dimension & ( 1 << i ) ) )
1389 return mRelayoutData->dimensionDependencies[ i ];
1394 return Dimension::ALL_DIMENSIONS; // Default
1397 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1399 // If relayout data has not been allocated yet and the client is requesting
1400 // to disable it, do nothing
1401 if( mRelayoutData || relayoutEnabled )
1403 EnsureRelayoutData();
1405 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1407 mRelayoutData->relayoutEnabled = relayoutEnabled;
1411 bool Actor::IsRelayoutEnabled() const
1413 // Assume that if relayout data has not been allocated yet then
1414 // relayout is disabled
1415 return mRelayoutData && mRelayoutData->relayoutEnabled;
1418 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1420 EnsureRelayoutData();
1422 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1424 if( dimension & ( 1 << i ) )
1426 mRelayoutData->dimensionDirty[ i ] = dirty;
1431 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1433 if ( mRelayoutData )
1435 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1437 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1447 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1449 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1452 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1454 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1457 uint32_t Actor::AddRenderer( Renderer& renderer )
1461 mRenderers = new RendererContainer;
1464 uint32_t index = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1465 RendererPtr rendererPtr = RendererPtr( &renderer );
1466 mRenderers->push_back( rendererPtr );
1467 AttachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1471 uint32_t Actor::GetRendererCount() const
1473 uint32_t rendererCount(0);
1476 rendererCount = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1479 return rendererCount;
1482 RendererPtr Actor::GetRendererAt( uint32_t index )
1484 RendererPtr renderer;
1485 if( index < GetRendererCount() )
1487 renderer = ( *mRenderers )[ index ];
1493 void Actor::RemoveRenderer( Renderer& renderer )
1497 RendererIter end = mRenderers->end();
1498 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1500 if( (*iter).Get() == &renderer )
1502 mRenderers->erase( iter );
1503 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1510 void Actor::RemoveRenderer( uint32_t index )
1512 if( index < GetRendererCount() )
1514 RendererPtr renderer = ( *mRenderers )[ index ];
1515 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.Get()->GetRendererSceneObject() );
1516 mRenderers->erase( mRenderers->begin()+index );
1520 bool Actor::IsOverlay() const
1522 return ( DrawMode::OVERLAY_2D == mDrawMode );
1525 void Actor::SetDrawMode( DrawMode::Type drawMode )
1527 // this flag is not animatable so keep the value
1528 mDrawMode = drawMode;
1530 // node is being used in a separate thread; queue a message to set the value
1531 SetDrawModeMessage( GetEventThreadServices(), GetNode(), drawMode );
1534 DrawMode::Type Actor::GetDrawMode() const
1539 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1541 // only valid when on-stage
1542 if( mScene && OnStage() )
1544 const RenderTaskList& taskList = mScene->GetRenderTaskList();
1546 Vector2 converted( screenX, screenY );
1548 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1549 uint32_t taskCount = taskList.GetTaskCount();
1550 for( uint32_t i = taskCount; i > 0; --i )
1552 RenderTaskPtr task = taskList.GetTask( i - 1 );
1553 if( ScreenToLocal( *task, localX, localY, screenX, screenY ) )
1555 // found a task where this conversion was ok so return
1563 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1565 bool retval = false;
1566 // only valid when on-stage
1569 CameraActor* camera = renderTask.GetCameraActor();
1573 renderTask.GetViewport( viewport );
1575 // need to translate coordinates to render tasks coordinate space
1576 Vector2 converted( screenX, screenY );
1577 if( renderTask.TranslateCoordinates( converted ) )
1579 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1586 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1588 // Early-out if not on stage
1594 // Get the ModelView matrix
1596 Matrix::Multiply( modelView, GetNode().GetWorldMatrix(0), viewMatrix );
1598 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1599 Matrix invertedMvp( false/*don't init*/);
1600 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1601 bool success = invertedMvp.Invert();
1603 // Convert to GL coordinates
1604 Vector4 screenPos( screenX - static_cast<float>( viewport.x ), static_cast<float>( viewport.height ) - screenY - static_cast<float>( viewport.y ), 0.f, 1.f );
1609 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), nearPos );
1616 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), farPos );
1622 if( XyPlaneIntersect( nearPos, farPos, local ) )
1624 Vector3 size = GetCurrentSize();
1625 localX = local.x + size.x * 0.5f;
1626 localY = local.y + size.y * 0.5f;
1637 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1640 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1642 Mathematical Formulation
1644 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1646 ( p - c ) dot ( p - c ) = r^2
1648 Given a ray with a point of origin 'o', and a direction vector 'd':
1650 ray(t) = o + td, t >= 0
1652 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1654 (o + td - c ) dot ( o + td - c ) = r^2
1656 To solve for t we first expand the above into a more recognisable quadratic equation form
1658 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1667 B = 2( o - c ) dot d
1668 C = ( o - c ) dot ( o - c ) - r^2
1670 which can be solved using a standard quadratic formula.
1672 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1674 Practical Simplification
1676 In a renderer, we often differentiate between world space and object space. In the object space
1677 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1678 into object space, the mathematical solution presented above can be simplified significantly.
1680 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1684 and we can find the t at which the (transformed) ray intersects the sphere by
1686 ( o + td ) dot ( o + td ) = r^2
1688 According to the reasoning above, we expand the above quadratic equation into the general form
1692 which now has coefficients:
1699 // Early-out if not on stage
1705 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1707 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1708 const Vector3& translation( GetNode().GetWorldPosition( bufferIndex ) );
1709 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1711 // Compute the radius is not needed, square radius it's enough.
1712 const Vector3& size( GetNode().GetSize( bufferIndex ) );
1714 // Scale the sphere.
1715 const Vector3& scale( GetNode().GetWorldScale( bufferIndex ) );
1717 const float width = size.width * scale.width;
1718 const float height = size.height * scale.height;
1720 float squareSphereRadius = 0.5f * ( width * width + height * height );
1722 float a = rayDir.Dot( rayDir ); // a
1723 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1724 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1726 return ( b2 * b2 - a * c ) >= 0.f;
1729 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector2& hitPointLocal, float& distance ) const
1735 // Transforms the ray to the local reference system.
1736 // Calculate the inverse of Model matrix
1737 Matrix invModelMatrix( false/*don't init*/);
1739 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1740 invModelMatrix = GetNode().GetWorldMatrix(0);
1741 invModelMatrix.Invert();
1743 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1744 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1746 // Test with the actor's XY plane (Normal = 0 0 1 1).
1748 float a = -rayOriginLocal.z;
1749 float b = rayDirLocal.z;
1751 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1753 // Ray travels distance * rayDirLocal to intersect with plane.
1756 const Vector3& size = GetNode().GetSize( bufferIndex );
1758 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1759 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1761 // Test with the actor's geometry.
1762 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1769 void Actor::SetLeaveRequired( bool required )
1771 mLeaveRequired = required;
1774 bool Actor::GetLeaveRequired() const
1776 return mLeaveRequired;
1779 void Actor::SetKeyboardFocusable( bool focusable )
1781 mKeyboardFocusable = focusable;
1784 bool Actor::IsKeyboardFocusable() const
1786 return mKeyboardFocusable;
1789 bool Actor::GetTouchRequired() const
1791 return !mTouchedSignal.Empty() || !mTouchSignal.Empty() || mDerivedRequiresTouch;
1794 bool Actor::GetHoverRequired() const
1796 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1799 bool Actor::GetWheelEventRequired() const
1801 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1804 bool Actor::IsHittable() const
1806 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1809 ActorGestureData& Actor::GetGestureData()
1811 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1812 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1813 if( NULL == mGestureData )
1815 mGestureData = new ActorGestureData;
1817 return *mGestureData;
1820 bool Actor::IsGestureRequred( DevelGesture::Type type ) const
1822 return mGestureData && mGestureData->IsGestureRequred( type );
1825 bool Actor::EmitTouchEventSignal( const TouchEvent& event, const Dali::TouchData& touch )
1827 bool consumed = false;
1829 if( !mTouchSignal.Empty() )
1831 Dali::Actor handle( this );
1832 consumed = mTouchSignal.Emit( handle, touch );
1835 if( !mTouchedSignal.Empty() )
1837 Dali::Actor handle( this );
1838 consumed |= mTouchedSignal.Emit( handle, event );
1843 // Notification for derived classes
1844 consumed = OnTouchEvent( event ); // TODO
1850 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1852 bool consumed = false;
1854 if( !mHoveredSignal.Empty() )
1856 Dali::Actor handle( this );
1857 consumed = mHoveredSignal.Emit( handle, event );
1862 // Notification for derived classes
1863 consumed = OnHoverEvent( event );
1869 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1871 bool consumed = false;
1873 if( !mWheelEventSignal.Empty() )
1875 Dali::Actor handle( this );
1876 consumed = mWheelEventSignal.Emit( handle, event );
1881 // Notification for derived classes
1882 consumed = OnWheelEvent( event );
1888 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
1890 if( ! mVisibilityChangedSignal.Empty() )
1892 Dali::Actor handle( this );
1893 mVisibilityChangedSignal.Emit( handle, visible, type );
1897 void Actor::EmitLayoutDirectionChangedSignal( LayoutDirection::Type type )
1899 if( ! mLayoutDirectionChangedSignal.Empty() )
1901 Dali::Actor handle( this );
1902 mLayoutDirectionChangedSignal.Emit( handle, type );
1906 void Actor::EmitChildAddedSignal( Actor& child )
1908 if( ! mChildAddedSignal.Empty() )
1910 Dali::Actor handle( &child );
1911 mChildAddedSignal.Emit( handle );
1915 void Actor::EmitChildRemovedSignal( Actor& child )
1917 if( ! mChildRemovedSignal.Empty() )
1919 Dali::Actor handle( &child );
1920 mChildRemovedSignal.Emit( handle );
1924 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
1926 return mTouchedSignal;
1929 Dali::Actor::TouchDataSignalType& Actor::TouchSignal()
1931 return mTouchSignal;
1934 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
1936 return mHoveredSignal;
1939 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
1941 return mWheelEventSignal;
1944 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
1946 return mOnStageSignal;
1949 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
1951 return mOffStageSignal;
1954 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
1956 return mOnRelayoutSignal;
1959 DevelActor::VisibilityChangedSignalType& Actor::VisibilityChangedSignal()
1961 return mVisibilityChangedSignal;
1964 Dali::Actor::LayoutDirectionChangedSignalType& Actor::LayoutDirectionChangedSignal()
1966 return mLayoutDirectionChangedSignal;
1969 DevelActor::ChildChangedSignalType& Actor::ChildAddedSignal()
1971 return mChildAddedSignal;
1974 DevelActor::ChildChangedSignalType& Actor::ChildRemovedSignal()
1976 return mChildRemovedSignal;
1979 DevelActor::ChildOrderChangedSignalType& Actor::ChildOrderChangedSignal()
1981 return mChildOrderChangedSignal;
1984 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1986 bool connected( true );
1987 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
1989 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1991 actor->TouchedSignal().Connect( tracker, functor );
1993 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1995 actor->HoveredSignal().Connect( tracker, functor );
1997 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1999 actor->WheelEventSignal().Connect( tracker, functor );
2001 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
2003 actor->OnStageSignal().Connect( tracker, functor );
2005 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
2007 actor->OffStageSignal().Connect( tracker, functor );
2009 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
2011 actor->OnRelayoutSignal().Connect( tracker, functor );
2013 else if( 0 == signalName.compare( SIGNAL_TOUCH ) )
2015 actor->TouchSignal().Connect( tracker, functor );
2017 else if( 0 == signalName.compare( SIGNAL_VISIBILITY_CHANGED ) )
2019 actor->VisibilityChangedSignal().Connect( tracker, functor );
2021 else if( 0 == signalName.compare( SIGNAL_LAYOUT_DIRECTION_CHANGED ) )
2023 actor->LayoutDirectionChangedSignal().Connect( tracker, functor );
2025 else if( 0 == signalName.compare( SIGNAL_CHILD_ADDED ) )
2027 actor->ChildAddedSignal().Connect( tracker, functor );
2029 else if( 0 == signalName.compare( SIGNAL_CHILD_REMOVED ) )
2031 actor->ChildRemovedSignal().Connect( tracker, functor );
2035 // signalName does not match any signal
2042 Actor::Actor( DerivedType derivedType, const SceneGraph::Node& node )
2048 mParentOrigin( NULL ),
2049 mAnchorPoint( NULL ),
2050 mRelayoutData( NULL ),
2051 mGestureData( NULL ),
2055 mWheelEventSignal(),
2058 mOnRelayoutSignal(),
2059 mVisibilityChangedSignal(),
2060 mLayoutDirectionChangedSignal(),
2061 mChildAddedSignal(),
2062 mChildRemovedSignal(),
2063 mChildOrderChangedSignal(),
2064 mTargetOrientation( Quaternion::IDENTITY ),
2065 mTargetColor( Color::WHITE ),
2066 mTargetSize( Vector3::ZERO ),
2067 mTargetPosition( Vector3::ZERO ),
2068 mTargetScale( Vector3::ONE ),
2069 mAnimatedSize( Vector3::ZERO ),
2073 mUseAnimatedSize( AnimatedSizeFlag::CLEAR ),
2074 mIsRoot( ROOT_LAYER == derivedType ),
2075 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2076 mIsOnStage( false ),
2078 mLeaveRequired( false ),
2079 mKeyboardFocusable( false ),
2080 mDerivedRequiresTouch( false ),
2081 mDerivedRequiresHover( false ),
2082 mDerivedRequiresWheelEvent( false ),
2083 mOnStageSignalled( false ),
2084 mInsideOnSizeSet( false ),
2085 mInheritPosition( true ),
2086 mInheritOrientation( true ),
2087 mInheritScale( true ),
2088 mPositionUsesAnchorPoint( true ),
2090 mInheritLayoutDirection( true ),
2091 mLayoutDirection( LayoutDirection::LEFT_TO_RIGHT ),
2092 mDrawMode( DrawMode::NORMAL ),
2093 mColorMode( Node::DEFAULT_COLOR_MODE ),
2094 mClippingMode( ClippingMode::DISABLED )
2098 void Actor::Initialize()
2102 GetEventThreadServices().RegisterObject( this );
2107 // Remove mParent pointers from children even if we're destroying core,
2108 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2111 ActorConstIter endIter = mChildren->end();
2112 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2114 (*iter)->SetParent( NULL );
2120 // Guard to allow handle destruction after Core has been destroyed
2121 if( EventThreadServices::IsCoreRunning() )
2123 // Root layer will destroy its node in its own destructor
2126 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
2128 GetEventThreadServices().UnregisterObject( this );
2132 // Cleanup optional gesture data
2133 delete mGestureData;
2135 // Cleanup optional parent origin and anchor
2136 delete mParentOrigin;
2137 delete mAnchorPoint;
2139 // Delete optional relayout data
2140 delete mRelayoutData;
2143 void Actor::ConnectToStage( uint32_t parentDepth )
2145 // This container is used instead of walking the Actor hierarchy.
2146 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
2147 ActorContainer connectionList;
2151 mScene->RequestRebuildDepthTree();
2154 // This stage is atomic i.e. not interrupted by user callbacks.
2155 RecursiveConnectToStage( connectionList, parentDepth + 1 );
2157 // Notify applications about the newly connected actors.
2158 const ActorIter endIter = connectionList.end();
2159 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2161 (*iter)->NotifyStageConnection();
2167 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, uint32_t depth )
2169 DALI_ASSERT_ALWAYS( !OnStage() );
2172 mDepth = static_cast< uint16_t >( depth ); // overflow ignored, not expected in practice
2174 ConnectToSceneGraph();
2176 // Notification for internal derived classes
2177 OnStageConnectionInternal();
2179 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2180 connectionList.push_back( ActorPtr( this ) );
2182 // Recursively connect children
2185 ActorConstIter endIter = mChildren->end();
2186 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2188 (*iter)->SetScene( *mScene );
2189 (*iter)->RecursiveConnectToStage( connectionList, depth + 1 );
2195 * This method is called when the Actor is connected to the Stage.
2196 * The parent must have added its Node to the scene-graph.
2197 * The child must connect its Node to the parent's Node.
2198 * This is recursive; the child calls ConnectToStage() for its children.
2200 void Actor::ConnectToSceneGraph()
2202 DALI_ASSERT_DEBUG( mParent != NULL);
2204 // Reparent Node in next Update
2205 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), mParent->GetNode(), GetNode() );
2207 // Request relayout on all actors that are added to the scenegraph
2210 // Notification for Object::Observers
2214 void Actor::NotifyStageConnection()
2216 // Actors can be removed (in a callback), before the on-stage stage is reported.
2217 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2218 if( OnStage() && !mOnStageSignalled )
2220 // Notification for external (CustomActor) derived classes
2221 OnStageConnectionExternal( mDepth );
2223 if( !mOnStageSignal.Empty() )
2225 Dali::Actor handle( this );
2226 mOnStageSignal.Emit( handle );
2229 // Guard against Remove during callbacks
2232 mOnStageSignalled = true; // signal required next time Actor is removed
2237 void Actor::DisconnectFromStage()
2239 // This container is used instead of walking the Actor hierachy.
2240 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2241 ActorContainer disconnectionList;
2245 mScene->RequestRebuildDepthTree();
2248 // This stage is atomic i.e. not interrupted by user callbacks
2249 RecursiveDisconnectFromStage( disconnectionList );
2251 // Notify applications about the newly disconnected actors.
2252 const ActorIter endIter = disconnectionList.end();
2253 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2255 (*iter)->NotifyStageDisconnection();
2259 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2261 // need to change state first so that internals relying on IsOnStage() inside OnStageDisconnectionInternal() get the correct value
2264 // Recursively disconnect children
2267 ActorConstIter endIter = mChildren->end();
2268 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2270 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2274 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2275 disconnectionList.push_back( ActorPtr( this ) );
2277 // Notification for internal derived classes
2278 OnStageDisconnectionInternal();
2280 DisconnectFromSceneGraph();
2284 * This method is called by an actor or its parent, before a node removal message is sent.
2285 * This is recursive; the child calls DisconnectFromStage() for its children.
2287 void Actor::DisconnectFromSceneGraph()
2289 // Notification for Object::Observers
2290 OnSceneObjectRemove();
2293 void Actor::NotifyStageDisconnection()
2295 // Actors can be added (in a callback), before the off-stage state is reported.
2296 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2297 // only do this step if there is a stage, i.e. Core is not being shut down
2298 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2300 // Notification for external (CustomeActor) derived classes
2301 OnStageDisconnectionExternal();
2303 if( !mOffStageSignal.Empty() )
2305 Dali::Actor handle( this );
2306 mOffStageSignal.Emit( handle );
2309 // Guard against Add during callbacks
2312 mOnStageSignalled = false; // signal required next time Actor is added
2317 bool Actor::IsNodeConnected() const
2319 bool connected( false );
2323 if( IsRoot() || GetNode().GetParent() )
2332 // This method initiates traversal of the actor tree using depth-first
2333 // traversal to set a depth index based on traversal order. It sends a
2334 // single message to update manager to update all the actor's nodes in
2335 // this tree with the depth index. The sceneGraphNodeDepths vector's
2336 // elements are ordered by depth, and could be used to reduce sorting
2337 // in the update thread.
2338 void Actor::RebuildDepthTree()
2340 DALI_LOG_TIMER_START(depthTimer);
2342 // Vector of scene-graph nodes and their depths to send to UpdateManager
2343 // in a single message
2344 OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths( new SceneGraph::NodeDepths() );
2346 int32_t depthIndex = 1;
2347 DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
2349 SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths );
2350 DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
2353 void Actor::DepthTraverseActorTree( OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths, int32_t& depthIndex )
2355 mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
2356 sceneGraphNodeDepths->Add( const_cast<SceneGraph::Node*>( &GetNode() ), mSortedDepth );
2358 // Create/add to children of this node
2361 for( ActorContainer::iterator it = mChildren->begin(); it != mChildren->end(); ++it )
2363 Actor* childActor = (*it).Get();
2365 childActor->DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
2370 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2374 case Dali::Actor::Property::PARENT_ORIGIN:
2376 Property::Type type = property.GetType();
2377 if( type == Property::VECTOR3 )
2379 SetParentOrigin( property.Get< Vector3 >() );
2381 else if ( type == Property::STRING )
2383 std::string parentOriginString;
2384 property.Get( parentOriginString );
2385 Vector3 parentOrigin;
2386 if( GetParentOriginConstant( parentOriginString, parentOrigin ) )
2388 SetParentOrigin( parentOrigin );
2394 case Dali::Actor::Property::PARENT_ORIGIN_X:
2396 SetParentOriginX( property.Get< float >() );
2400 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2402 SetParentOriginY( property.Get< float >() );
2406 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2408 SetParentOriginZ( property.Get< float >() );
2412 case Dali::Actor::Property::ANCHOR_POINT:
2414 Property::Type type = property.GetType();
2415 if( type == Property::VECTOR3 )
2417 SetAnchorPoint( property.Get< Vector3 >() );
2419 else if ( type == Property::STRING )
2421 std::string anchorPointString;
2422 property.Get( anchorPointString );
2424 if( GetAnchorPointConstant( anchorPointString, anchor ) )
2426 SetAnchorPoint( anchor );
2432 case Dali::Actor::Property::ANCHOR_POINT_X:
2434 SetAnchorPointX( property.Get< float >() );
2438 case Dali::Actor::Property::ANCHOR_POINT_Y:
2440 SetAnchorPointY( property.Get< float >() );
2444 case Dali::Actor::Property::ANCHOR_POINT_Z:
2446 SetAnchorPointZ( property.Get< float >() );
2450 case Dali::Actor::Property::SIZE:
2452 Property::Type type = property.GetType();
2453 if( type == Property::VECTOR2 )
2455 SetSize( property.Get< Vector2 >() );
2457 else if ( type == Property::VECTOR3 )
2459 SetSize( property.Get< Vector3 >() );
2464 case Dali::Actor::Property::SIZE_WIDTH:
2466 SetWidth( property.Get< float >() );
2470 case Dali::Actor::Property::SIZE_HEIGHT:
2472 SetHeight( property.Get< float >() );
2476 case Dali::Actor::Property::SIZE_DEPTH:
2478 SetDepth( property.Get< float >() );
2482 case Dali::Actor::Property::POSITION:
2484 Property::Type type = property.GetType();
2485 if( type == Property::VECTOR2 )
2487 Vector2 position = property.Get< Vector2 >();
2488 SetPosition( Vector3( position.x, position.y, 0.0f ) );
2490 else if ( type == Property::VECTOR3 )
2492 SetPosition( property.Get< Vector3 >() );
2497 case Dali::Actor::Property::POSITION_X:
2499 SetX( property.Get< float >() );
2503 case Dali::Actor::Property::POSITION_Y:
2505 SetY( property.Get< float >() );
2509 case Dali::Actor::Property::POSITION_Z:
2511 SetZ( property.Get< float >() );
2515 case Dali::Actor::Property::ORIENTATION:
2517 SetOrientation( property.Get< Quaternion >() );
2521 case Dali::Actor::Property::SCALE:
2523 Property::Type type = property.GetType();
2524 if( type == Property::FLOAT )
2526 float scale = property.Get< float >();
2527 SetScale( scale, scale, scale );
2529 else if ( type == Property::VECTOR3 )
2531 SetScale( property.Get< Vector3 >() );
2536 case Dali::Actor::Property::SCALE_X:
2538 SetScaleX( property.Get< float >() );
2542 case Dali::Actor::Property::SCALE_Y:
2544 SetScaleY( property.Get< float >() );
2548 case Dali::Actor::Property::SCALE_Z:
2550 SetScaleZ( property.Get< float >() );
2554 case Dali::Actor::Property::VISIBLE:
2556 SetVisible( property.Get< bool >() );
2560 case Dali::Actor::Property::COLOR:
2562 Property::Type type = property.GetType();
2563 if( type == Property::VECTOR3 )
2565 Vector3 color = property.Get< Vector3 >();
2566 SetColor( Vector4( color.r, color.g, color.b, 1.0f ) );
2568 else if( type == Property::VECTOR4 )
2570 SetColor( property.Get< Vector4 >() );
2575 case Dali::Actor::Property::COLOR_RED:
2577 SetColorRed( property.Get< float >() );
2581 case Dali::Actor::Property::COLOR_GREEN:
2583 SetColorGreen( property.Get< float >() );
2587 case Dali::Actor::Property::COLOR_BLUE:
2589 SetColorBlue( property.Get< float >() );
2593 case Dali::Actor::Property::COLOR_ALPHA:
2594 case Dali::Actor::Property::OPACITY:
2597 if( property.Get( value ) )
2599 SetOpacity( value );
2604 case Dali::Actor::Property::NAME:
2606 SetName( property.Get< std::string >() );
2610 case Dali::Actor::Property::SENSITIVE:
2612 SetSensitive( property.Get< bool >() );
2616 case Dali::Actor::Property::LEAVE_REQUIRED:
2618 SetLeaveRequired( property.Get< bool >() );
2622 case Dali::Actor::Property::INHERIT_POSITION:
2624 SetInheritPosition( property.Get< bool >() );
2628 case Dali::Actor::Property::INHERIT_ORIENTATION:
2630 SetInheritOrientation( property.Get< bool >() );
2634 case Dali::Actor::Property::INHERIT_SCALE:
2636 SetInheritScale( property.Get< bool >() );
2640 case Dali::Actor::Property::COLOR_MODE:
2642 ColorMode mode = mColorMode;
2643 if ( Scripting::GetEnumerationProperty< ColorMode >( property, COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT, mode ) )
2645 SetColorMode( mode );
2650 case Dali::Actor::Property::DRAW_MODE:
2652 DrawMode::Type mode = mDrawMode;
2653 if( Scripting::GetEnumerationProperty< DrawMode::Type >( property, DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT, mode ) )
2655 SetDrawMode( mode );
2660 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2662 SetSizeModeFactor( property.Get< Vector3 >() );
2666 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2668 ResizePolicy::Type type = GetResizePolicy( Dimension::WIDTH );
2669 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2671 SetResizePolicy( type, Dimension::WIDTH );
2676 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2678 ResizePolicy::Type type = GetResizePolicy( Dimension::HEIGHT );
2679 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2681 SetResizePolicy( type, Dimension::HEIGHT );
2686 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2688 SizeScalePolicy::Type type = GetSizeScalePolicy();
2689 if( Scripting::GetEnumerationProperty< SizeScalePolicy::Type >( property, SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT, type ) )
2691 SetSizeScalePolicy( type );
2696 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2698 if( property.Get< bool >() )
2700 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2705 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2707 if( property.Get< bool >() )
2709 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2714 case Dali::Actor::Property::PADDING:
2716 Vector4 padding = property.Get< Vector4 >();
2717 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2718 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2722 case Dali::Actor::Property::MINIMUM_SIZE:
2724 Vector2 size = property.Get< Vector2 >();
2725 SetMinimumSize( size.x, Dimension::WIDTH );
2726 SetMinimumSize( size.y, Dimension::HEIGHT );
2730 case Dali::Actor::Property::MAXIMUM_SIZE:
2732 Vector2 size = property.Get< Vector2 >();
2733 SetMaximumSize( size.x, Dimension::WIDTH );
2734 SetMaximumSize( size.y, Dimension::HEIGHT );
2738 case Dali::DevelActor::Property::SIBLING_ORDER:
2742 if( property.Get( value ) )
2744 SetSiblingOrder( value );
2749 case Dali::Actor::Property::CLIPPING_MODE:
2751 ClippingMode::Type convertedValue = mClippingMode;
2752 if( Scripting::GetEnumerationProperty< ClippingMode::Type >( property, CLIPPING_MODE_TABLE, CLIPPING_MODE_TABLE_COUNT, convertedValue ) )
2754 mClippingMode = convertedValue;
2755 SetClippingModeMessage( GetEventThreadServices(), GetNode(), mClippingMode );
2760 case Dali::Actor::Property::POSITION_USES_ANCHOR_POINT:
2763 if( property.Get( value ) && value != mPositionUsesAnchorPoint )
2765 mPositionUsesAnchorPoint = value;
2766 SetPositionUsesAnchorPointMessage( GetEventThreadServices(), GetNode(), mPositionUsesAnchorPoint );
2771 case Dali::Actor::Property::LAYOUT_DIRECTION:
2773 Dali::LayoutDirection::Type direction = mLayoutDirection;
2774 mInheritLayoutDirection = false;
2776 if( Scripting::GetEnumerationProperty< LayoutDirection::Type >( property, LAYOUT_DIRECTION_TABLE, LAYOUT_DIRECTION_TABLE_COUNT, direction ) )
2778 InheritLayoutDirectionRecursively( this, direction, true );
2783 case Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION:
2786 if( property.Get( value ) )
2788 SetInheritLayoutDirection( value );
2793 case Dali::Actor::Property::KEYBOARD_FOCUSABLE:
2796 if( property.Get( value ) )
2798 SetKeyboardFocusable( value );
2805 // this can happen in the case of a non-animatable default property so just do nothing
2811 // TODO: This method needs to be removed
2812 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2814 switch( entry.GetType() )
2816 case Property::BOOLEAN:
2818 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2819 DALI_ASSERT_DEBUG( NULL != property );
2821 // property is being used in a separate thread; queue a message to set the property
2822 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2827 case Property::INTEGER:
2829 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2830 DALI_ASSERT_DEBUG( NULL != property );
2832 // property is being used in a separate thread; queue a message to set the property
2833 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2838 case Property::FLOAT:
2840 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2841 DALI_ASSERT_DEBUG( NULL != property );
2843 // property is being used in a separate thread; queue a message to set the property
2844 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2849 case Property::VECTOR2:
2851 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2852 DALI_ASSERT_DEBUG( NULL != property );
2854 // property is being used in a separate thread; queue a message to set the property
2855 if(entry.componentIndex == 0)
2857 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2859 else if(entry.componentIndex == 1)
2861 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2865 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2871 case Property::VECTOR3:
2873 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2874 DALI_ASSERT_DEBUG( NULL != property );
2876 // property is being used in a separate thread; queue a message to set the property
2877 if(entry.componentIndex == 0)
2879 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2881 else if(entry.componentIndex == 1)
2883 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2885 else if(entry.componentIndex == 2)
2887 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2891 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2897 case Property::VECTOR4:
2899 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2900 DALI_ASSERT_DEBUG( NULL != property );
2902 // property is being used in a separate thread; queue a message to set the property
2903 if(entry.componentIndex == 0)
2905 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
2907 else if(entry.componentIndex == 1)
2909 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
2911 else if(entry.componentIndex == 2)
2913 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
2915 else if(entry.componentIndex == 3)
2917 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
2921 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2927 case Property::ROTATION:
2929 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
2930 DALI_ASSERT_DEBUG( NULL != property );
2932 // property is being used in a separate thread; queue a message to set the property
2933 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
2938 case Property::MATRIX:
2940 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
2941 DALI_ASSERT_DEBUG( NULL != property );
2943 // property is being used in a separate thread; queue a message to set the property
2944 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), &GetNode(), property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
2949 case Property::MATRIX3:
2951 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
2952 DALI_ASSERT_DEBUG( NULL != property );
2954 // property is being used in a separate thread; queue a message to set the property
2955 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), &GetNode(), property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
2962 // nothing to do for other types
2967 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
2969 Property::Value value;
2971 if( ! GetCachedPropertyValue( index, value ) )
2973 // If property value is not stored in the event-side, then it must be a scene-graph only property
2974 GetCurrentPropertyValue( index, value );
2980 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
2982 Property::Value value;
2984 if( ! GetCurrentPropertyValue( index, value ) )
2986 // If unable to retrieve scene-graph property value, then it must be an event-side only property
2987 GetCachedPropertyValue( index, value );
2993 void Actor::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
2995 switch( animationType )
2998 case Animation::BETWEEN:
3002 case Dali::Actor::Property::SIZE:
3004 if( value.Get( mTargetSize ) )
3006 mAnimatedSize = mTargetSize;
3007 mUseAnimatedSize = AnimatedSizeFlag::WIDTH | AnimatedSizeFlag::HEIGHT | AnimatedSizeFlag::DEPTH;
3009 // Notify deriving classes
3010 OnSizeAnimation( animation, mTargetSize );
3015 case Dali::Actor::Property::SIZE_WIDTH:
3017 if( value.Get( mTargetSize.width ) )
3019 mAnimatedSize.width = mTargetSize.width;
3020 mUseAnimatedSize |= AnimatedSizeFlag::WIDTH;
3022 // Notify deriving classes
3023 OnSizeAnimation( animation, mTargetSize );
3028 case Dali::Actor::Property::SIZE_HEIGHT:
3030 if( value.Get( mTargetSize.height ) )
3032 mAnimatedSize.height = mTargetSize.height;
3033 mUseAnimatedSize |= AnimatedSizeFlag::HEIGHT;
3035 // Notify deriving classes
3036 OnSizeAnimation( animation, mTargetSize );
3041 case Dali::Actor::Property::SIZE_DEPTH:
3043 if( value.Get( mTargetSize.depth ) )
3045 mAnimatedSize.depth = mTargetSize.depth;
3046 mUseAnimatedSize |= AnimatedSizeFlag::DEPTH;
3048 // Notify deriving classes
3049 OnSizeAnimation( animation, mTargetSize );
3054 case Dali::Actor::Property::POSITION:
3056 value.Get( mTargetPosition );
3060 case Dali::Actor::Property::POSITION_X:
3062 value.Get( mTargetPosition.x );
3066 case Dali::Actor::Property::POSITION_Y:
3068 value.Get( mTargetPosition.y );
3072 case Dali::Actor::Property::POSITION_Z:
3074 value.Get( mTargetPosition.z );
3078 case Dali::Actor::Property::ORIENTATION:
3080 value.Get( mTargetOrientation );
3084 case Dali::Actor::Property::SCALE:
3086 value.Get( mTargetScale );
3090 case Dali::Actor::Property::SCALE_X:
3092 value.Get( mTargetScale.x );
3096 case Dali::Actor::Property::SCALE_Y:
3098 value.Get( mTargetScale.y );
3102 case Dali::Actor::Property::SCALE_Z:
3104 value.Get( mTargetScale.z );
3108 case Dali::Actor::Property::VISIBLE:
3110 SetVisibleInternal( value.Get< bool >(), SendMessage::FALSE );
3114 case Dali::Actor::Property::COLOR:
3116 value.Get( mTargetColor );
3120 case Dali::Actor::Property::COLOR_RED:
3122 value.Get( mTargetColor.r );
3126 case Dali::Actor::Property::COLOR_GREEN:
3128 value.Get( mTargetColor.g );
3132 case Dali::Actor::Property::COLOR_BLUE:
3134 value.Get( mTargetColor.b );
3138 case Dali::Actor::Property::COLOR_ALPHA:
3139 case Dali::Actor::Property::OPACITY:
3141 value.Get( mTargetColor.a );
3147 // Not an animatable property. Do nothing.
3158 case Dali::Actor::Property::SIZE:
3160 if( AdjustValue< Vector3 >( mTargetSize, value ) )
3162 mAnimatedSize = mTargetSize;
3163 mUseAnimatedSize = AnimatedSizeFlag::WIDTH | AnimatedSizeFlag::HEIGHT | AnimatedSizeFlag::DEPTH;
3165 // Notify deriving classes
3166 OnSizeAnimation( animation, mTargetSize );
3171 case Dali::Actor::Property::SIZE_WIDTH:
3173 if( AdjustValue< float >( mTargetSize.width, value ) )
3175 mAnimatedSize.width = mTargetSize.width;
3176 mUseAnimatedSize |= AnimatedSizeFlag::WIDTH;
3178 // Notify deriving classes
3179 OnSizeAnimation( animation, mTargetSize );
3184 case Dali::Actor::Property::SIZE_HEIGHT:
3186 if( AdjustValue< float >( mTargetSize.height, value ) )
3188 mAnimatedSize.height = mTargetSize.height;
3189 mUseAnimatedSize |= AnimatedSizeFlag::HEIGHT;
3191 // Notify deriving classes
3192 OnSizeAnimation( animation, mTargetSize );
3197 case Dali::Actor::Property::SIZE_DEPTH:
3199 if( AdjustValue< float >( mTargetSize.depth, value ) )
3201 mAnimatedSize.depth = mTargetSize.depth;
3202 mUseAnimatedSize |= AnimatedSizeFlag::DEPTH;
3204 // Notify deriving classes
3205 OnSizeAnimation( animation, mTargetSize );
3210 case Dali::Actor::Property::POSITION:
3212 AdjustValue< Vector3 >( mTargetPosition, value );
3216 case Dali::Actor::Property::POSITION_X:
3218 AdjustValue< float >( mTargetPosition.x, value );
3222 case Dali::Actor::Property::POSITION_Y:
3224 AdjustValue< float >( mTargetPosition.y, value );
3228 case Dali::Actor::Property::POSITION_Z:
3230 AdjustValue< float >( mTargetPosition.z, value );
3234 case Dali::Actor::Property::ORIENTATION:
3236 Quaternion relativeValue;
3237 if( value.Get( relativeValue ) )
3239 mTargetOrientation *= relativeValue;
3244 case Dali::Actor::Property::SCALE:
3246 AdjustValue< Vector3 >( mTargetScale, value );
3250 case Dali::Actor::Property::SCALE_X:
3252 AdjustValue< float >( mTargetScale.x, value );
3256 case Dali::Actor::Property::SCALE_Y:
3258 AdjustValue< float >( mTargetScale.y, value );
3262 case Dali::Actor::Property::SCALE_Z:
3264 AdjustValue< float >( mTargetScale.z, value );
3268 case Dali::Actor::Property::VISIBLE:
3270 bool relativeValue = false;
3271 if( value.Get( relativeValue ) )
3273 bool visible = mVisible || relativeValue;
3274 SetVisibleInternal( visible, SendMessage::FALSE );
3279 case Dali::Actor::Property::COLOR:
3281 AdjustValue< Vector4 >( mTargetColor, value );
3285 case Dali::Actor::Property::COLOR_RED:
3287 AdjustValue< float >( mTargetColor.r, value );
3291 case Dali::Actor::Property::COLOR_GREEN:
3293 AdjustValue< float >( mTargetColor.g, value );
3297 case Dali::Actor::Property::COLOR_BLUE:
3299 AdjustValue< float >( mTargetColor.b, value );
3303 case Dali::Actor::Property::COLOR_ALPHA:
3304 case Dali::Actor::Property::OPACITY:
3306 AdjustValue< float >( mTargetColor.a, value );
3312 // Not an animatable property. Do nothing.
3321 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3323 const PropertyBase* property( NULL );
3327 case Dali::Actor::Property::SIZE: // FALLTHROUGH
3328 case Dali::Actor::Property::SIZE_WIDTH: // FALLTHROUGH
3329 case Dali::Actor::Property::SIZE_HEIGHT: // FALLTHROUGH
3330 case Dali::Actor::Property::SIZE_DEPTH:
3332 property = &GetNode().mSize;
3335 case Dali::Actor::Property::POSITION: // FALLTHROUGH
3336 case Dali::Actor::Property::POSITION_X: // FALLTHROUGH
3337 case Dali::Actor::Property::POSITION_Y: // FALLTHROUGH
3338 case Dali::Actor::Property::POSITION_Z:
3340 property = &GetNode().mPosition;
3343 case Dali::Actor::Property::ORIENTATION:
3345 property = &GetNode().mOrientation;
3348 case Dali::Actor::Property::SCALE: // FALLTHROUGH
3349 case Dali::Actor::Property::SCALE_X: // FALLTHROUGH
3350 case Dali::Actor::Property::SCALE_Y: // FALLTHROUGH
3351 case Dali::Actor::Property::SCALE_Z:
3353 property = &GetNode().mScale;
3356 case Dali::Actor::Property::VISIBLE:
3358 property = &GetNode().mVisible;
3361 case Dali::Actor::Property::COLOR: // FALLTHROUGH
3362 case Dali::Actor::Property::COLOR_RED: // FALLTHROUGH
3363 case Dali::Actor::Property::COLOR_GREEN: // FALLTHROUGH
3364 case Dali::Actor::Property::COLOR_BLUE: // FALLTHROUGH
3365 case Dali::Actor::Property::COLOR_ALPHA: // FALLTHROUGH
3366 case Dali::Actor::Property::OPACITY:
3368 property = &GetNode().mColor;
3378 // not our property, ask base
3379 property = Object::GetSceneObjectAnimatableProperty( index );
3385 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3387 const PropertyInputImpl* property( NULL );
3391 case Dali::Actor::Property::PARENT_ORIGIN: // FALLTHROUGH
3392 case Dali::Actor::Property::PARENT_ORIGIN_X: // FALLTHROUGH
3393 case Dali::Actor::Property::PARENT_ORIGIN_Y: // FALLTHROUGH
3394 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3396 property = &GetNode().mParentOrigin;
3399 case Dali::Actor::Property::ANCHOR_POINT: // FALLTHROUGH
3400 case Dali::Actor::Property::ANCHOR_POINT_X: // FALLTHROUGH
3401 case Dali::Actor::Property::ANCHOR_POINT_Y: // FALLTHROUGH
3402 case Dali::Actor::Property::ANCHOR_POINT_Z:
3404 property = &GetNode().mAnchorPoint;
3407 case Dali::Actor::Property::WORLD_POSITION: // FALLTHROUGH
3408 case Dali::Actor::Property::WORLD_POSITION_X: // FALLTHROUGH
3409 case Dali::Actor::Property::WORLD_POSITION_Y: // FALLTHROUGH
3410 case Dali::Actor::Property::WORLD_POSITION_Z:
3412 property = &GetNode().mWorldPosition;
3415 case Dali::Actor::Property::WORLD_ORIENTATION:
3417 property = &GetNode().mWorldOrientation;
3420 case Dali::Actor::Property::WORLD_SCALE:
3422 property = &GetNode().mWorldScale;
3425 case Dali::Actor::Property::WORLD_COLOR:
3427 property = &GetNode().mWorldColor;
3430 case Dali::Actor::Property::WORLD_MATRIX:
3432 property = &GetNode().mWorldMatrix;
3435 case Dali::Actor::Property::CULLED:
3437 property = &GetNode().mCulled;
3447 // reuse animatable property getter as animatable properties are inputs as well
3448 // animatable property chains back to Object::GetSceneObjectInputProperty() so all properties get covered
3449 property = GetSceneObjectAnimatableProperty( index );
3455 int32_t Actor::GetPropertyComponentIndex( Property::Index index ) const
3457 int32_t componentIndex = Property::INVALID_COMPONENT_INDEX;
3461 case Dali::Actor::Property::PARENT_ORIGIN_X:
3462 case Dali::Actor::Property::ANCHOR_POINT_X:
3463 case Dali::Actor::Property::SIZE_WIDTH:
3464 case Dali::Actor::Property::POSITION_X:
3465 case Dali::Actor::Property::WORLD_POSITION_X:
3466 case Dali::Actor::Property::SCALE_X:
3467 case Dali::Actor::Property::COLOR_RED:
3473 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3474 case Dali::Actor::Property::ANCHOR_POINT_Y:
3475 case Dali::Actor::Property::SIZE_HEIGHT:
3476 case Dali::Actor::Property::POSITION_Y:
3477 case Dali::Actor::Property::WORLD_POSITION_Y:
3478 case Dali::Actor::Property::SCALE_Y:
3479 case Dali::Actor::Property::COLOR_GREEN:
3485 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3486 case Dali::Actor::Property::ANCHOR_POINT_Z:
3487 case Dali::Actor::Property::SIZE_DEPTH:
3488 case Dali::Actor::Property::POSITION_Z:
3489 case Dali::Actor::Property::WORLD_POSITION_Z:
3490 case Dali::Actor::Property::SCALE_Z:
3491 case Dali::Actor::Property::COLOR_BLUE:
3497 case Dali::Actor::Property::COLOR_ALPHA:
3498 case Dali::Actor::Property::OPACITY:
3510 if( Property::INVALID_COMPONENT_INDEX == componentIndex )
3513 componentIndex = Object::GetPropertyComponentIndex( index );
3516 return componentIndex;
3519 void Actor::SetParent( Actor* parent )
3523 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3527 mScene = parent->mScene;
3529 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3532 // Instruct each actor to create a corresponding node in the scene graph
3533 ConnectToStage( parent->GetHierarchyDepth() );
3536 // Resolve the name and index for the child properties if any
3537 ResolveChildProperties();
3539 else // parent being set to NULL
3541 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3545 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3548 // Disconnect the Node & its children from the scene-graph.
3549 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
3551 // Instruct each actor to discard pointers to the scene-graph
3552 DisconnectFromStage();
3559 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3562 Actor* actor = dynamic_cast< Actor* >( object );
3566 if( 0 == actionName.compare( ACTION_SHOW ) )
3568 actor->SetVisible( true );
3571 else if( 0 == actionName.compare( ACTION_HIDE ) )
3573 actor->SetVisible( false );
3581 Rect<> Actor::CalculateScreenExtents( ) const
3583 auto screenPosition = GetCurrentScreenPosition();
3584 Vector3 size = GetCurrentSize() * GetCurrentWorldScale();
3585 Vector3 anchorPointOffSet = size * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
3586 Vector2 position = Vector2( screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y );
3587 return { position.x, position.y, size.x, size.y };
3590 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
3592 bool valueSet = true;
3596 case Dali::Actor::Property::PARENT_ORIGIN:
3598 value = GetCurrentParentOrigin();
3602 case Dali::Actor::Property::PARENT_ORIGIN_X:
3604 value = GetCurrentParentOrigin().x;
3608 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3610 value = GetCurrentParentOrigin().y;
3614 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3616 value = GetCurrentParentOrigin().z;
3620 case Dali::Actor::Property::ANCHOR_POINT:
3622 value = GetCurrentAnchorPoint();
3626 case Dali::Actor::Property::ANCHOR_POINT_X:
3628 value = GetCurrentAnchorPoint().x;
3632 case Dali::Actor::Property::ANCHOR_POINT_Y:
3634 value = GetCurrentAnchorPoint().y;
3638 case Dali::Actor::Property::ANCHOR_POINT_Z:
3640 value = GetCurrentAnchorPoint().z;
3644 case Dali::Actor::Property::SIZE:
3646 value = GetTargetSize();
3650 case Dali::Actor::Property::SIZE_WIDTH:
3652 value = GetTargetSize().width;
3656 case Dali::Actor::Property::SIZE_HEIGHT:
3658 value = GetTargetSize().height;
3662 case Dali::Actor::Property::SIZE_DEPTH:
3664 value = GetTargetSize().depth;
3668 case Dali::Actor::Property::POSITION:
3670 value = GetTargetPosition();
3674 case Dali::Actor::Property::POSITION_X:
3676 value = GetTargetPosition().x;
3680 case Dali::Actor::Property::POSITION_Y:
3682 value = GetTargetPosition().y;
3686 case Dali::Actor::Property::POSITION_Z:
3688 value = GetTargetPosition().z;
3692 case Dali::Actor::Property::ORIENTATION:
3694 value = mTargetOrientation;
3698 case Dali::Actor::Property::SCALE:
3700 value = mTargetScale;
3704 case Dali::Actor::Property::SCALE_X:
3706 value = mTargetScale.x;
3710 case Dali::Actor::Property::SCALE_Y:
3712 value = mTargetScale.y;
3716 case Dali::Actor::Property::SCALE_Z:
3718 value = mTargetScale.z;
3722 case Dali::Actor::Property::VISIBLE:
3728 case Dali::Actor::Property::COLOR:
3730 value = mTargetColor;
3734 case Dali::Actor::Property::COLOR_RED:
3736 value = mTargetColor.r;
3740 case Dali::Actor::Property::COLOR_GREEN:
3742 value = mTargetColor.g;
3746 case Dali::Actor::Property::COLOR_BLUE:
3748 value = mTargetColor.b;
3752 case Dali::Actor::Property::COLOR_ALPHA:
3753 case Dali::Actor::Property::OPACITY:
3755 value = mTargetColor.a;
3759 case Dali::Actor::Property::NAME:
3765 case Dali::Actor::Property::SENSITIVE:
3767 value = IsSensitive();
3771 case Dali::Actor::Property::LEAVE_REQUIRED:
3773 value = GetLeaveRequired();
3777 case Dali::Actor::Property::INHERIT_POSITION:
3779 value = IsPositionInherited();
3783 case Dali::Actor::Property::INHERIT_ORIENTATION:
3785 value = IsOrientationInherited();
3789 case Dali::Actor::Property::INHERIT_SCALE:
3791 value = IsScaleInherited();
3795 case Dali::Actor::Property::COLOR_MODE:
3797 value = GetColorMode();
3801 case Dali::Actor::Property::DRAW_MODE:
3803 value = GetDrawMode();
3807 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3809 value = GetSizeModeFactor();
3813 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3815 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3819 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3821 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3825 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3827 value = GetSizeScalePolicy();
3831 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3833 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3837 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3839 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3843 case Dali::Actor::Property::PADDING:
3845 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3846 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3847 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3851 case Dali::Actor::Property::MINIMUM_SIZE:
3853 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3857 case Dali::Actor::Property::MAXIMUM_SIZE:
3859 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3863 case Dali::Actor::Property::CLIPPING_MODE:
3865 value = mClippingMode;
3869 case Dali::DevelActor::Property::SIBLING_ORDER:
3871 value = static_cast<int>( GetSiblingOrder() );
3875 case Dali::Actor::Property::SCREEN_POSITION:
3877 value = GetCurrentScreenPosition();
3881 case Dali::Actor::Property::POSITION_USES_ANCHOR_POINT:
3883 value = mPositionUsesAnchorPoint;
3887 case Dali::Actor::Property::LAYOUT_DIRECTION:
3889 value = mLayoutDirection;
3893 case Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION:
3895 value = IsLayoutDirectionInherited();
3899 case Dali::Actor::Property::ID:
3901 value = static_cast<int>( GetId() );
3905 case Dali::Actor::Property::HIERARCHY_DEPTH:
3907 value = GetHierarchyDepth();
3911 case Dali::Actor::Property::IS_ROOT:
3917 case Dali::Actor::Property::IS_LAYER:
3923 case Dali::Actor::Property::CONNECTED_TO_SCENE:
3929 case Dali::Actor::Property::KEYBOARD_FOCUSABLE:
3931 value = IsKeyboardFocusable();
3937 // Must be a scene-graph only property
3946 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
3948 bool valueSet = true;
3952 case Dali::Actor::Property::SIZE:
3954 value = GetCurrentSize();
3958 case Dali::Actor::Property::SIZE_WIDTH:
3960 value = GetCurrentSize().width;
3964 case Dali::Actor::Property::SIZE_HEIGHT:
3966 value = GetCurrentSize().height;
3970 case Dali::Actor::Property::SIZE_DEPTH:
3972 value = GetCurrentSize().depth;
3976 case Dali::Actor::Property::POSITION:
3978 value = GetCurrentPosition();
3982 case Dali::Actor::Property::POSITION_X:
3984 value = GetCurrentPosition().x;
3988 case Dali::Actor::Property::POSITION_Y:
3990 value = GetCurrentPosition().y;
3994 case Dali::Actor::Property::POSITION_Z:
3996 value = GetCurrentPosition().z;
4000 case Dali::Actor::Property::WORLD_POSITION:
4002 value = GetCurrentWorldPosition();
4006 case Dali::Actor::Property::WORLD_POSITION_X:
4008 value = GetCurrentWorldPosition().x;
4012 case Dali::Actor::Property::WORLD_POSITION_Y:
4014 value = GetCurrentWorldPosition().y;
4018 case Dali::Actor::Property::WORLD_POSITION_Z:
4020 value = GetCurrentWorldPosition().z;
4024 case Dali::Actor::Property::ORIENTATION:
4026 value = GetCurrentOrientation();
4030 case Dali::Actor::Property::WORLD_ORIENTATION:
4032 value = GetCurrentWorldOrientation();
4036 case Dali::Actor::Property::SCALE:
4038 value = GetCurrentScale();
4042 case Dali::Actor::Property::SCALE_X:
4044 value = GetCurrentScale().x;
4048 case Dali::Actor::Property::SCALE_Y:
4050 value = GetCurrentScale().y;
4054 case Dali::Actor::Property::SCALE_Z:
4056 value = GetCurrentScale().z;
4060 case Dali::Actor::Property::WORLD_SCALE:
4062 value = GetCurrentWorldScale();
4066 case Dali::Actor::Property::COLOR:
4068 value = GetCurrentColor();
4072 case Dali::Actor::Property::COLOR_RED:
4074 value = GetCurrentColor().r;
4078 case Dali::Actor::Property::COLOR_GREEN:
4080 value = GetCurrentColor().g;
4084 case Dali::Actor::Property::COLOR_BLUE:
4086 value = GetCurrentColor().b;
4090 case Dali::Actor::Property::COLOR_ALPHA:
4091 case Dali::Actor::Property::OPACITY:
4093 value = GetCurrentColor().a;
4097 case Dali::Actor::Property::WORLD_COLOR:
4099 value = GetCurrentWorldColor();
4103 case Dali::Actor::Property::WORLD_MATRIX:
4105 value = GetCurrentWorldMatrix();
4109 case Dali::Actor::Property::VISIBLE:
4111 value = IsVisible();
4115 case Dali::Actor::Property::CULLED:
4117 value = GetNode().IsCulled( GetEventThreadServices().GetEventBufferIndex() );
4123 // Must be an event-side only property
4132 void Actor::EnsureRelayoutData()
4134 // Assign relayout data.
4135 if( !mRelayoutData )
4137 mRelayoutData = new RelayoutData();
4141 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
4143 // Check if actor is dependent on parent
4144 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4146 if( ( dimension & ( 1 << i ) ) )
4148 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4149 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
4159 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
4161 // Check if actor is dependent on children
4162 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4164 if( ( dimension & ( 1 << i ) ) )
4166 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4167 switch( resizePolicy )
4169 case ResizePolicy::FIT_TO_CHILDREN:
4170 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
4186 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
4188 return Actor::RelayoutDependentOnChildren( dimension );
4191 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
4193 // Check each possible dimension and see if it is dependent on the input one
4194 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4196 if( dimension & ( 1 << i ) )
4198 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
4205 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
4207 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4209 if( dimension & ( 1 << i ) )
4211 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
4216 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
4218 // If more than one dimension is requested, just return the first one found
4219 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4221 if( ( dimension & ( 1 << i ) ) )
4223 return mRelayoutData->negotiatedDimensions[ i ];
4227 return 0.0f; // Default
4230 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
4232 EnsureRelayoutData();
4234 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4236 if( dimension & ( 1 << i ) )
4238 mRelayoutData->dimensionPadding[ i ] = padding;
4243 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4245 if ( mRelayoutData )
4247 // If more than one dimension is requested, just return the first one found
4248 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4250 if( ( dimension & ( 1 << i ) ) )
4252 return mRelayoutData->dimensionPadding[ i ];
4257 return GetDefaultDimensionPadding();
4260 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4262 EnsureRelayoutData();
4264 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4266 if( dimension & ( 1 << i ) )
4268 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4273 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4275 if ( mRelayoutData )
4277 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4279 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4289 float Actor::GetHeightForWidthBase( float width )
4291 float height = 0.0f;
4293 const Vector3 naturalSize = GetNaturalSize();
4294 if( naturalSize.width > 0.0f )
4296 height = naturalSize.height * width / naturalSize.width;
4298 else // we treat 0 as 1:1 aspect ratio
4306 float Actor::GetWidthForHeightBase( float height )
4310 const Vector3 naturalSize = GetNaturalSize();
4311 if( naturalSize.height > 0.0f )
4313 width = naturalSize.width * height / naturalSize.height;
4315 else // we treat 0 as 1:1 aspect ratio
4323 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4325 // Fill to parent, taking size mode factor into account
4326 switch( child.GetResizePolicy( dimension ) )
4328 case ResizePolicy::FILL_TO_PARENT:
4330 return GetLatestSize( dimension );
4333 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4335 return GetLatestSize( dimension ) * GetDimensionValue( child.GetProperty< Vector3 >( Dali::Actor::Property::SIZE_MODE_FACTOR ), dimension );
4338 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4340 return GetLatestSize( dimension ) + GetDimensionValue( child.GetProperty< Vector3 >( Dali::Actor::Property::SIZE_MODE_FACTOR ), dimension );
4345 return GetLatestSize( dimension );
4350 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4352 // Can be overridden in derived class
4353 return CalculateChildSizeBase( child, dimension );
4356 float Actor::GetHeightForWidth( float width )
4358 // Can be overridden in derived class
4359 return GetHeightForWidthBase( width );
4362 float Actor::GetWidthForHeight( float height )
4364 // Can be overridden in derived class
4365 return GetWidthForHeightBase( height );
4368 float Actor::GetLatestSize( Dimension::Type dimension ) const
4370 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4373 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4375 Vector2 padding = GetPadding( dimension );
4377 return GetLatestSize( dimension ) + padding.x + padding.y;
4380 float Actor::NegotiateFromParent( Dimension::Type dimension )
4382 Actor* parent = GetParent();
4385 Vector2 padding( GetPadding( dimension ) );
4386 Vector2 parentPadding( parent->GetPadding( dimension ) );
4387 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4393 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4395 float maxDimensionPoint = 0.0f;
4397 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4399 ActorPtr child = GetChildAt( i );
4401 if( !child->RelayoutDependentOnParent( dimension ) )
4403 // Calculate the min and max points that the children range across
4404 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
4405 float dimensionSize = child->GetRelayoutSize( dimension );
4406 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4410 return maxDimensionPoint;
4413 float Actor::GetSize( Dimension::Type dimension ) const
4415 return GetDimensionValue( mTargetSize, dimension );
4418 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4420 return GetDimensionValue( GetNaturalSize(), dimension );
4423 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4425 switch( GetResizePolicy( dimension ) )
4427 case ResizePolicy::USE_NATURAL_SIZE:
4429 return GetNaturalSize( dimension );
4432 case ResizePolicy::FIXED:
4434 return GetDimensionValue( GetPreferredSize(), dimension );
4437 case ResizePolicy::USE_ASSIGNED_SIZE:
4439 return GetDimensionValue( maximumSize, dimension );
4442 case ResizePolicy::FILL_TO_PARENT:
4443 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4444 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4446 return NegotiateFromParent( dimension );
4449 case ResizePolicy::FIT_TO_CHILDREN:
4451 return NegotiateFromChildren( dimension );
4454 case ResizePolicy::DIMENSION_DEPENDENCY:
4456 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4459 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4461 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4464 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4466 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4478 return 0.0f; // Default
4481 float Actor::ClampDimension( float size, Dimension::Type dimension )
4483 const float minSize = GetMinimumSize( dimension );
4484 const float maxSize = GetMaximumSize( dimension );
4486 return std::max( minSize, std::min( size, maxSize ) );
4489 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4491 // Check if it needs to be negotiated
4492 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4494 // Check that we havn't gotten into an infinite loop
4495 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4496 bool recursionFound = false;
4497 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4499 if( *it == searchActor )
4501 recursionFound = true;
4506 if( !recursionFound )
4508 // Record the path that we have taken
4509 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4511 // Dimension dependency check
4512 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4514 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4516 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4518 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4522 // Parent dependency check
4523 Actor* parent = GetParent();
4524 if( parent && RelayoutDependentOnParent( dimension ) )
4526 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4529 // Children dependency check
4530 if( RelayoutDependentOnChildren( dimension ) )
4532 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4534 ActorPtr child = GetChildAt( i );
4536 // Only relayout child first if it is not dependent on this actor
4537 if( !child->RelayoutDependentOnParent( dimension ) )
4539 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
4544 // For deriving classes
4545 OnCalculateRelayoutSize( dimension );
4547 // All dependencies checked, calculate the size and set negotiated flag
4548 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4550 SetNegotiatedDimension( newSize, dimension );
4551 SetLayoutNegotiated( true, dimension );
4553 // For deriving classes
4554 OnLayoutNegotiated( newSize, dimension );
4556 // This actor has been successfully processed, pop it off the recursion stack
4557 recursionStack.pop_back();
4561 // TODO: Break infinite loop
4562 SetLayoutNegotiated( true, dimension );
4567 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4569 // Negotiate all dimensions that require it
4570 ActorDimensionStack recursionStack;
4572 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4574 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4577 NegotiateDimension( dimension, allocatedSize, recursionStack );
4581 Vector2 Actor::ApplySizeSetPolicy( const Vector2& size )
4583 switch( mRelayoutData->sizeSetPolicy )
4585 case SizeScalePolicy::USE_SIZE_SET:
4590 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4592 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4593 const Vector3 naturalSize = GetNaturalSize();
4594 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4596 const float sizeRatio = size.width / size.height;
4597 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4599 if( naturalSizeRatio < sizeRatio )
4601 return Vector2( naturalSizeRatio * size.height, size.height );
4603 else if( naturalSizeRatio > sizeRatio )
4605 return Vector2( size.width, size.width / naturalSizeRatio );
4616 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4618 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4619 const Vector3 naturalSize = GetNaturalSize();
4620 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4622 const float sizeRatio = size.width / size.height;
4623 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4625 if( naturalSizeRatio < sizeRatio )
4627 return Vector2( size.width, size.width / naturalSizeRatio );
4629 else if( naturalSizeRatio > sizeRatio )
4631 return Vector2( naturalSizeRatio * size.height, size.height );
4650 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4652 // Do the set actor size
4653 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4655 // Adjust for size set policy
4656 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4658 // Lock the flag to stop recursive relayouts on set size
4659 mRelayoutData->insideRelayout = true;
4660 SetSize( negotiatedSize );
4661 mRelayoutData->insideRelayout = false;
4663 // Clear flags for all dimensions
4664 SetLayoutDirty( false );
4666 // Give deriving classes a chance to respond
4667 OnRelayout( negotiatedSize, container );
4669 if( !mOnRelayoutSignal.Empty() )
4671 Dali::Actor handle( this );
4672 mOnRelayoutSignal.Emit( handle );
4676 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4678 // Force a size negotiation for actors that has assigned size during relayout
4679 // This is required as otherwise the flags that force a relayout will not
4680 // necessarilly be set. This will occur if the actor has already been laid out.
4681 // The dirty flags are then cleared. Then if the actor is added back into the
4682 // relayout container afterwards, the dirty flags would still be clear...
4683 // causing a relayout to be skipped. Here we force any actors added to the
4684 // container to be relayed out.
4685 DALI_LOG_TIMER_START( NegSizeTimer1 );
4687 if( GetUseAssignedSize(Dimension::WIDTH ) )
4689 SetLayoutNegotiated( false, Dimension::WIDTH );
4691 if( GetUseAssignedSize( Dimension::HEIGHT ) )
4693 SetLayoutNegotiated( false, Dimension::HEIGHT );
4696 // Do the negotiation
4697 NegotiateDimensions( allocatedSize );
4699 // Set the actor size
4700 SetNegotiatedSize( container );
4702 // Negotiate down to children
4703 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4705 ActorPtr child = GetChildAt( i );
4707 // Forces children that have already been laid out to be relayed out
4708 // if they have assigned size during relayout.
4709 if( child->GetUseAssignedSize(Dimension::WIDTH) )
4711 child->SetLayoutNegotiated(false, Dimension::WIDTH);
4712 child->SetLayoutDirty(true, Dimension::WIDTH);
4715 if( child->GetUseAssignedSize(Dimension::HEIGHT) )
4717 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
4718 child->SetLayoutDirty(true, Dimension::HEIGHT);
4721 // Only relayout if required
4722 if( child->RelayoutRequired() )
4724 container.Add( Dali::Actor( child.Get() ), mTargetSize.GetVectorXY() );
4727 DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
4730 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
4734 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4736 if( dimension & ( 1 << i ) )
4738 mRelayoutData->useAssignedSize[ i ] = use;
4744 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
4746 if ( mRelayoutData )
4748 // If more than one dimension is requested, just return the first one found
4749 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4751 if( dimension & ( 1 << i ) )
4753 return mRelayoutData->useAssignedSize[ i ];
4761 void Actor::RelayoutRequest( Dimension::Type dimension )
4763 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4764 if( relayoutController )
4766 Dali::Actor self( this );
4767 relayoutController->RequestRelayout( self, dimension );
4771 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4775 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4779 void Actor::SetPreferredSize( const Vector2& size )
4781 EnsureRelayoutData();
4783 // If valid width or height, then set the resize policy to FIXED
4784 // 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,
4785 // then change to FIXED as well
4787 if( size.width > 0.0f || GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DEFAULT )
4789 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4792 if( size.height > 0.0f || GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DEFAULT )
4794 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4797 mRelayoutData->preferredSize = size;
4799 mUseAnimatedSize = AnimatedSizeFlag::CLEAR;
4804 Vector2 Actor::GetPreferredSize() const
4806 if ( mRelayoutData )
4808 return Vector2( mRelayoutData->preferredSize );
4811 return GetDefaultPreferredSize();
4814 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4816 EnsureRelayoutData();
4818 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4820 if( dimension & ( 1 << i ) )
4822 mRelayoutData->minimumSize[ i ] = size;
4829 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4831 if ( mRelayoutData )
4833 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4835 if( dimension & ( 1 << i ) )
4837 return mRelayoutData->minimumSize[ i ];
4842 return 0.0f; // Default
4845 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4847 EnsureRelayoutData();
4849 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4851 if( dimension & ( 1 << i ) )
4853 mRelayoutData->maximumSize[ i ] = size;
4860 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4862 if ( mRelayoutData )
4864 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4866 if( dimension & ( 1 << i ) )
4868 return mRelayoutData->maximumSize[ i ];
4873 return FLT_MAX; // Default
4876 Object* Actor::GetParentObject() const
4881 void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
4883 if( mVisible != visible )
4885 if( sendMessage == SendMessage::TRUE )
4887 // node is being used in a separate thread; queue a message to set the value & base value
4888 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible );
4893 // Emit the signal on this actor and all its children
4894 EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
4898 void Actor::SetSiblingOrder( uint32_t order )
4902 ActorContainer& siblings = *(mParent->mChildren);
4903 uint32_t currentOrder = GetSiblingOrder();
4905 if( order != currentOrder )
4911 else if( order < siblings.size() -1 )
4913 if( order > currentOrder )
4915 RaiseAbove( *siblings[order] );
4919 LowerBelow( *siblings[order] );
4930 uint32_t Actor::GetSiblingOrder() const
4936 ActorContainer& siblings = *(mParent->mChildren);
4937 for( std::size_t i = 0; i < siblings.size(); ++i )
4939 if( siblings[i] == this )
4941 order = static_cast<uint32_t>( i );
4950 void Actor::RequestRebuildDepthTree()
4956 mScene->RequestRebuildDepthTree();
4965 ActorContainer& siblings = *(mParent->mChildren);
4966 if( siblings.back() != this ) // If not already at end
4968 for( std::size_t i=0; i<siblings.size(); ++i )
4970 if( siblings[i] == this )
4973 ActorPtr next = siblings[i+1];
4974 siblings[i+1] = this;
4981 Dali::Actor handle( this );
4982 mParent->mChildOrderChangedSignal.Emit( handle );
4984 RequestRebuildDepthTree();
4988 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4996 ActorContainer& siblings = *(mParent->mChildren);
4997 if( siblings.front() != this ) // If not already at beginning
4999 for( std::size_t i=1; i<siblings.size(); ++i )
5001 if( siblings[i] == this )
5003 // Swap with previous
5004 ActorPtr previous = siblings[i-1];
5005 siblings[i-1] = this;
5006 siblings[i] = previous;
5012 Dali::Actor handle( this );
5013 mParent->mChildOrderChangedSignal.Emit( handle );
5015 RequestRebuildDepthTree();
5019 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5023 void Actor::RaiseToTop()
5027 ActorContainer& siblings = *(mParent->mChildren);
5028 if( siblings.back() != this ) // If not already at end
5030 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
5031 if( iter != siblings.end() )
5033 siblings.erase(iter);
5034 siblings.push_back(ActorPtr(this));
5038 Dali::Actor handle( this );
5039 mParent->mChildOrderChangedSignal.Emit( handle );
5041 RequestRebuildDepthTree();
5045 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5049 void Actor::LowerToBottom()
5053 ActorContainer& siblings = *(mParent->mChildren);
5054 if( siblings.front() != this ) // If not already at bottom,
5056 ActorPtr thisPtr(this); // ensure this actor remains referenced.
5058 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
5059 if( iter != siblings.end() )
5061 siblings.erase(iter);
5062 siblings.insert(siblings.begin(), thisPtr);
5066 Dali::Actor handle( this );
5067 mParent->mChildOrderChangedSignal.Emit( handle );
5069 RequestRebuildDepthTree();
5073 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5077 void Actor::RaiseAbove( Internal::Actor& target )
5081 ActorContainer& siblings = *(mParent->mChildren);
5082 if( siblings.back() != this && target.mParent == mParent ) // If not already at top
5084 ActorPtr thisPtr(this); // ensure this actor remains referenced.
5086 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
5087 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
5088 if( thisIter < targetIter )
5090 siblings.erase(thisIter);
5091 // Erasing early invalidates the targetIter. (Conversely, inserting first may also
5092 // invalidate thisIter)
5093 targetIter = std::find( siblings.begin(), siblings.end(), &target );
5095 siblings.insert(targetIter, thisPtr);
5098 Dali::Actor handle( this );
5099 mParent->mChildOrderChangedSignal.Emit( handle );
5101 RequestRebuildDepthTree();
5106 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5110 void Actor::LowerBelow( Internal::Actor& target )
5114 ActorContainer& siblings = *(mParent->mChildren);
5115 if( siblings.front() != this && target.mParent == mParent ) // If not already at bottom
5117 ActorPtr thisPtr(this); // ensure this actor remains referenced.
5119 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
5120 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
5122 if( thisIter > targetIter )
5124 siblings.erase(thisIter); // this only invalidates iterators at or after this point.
5125 siblings.insert(targetIter, thisPtr);
5128 Dali::Actor handle( this );
5129 mParent->mChildOrderChangedSignal.Emit( handle );
5131 RequestRebuildDepthTree();
5136 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5140 void Actor::SetScene( Scene& scene )
5145 Scene& Actor::GetScene() const
5150 void Actor::SetInheritLayoutDirection( bool inherit )
5152 if( mInheritLayoutDirection != inherit )
5154 mInheritLayoutDirection = inherit;
5156 if( inherit && mParent )
5158 InheritLayoutDirectionRecursively( this, mParent->mLayoutDirection );
5163 bool Actor::IsLayoutDirectionInherited() const
5165 return mInheritLayoutDirection;
5168 void Actor::InheritLayoutDirectionRecursively( ActorPtr actor, Dali::LayoutDirection::Type direction, bool set )
5170 if( actor && ( actor->mInheritLayoutDirection || set ) )
5172 if( actor->mLayoutDirection != direction )
5174 actor->mLayoutDirection = direction;
5175 actor->EmitLayoutDirectionChangedSignal( direction );
5176 actor->RelayoutRequest();
5179 if( actor->GetChildCount() > 0 )
5181 ActorContainer& children = actor->GetChildrenInternal();
5182 for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter )
5184 InheritLayoutDirectionRecursively( *iter, direction );
5190 } // namespace Internal