2 * Copyright (c) 2018 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/event/actors/actor-impl.h>
27 #include <dali/devel-api/actors/layer-devel.h>
28 #include <dali/public-api/common/dali-common.h>
29 #include <dali/public-api/common/constants.h>
30 #include <dali/public-api/events/touch-data.h>
31 #include <dali/public-api/math/vector2.h>
32 #include <dali/public-api/math/vector3.h>
33 #include <dali/public-api/math/radian.h>
34 #include <dali/public-api/object/type-registry.h>
35 #include <dali/devel-api/actors/actor-devel.h>
36 #include <dali/devel-api/scripting/scripting.h>
37 #include <dali/internal/common/internal-constants.h>
38 #include <dali/internal/event/common/event-thread-services.h>
39 #include <dali/internal/event/render-tasks/render-task-impl.h>
40 #include <dali/internal/event/actors/camera-actor-impl.h>
41 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
42 #include <dali/internal/event/common/property-helper.h>
43 #include <dali/internal/event/common/stage-impl.h>
44 #include <dali/internal/event/common/type-info-impl.h>
45 #include <dali/internal/event/animation/constraint-impl.h>
46 #include <dali/internal/event/common/projection.h>
47 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
48 #include <dali/internal/update/common/animatable-property.h>
49 #include <dali/internal/update/nodes/node-messages.h>
50 #include <dali/internal/update/nodes/node-declarations.h>
51 #include <dali/internal/update/animation/scene-graph-constraint.h>
52 #include <dali/internal/event/events/actor-gesture-data.h>
53 #include <dali/internal/common/message.h>
54 #include <dali/integration-api/debug.h>
56 using Dali::Internal::SceneGraph::Node;
57 using Dali::Internal::SceneGraph::AnimatableProperty;
58 using Dali::Internal::SceneGraph::PropertyBase;
60 #if defined(DEBUG_ENABLED)
61 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_DEPTH_TIMER" );
62 Debug::Filter* gLogRelayoutFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_TIMER" );
71 uint32_t Actor::mActorCounter = 0;
75 /// Using a function because of library initialisation order. Vector3::ONE may not have been initialised yet.
76 inline const Vector3& GetDefaultSizeModeFactor()
81 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
82 inline const Vector2& GetDefaultPreferredSize()
87 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
88 inline const Vector2& GetDefaultDimensionPadding()
93 const SizeScalePolicy::Type DEFAULT_SIZE_SCALE_POLICY = SizeScalePolicy::USE_SIZE_SET;
95 } // unnamed namespace
98 * Struct to collect relayout variables
100 struct Actor::RelayoutData
103 : sizeModeFactor( GetDefaultSizeModeFactor() ), preferredSize( GetDefaultPreferredSize() ), sizeSetPolicy( DEFAULT_SIZE_SCALE_POLICY ), relayoutEnabled( false ), insideRelayout( false )
105 // Set size negotiation defaults
106 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
108 resizePolicies[ i ] = ResizePolicy::DEFAULT;
109 useAssignedSize[ i ] = false;
110 negotiatedDimensions[ i ] = 0.0f;
111 dimensionNegotiated[ i ] = false;
112 dimensionDirty[ i ] = false;
113 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
114 dimensionPadding[ i ] = GetDefaultDimensionPadding();
115 minimumSize[ i ] = 0.0f;
116 maximumSize[ i ] = FLT_MAX;
120 ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies
121 bool useAssignedSize[ Dimension::DIMENSION_COUNT ]; ///< The flag to specify whether the size should be assigned to the actor
123 Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies
125 Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
127 float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
129 float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be
130 float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be
132 bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated
133 bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
135 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
137 Vector2 preferredSize; ///< The preferred size of the actor
139 SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
141 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
142 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
145 namespace // unnamed namespace
151 * We want to discourage the use of property strings (minimize string comparisons),
152 * particularly for the default properties.
153 * Name Type writable animatable constraint-input enum for index-checking
155 DALI_PROPERTY_TABLE_BEGIN
156 DALI_PROPERTY( "parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
157 DALI_PROPERTY( "parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
158 DALI_PROPERTY( "parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
159 DALI_PROPERTY( "parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
160 DALI_PROPERTY( "anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
161 DALI_PROPERTY( "anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
162 DALI_PROPERTY( "anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
163 DALI_PROPERTY( "anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
164 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
165 DALI_PROPERTY( "sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
166 DALI_PROPERTY( "sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
167 DALI_PROPERTY( "sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
168 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
169 DALI_PROPERTY( "positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
170 DALI_PROPERTY( "positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
171 DALI_PROPERTY( "positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
172 DALI_PROPERTY( "worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
173 DALI_PROPERTY( "worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
174 DALI_PROPERTY( "worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
175 DALI_PROPERTY( "worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
176 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
177 DALI_PROPERTY( "worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
178 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
179 DALI_PROPERTY( "scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
180 DALI_PROPERTY( "scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
181 DALI_PROPERTY( "scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
182 DALI_PROPERTY( "worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
183 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
184 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
185 DALI_PROPERTY( "colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
186 DALI_PROPERTY( "colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
187 DALI_PROPERTY( "colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
188 DALI_PROPERTY( "colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
189 DALI_PROPERTY( "worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
190 DALI_PROPERTY( "worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
191 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
192 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
193 DALI_PROPERTY( "leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
194 DALI_PROPERTY( "inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
195 DALI_PROPERTY( "inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
196 DALI_PROPERTY( "colorMode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
197 DALI_PROPERTY( "positionInheritance", STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE )
198 DALI_PROPERTY( "drawMode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
199 DALI_PROPERTY( "sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
200 DALI_PROPERTY( "widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
201 DALI_PROPERTY( "heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
202 DALI_PROPERTY( "sizeScalePolicy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
203 DALI_PROPERTY( "widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
204 DALI_PROPERTY( "heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
205 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
206 DALI_PROPERTY( "minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
207 DALI_PROPERTY( "maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
208 DALI_PROPERTY( "inheritPosition", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_POSITION )
209 DALI_PROPERTY( "clippingMode", STRING, true, false, false, Dali::Actor::Property::CLIPPING_MODE )
210 DALI_PROPERTY( "layoutDirection", STRING, true, false, false, Dali::Actor::Property::LAYOUT_DIRECTION )
211 DALI_PROPERTY( "inheritLayoutDirection", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION )
212 DALI_PROPERTY( "siblingOrder", INTEGER, true, false, false, Dali::DevelActor::Property::SIBLING_ORDER )
213 DALI_PROPERTY( "opacity", FLOAT, true, true, true, Dali::DevelActor::Property::OPACITY )
214 DALI_PROPERTY( "screenPosition", VECTOR2, false, false, false, Dali::DevelActor::Property::SCREEN_POSITION )
215 DALI_PROPERTY( "positionUsesAnchorPoint", BOOLEAN, true, false, false, Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT )
216 DALI_PROPERTY( "culled", BOOLEAN, false, false, true, Dali::DevelActor::Property::CULLED )
217 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperties )
221 const char* const SIGNAL_TOUCHED = "touched";
222 const char* const SIGNAL_HOVERED = "hovered";
223 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
224 const char* const SIGNAL_ON_STAGE = "onStage";
225 const char* const SIGNAL_OFF_STAGE = "offStage";
226 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
227 const char* const SIGNAL_TOUCH = "touch";
228 const char* const SIGNAL_VISIBILITY_CHANGED = "visibilityChanged";
229 const char* const SIGNAL_LAYOUT_DIRECTION_CHANGED = "layoutDirectionChanged";
230 const char* const SIGNAL_CHILD_ADDED = "childAdded";
231 const char* const SIGNAL_CHILD_REMOVED = "childRemoved";
235 const char* const ACTION_SHOW = "show";
236 const char* const ACTION_HIDE = "hide";
238 BaseHandle CreateActor()
240 return Dali::Actor::New();
243 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor, ActorDefaultProperties );
245 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
246 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
247 SignalConnectorType signalConnector3( mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal );
248 SignalConnectorType signalConnector4( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
249 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
250 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
251 SignalConnectorType signalConnector7( mType, SIGNAL_TOUCH, &Actor::DoConnectSignal );
252 SignalConnectorType signalConnector8( mType, SIGNAL_VISIBILITY_CHANGED, &Actor::DoConnectSignal );
253 SignalConnectorType signalConnector9( mType, SIGNAL_LAYOUT_DIRECTION_CHANGED, &Actor::DoConnectSignal );
254 SignalConnectorType signalConnector10( mType, SIGNAL_CHILD_ADDED, &Actor::DoConnectSignal );
255 SignalConnectorType signalConnector11( mType, SIGNAL_CHILD_REMOVED, &Actor::DoConnectSignal );
257 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
258 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
263 const Vector3& value;
266 DALI_ENUM_TO_STRING_TABLE_BEGIN_WITH_TYPE( AnchorValue, ANCHOR_CONSTANT )
267 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_LEFT )
268 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_CENTER )
269 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_RIGHT )
270 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_LEFT )
271 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER )
272 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_RIGHT )
273 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_LEFT )
274 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_CENTER )
275 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_RIGHT )
276 DALI_ENUM_TO_STRING_TABLE_END( ANCHOR_CONSTANT )
278 DALI_ENUM_TO_STRING_TABLE_BEGIN( COLOR_MODE )
279 DALI_ENUM_TO_STRING( USE_OWN_COLOR )
280 DALI_ENUM_TO_STRING( USE_PARENT_COLOR )
281 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_COLOR )
282 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_ALPHA )
283 DALI_ENUM_TO_STRING_TABLE_END( COLOR_MODE )
285 DALI_ENUM_TO_STRING_TABLE_BEGIN( POSITION_INHERITANCE_MODE )
286 DALI_ENUM_TO_STRING( INHERIT_PARENT_POSITION )
287 DALI_ENUM_TO_STRING( USE_PARENT_POSITION )
288 DALI_ENUM_TO_STRING( USE_PARENT_POSITION_PLUS_LOCAL_POSITION )
289 DALI_ENUM_TO_STRING( DONT_INHERIT_POSITION )
290 DALI_ENUM_TO_STRING_TABLE_END( POSITION_INHERITANCE_MODE )
292 DALI_ENUM_TO_STRING_TABLE_BEGIN( DRAW_MODE )
293 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, NORMAL )
294 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, OVERLAY_2D )
295 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, STENCIL )
296 DALI_ENUM_TO_STRING_TABLE_END( DRAW_MODE )
298 DALI_ENUM_TO_STRING_TABLE_BEGIN( RESIZE_POLICY )
299 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIXED )
300 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_NATURAL_SIZE )
301 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FILL_TO_PARENT )
302 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_RELATIVE_TO_PARENT )
303 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_FIXED_OFFSET_FROM_PARENT )
304 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIT_TO_CHILDREN )
305 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, DIMENSION_DEPENDENCY )
306 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_ASSIGNED_SIZE )
307 DALI_ENUM_TO_STRING_TABLE_END( RESIZE_POLICY )
309 DALI_ENUM_TO_STRING_TABLE_BEGIN( SIZE_SCALE_POLICY )
310 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, USE_SIZE_SET )
311 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FIT_WITH_ASPECT_RATIO )
312 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FILL_WITH_ASPECT_RATIO )
313 DALI_ENUM_TO_STRING_TABLE_END( SIZE_SCALE_POLICY )
315 DALI_ENUM_TO_STRING_TABLE_BEGIN( CLIPPING_MODE )
316 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, DISABLED )
317 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, CLIP_CHILDREN )
318 DALI_ENUM_TO_STRING_TABLE_END( CLIPPING_MODE )
320 DALI_ENUM_TO_STRING_TABLE_BEGIN( LAYOUT_DIRECTION )
321 DALI_ENUM_TO_STRING_WITH_SCOPE( LayoutDirection, LEFT_TO_RIGHT )
322 DALI_ENUM_TO_STRING_WITH_SCOPE( LayoutDirection, RIGHT_TO_LEFT )
323 DALI_ENUM_TO_STRING_TABLE_END( LAYOUT_DIRECTION )
325 bool GetAnchorPointConstant( const std::string& value, Vector3& anchor )
327 for( uint32_t i = 0; i < ANCHOR_CONSTANT_TABLE_COUNT; ++i )
329 uint32_t sizeIgnored = 0;
330 if( CompareTokens( value.c_str(), ANCHOR_CONSTANT_TABLE[ i ].name, sizeIgnored ) )
332 anchor = ANCHOR_CONSTANT_TABLE[ i ].value;
339 inline bool GetParentOriginConstant( const std::string& value, Vector3& parentOrigin )
341 // Values are the same so just use the same table as anchor-point
342 return GetAnchorPointConstant( value, parentOrigin );
346 * @brief Extract a given dimension from a Vector2
348 * @param[in] values The values to extract from
349 * @param[in] dimension The dimension to extract
350 * @return Return the value for the dimension
352 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
356 case Dimension::WIDTH:
360 case Dimension::HEIGHT:
362 return values.height;
373 * @brief Extract a given dimension from a Vector3
375 * @param[in] values The values to extract from
376 * @param[in] dimension The dimension to extract
377 * @return Return the value for the dimension
379 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
381 return GetDimensionValue( values.GetVectorXY(), dimension );
385 * @brief Recursively emits the visibility-changed-signal on the actor tree.
386 * @param[in] actor The actor to emit the signal on
387 * @param[in] visible The new visibility of the actor
388 * @param[in] type Whether the actor's visible property has changed or a parent's
390 void EmitVisibilityChangedSignalRecursively( ActorPtr actor, bool visible, DevelActor::VisibilityChange::Type type )
394 actor->EmitVisibilityChangedSignal( visible, type );
396 if( actor->GetChildCount() > 0 )
398 ActorContainer& children = actor->GetChildrenInternal();
399 for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter )
401 EmitVisibilityChangedSignalRecursively( *iter, visible, DevelActor::VisibilityChange::PARENT );
407 } // unnamed namespace
409 ActorPtr Actor::New()
411 ActorPtr actor( new Actor( BASIC ) );
413 // Second-phase construction
419 const std::string& Actor::GetName() const
424 void Actor::SetName( const std::string& name )
430 // ATTENTION: string for debug purposes is not thread safe.
431 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
435 uint32_t Actor::GetId() const
440 bool Actor::OnStage() const
445 Dali::Layer Actor::GetLayer()
449 // Short-circuit for Layer derived actors
452 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
455 // Find the immediate Layer parent
456 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
458 if( parent->IsLayer() )
460 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
467 void Actor::Add( Actor& child )
469 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
470 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
474 mChildren = new ActorContainer;
477 Actor* const oldParent( child.mParent );
479 // child might already be ours
480 if( this != oldParent )
482 // if we already have parent, unparent us first
485 oldParent->Remove( child ); // This causes OnChildRemove callback & ChildRemoved signal
487 // Old parent may need to readjust to missing child
488 if( oldParent->RelayoutDependentOnChildren() )
490 oldParent->RelayoutRequest();
494 // Guard against Add() during previous OnChildRemove callback
497 // Do this first, since user callbacks from within SetParent() may need to remove child
498 mChildren->push_back( ActorPtr( &child ) );
500 // SetParent asserts that child can be added
501 child.SetParent( this );
503 // Notification for derived classes
505 EmitChildAddedSignal( child );
507 InheritLayoutDirectionRecursively( ActorPtr( &child ), mLayoutDirection );
509 // Only put in a relayout request if there is a suitable dependency
510 if( RelayoutDependentOnChildren() )
518 void Actor::Remove( Actor& child )
520 if( (this == &child) || (!mChildren) )
522 // no children or removing itself
528 // Find the child in mChildren, and unparent it
529 ActorIter end = mChildren->end();
530 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
532 ActorPtr actor = (*iter);
534 if( actor.Get() == &child )
536 // Keep handle for OnChildRemove notification
539 // Do this first, since user callbacks from within SetParent() may need to add the child
540 mChildren->erase( iter );
542 DALI_ASSERT_DEBUG( actor->GetParent() == this );
543 actor->SetParent( NULL );
551 // Only put in a relayout request if there is a suitable dependency
552 if( RelayoutDependentOnChildren() )
558 // Notification for derived classes
559 OnChildRemove( child );
560 EmitChildRemovedSignal( child );
563 void Actor::Unparent()
567 // Remove this actor from the parent. The remove will put a relayout request in for
568 // the parent if required
569 mParent->Remove( *this );
570 // mParent is now NULL!
574 uint32_t Actor::GetChildCount() const
576 return ( NULL != mChildren ) ? static_cast<uint32_t>( mChildren->size() ) : 0; // only 4,294,967,295 children per actor
579 ActorPtr Actor::GetChildAt( uint32_t index ) const
581 DALI_ASSERT_ALWAYS( index < GetChildCount() );
583 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
586 ActorPtr Actor::FindChildByName( const std::string& actorName )
589 if( actorName == mName )
595 ActorIter end = mChildren->end();
596 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
598 child = (*iter)->FindChildByName( actorName );
609 ActorPtr Actor::FindChildById( const uint32_t id )
618 ActorIter end = mChildren->end();
619 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
621 child = (*iter)->FindChildById( id );
632 void Actor::SetParentOrigin( const Vector3& origin )
636 // mNode is being used in a separate thread; queue a message to set the value & base value
637 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
640 // Cache for event-thread access
643 // not allocated, check if different from default
644 if( ParentOrigin::DEFAULT != origin )
646 mParentOrigin = new Vector3( origin );
651 // check if different from current costs more than just set
652 *mParentOrigin = origin;
656 void Actor::SetParentOriginX( float x )
658 const Vector3& current = GetCurrentParentOrigin();
660 SetParentOrigin( Vector3( x, current.y, current.z ) );
663 void Actor::SetParentOriginY( float y )
665 const Vector3& current = GetCurrentParentOrigin();
667 SetParentOrigin( Vector3( current.x, y, current.z ) );
670 void Actor::SetParentOriginZ( float z )
672 const Vector3& current = GetCurrentParentOrigin();
674 SetParentOrigin( Vector3( current.x, current.y, z ) );
677 const Vector3& Actor::GetCurrentParentOrigin() const
679 // Cached for event-thread access
680 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
683 void Actor::SetAnchorPoint( const Vector3& anchor )
687 // mNode is being used in a separate thread; queue a message to set the value & base value
688 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
691 // Cache for event-thread access
694 // not allocated, check if different from default
695 if( AnchorPoint::DEFAULT != anchor )
697 mAnchorPoint = new Vector3( anchor );
702 // check if different from current costs more than just set
703 *mAnchorPoint = anchor;
707 void Actor::SetAnchorPointX( float x )
709 const Vector3& current = GetCurrentAnchorPoint();
711 SetAnchorPoint( Vector3( x, current.y, current.z ) );
714 void Actor::SetAnchorPointY( float y )
716 const Vector3& current = GetCurrentAnchorPoint();
718 SetAnchorPoint( Vector3( current.x, y, current.z ) );
721 void Actor::SetAnchorPointZ( float z )
723 const Vector3& current = GetCurrentAnchorPoint();
725 SetAnchorPoint( Vector3( current.x, current.y, z ) );
728 const Vector3& Actor::GetCurrentAnchorPoint() const
730 // Cached for event-thread access
731 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
734 void Actor::SetPosition( float x, float y )
736 SetPosition( Vector3( x, y, 0.0f ) );
739 void Actor::SetPosition( float x, float y, float z )
741 SetPosition( Vector3( x, y, z ) );
744 void Actor::SetPosition( const Vector3& position )
746 mTargetPosition = position;
750 // mNode is being used in a separate thread; queue a message to set the value & base value
751 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
755 void Actor::SetX( float x )
757 mTargetPosition.x = x;
761 // mNode is being used in a separate thread; queue a message to set the value & base value
762 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
766 void Actor::SetY( float y )
768 mTargetPosition.y = y;
772 // mNode is being used in a separate thread; queue a message to set the value & base value
773 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
777 void Actor::SetZ( float z )
779 mTargetPosition.z = z;
783 // mNode is being used in a separate thread; queue a message to set the value & base value
784 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
788 void Actor::TranslateBy( const Vector3& distance )
790 mTargetPosition += distance;
794 // mNode is being used in a separate thread; queue a message to set the value & base value
795 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
799 const Vector3& Actor::GetCurrentPosition() const
803 // mNode is being used in a separate thread; copy the value from the previous update
804 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
807 return Vector3::ZERO;
810 const Vector3& Actor::GetTargetPosition() const
812 return mTargetPosition;
815 const Vector3& Actor::GetCurrentWorldPosition() const
819 // mNode is being used in a separate thread; copy the value from the previous update
820 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
823 return Vector3::ZERO;
826 const Vector2 Actor::GetCurrentScreenPosition() const
828 StagePtr stage = Stage::GetCurrent();
829 if( stage && OnStage() && NULL != mNode )
831 Vector3 worldPosition = mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
832 Vector3 cameraPosition = stage->GetDefaultCameraActor().mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
833 worldPosition -= cameraPosition;
835 Vector3 actorSize = GetCurrentSize() * GetCurrentWorldScale();
836 Vector2 halfStageSize( stage->GetSize() * 0.5f ); // World position origin is center of stage
837 Vector3 halfActorSize( actorSize * 0.5f );
838 Vector3 anchorPointOffSet = halfActorSize - actorSize * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
840 return Vector2( halfStageSize.width + worldPosition.x - anchorPointOffSet.x,
841 halfStageSize.height + worldPosition.y - anchorPointOffSet.y );
844 return Vector2::ZERO;
847 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
849 // this flag is not animatable so keep the value
850 mPositionInheritanceMode = mode;
853 // mNode is being used in a separate thread; queue a message to set the value
854 SetInheritPositionMessage( GetEventThreadServices(), *mNode, mode == INHERIT_PARENT_POSITION );
858 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
860 // Cached for event-thread access
861 return mPositionInheritanceMode;
864 void Actor::SetInheritPosition( bool inherit )
866 if( mInheritPosition != inherit && NULL != mNode )
868 // non animateable so keep local copy
869 mInheritPosition = inherit;
870 SetInheritPositionMessage( GetEventThreadServices(), *mNode, inherit );
874 bool Actor::IsPositionInherited() const
876 return mInheritPosition;
879 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
881 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
882 normalizedAxis.Normalize();
884 Quaternion orientation( angle, normalizedAxis );
886 SetOrientation( orientation );
889 void Actor::SetOrientation( const Quaternion& orientation )
891 mTargetOrientation = orientation;
895 // mNode is being used in a separate thread; queue a message to set the value & base value
896 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation );
900 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
902 RotateBy( Quaternion(angle, axis) );
905 void Actor::RotateBy( const Quaternion& relativeRotation )
907 mTargetOrientation *= Quaternion( relativeRotation );
911 // mNode is being used in a separate thread; queue a message to set the value & base value
912 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
916 const Quaternion& Actor::GetCurrentOrientation() const
920 // mNode is being used in a separate thread; copy the value from the previous update
921 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
924 return Quaternion::IDENTITY;
927 const Quaternion& Actor::GetCurrentWorldOrientation() const
931 // mNode is being used in a separate thread; copy the value from the previous update
932 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
935 return Quaternion::IDENTITY;
938 void Actor::SetScale( float scale )
940 SetScale( Vector3( scale, scale, scale ) );
943 void Actor::SetScale( float x, float y, float z )
945 SetScale( Vector3( x, y, z ) );
948 void Actor::SetScale( const Vector3& scale )
950 mTargetScale = scale;
954 // mNode is being used in a separate thread; queue a message to set the value & base value
955 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
959 void Actor::SetScaleX( float x )
965 // mNode is being used in a separate thread; queue a message to set the value & base value
966 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
970 void Actor::SetScaleY( float y )
976 // mNode is being used in a separate thread; queue a message to set the value & base value
977 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
981 void Actor::SetScaleZ( float z )
987 // mNode is being used in a separate thread; queue a message to set the value & base value
988 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
992 void Actor::ScaleBy(const Vector3& relativeScale)
994 mTargetScale *= relativeScale;
998 // mNode is being used in a separate thread; queue a message to set the value & base value
999 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
1003 const Vector3& Actor::GetCurrentScale() const
1007 // mNode is being used in a separate thread; copy the value from the previous update
1008 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
1011 return Vector3::ONE;
1014 const Vector3& Actor::GetCurrentWorldScale() const
1018 // mNode is being used in a separate thread; copy the value from the previous update
1019 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
1022 return Vector3::ONE;
1025 void Actor::SetInheritScale( bool inherit )
1028 if( mInheritScale != inherit && NULL != mNode )
1030 // non animateable so keep local copy
1031 mInheritScale = inherit;
1032 // mNode is being used in a separate thread; queue a message to set the value
1033 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
1037 bool Actor::IsScaleInherited() const
1039 return mInheritScale;
1042 Matrix Actor::GetCurrentWorldMatrix() const
1046 return mNode->GetWorldMatrix(0);
1049 return Matrix::IDENTITY;
1052 void Actor::SetVisible( bool visible )
1054 SetVisibleInternal( visible, SendMessage::TRUE );
1057 bool Actor::IsVisible() const
1061 // mNode is being used in a separate thread; copy the value from the previous update
1062 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
1068 void Actor::SetOpacity( float opacity )
1070 mTargetColor.a = opacity;
1074 // mNode is being used in a separate thread; queue a message to set the value & base value
1075 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
1079 float Actor::GetCurrentOpacity() const
1083 // mNode is being used in a separate thread; copy the value from the previous update
1084 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1090 ClippingMode::Type Actor::GetClippingMode() const
1092 return mClippingMode;
1095 uint32_t Actor::GetSortingDepth()
1097 return mSortedDepth;
1100 const Vector4& Actor::GetCurrentWorldColor() const
1104 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1107 return Color::WHITE;
1110 void Actor::SetColor( const Vector4& color )
1112 mTargetColor = color;
1116 // mNode is being used in a separate thread; queue a message to set the value & base value
1117 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1121 void Actor::SetColorRed( float red )
1123 mTargetColor.r = red;
1127 // mNode is being used in a separate thread; queue a message to set the value & base value
1128 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1132 void Actor::SetColorGreen( float green )
1134 mTargetColor.g = green;
1138 // mNode is being used in a separate thread; queue a message to set the value & base value
1139 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1143 void Actor::SetColorBlue( float blue )
1145 mTargetColor.b = blue;
1149 // mNode is being used in a separate thread; queue a message to set the value & base value
1150 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1154 const Vector4& Actor::GetCurrentColor() const
1158 // mNode is being used in a separate thread; copy the value from the previous update
1159 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1162 return Color::WHITE;
1165 void Actor::SetInheritOrientation( bool inherit )
1167 if( mInheritOrientation != inherit && NULL != mNode)
1169 // non animateable so keep local copy
1170 mInheritOrientation = inherit;
1171 // mNode is being used in a separate thread; queue a message to set the value
1172 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1176 bool Actor::IsOrientationInherited() const
1178 return mInheritOrientation;
1181 void Actor::SetSizeModeFactor( const Vector3& factor )
1183 EnsureRelayoutData();
1185 mRelayoutData->sizeModeFactor = factor;
1188 const Vector3& Actor::GetSizeModeFactor() const
1190 if ( mRelayoutData )
1192 return mRelayoutData->sizeModeFactor;
1195 return GetDefaultSizeModeFactor();
1198 void Actor::SetColorMode( ColorMode colorMode )
1200 // non animateable so keep local copy
1201 mColorMode = colorMode;
1204 // mNode is being used in a separate thread; queue a message to set the value
1205 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1209 ColorMode Actor::GetColorMode() const
1211 // we have cached copy
1215 void Actor::SetSize( float width, float height )
1217 SetSize( Vector2( width, height ) );
1220 void Actor::SetSize( float width, float height, float depth )
1222 SetSize( Vector3( width, height, depth ) );
1225 void Actor::SetSize( const Vector2& size )
1227 SetSize( Vector3( size.width, size.height, 0.f ) );
1230 void Actor::SetSizeInternal( const Vector2& size )
1232 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1235 void Actor::SetSize( const Vector3& size )
1237 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1239 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1240 SetPreferredSize( size.GetVectorXY() );
1244 SetSizeInternal( size );
1248 void Actor::SetSizeInternal( const Vector3& size )
1250 // dont allow recursive loop
1251 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1252 // 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
1253 if( ( NULL != mNode )&&
1254 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1255 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1256 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1260 // mNode is being used in a separate thread; queue a message to set the value & base value
1261 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
1263 // Notification for derived classes
1264 mInsideOnSizeSet = true;
1265 OnSizeSet( mTargetSize );
1266 mInsideOnSizeSet = false;
1268 // Raise a relayout request if the flag is not locked
1269 if( mRelayoutData && !mRelayoutData->insideRelayout )
1276 void Actor::SetWidth( float width )
1278 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1280 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
1281 mRelayoutData->preferredSize.width = width;
1285 mTargetSize.width = width;
1289 // mNode is being used in a separate thread; queue a message to set the value & base value
1290 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1297 void Actor::SetHeight( float height )
1299 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1301 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
1302 mRelayoutData->preferredSize.height = height;
1306 mTargetSize.height = height;
1310 // mNode is being used in a separate thread; queue a message to set the value & base value
1311 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1318 void Actor::SetDepth( float depth )
1320 mTargetSize.depth = depth;
1324 // mNode is being used in a separate thread; queue a message to set the value & base value
1325 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1329 Vector3 Actor::GetTargetSize() const
1331 Vector3 size = mTargetSize;
1333 // Should return preferred size if size is fixed as set by SetSize
1334 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
1336 size.width = GetPreferredSize().width;
1338 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
1340 size.height = GetPreferredSize().height;
1346 const Vector3& Actor::GetCurrentSize() const
1350 // mNode is being used in a separate thread; copy the value from the previous update
1351 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1354 return Vector3::ZERO;
1357 Vector3 Actor::GetNaturalSize() const
1359 // It is up to deriving classes to return the appropriate natural size
1360 return Vector3( 0.0f, 0.0f, 0.0f );
1363 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1365 EnsureRelayoutData();
1367 ResizePolicy::Type originalWidthPolicy = GetResizePolicy(Dimension::WIDTH);
1368 ResizePolicy::Type originalHeightPolicy = GetResizePolicy(Dimension::HEIGHT);
1370 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1372 if( dimension & ( 1 << i ) )
1374 if ( policy == ResizePolicy::USE_ASSIGNED_SIZE )
1376 mRelayoutData->useAssignedSize[ i ] = true;
1380 mRelayoutData->resizePolicies[ i ] = policy;
1381 mRelayoutData->useAssignedSize[ i ] = false;
1386 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1388 if( dimension & Dimension::WIDTH )
1390 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1393 if( dimension & Dimension::HEIGHT )
1395 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1399 // If calling SetResizePolicy, assume we want relayout enabled
1400 SetRelayoutEnabled( true );
1402 // If the resize policy is set to be FIXED, the preferred size
1403 // should be overrided by the target size. Otherwise the target
1404 // size should be overrided by the preferred size.
1406 if( dimension & Dimension::WIDTH )
1408 if( originalWidthPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1410 mRelayoutData->preferredSize.width = mTargetSize.width;
1412 else if( originalWidthPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1414 mTargetSize.width = mRelayoutData->preferredSize.width;
1418 if( dimension & Dimension::HEIGHT )
1420 if( originalHeightPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1422 mRelayoutData->preferredSize.height = mTargetSize.height;
1424 else if( originalHeightPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1426 mTargetSize.height = mRelayoutData->preferredSize.height;
1430 OnSetResizePolicy( policy, dimension );
1432 // Trigger relayout on this control
1436 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1438 if ( mRelayoutData )
1440 // If more than one dimension is requested, just return the first one found
1441 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1443 if( ( dimension & ( 1 << i ) ) )
1445 if( mRelayoutData->useAssignedSize[ i ] )
1447 return ResizePolicy::USE_ASSIGNED_SIZE;
1451 return mRelayoutData->resizePolicies[ i ];
1457 return ResizePolicy::DEFAULT;
1460 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1462 EnsureRelayoutData();
1464 mRelayoutData->sizeSetPolicy = policy;
1467 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1469 if ( mRelayoutData )
1471 return mRelayoutData->sizeSetPolicy;
1474 return DEFAULT_SIZE_SCALE_POLICY;
1477 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1479 EnsureRelayoutData();
1481 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1483 if( dimension & ( 1 << i ) )
1485 mRelayoutData->dimensionDependencies[ i ] = dependency;
1490 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1492 if ( mRelayoutData )
1494 // If more than one dimension is requested, just return the first one found
1495 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1497 if( ( dimension & ( 1 << i ) ) )
1499 return mRelayoutData->dimensionDependencies[ i ];
1504 return Dimension::ALL_DIMENSIONS; // Default
1507 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1509 // If relayout data has not been allocated yet and the client is requesting
1510 // to disable it, do nothing
1511 if( mRelayoutData || relayoutEnabled )
1513 EnsureRelayoutData();
1515 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1517 mRelayoutData->relayoutEnabled = relayoutEnabled;
1521 bool Actor::IsRelayoutEnabled() const
1523 // Assume that if relayout data has not been allocated yet then
1524 // relayout is disabled
1525 return mRelayoutData && mRelayoutData->relayoutEnabled;
1528 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1530 EnsureRelayoutData();
1532 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1534 if( dimension & ( 1 << i ) )
1536 mRelayoutData->dimensionDirty[ i ] = dirty;
1541 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1543 if ( mRelayoutData )
1545 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1547 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1557 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1559 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1562 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1564 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1567 uint32_t Actor::AddRenderer( Renderer& renderer )
1571 mRenderers = new RendererContainer;
1574 uint32_t index = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1575 RendererPtr rendererPtr = RendererPtr( &renderer );
1576 mRenderers->push_back( rendererPtr );
1577 AddRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1581 uint32_t Actor::GetRendererCount() const
1583 uint32_t rendererCount(0);
1586 rendererCount = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1589 return rendererCount;
1592 RendererPtr Actor::GetRendererAt( uint32_t index )
1594 RendererPtr renderer;
1595 if( index < GetRendererCount() )
1597 renderer = ( *mRenderers )[ index ];
1603 void Actor::RemoveRenderer( Renderer& renderer )
1607 RendererIter end = mRenderers->end();
1608 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1610 if( (*iter).Get() == &renderer )
1612 mRenderers->erase( iter );
1613 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1620 void Actor::RemoveRenderer( uint32_t index )
1622 if( index < GetRendererCount() )
1624 RendererPtr renderer = ( *mRenderers )[ index ];
1625 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.Get()->GetRendererSceneObject() );
1626 mRenderers->erase( mRenderers->begin()+index );
1630 bool Actor::IsOverlay() const
1632 return ( DrawMode::OVERLAY_2D == mDrawMode );
1635 void Actor::SetDrawMode( DrawMode::Type drawMode )
1637 // this flag is not animatable so keep the value
1638 mDrawMode = drawMode;
1639 if( ( NULL != mNode ) && ( drawMode != DrawMode::STENCIL ) )
1641 // mNode is being used in a separate thread; queue a message to set the value
1642 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1646 DrawMode::Type Actor::GetDrawMode() const
1651 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1653 // only valid when on-stage
1654 StagePtr stage = Stage::GetCurrent();
1655 if( stage && OnStage() )
1657 const RenderTaskList& taskList = stage->GetRenderTaskList();
1659 Vector2 converted( screenX, screenY );
1661 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1662 uint32_t taskCount = taskList.GetTaskCount();
1663 for( uint32_t i = taskCount; i > 0; --i )
1665 Dali::RenderTask task = taskList.GetTask( i - 1 );
1666 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1668 // found a task where this conversion was ok so return
1676 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1678 bool retval = false;
1679 // only valid when on-stage
1682 CameraActor* camera = renderTask.GetCameraActor();
1686 renderTask.GetViewport( viewport );
1688 // need to translate coordinates to render tasks coordinate space
1689 Vector2 converted( screenX, screenY );
1690 if( renderTask.TranslateCoordinates( converted ) )
1692 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1699 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1701 // Early-out if mNode is NULL
1707 // Get the ModelView matrix
1709 Matrix::Multiply( modelView, mNode->GetWorldMatrix(0), viewMatrix );
1711 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1712 Matrix invertedMvp( false/*don't init*/);
1713 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1714 bool success = invertedMvp.Invert();
1716 // Convert to GL coordinates
1717 Vector4 screenPos( screenX - static_cast<float>( viewport.x ), static_cast<float>( viewport.height ) - screenY - static_cast<float>( viewport.y ), 0.f, 1.f );
1722 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), nearPos );
1729 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), farPos );
1735 if( XyPlaneIntersect( nearPos, farPos, local ) )
1737 Vector3 size = GetCurrentSize();
1738 localX = local.x + size.x * 0.5f;
1739 localY = local.y + size.y * 0.5f;
1750 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1753 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1755 Mathematical Formulation
1757 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1759 ( p - c ) dot ( p - c ) = r^2
1761 Given a ray with a point of origin 'o', and a direction vector 'd':
1763 ray(t) = o + td, t >= 0
1765 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1767 (o + td - c ) dot ( o + td - c ) = r^2
1769 To solve for t we first expand the above into a more recognisable quadratic equation form
1771 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1780 B = 2( o - c ) dot d
1781 C = ( o - c ) dot ( o - c ) - r^2
1783 which can be solved using a standard quadratic formula.
1785 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1787 Practical Simplification
1789 In a renderer, we often differentiate between world space and object space. In the object space
1790 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1791 into object space, the mathematical solution presented above can be simplified significantly.
1793 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1797 and we can find the t at which the (transformed) ray intersects the sphere by
1799 ( o + td ) dot ( o + td ) = r^2
1801 According to the reasoning above, we expand the above quadratic equation into the general form
1805 which now has coefficients:
1812 // Early out if mNode is NULL
1818 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1820 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1821 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1822 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1824 // Compute the radius is not needed, square radius it's enough.
1825 const Vector3& size( mNode->GetSize( bufferIndex ) );
1827 // Scale the sphere.
1828 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1830 const float width = size.width * scale.width;
1831 const float height = size.height * scale.height;
1833 float squareSphereRadius = 0.5f * ( width * width + height * height );
1835 float a = rayDir.Dot( rayDir ); // a
1836 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1837 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1839 return ( b2 * b2 - a * c ) >= 0.f;
1842 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector2& hitPointLocal, float& distance ) const
1846 if( OnStage() && NULL != mNode )
1848 // Transforms the ray to the local reference system.
1849 // Calculate the inverse of Model matrix
1850 Matrix invModelMatrix( false/*don't init*/);
1852 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1853 invModelMatrix = mNode->GetWorldMatrix(0);
1854 invModelMatrix.Invert();
1856 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1857 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1859 // Test with the actor's XY plane (Normal = 0 0 1 1).
1861 float a = -rayOriginLocal.z;
1862 float b = rayDirLocal.z;
1864 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1866 // Ray travels distance * rayDirLocal to intersect with plane.
1869 const Vector3& size = mNode->GetSize( bufferIndex );
1871 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1872 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1874 // Test with the actor's geometry.
1875 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1882 void Actor::SetLeaveRequired( bool required )
1884 mLeaveRequired = required;
1887 bool Actor::GetLeaveRequired() const
1889 return mLeaveRequired;
1892 void Actor::SetKeyboardFocusable( bool focusable )
1894 mKeyboardFocusable = focusable;
1897 bool Actor::IsKeyboardFocusable() const
1899 return mKeyboardFocusable;
1902 bool Actor::GetTouchRequired() const
1904 return !mTouchedSignal.Empty() || !mTouchSignal.Empty() || mDerivedRequiresTouch;
1907 bool Actor::GetHoverRequired() const
1909 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1912 bool Actor::GetWheelEventRequired() const
1914 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1917 bool Actor::IsHittable() const
1919 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1922 ActorGestureData& Actor::GetGestureData()
1924 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1925 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1926 if( NULL == mGestureData )
1928 mGestureData = new ActorGestureData;
1930 return *mGestureData;
1933 bool Actor::IsGestureRequred( Gesture::Type type ) const
1935 return mGestureData && mGestureData->IsGestureRequred( type );
1938 bool Actor::EmitTouchEventSignal( const TouchEvent& event, const Dali::TouchData& touch )
1940 bool consumed = false;
1942 if( !mTouchSignal.Empty() )
1944 Dali::Actor handle( this );
1945 consumed = mTouchSignal.Emit( handle, touch );
1948 if( !mTouchedSignal.Empty() )
1950 Dali::Actor handle( this );
1951 consumed |= mTouchedSignal.Emit( handle, event );
1956 // Notification for derived classes
1957 consumed = OnTouchEvent( event ); // TODO
1963 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1965 bool consumed = false;
1967 if( !mHoveredSignal.Empty() )
1969 Dali::Actor handle( this );
1970 consumed = mHoveredSignal.Emit( handle, event );
1975 // Notification for derived classes
1976 consumed = OnHoverEvent( event );
1982 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1984 bool consumed = false;
1986 if( !mWheelEventSignal.Empty() )
1988 Dali::Actor handle( this );
1989 consumed = mWheelEventSignal.Emit( handle, event );
1994 // Notification for derived classes
1995 consumed = OnWheelEvent( event );
2001 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
2003 if( ! mVisibilityChangedSignal.Empty() )
2005 Dali::Actor handle( this );
2006 mVisibilityChangedSignal.Emit( handle, visible, type );
2010 void Actor::EmitLayoutDirectionChangedSignal( LayoutDirection::Type type )
2012 if( ! mLayoutDirectionChangedSignal.Empty() )
2014 Dali::Actor handle( this );
2015 mLayoutDirectionChangedSignal.Emit( handle, type );
2019 void Actor::EmitChildAddedSignal( Actor& child )
2021 if( ! mChildAddedSignal.Empty() )
2023 Dali::Actor handle( &child );
2024 mChildAddedSignal.Emit( handle );
2028 void Actor::EmitChildRemovedSignal( Actor& child )
2030 if( ! mChildRemovedSignal.Empty() )
2032 Dali::Actor handle( &child );
2033 mChildRemovedSignal.Emit( handle );
2037 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
2039 return mTouchedSignal;
2042 Dali::Actor::TouchDataSignalType& Actor::TouchSignal()
2044 return mTouchSignal;
2047 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
2049 return mHoveredSignal;
2052 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
2054 return mWheelEventSignal;
2057 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
2059 return mOnStageSignal;
2062 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
2064 return mOffStageSignal;
2067 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
2069 return mOnRelayoutSignal;
2072 DevelActor::VisibilityChangedSignalType& Actor::VisibilityChangedSignal()
2074 return mVisibilityChangedSignal;
2077 Dali::Actor::LayoutDirectionChangedSignalType& Actor::LayoutDirectionChangedSignal()
2079 return mLayoutDirectionChangedSignal;
2082 DevelActor::ChildChangedSignalType& Actor::ChildAddedSignal()
2084 return mChildAddedSignal;
2087 DevelActor::ChildChangedSignalType& Actor::ChildRemovedSignal()
2089 return mChildRemovedSignal;
2092 DevelActor::ChildOrderChangedSignalType& Actor::ChildOrderChangedSignal()
2094 return mChildOrderChangedSignal;
2097 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
2099 bool connected( true );
2100 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
2102 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
2104 actor->TouchedSignal().Connect( tracker, functor );
2106 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
2108 actor->HoveredSignal().Connect( tracker, functor );
2110 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
2112 actor->WheelEventSignal().Connect( tracker, functor );
2114 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
2116 actor->OnStageSignal().Connect( tracker, functor );
2118 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
2120 actor->OffStageSignal().Connect( tracker, functor );
2122 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
2124 actor->OnRelayoutSignal().Connect( tracker, functor );
2126 else if( 0 == signalName.compare( SIGNAL_TOUCH ) )
2128 actor->TouchSignal().Connect( tracker, functor );
2130 else if( 0 == signalName.compare( SIGNAL_VISIBILITY_CHANGED ) )
2132 actor->VisibilityChangedSignal().Connect( tracker, functor );
2134 else if( 0 == signalName.compare( SIGNAL_LAYOUT_DIRECTION_CHANGED ) )
2136 actor->LayoutDirectionChangedSignal().Connect( tracker, functor );
2138 else if( 0 == signalName.compare( SIGNAL_CHILD_ADDED ) )
2140 actor->ChildAddedSignal().Connect( tracker, functor );
2142 else if( 0 == signalName.compare( SIGNAL_CHILD_REMOVED ) )
2144 actor->ChildRemovedSignal().Connect( tracker, functor );
2148 // signalName does not match any signal
2155 Actor::Actor( DerivedType derivedType )
2160 mParentOrigin( NULL ),
2161 mAnchorPoint( NULL ),
2162 mRelayoutData( NULL ),
2163 mGestureData( NULL ),
2167 mWheelEventSignal(),
2170 mOnRelayoutSignal(),
2171 mVisibilityChangedSignal(),
2172 mLayoutDirectionChangedSignal(),
2173 mChildAddedSignal(),
2174 mChildRemovedSignal(),
2175 mChildOrderChangedSignal(),
2176 mTargetOrientation( Quaternion::IDENTITY ),
2177 mTargetColor( Color::WHITE ),
2178 mTargetSize( Vector3::ZERO ),
2179 mTargetPosition( Vector3::ZERO ),
2180 mTargetScale( Vector3::ONE ),
2182 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
2185 mIsRoot( ROOT_LAYER == derivedType ),
2186 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2187 mIsOnStage( false ),
2189 mLeaveRequired( false ),
2190 mKeyboardFocusable( false ),
2191 mDerivedRequiresTouch( false ),
2192 mDerivedRequiresHover( false ),
2193 mDerivedRequiresWheelEvent( false ),
2194 mOnStageSignalled( false ),
2195 mInsideOnSizeSet( false ),
2196 mInheritPosition( true ),
2197 mInheritOrientation( true ),
2198 mInheritScale( true ),
2199 mPositionUsesAnchorPoint( true ),
2201 mInheritLayoutDirection( true ),
2202 mLayoutDirection( LayoutDirection::LEFT_TO_RIGHT ),
2203 mDrawMode( DrawMode::NORMAL ),
2204 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2205 mColorMode( Node::DEFAULT_COLOR_MODE ),
2206 mClippingMode( ClippingMode::DISABLED )
2210 void Actor::Initialize()
2212 // Node creation, keep raw-pointer to Node for messaging
2213 mNode = CreateNode();
2214 OwnerPointer< SceneGraph::Node > transferOwnership( const_cast< SceneGraph::Node* >( mNode ) );
2215 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), transferOwnership );
2219 GetEventThreadServices().RegisterObject( this );
2224 // Remove mParent pointers from children even if we're destroying core,
2225 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2228 ActorConstIter endIter = mChildren->end();
2229 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2231 (*iter)->SetParent( NULL );
2237 // Guard to allow handle destruction after Core has been destroyed
2238 if( EventThreadServices::IsCoreRunning() )
2242 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2243 mNode = NULL; // Node is about to be destroyed
2246 GetEventThreadServices().UnregisterObject( this );
2249 // Cleanup optional gesture data
2250 delete mGestureData;
2252 // Cleanup optional parent origin and anchor
2253 delete mParentOrigin;
2254 delete mAnchorPoint;
2256 // Delete optional relayout data
2259 delete mRelayoutData;
2263 void Actor::ConnectToStage( uint32_t parentDepth )
2265 // This container is used instead of walking the Actor hierarchy.
2266 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
2267 ActorContainer connectionList;
2269 StagePtr stage = Stage::GetCurrent();
2272 stage->RequestRebuildDepthTree();
2275 // This stage is atomic i.e. not interrupted by user callbacks.
2276 RecursiveConnectToStage( connectionList, parentDepth + 1 );
2278 // Notify applications about the newly connected actors.
2279 const ActorIter endIter = connectionList.end();
2280 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2282 (*iter)->NotifyStageConnection();
2288 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, uint32_t depth )
2290 DALI_ASSERT_ALWAYS( !OnStage() );
2293 mDepth = static_cast< uint16_t >( depth ); // overflow ignored, not expected in practice
2295 ConnectToSceneGraph();
2297 // Notification for internal derived classes
2298 OnStageConnectionInternal();
2300 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2301 connectionList.push_back( ActorPtr( this ) );
2303 // Recursively connect children
2306 ActorConstIter endIter = mChildren->end();
2307 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2309 (*iter)->RecursiveConnectToStage( connectionList, depth + 1 );
2315 * This method is called when the Actor is connected to the Stage.
2316 * The parent must have added its Node to the scene-graph.
2317 * The child must connect its Node to the parent's Node.
2318 * This is recursive; the child calls ConnectToStage() for its children.
2320 void Actor::ConnectToSceneGraph()
2322 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2326 // Reparent Node in next Update
2327 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode );
2330 // Request relayout on all actors that are added to the scenegraph
2333 // Notification for Object::Observers
2337 void Actor::NotifyStageConnection()
2339 // Actors can be removed (in a callback), before the on-stage stage is reported.
2340 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2341 if( OnStage() && !mOnStageSignalled )
2343 // Notification for external (CustomActor) derived classes
2344 OnStageConnectionExternal( mDepth );
2346 if( !mOnStageSignal.Empty() )
2348 Dali::Actor handle( this );
2349 mOnStageSignal.Emit( handle );
2352 // Guard against Remove during callbacks
2355 mOnStageSignalled = true; // signal required next time Actor is removed
2360 void Actor::DisconnectFromStage()
2362 // This container is used instead of walking the Actor hierachy.
2363 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2364 ActorContainer disconnectionList;
2366 StagePtr stage = Stage::GetCurrent();
2369 stage->RequestRebuildDepthTree();
2372 // This stage is atomic i.e. not interrupted by user callbacks
2373 RecursiveDisconnectFromStage( disconnectionList );
2375 // Notify applications about the newly disconnected actors.
2376 const ActorIter endIter = disconnectionList.end();
2377 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2379 (*iter)->NotifyStageDisconnection();
2383 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2385 DALI_ASSERT_ALWAYS( OnStage() );
2387 // Recursively disconnect children
2390 ActorConstIter endIter = mChildren->end();
2391 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2393 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2397 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2398 disconnectionList.push_back( ActorPtr( this ) );
2400 // Notification for internal derived classes
2401 OnStageDisconnectionInternal();
2403 DisconnectFromSceneGraph();
2409 * This method is called by an actor or its parent, before a node removal message is sent.
2410 * This is recursive; the child calls DisconnectFromStage() for its children.
2412 void Actor::DisconnectFromSceneGraph()
2414 // Notification for Object::Observers
2415 OnSceneObjectRemove();
2418 void Actor::NotifyStageDisconnection()
2420 // Actors can be added (in a callback), before the off-stage state is reported.
2421 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2422 // only do this step if there is a stage, i.e. Core is not being shut down
2423 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2425 // Notification for external (CustomeActor) derived classes
2426 OnStageDisconnectionExternal();
2428 if( !mOffStageSignal.Empty() )
2430 Dali::Actor handle( this );
2431 mOffStageSignal.Emit( handle );
2434 // Guard against Add during callbacks
2437 mOnStageSignalled = false; // signal required next time Actor is added
2442 bool Actor::IsNodeConnected() const
2444 bool connected( false );
2446 if( OnStage() && ( NULL != mNode ) )
2448 if( IsRoot() || mNode->GetParent() )
2457 // This method initiates traversal of the actor tree using depth-first
2458 // traversal to set a depth index based on traversal order. It sends a
2459 // single message to update manager to update all the actor's nodes in
2460 // this tree with the depth index. The sceneGraphNodeDepths vector's
2461 // elements are ordered by depth, and could be used to reduce sorting
2462 // in the update thread.
2463 void Actor::RebuildDepthTree()
2465 DALI_LOG_TIMER_START(depthTimer);
2467 // Vector of scene-graph nodes and their depths to send to UpdateManager
2468 // in a single message
2469 OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths( new SceneGraph::NodeDepths() );
2471 int32_t depthIndex = 1;
2472 DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
2474 SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths );
2475 DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
2478 void Actor::DepthTraverseActorTree( OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths, int32_t& depthIndex )
2480 mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
2481 sceneGraphNodeDepths->Add( const_cast<SceneGraph::Node*>( mNode ), mSortedDepth );
2483 // Create/add to children of this node
2486 for( ActorContainer::iterator it = mChildren->begin(); it != mChildren->end(); ++it )
2488 Actor* childActor = (*it).Get();
2490 childActor->DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
2495 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2499 case Dali::Actor::Property::PARENT_ORIGIN:
2501 Property::Type type = property.GetType();
2502 if( type == Property::VECTOR3 )
2504 SetParentOrigin( property.Get< Vector3 >() );
2506 else if ( type == Property::STRING )
2508 std::string parentOriginString;
2509 property.Get( parentOriginString );
2510 Vector3 parentOrigin;
2511 if( GetParentOriginConstant( parentOriginString, parentOrigin ) )
2513 SetParentOrigin( parentOrigin );
2519 case Dali::Actor::Property::PARENT_ORIGIN_X:
2521 SetParentOriginX( property.Get< float >() );
2525 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2527 SetParentOriginY( property.Get< float >() );
2531 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2533 SetParentOriginZ( property.Get< float >() );
2537 case Dali::Actor::Property::ANCHOR_POINT:
2539 Property::Type type = property.GetType();
2540 if( type == Property::VECTOR3 )
2542 SetAnchorPoint( property.Get< Vector3 >() );
2544 else if ( type == Property::STRING )
2546 std::string anchorPointString;
2547 property.Get( anchorPointString );
2549 if( GetAnchorPointConstant( anchorPointString, anchor ) )
2551 SetAnchorPoint( anchor );
2557 case Dali::Actor::Property::ANCHOR_POINT_X:
2559 SetAnchorPointX( property.Get< float >() );
2563 case Dali::Actor::Property::ANCHOR_POINT_Y:
2565 SetAnchorPointY( property.Get< float >() );
2569 case Dali::Actor::Property::ANCHOR_POINT_Z:
2571 SetAnchorPointZ( property.Get< float >() );
2575 case Dali::Actor::Property::SIZE:
2577 SetSize( property.Get< Vector3 >() );
2581 case Dali::Actor::Property::SIZE_WIDTH:
2583 SetWidth( property.Get< float >() );
2587 case Dali::Actor::Property::SIZE_HEIGHT:
2589 SetHeight( property.Get< float >() );
2593 case Dali::Actor::Property::SIZE_DEPTH:
2595 SetDepth( property.Get< float >() );
2599 case Dali::Actor::Property::POSITION:
2601 SetPosition( property.Get< Vector3 >() );
2605 case Dali::Actor::Property::POSITION_X:
2607 SetX( property.Get< float >() );
2611 case Dali::Actor::Property::POSITION_Y:
2613 SetY( property.Get< float >() );
2617 case Dali::Actor::Property::POSITION_Z:
2619 SetZ( property.Get< float >() );
2623 case Dali::Actor::Property::ORIENTATION:
2625 SetOrientation( property.Get< Quaternion >() );
2629 case Dali::Actor::Property::SCALE:
2631 SetScale( property.Get< Vector3 >() );
2635 case Dali::Actor::Property::SCALE_X:
2637 SetScaleX( property.Get< float >() );
2641 case Dali::Actor::Property::SCALE_Y:
2643 SetScaleY( property.Get< float >() );
2647 case Dali::Actor::Property::SCALE_Z:
2649 SetScaleZ( property.Get< float >() );
2653 case Dali::Actor::Property::VISIBLE:
2655 SetVisible( property.Get< bool >() );
2659 case Dali::Actor::Property::COLOR:
2661 SetColor( property.Get< Vector4 >() );
2665 case Dali::Actor::Property::COLOR_RED:
2667 SetColorRed( property.Get< float >() );
2671 case Dali::Actor::Property::COLOR_GREEN:
2673 SetColorGreen( property.Get< float >() );
2677 case Dali::Actor::Property::COLOR_BLUE:
2679 SetColorBlue( property.Get< float >() );
2683 case Dali::Actor::Property::COLOR_ALPHA:
2684 case Dali::DevelActor::Property::OPACITY:
2687 if( property.Get( value ) )
2689 SetOpacity( value );
2694 case Dali::Actor::Property::NAME:
2696 SetName( property.Get< std::string >() );
2700 case Dali::Actor::Property::SENSITIVE:
2702 SetSensitive( property.Get< bool >() );
2706 case Dali::Actor::Property::LEAVE_REQUIRED:
2708 SetLeaveRequired( property.Get< bool >() );
2712 case Dali::Actor::Property::INHERIT_POSITION:
2714 SetInheritPosition( property.Get< bool >() );
2718 case Dali::Actor::Property::INHERIT_ORIENTATION:
2720 SetInheritOrientation( property.Get< bool >() );
2724 case Dali::Actor::Property::INHERIT_SCALE:
2726 SetInheritScale( property.Get< bool >() );
2730 case Dali::Actor::Property::COLOR_MODE:
2732 ColorMode mode = mColorMode;
2733 if ( Scripting::GetEnumerationProperty< ColorMode >( property, COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT, mode ) )
2735 SetColorMode( mode );
2740 case Dali::Actor::Property::POSITION_INHERITANCE:
2742 PositionInheritanceMode mode = mPositionInheritanceMode;
2743 if( Scripting::GetEnumerationProperty< PositionInheritanceMode >( property, POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT, mode ) )
2745 SetPositionInheritanceMode( mode );
2750 case Dali::Actor::Property::DRAW_MODE:
2752 DrawMode::Type mode = mDrawMode;
2753 if( Scripting::GetEnumerationProperty< DrawMode::Type >( property, DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT, mode ) )
2755 SetDrawMode( mode );
2760 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2762 SetSizeModeFactor( property.Get< Vector3 >() );
2766 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2768 ResizePolicy::Type type = GetResizePolicy( Dimension::WIDTH );
2769 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2771 SetResizePolicy( type, Dimension::WIDTH );
2776 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2778 ResizePolicy::Type type = GetResizePolicy( Dimension::HEIGHT );
2779 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2781 SetResizePolicy( type, Dimension::HEIGHT );
2786 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2788 SizeScalePolicy::Type type = GetSizeScalePolicy();
2789 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT, type ) )
2791 SetSizeScalePolicy( type );
2796 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2798 if( property.Get< bool >() )
2800 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2805 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2807 if( property.Get< bool >() )
2809 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2814 case Dali::Actor::Property::PADDING:
2816 Vector4 padding = property.Get< Vector4 >();
2817 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2818 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2822 case Dali::Actor::Property::MINIMUM_SIZE:
2824 Vector2 size = property.Get< Vector2 >();
2825 SetMinimumSize( size.x, Dimension::WIDTH );
2826 SetMinimumSize( size.y, Dimension::HEIGHT );
2830 case Dali::Actor::Property::MAXIMUM_SIZE:
2832 Vector2 size = property.Get< Vector2 >();
2833 SetMaximumSize( size.x, Dimension::WIDTH );
2834 SetMaximumSize( size.y, Dimension::HEIGHT );
2838 case Dali::DevelActor::Property::SIBLING_ORDER:
2842 if( property.Get( value ) )
2844 SetSiblingOrder( value );
2849 case Dali::Actor::Property::CLIPPING_MODE:
2851 ClippingMode::Type convertedValue = mClippingMode;
2852 if( Scripting::GetEnumerationProperty< ClippingMode::Type >( property, CLIPPING_MODE_TABLE, CLIPPING_MODE_TABLE_COUNT, convertedValue ) )
2854 mClippingMode = convertedValue;
2857 SetClippingModeMessage( GetEventThreadServices(), *mNode, mClippingMode );
2863 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
2866 if( property.Get( value ) && value != mPositionUsesAnchorPoint )
2868 mPositionUsesAnchorPoint = value;
2871 SetPositionUsesAnchorPointMessage( GetEventThreadServices(), *mNode, mPositionUsesAnchorPoint );
2877 case Dali::Actor::Property::LAYOUT_DIRECTION:
2879 Dali::LayoutDirection::Type direction = mLayoutDirection;
2880 mInheritLayoutDirection = false;
2882 if( Scripting::GetEnumerationProperty< LayoutDirection::Type >( property, LAYOUT_DIRECTION_TABLE, LAYOUT_DIRECTION_TABLE_COUNT, direction ) )
2884 InheritLayoutDirectionRecursively( this, direction, true );
2889 case Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION:
2892 if( property.Get( value ) )
2894 SetInheritLayoutDirection( value );
2901 // this can happen in the case of a non-animatable default property so just do nothing
2907 // TODO: This method needs to be removed
2908 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2910 switch( entry.GetType() )
2912 case Property::BOOLEAN:
2914 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2915 DALI_ASSERT_DEBUG( NULL != property );
2917 // property is being used in a separate thread; queue a message to set the property
2918 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2923 case Property::INTEGER:
2925 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2926 DALI_ASSERT_DEBUG( NULL != property );
2928 // property is being used in a separate thread; queue a message to set the property
2929 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2934 case Property::FLOAT:
2936 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2937 DALI_ASSERT_DEBUG( NULL != property );
2939 // property is being used in a separate thread; queue a message to set the property
2940 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2945 case Property::VECTOR2:
2947 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2948 DALI_ASSERT_DEBUG( NULL != property );
2950 // property is being used in a separate thread; queue a message to set the property
2951 if(entry.componentIndex == 0)
2953 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2955 else if(entry.componentIndex == 1)
2957 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2961 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2967 case Property::VECTOR3:
2969 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2970 DALI_ASSERT_DEBUG( NULL != property );
2972 // property is being used in a separate thread; queue a message to set the property
2973 if(entry.componentIndex == 0)
2975 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2977 else if(entry.componentIndex == 1)
2979 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2981 else if(entry.componentIndex == 2)
2983 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2987 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2993 case Property::VECTOR4:
2995 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2996 DALI_ASSERT_DEBUG( NULL != property );
2998 // property is being used in a separate thread; queue a message to set the property
2999 if(entry.componentIndex == 0)
3001 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
3003 else if(entry.componentIndex == 1)
3005 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
3007 else if(entry.componentIndex == 2)
3009 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
3011 else if(entry.componentIndex == 3)
3013 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
3017 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3023 case Property::ROTATION:
3025 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3026 DALI_ASSERT_DEBUG( NULL != property );
3028 // property is being used in a separate thread; queue a message to set the property
3029 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3034 case Property::MATRIX:
3036 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3037 DALI_ASSERT_DEBUG( NULL != property );
3039 // property is being used in a separate thread; queue a message to set the property
3040 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3045 case Property::MATRIX3:
3047 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3048 DALI_ASSERT_DEBUG( NULL != property );
3050 // property is being used in a separate thread; queue a message to set the property
3051 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3058 // nothing to do for other types
3063 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3065 Property::Value value;
3067 if( ! GetCachedPropertyValue( index, value ) )
3069 // If property value is not stored in the event-side, then it must be a scene-graph only property
3070 GetCurrentPropertyValue( index, value );
3076 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
3078 Property::Value value;
3080 if( ! GetCurrentPropertyValue( index, value ) )
3082 // If unable to retrieve scene-graph property value, then it must be an event-side only property
3083 GetCachedPropertyValue( index, value );
3089 void Actor::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
3091 switch( animationType )
3094 case Animation::BETWEEN:
3098 case Dali::Actor::Property::SIZE:
3100 if( value.Get( mTargetSize ) )
3102 // Notify deriving classes
3103 OnSizeAnimation( animation, mTargetSize );
3108 case Dali::Actor::Property::SIZE_WIDTH:
3110 if( value.Get( mTargetSize.width ) )
3112 // Notify deriving classes
3113 OnSizeAnimation( animation, mTargetSize );
3118 case Dali::Actor::Property::SIZE_HEIGHT:
3120 if( value.Get( mTargetSize.height ) )
3122 // Notify deriving classes
3123 OnSizeAnimation( animation, mTargetSize );
3128 case Dali::Actor::Property::SIZE_DEPTH:
3130 if( value.Get( mTargetSize.depth ) )
3132 // Notify deriving classes
3133 OnSizeAnimation( animation, mTargetSize );
3138 case Dali::Actor::Property::POSITION:
3140 value.Get( mTargetPosition );
3144 case Dali::Actor::Property::POSITION_X:
3146 value.Get( mTargetPosition.x );
3150 case Dali::Actor::Property::POSITION_Y:
3152 value.Get( mTargetPosition.y );
3156 case Dali::Actor::Property::POSITION_Z:
3158 value.Get( mTargetPosition.z );
3162 case Dali::Actor::Property::ORIENTATION:
3164 value.Get( mTargetOrientation );
3168 case Dali::Actor::Property::SCALE:
3170 value.Get( mTargetScale );
3174 case Dali::Actor::Property::SCALE_X:
3176 value.Get( mTargetScale.x );
3180 case Dali::Actor::Property::SCALE_Y:
3182 value.Get( mTargetScale.y );
3186 case Dali::Actor::Property::SCALE_Z:
3188 value.Get( mTargetScale.z );
3192 case Dali::Actor::Property::VISIBLE:
3194 SetVisibleInternal( value.Get< bool >(), SendMessage::FALSE );
3198 case Dali::Actor::Property::COLOR:
3200 value.Get( mTargetColor );
3204 case Dali::Actor::Property::COLOR_RED:
3206 value.Get( mTargetColor.r );
3210 case Dali::Actor::Property::COLOR_GREEN:
3212 value.Get( mTargetColor.g );
3216 case Dali::Actor::Property::COLOR_BLUE:
3218 value.Get( mTargetColor.b );
3222 case Dali::Actor::Property::COLOR_ALPHA:
3223 case Dali::DevelActor::Property::OPACITY:
3225 value.Get( mTargetColor.a );
3231 // Not an animatable property. Do nothing.
3242 case Dali::Actor::Property::SIZE:
3244 if( AdjustValue< Vector3 >( mTargetSize, value ) )
3246 // Notify deriving classes
3247 OnSizeAnimation( animation, mTargetSize );
3252 case Dali::Actor::Property::SIZE_WIDTH:
3254 if( AdjustValue< float >( mTargetSize.width, value ) )
3256 // Notify deriving classes
3257 OnSizeAnimation( animation, mTargetSize );
3262 case Dali::Actor::Property::SIZE_HEIGHT:
3264 if( AdjustValue< float >( mTargetSize.height, value ) )
3266 // Notify deriving classes
3267 OnSizeAnimation( animation, mTargetSize );
3272 case Dali::Actor::Property::SIZE_DEPTH:
3274 if( AdjustValue< float >( mTargetSize.depth, value ) )
3276 // Notify deriving classes
3277 OnSizeAnimation( animation, mTargetSize );
3282 case Dali::Actor::Property::POSITION:
3284 AdjustValue< Vector3 >( mTargetPosition, value );
3288 case Dali::Actor::Property::POSITION_X:
3290 AdjustValue< float >( mTargetPosition.x, value );
3294 case Dali::Actor::Property::POSITION_Y:
3296 AdjustValue< float >( mTargetPosition.y, value );
3300 case Dali::Actor::Property::POSITION_Z:
3302 AdjustValue< float >( mTargetPosition.z, value );
3306 case Dali::Actor::Property::ORIENTATION:
3308 Quaternion relativeValue;
3309 if( value.Get( relativeValue ) )
3311 mTargetOrientation *= relativeValue;
3316 case Dali::Actor::Property::SCALE:
3318 AdjustValue< Vector3 >( mTargetScale, value );
3322 case Dali::Actor::Property::SCALE_X:
3324 AdjustValue< float >( mTargetScale.x, value );
3328 case Dali::Actor::Property::SCALE_Y:
3330 AdjustValue< float >( mTargetScale.y, value );
3334 case Dali::Actor::Property::SCALE_Z:
3336 AdjustValue< float >( mTargetScale.z, value );
3340 case Dali::Actor::Property::VISIBLE:
3342 bool relativeValue = false;
3343 if( value.Get( relativeValue ) )
3345 bool visible = mVisible || relativeValue;
3346 SetVisibleInternal( visible, SendMessage::FALSE );
3351 case Dali::Actor::Property::COLOR:
3353 AdjustValue< Vector4 >( mTargetColor, value );
3357 case Dali::Actor::Property::COLOR_RED:
3359 AdjustValue< float >( mTargetColor.r, value );
3363 case Dali::Actor::Property::COLOR_GREEN:
3365 AdjustValue< float >( mTargetColor.g, value );
3369 case Dali::Actor::Property::COLOR_BLUE:
3371 AdjustValue< float >( mTargetColor.b, value );
3375 case Dali::Actor::Property::COLOR_ALPHA:
3376 case Dali::DevelActor::Property::OPACITY:
3378 AdjustValue< float >( mTargetColor.a, value );
3384 // Not an animatable property. Do nothing.
3393 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3398 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3400 // This method should only return an object connected to the scene-graph
3401 return OnStage() ? mNode : NULL;
3404 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3406 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3408 const PropertyBase* property( NULL );
3410 // This method should only return a property of an object connected to the scene-graph
3416 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3418 AnimatablePropertyMetadata* animatable = GetSceneAnimatableProperty( index, nullptr );
3419 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3421 property = animatable->GetSceneGraphProperty();
3423 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3424 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3426 CustomPropertyMetadata* custom = FindCustomProperty( index );
3427 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3429 property = custom->GetSceneGraphProperty();
3431 else if( NULL != mNode )
3435 case Dali::Actor::Property::SIZE:
3436 property = &mNode->mSize;
3439 case Dali::Actor::Property::SIZE_WIDTH:
3440 property = &mNode->mSize;
3443 case Dali::Actor::Property::SIZE_HEIGHT:
3444 property = &mNode->mSize;
3447 case Dali::Actor::Property::SIZE_DEPTH:
3448 property = &mNode->mSize;
3451 case Dali::Actor::Property::POSITION:
3452 property = &mNode->mPosition;
3455 case Dali::Actor::Property::POSITION_X:
3456 property = &mNode->mPosition;
3459 case Dali::Actor::Property::POSITION_Y:
3460 property = &mNode->mPosition;
3463 case Dali::Actor::Property::POSITION_Z:
3464 property = &mNode->mPosition;
3467 case Dali::Actor::Property::ORIENTATION:
3468 property = &mNode->mOrientation;
3471 case Dali::Actor::Property::SCALE:
3472 property = &mNode->mScale;
3475 case Dali::Actor::Property::SCALE_X:
3476 property = &mNode->mScale;
3479 case Dali::Actor::Property::SCALE_Y:
3480 property = &mNode->mScale;
3483 case Dali::Actor::Property::SCALE_Z:
3484 property = &mNode->mScale;
3487 case Dali::Actor::Property::VISIBLE:
3488 property = &mNode->mVisible;
3491 case Dali::Actor::Property::COLOR:
3492 property = &mNode->mColor;
3495 case Dali::Actor::Property::COLOR_RED:
3496 property = &mNode->mColor;
3499 case Dali::Actor::Property::COLOR_GREEN:
3500 property = &mNode->mColor;
3503 case Dali::Actor::Property::COLOR_BLUE:
3504 property = &mNode->mColor;
3507 case Dali::Actor::Property::COLOR_ALPHA:
3508 case Dali::DevelActor::Property::OPACITY:
3509 property = &mNode->mColor;
3520 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3522 const PropertyInputImpl* property( NULL );
3524 // This method should only return a property of an object connected to the scene-graph
3530 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3532 AnimatablePropertyMetadata* animatable = GetSceneAnimatableProperty( index, nullptr );
3533 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3535 property = animatable->GetSceneGraphProperty();
3537 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3538 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3540 CustomPropertyMetadata* custom = FindCustomProperty( index );
3541 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3542 property = custom->GetSceneGraphProperty();
3544 else if( NULL != mNode )
3548 case Dali::Actor::Property::PARENT_ORIGIN:
3549 property = &mNode->mParentOrigin;
3552 case Dali::Actor::Property::PARENT_ORIGIN_X:
3553 property = &mNode->mParentOrigin;
3556 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3557 property = &mNode->mParentOrigin;
3560 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3561 property = &mNode->mParentOrigin;
3564 case Dali::Actor::Property::ANCHOR_POINT:
3565 property = &mNode->mAnchorPoint;
3568 case Dali::Actor::Property::ANCHOR_POINT_X:
3569 property = &mNode->mAnchorPoint;
3572 case Dali::Actor::Property::ANCHOR_POINT_Y:
3573 property = &mNode->mAnchorPoint;
3576 case Dali::Actor::Property::ANCHOR_POINT_Z:
3577 property = &mNode->mAnchorPoint;
3580 case Dali::Actor::Property::SIZE:
3581 property = &mNode->mSize;
3584 case Dali::Actor::Property::SIZE_WIDTH:
3585 property = &mNode->mSize;
3588 case Dali::Actor::Property::SIZE_HEIGHT:
3589 property = &mNode->mSize;
3592 case Dali::Actor::Property::SIZE_DEPTH:
3593 property = &mNode->mSize;
3596 case Dali::Actor::Property::POSITION:
3597 property = &mNode->mPosition;
3600 case Dali::Actor::Property::POSITION_X:
3601 property = &mNode->mPosition;
3604 case Dali::Actor::Property::POSITION_Y:
3605 property = &mNode->mPosition;
3608 case Dali::Actor::Property::POSITION_Z:
3609 property = &mNode->mPosition;
3612 case Dali::Actor::Property::WORLD_POSITION:
3613 property = &mNode->mWorldPosition;
3616 case Dali::Actor::Property::WORLD_POSITION_X:
3617 property = &mNode->mWorldPosition;
3620 case Dali::Actor::Property::WORLD_POSITION_Y:
3621 property = &mNode->mWorldPosition;
3624 case Dali::Actor::Property::WORLD_POSITION_Z:
3625 property = &mNode->mWorldPosition;
3628 case Dali::Actor::Property::ORIENTATION:
3629 property = &mNode->mOrientation;
3632 case Dali::Actor::Property::WORLD_ORIENTATION:
3633 property = &mNode->mWorldOrientation;
3636 case Dali::Actor::Property::SCALE:
3637 property = &mNode->mScale;
3640 case Dali::Actor::Property::SCALE_X:
3641 property = &mNode->mScale;
3644 case Dali::Actor::Property::SCALE_Y:
3645 property = &mNode->mScale;
3648 case Dali::Actor::Property::SCALE_Z:
3649 property = &mNode->mScale;
3652 case Dali::Actor::Property::WORLD_SCALE:
3653 property = &mNode->mWorldScale;
3656 case Dali::Actor::Property::VISIBLE:
3657 property = &mNode->mVisible;
3660 case Dali::Actor::Property::COLOR:
3661 property = &mNode->mColor;
3664 case Dali::Actor::Property::COLOR_RED:
3665 property = &mNode->mColor;
3668 case Dali::Actor::Property::COLOR_GREEN:
3669 property = &mNode->mColor;
3672 case Dali::Actor::Property::COLOR_BLUE:
3673 property = &mNode->mColor;
3676 case Dali::Actor::Property::COLOR_ALPHA:
3677 case Dali::DevelActor::Property::OPACITY:
3679 property = &mNode->mColor;
3683 case Dali::Actor::Property::WORLD_COLOR:
3684 property = &mNode->mWorldColor;
3687 case Dali::Actor::Property::WORLD_MATRIX:
3688 property = &mNode->mWorldMatrix;
3691 case Dali::DevelActor::Property::CULLED:
3692 property = &mNode->mCulled;
3703 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3705 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3707 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3709 // check whether the animatable property is registered already, if not then register one.
3710 AnimatablePropertyMetadata* animatableProperty = GetSceneAnimatableProperty( index, nullptr );
3711 if( animatableProperty )
3713 componentIndex = animatableProperty->componentIndex;
3720 case Dali::Actor::Property::PARENT_ORIGIN_X:
3721 case Dali::Actor::Property::ANCHOR_POINT_X:
3722 case Dali::Actor::Property::SIZE_WIDTH:
3723 case Dali::Actor::Property::POSITION_X:
3724 case Dali::Actor::Property::WORLD_POSITION_X:
3725 case Dali::Actor::Property::SCALE_X:
3726 case Dali::Actor::Property::COLOR_RED:
3732 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3733 case Dali::Actor::Property::ANCHOR_POINT_Y:
3734 case Dali::Actor::Property::SIZE_HEIGHT:
3735 case Dali::Actor::Property::POSITION_Y:
3736 case Dali::Actor::Property::WORLD_POSITION_Y:
3737 case Dali::Actor::Property::SCALE_Y:
3738 case Dali::Actor::Property::COLOR_GREEN:
3744 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3745 case Dali::Actor::Property::ANCHOR_POINT_Z:
3746 case Dali::Actor::Property::SIZE_DEPTH:
3747 case Dali::Actor::Property::POSITION_Z:
3748 case Dali::Actor::Property::WORLD_POSITION_Z:
3749 case Dali::Actor::Property::SCALE_Z:
3750 case Dali::Actor::Property::COLOR_BLUE:
3756 case Dali::Actor::Property::COLOR_ALPHA:
3757 case Dali::DevelActor::Property::OPACITY:
3771 return componentIndex;
3774 void Actor::SetParent( Actor* parent )
3778 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3782 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3785 // Instruct each actor to create a corresponding node in the scene graph
3786 ConnectToStage( parent->GetHierarchyDepth() );
3789 // Resolve the name and index for the child properties if any
3790 ResolveChildProperties();
3792 else // parent being set to NULL
3794 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3798 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3801 DALI_ASSERT_ALWAYS( mNode != NULL );
3805 // Disconnect the Node & its children from the scene-graph.
3806 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3809 // Instruct each actor to discard pointers to the scene-graph
3810 DisconnectFromStage();
3815 SceneGraph::Node* Actor::CreateNode() const
3817 return Node::New( mId );
3820 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3823 Actor* actor = dynamic_cast< Actor* >( object );
3827 if( 0 == actionName.compare( ACTION_SHOW ) )
3829 actor->SetVisible( true );
3832 else if( 0 == actionName.compare( ACTION_HIDE ) )
3834 actor->SetVisible( false );
3842 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
3844 bool valueSet = true;
3848 case Dali::Actor::Property::PARENT_ORIGIN:
3850 value = GetCurrentParentOrigin();
3854 case Dali::Actor::Property::PARENT_ORIGIN_X:
3856 value = GetCurrentParentOrigin().x;
3860 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3862 value = GetCurrentParentOrigin().y;
3866 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3868 value = GetCurrentParentOrigin().z;
3872 case Dali::Actor::Property::ANCHOR_POINT:
3874 value = GetCurrentAnchorPoint();
3878 case Dali::Actor::Property::ANCHOR_POINT_X:
3880 value = GetCurrentAnchorPoint().x;
3884 case Dali::Actor::Property::ANCHOR_POINT_Y:
3886 value = GetCurrentAnchorPoint().y;
3890 case Dali::Actor::Property::ANCHOR_POINT_Z:
3892 value = GetCurrentAnchorPoint().z;
3896 case Dali::Actor::Property::SIZE:
3898 value = GetTargetSize();
3902 case Dali::Actor::Property::SIZE_WIDTH:
3904 value = GetTargetSize().width;
3908 case Dali::Actor::Property::SIZE_HEIGHT:
3910 value = GetTargetSize().height;
3914 case Dali::Actor::Property::SIZE_DEPTH:
3916 value = GetTargetSize().depth;
3920 case Dali::Actor::Property::POSITION:
3922 value = GetTargetPosition();
3926 case Dali::Actor::Property::POSITION_X:
3928 value = GetTargetPosition().x;
3932 case Dali::Actor::Property::POSITION_Y:
3934 value = GetTargetPosition().y;
3938 case Dali::Actor::Property::POSITION_Z:
3940 value = GetTargetPosition().z;
3944 case Dali::Actor::Property::ORIENTATION:
3946 value = mTargetOrientation;
3950 case Dali::Actor::Property::SCALE:
3952 value = mTargetScale;
3956 case Dali::Actor::Property::SCALE_X:
3958 value = mTargetScale.x;
3962 case Dali::Actor::Property::SCALE_Y:
3964 value = mTargetScale.y;
3968 case Dali::Actor::Property::SCALE_Z:
3970 value = mTargetScale.z;
3974 case Dali::Actor::Property::VISIBLE:
3980 case Dali::Actor::Property::COLOR:
3982 value = mTargetColor;
3986 case Dali::Actor::Property::COLOR_RED:
3988 value = mTargetColor.r;
3992 case Dali::Actor::Property::COLOR_GREEN:
3994 value = mTargetColor.g;
3998 case Dali::Actor::Property::COLOR_BLUE:
4000 value = mTargetColor.b;
4004 case Dali::Actor::Property::COLOR_ALPHA:
4005 case Dali::DevelActor::Property::OPACITY:
4007 value = mTargetColor.a;
4011 case Dali::Actor::Property::NAME:
4017 case Dali::Actor::Property::SENSITIVE:
4019 value = IsSensitive();
4023 case Dali::Actor::Property::LEAVE_REQUIRED:
4025 value = GetLeaveRequired();
4029 case Dali::Actor::Property::INHERIT_POSITION:
4031 value = IsPositionInherited();
4035 case Dali::Actor::Property::INHERIT_ORIENTATION:
4037 value = IsOrientationInherited();
4041 case Dali::Actor::Property::INHERIT_SCALE:
4043 value = IsScaleInherited();
4047 case Dali::Actor::Property::COLOR_MODE:
4049 value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
4053 case Dali::Actor::Property::POSITION_INHERITANCE:
4055 value = Scripting::GetLinearEnumerationName< PositionInheritanceMode >( GetPositionInheritanceMode(), POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT );
4059 case Dali::Actor::Property::DRAW_MODE:
4061 value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
4065 case Dali::Actor::Property::SIZE_MODE_FACTOR:
4067 value = GetSizeModeFactor();
4071 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
4073 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
4077 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
4079 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
4083 case Dali::Actor::Property::SIZE_SCALE_POLICY:
4085 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT );
4089 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
4091 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
4095 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
4097 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
4101 case Dali::Actor::Property::PADDING:
4103 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
4104 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
4105 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
4109 case Dali::Actor::Property::MINIMUM_SIZE:
4111 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
4115 case Dali::Actor::Property::MAXIMUM_SIZE:
4117 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
4121 case Dali::Actor::Property::CLIPPING_MODE:
4123 value = mClippingMode;
4127 case Dali::DevelActor::Property::SIBLING_ORDER:
4129 value = static_cast<int>( GetSiblingOrder() );
4133 case Dali::DevelActor::Property::SCREEN_POSITION:
4135 value = GetCurrentScreenPosition();
4139 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
4141 value = mPositionUsesAnchorPoint;
4145 case Dali::Actor::Property::LAYOUT_DIRECTION:
4147 value = mLayoutDirection;
4151 case Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION:
4153 value = IsLayoutDirectionInherited();
4159 // Must be a scene-graph only property
4168 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
4170 bool valueSet = true;
4174 case Dali::Actor::Property::SIZE:
4176 value = GetCurrentSize();
4180 case Dali::Actor::Property::SIZE_WIDTH:
4182 value = GetCurrentSize().width;
4186 case Dali::Actor::Property::SIZE_HEIGHT:
4188 value = GetCurrentSize().height;
4192 case Dali::Actor::Property::SIZE_DEPTH:
4194 value = GetCurrentSize().depth;
4198 case Dali::Actor::Property::POSITION:
4200 value = GetCurrentPosition();
4204 case Dali::Actor::Property::POSITION_X:
4206 value = GetCurrentPosition().x;
4210 case Dali::Actor::Property::POSITION_Y:
4212 value = GetCurrentPosition().y;
4216 case Dali::Actor::Property::POSITION_Z:
4218 value = GetCurrentPosition().z;
4222 case Dali::Actor::Property::WORLD_POSITION:
4224 value = GetCurrentWorldPosition();
4228 case Dali::Actor::Property::WORLD_POSITION_X:
4230 value = GetCurrentWorldPosition().x;
4234 case Dali::Actor::Property::WORLD_POSITION_Y:
4236 value = GetCurrentWorldPosition().y;
4240 case Dali::Actor::Property::WORLD_POSITION_Z:
4242 value = GetCurrentWorldPosition().z;
4246 case Dali::Actor::Property::ORIENTATION:
4248 value = GetCurrentOrientation();
4252 case Dali::Actor::Property::WORLD_ORIENTATION:
4254 value = GetCurrentWorldOrientation();
4258 case Dali::Actor::Property::SCALE:
4260 value = GetCurrentScale();
4264 case Dali::Actor::Property::SCALE_X:
4266 value = GetCurrentScale().x;
4270 case Dali::Actor::Property::SCALE_Y:
4272 value = GetCurrentScale().y;
4276 case Dali::Actor::Property::SCALE_Z:
4278 value = GetCurrentScale().z;
4282 case Dali::Actor::Property::WORLD_SCALE:
4284 value = GetCurrentWorldScale();
4288 case Dali::Actor::Property::COLOR:
4290 value = GetCurrentColor();
4294 case Dali::Actor::Property::COLOR_RED:
4296 value = GetCurrentColor().r;
4300 case Dali::Actor::Property::COLOR_GREEN:
4302 value = GetCurrentColor().g;
4306 case Dali::Actor::Property::COLOR_BLUE:
4308 value = GetCurrentColor().b;
4312 case Dali::Actor::Property::COLOR_ALPHA:
4313 case Dali::DevelActor::Property::OPACITY:
4315 value = GetCurrentColor().a;
4319 case Dali::Actor::Property::WORLD_COLOR:
4321 value = GetCurrentWorldColor();
4325 case Dali::Actor::Property::WORLD_MATRIX:
4327 value = GetCurrentWorldMatrix();
4331 case Dali::Actor::Property::VISIBLE:
4333 value = IsVisible();
4337 case DevelActor::Property::CULLED:
4339 value = mNode->IsCulled( GetEventThreadServices().GetEventBufferIndex() );
4345 // Must be an event-side only property
4354 void Actor::EnsureRelayoutData()
4356 // Assign relayout data.
4357 if( !mRelayoutData )
4359 mRelayoutData = new RelayoutData();
4363 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
4365 // Check if actor is dependent on parent
4366 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4368 if( ( dimension & ( 1 << i ) ) )
4370 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4371 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
4381 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
4383 // Check if actor is dependent on children
4384 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4386 if( ( dimension & ( 1 << i ) ) )
4388 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4389 switch( resizePolicy )
4391 case ResizePolicy::FIT_TO_CHILDREN:
4392 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
4408 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
4410 return Actor::RelayoutDependentOnChildren( dimension );
4413 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
4415 // Check each possible dimension and see if it is dependent on the input one
4416 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4418 if( dimension & ( 1 << i ) )
4420 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
4427 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
4429 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4431 if( dimension & ( 1 << i ) )
4433 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
4438 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
4440 // If more than one dimension is requested, just return the first one found
4441 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4443 if( ( dimension & ( 1 << i ) ) )
4445 return mRelayoutData->negotiatedDimensions[ i ];
4449 return 0.0f; // Default
4452 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
4454 EnsureRelayoutData();
4456 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4458 if( dimension & ( 1 << i ) )
4460 mRelayoutData->dimensionPadding[ i ] = padding;
4465 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4467 if ( mRelayoutData )
4469 // If more than one dimension is requested, just return the first one found
4470 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4472 if( ( dimension & ( 1 << i ) ) )
4474 return mRelayoutData->dimensionPadding[ i ];
4479 return GetDefaultDimensionPadding();
4482 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4484 EnsureRelayoutData();
4486 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4488 if( dimension & ( 1 << i ) )
4490 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4495 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4497 if ( mRelayoutData )
4499 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4501 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4511 float Actor::GetHeightForWidthBase( float width )
4513 float height = 0.0f;
4515 const Vector3 naturalSize = GetNaturalSize();
4516 if( naturalSize.width > 0.0f )
4518 height = naturalSize.height * width / naturalSize.width;
4520 else // we treat 0 as 1:1 aspect ratio
4528 float Actor::GetWidthForHeightBase( float height )
4532 const Vector3 naturalSize = GetNaturalSize();
4533 if( naturalSize.height > 0.0f )
4535 width = naturalSize.width * height / naturalSize.height;
4537 else // we treat 0 as 1:1 aspect ratio
4545 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4547 // Fill to parent, taking size mode factor into account
4548 switch( child.GetResizePolicy( dimension ) )
4550 case ResizePolicy::FILL_TO_PARENT:
4552 return GetLatestSize( dimension );
4555 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4557 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4560 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4562 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4567 return GetLatestSize( dimension );
4572 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4574 // Can be overridden in derived class
4575 return CalculateChildSizeBase( child, dimension );
4578 float Actor::GetHeightForWidth( float width )
4580 // Can be overridden in derived class
4581 return GetHeightForWidthBase( width );
4584 float Actor::GetWidthForHeight( float height )
4586 // Can be overridden in derived class
4587 return GetWidthForHeightBase( height );
4590 float Actor::GetLatestSize( Dimension::Type dimension ) const
4592 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4595 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4597 Vector2 padding = GetPadding( dimension );
4599 return GetLatestSize( dimension ) + padding.x + padding.y;
4602 float Actor::NegotiateFromParent( Dimension::Type dimension )
4604 Actor* parent = GetParent();
4607 Vector2 padding( GetPadding( dimension ) );
4608 Vector2 parentPadding( parent->GetPadding( dimension ) );
4609 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4615 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4617 float maxDimensionPoint = 0.0f;
4619 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4621 ActorPtr child = GetChildAt( i );
4623 if( !child->RelayoutDependentOnParent( dimension ) )
4625 // Calculate the min and max points that the children range across
4626 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
4627 float dimensionSize = child->GetRelayoutSize( dimension );
4628 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4632 return maxDimensionPoint;
4635 float Actor::GetSize( Dimension::Type dimension ) const
4637 return GetDimensionValue( mTargetSize, dimension );
4640 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4642 return GetDimensionValue( GetNaturalSize(), dimension );
4645 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4647 switch( GetResizePolicy( dimension ) )
4649 case ResizePolicy::USE_NATURAL_SIZE:
4651 return GetNaturalSize( dimension );
4654 case ResizePolicy::FIXED:
4656 return GetDimensionValue( GetPreferredSize(), dimension );
4659 case ResizePolicy::USE_ASSIGNED_SIZE:
4661 return GetDimensionValue( maximumSize, dimension );
4664 case ResizePolicy::FILL_TO_PARENT:
4665 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4666 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4668 return NegotiateFromParent( dimension );
4671 case ResizePolicy::FIT_TO_CHILDREN:
4673 return NegotiateFromChildren( dimension );
4676 case ResizePolicy::DIMENSION_DEPENDENCY:
4678 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4681 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4683 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4686 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4688 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4700 return 0.0f; // Default
4703 float Actor::ClampDimension( float size, Dimension::Type dimension )
4705 const float minSize = GetMinimumSize( dimension );
4706 const float maxSize = GetMaximumSize( dimension );
4708 return std::max( minSize, std::min( size, maxSize ) );
4711 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4713 // Check if it needs to be negotiated
4714 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4716 // Check that we havn't gotten into an infinite loop
4717 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4718 bool recursionFound = false;
4719 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4721 if( *it == searchActor )
4723 recursionFound = true;
4728 if( !recursionFound )
4730 // Record the path that we have taken
4731 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4733 // Dimension dependency check
4734 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4736 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4738 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4740 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4744 // Parent dependency check
4745 Actor* parent = GetParent();
4746 if( parent && RelayoutDependentOnParent( dimension ) )
4748 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4751 // Children dependency check
4752 if( RelayoutDependentOnChildren( dimension ) )
4754 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4756 ActorPtr child = GetChildAt( i );
4758 // Only relayout child first if it is not dependent on this actor
4759 if( !child->RelayoutDependentOnParent( dimension ) )
4761 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
4766 // For deriving classes
4767 OnCalculateRelayoutSize( dimension );
4769 // All dependencies checked, calculate the size and set negotiated flag
4770 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4772 SetNegotiatedDimension( newSize, dimension );
4773 SetLayoutNegotiated( true, dimension );
4775 // For deriving classes
4776 OnLayoutNegotiated( newSize, dimension );
4778 // This actor has been successfully processed, pop it off the recursion stack
4779 recursionStack.pop_back();
4783 // TODO: Break infinite loop
4784 SetLayoutNegotiated( true, dimension );
4789 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4791 // Negotiate all dimensions that require it
4792 ActorDimensionStack recursionStack;
4794 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4796 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4799 NegotiateDimension( dimension, allocatedSize, recursionStack );
4803 Vector2 Actor::ApplySizeSetPolicy( const Vector2& size )
4805 switch( mRelayoutData->sizeSetPolicy )
4807 case SizeScalePolicy::USE_SIZE_SET:
4812 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4814 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4815 const Vector3 naturalSize = GetNaturalSize();
4816 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4818 const float sizeRatio = size.width / size.height;
4819 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4821 if( naturalSizeRatio < sizeRatio )
4823 return Vector2( naturalSizeRatio * size.height, size.height );
4825 else if( naturalSizeRatio > sizeRatio )
4827 return Vector2( size.width, size.width / naturalSizeRatio );
4838 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4840 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4841 const Vector3 naturalSize = GetNaturalSize();
4842 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4844 const float sizeRatio = size.width / size.height;
4845 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4847 if( naturalSizeRatio < sizeRatio )
4849 return Vector2( size.width, size.width / naturalSizeRatio );
4851 else if( naturalSizeRatio > sizeRatio )
4853 return Vector2( naturalSizeRatio * size.height, size.height );
4872 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4874 // Do the set actor size
4875 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4877 // Adjust for size set policy
4878 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4880 // Lock the flag to stop recursive relayouts on set size
4881 mRelayoutData->insideRelayout = true;
4882 SetSize( negotiatedSize );
4883 mRelayoutData->insideRelayout = false;
4885 // Clear flags for all dimensions
4886 SetLayoutDirty( false );
4888 // Give deriving classes a chance to respond
4889 OnRelayout( negotiatedSize, container );
4891 if( !mOnRelayoutSignal.Empty() )
4893 Dali::Actor handle( this );
4894 mOnRelayoutSignal.Emit( handle );
4898 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4900 // Force a size negotiation for actors that has assigned size during relayout
4901 // This is required as otherwise the flags that force a relayout will not
4902 // necessarilly be set. This will occur if the actor has already been laid out.
4903 // The dirty flags are then cleared. Then if the actor is added back into the
4904 // relayout container afterwards, the dirty flags would still be clear...
4905 // causing a relayout to be skipped. Here we force any actors added to the
4906 // container to be relayed out.
4907 DALI_LOG_TIMER_START( NegSizeTimer1 );
4909 if( GetUseAssignedSize(Dimension::WIDTH ) )
4911 SetLayoutNegotiated( false, Dimension::WIDTH );
4913 if( GetUseAssignedSize( Dimension::HEIGHT ) )
4915 SetLayoutNegotiated( false, Dimension::HEIGHT );
4918 // Do the negotiation
4919 NegotiateDimensions( allocatedSize );
4921 // Set the actor size
4922 SetNegotiatedSize( container );
4924 // Negotiate down to children
4925 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4927 ActorPtr child = GetChildAt( i );
4929 // Forces children that have already been laid out to be relayed out
4930 // if they have assigned size during relayout.
4931 if( child->GetUseAssignedSize(Dimension::WIDTH) )
4933 child->SetLayoutNegotiated(false, Dimension::WIDTH);
4934 child->SetLayoutDirty(true, Dimension::WIDTH);
4937 if( child->GetUseAssignedSize(Dimension::HEIGHT) )
4939 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
4940 child->SetLayoutDirty(true, Dimension::HEIGHT);
4943 // Only relayout if required
4944 if( child->RelayoutRequired() )
4946 container.Add( Dali::Actor( child.Get() ), mTargetSize.GetVectorXY() );
4949 DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
4952 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
4956 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4958 if( dimension & ( 1 << i ) )
4960 mRelayoutData->useAssignedSize[ i ] = use;
4966 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
4968 if ( mRelayoutData )
4970 // If more than one dimension is requested, just return the first one found
4971 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4973 if( dimension & ( 1 << i ) )
4975 return mRelayoutData->useAssignedSize[ i ];
4983 void Actor::RelayoutRequest( Dimension::Type dimension )
4985 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4986 if( relayoutController )
4988 Dali::Actor self( this );
4989 relayoutController->RequestRelayout( self, dimension );
4993 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4997 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
5001 void Actor::SetPreferredSize( const Vector2& size )
5003 EnsureRelayoutData();
5005 if( size.width > 0.0f )
5007 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
5010 if( size.height > 0.0f )
5012 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
5015 mRelayoutData->preferredSize = size;
5020 Vector2 Actor::GetPreferredSize() const
5022 if ( mRelayoutData )
5024 return Vector2( mRelayoutData->preferredSize );
5027 return GetDefaultPreferredSize();
5030 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
5032 EnsureRelayoutData();
5034 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5036 if( dimension & ( 1 << i ) )
5038 mRelayoutData->minimumSize[ i ] = size;
5045 float Actor::GetMinimumSize( Dimension::Type dimension ) const
5047 if ( mRelayoutData )
5049 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5051 if( dimension & ( 1 << i ) )
5053 return mRelayoutData->minimumSize[ i ];
5058 return 0.0f; // Default
5061 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
5063 EnsureRelayoutData();
5065 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5067 if( dimension & ( 1 << i ) )
5069 mRelayoutData->maximumSize[ i ] = size;
5076 float Actor::GetMaximumSize( Dimension::Type dimension ) const
5078 if ( mRelayoutData )
5080 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5082 if( dimension & ( 1 << i ) )
5084 return mRelayoutData->maximumSize[ i ];
5089 return FLT_MAX; // Default
5092 Object* Actor::GetParentObject() const
5097 void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
5099 if( mVisible != visible )
5101 if( sendMessage == SendMessage::TRUE && NULL != mNode )
5103 // mNode is being used in a separate thread; queue a message to set the value & base value
5104 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
5109 // Emit the signal on this actor and all its children
5110 EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
5114 void Actor::SetSiblingOrder( uint32_t order )
5118 ActorContainer& siblings = *(mParent->mChildren);
5119 uint32_t currentOrder = GetSiblingOrder();
5121 if( order != currentOrder )
5127 else if( order < siblings.size() -1 )
5129 if( order > currentOrder )
5131 RaiseAbove( *siblings[order] );
5135 LowerBelow( *siblings[order] );
5146 uint32_t Actor::GetSiblingOrder() const
5152 ActorContainer& siblings = *(mParent->mChildren);
5153 for( std::size_t i = 0; i < siblings.size(); ++i )
5155 if( siblings[i] == this )
5157 order = static_cast<uint32_t>( i );
5166 void Actor::RequestRebuildDepthTree()
5170 StagePtr stage = Stage::GetCurrent();
5173 stage->RequestRebuildDepthTree();
5182 ActorContainer& siblings = *(mParent->mChildren);
5183 if( siblings.back() != this ) // If not already at end
5185 for( std::size_t i=0; i<siblings.size(); ++i )
5187 if( siblings[i] == this )
5190 ActorPtr next = siblings[i+1];
5191 siblings[i+1] = this;
5198 Dali::Actor handle( this );
5199 mParent->mChildOrderChangedSignal.Emit( handle );
5201 RequestRebuildDepthTree();
5205 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5213 ActorContainer& siblings = *(mParent->mChildren);
5214 if( siblings.front() != this ) // If not already at beginning
5216 for( std::size_t i=1; i<siblings.size(); ++i )
5218 if( siblings[i] == this )
5220 // Swap with previous
5221 ActorPtr previous = siblings[i-1];
5222 siblings[i-1] = this;
5223 siblings[i] = previous;
5229 Dali::Actor handle( this );
5230 mParent->mChildOrderChangedSignal.Emit( handle );
5232 RequestRebuildDepthTree();
5236 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5240 void Actor::RaiseToTop()
5244 ActorContainer& siblings = *(mParent->mChildren);
5245 if( siblings.back() != this ) // If not already at end
5247 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
5248 if( iter != siblings.end() )
5250 siblings.erase(iter);
5251 siblings.push_back(ActorPtr(this));
5255 Dali::Actor handle( this );
5256 mParent->mChildOrderChangedSignal.Emit( handle );
5258 RequestRebuildDepthTree();
5262 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5266 void Actor::LowerToBottom()
5270 ActorContainer& siblings = *(mParent->mChildren);
5271 if( siblings.front() != this ) // If not already at bottom,
5273 ActorPtr thisPtr(this); // ensure this actor remains referenced.
5275 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
5276 if( iter != siblings.end() )
5278 siblings.erase(iter);
5279 siblings.insert(siblings.begin(), thisPtr);
5283 Dali::Actor handle( this );
5284 mParent->mChildOrderChangedSignal.Emit( handle );
5286 RequestRebuildDepthTree();
5290 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5294 void Actor::RaiseAbove( Internal::Actor& target )
5298 ActorContainer& siblings = *(mParent->mChildren);
5299 if( siblings.back() != this && target.mParent == mParent ) // If not already at top
5301 ActorPtr thisPtr(this); // ensure this actor remains referenced.
5303 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
5304 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
5305 if( thisIter < targetIter )
5307 siblings.erase(thisIter);
5308 // Erasing early invalidates the targetIter. (Conversely, inserting first may also
5309 // invalidate thisIter)
5310 targetIter = std::find( siblings.begin(), siblings.end(), &target );
5312 siblings.insert(targetIter, thisPtr);
5315 Dali::Actor handle( this );
5316 mParent->mChildOrderChangedSignal.Emit( handle );
5318 RequestRebuildDepthTree();
5323 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5327 void Actor::LowerBelow( Internal::Actor& target )
5331 ActorContainer& siblings = *(mParent->mChildren);
5332 if( siblings.front() != this && target.mParent == mParent ) // If not already at bottom
5334 ActorPtr thisPtr(this); // ensure this actor remains referenced.
5336 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
5337 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
5339 if( thisIter > targetIter )
5341 siblings.erase(thisIter); // this only invalidates iterators at or after this point.
5342 siblings.insert(targetIter, thisPtr);
5345 Dali::Actor handle( this );
5346 mParent->mChildOrderChangedSignal.Emit( handle );
5348 RequestRebuildDepthTree();
5353 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5357 void Actor::SetInheritLayoutDirection( bool inherit )
5359 if( mInheritLayoutDirection != inherit )
5361 mInheritLayoutDirection = inherit;
5363 if( inherit && mParent )
5365 InheritLayoutDirectionRecursively( this, mParent->mLayoutDirection );
5370 bool Actor::IsLayoutDirectionInherited() const
5372 return mInheritLayoutDirection;
5375 void Actor::InheritLayoutDirectionRecursively( ActorPtr actor, Dali::LayoutDirection::Type direction, bool set )
5377 if( actor && ( actor->mInheritLayoutDirection || set ) )
5379 if( actor->mLayoutDirection != direction )
5381 actor->mLayoutDirection = direction;
5382 actor->EmitLayoutDirectionChangedSignal( direction );
5383 actor->RelayoutRequest();
5386 if( actor->GetChildCount() > 0 )
5388 ActorContainer& children = actor->GetChildrenInternal();
5389 for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter )
5391 InheritLayoutDirectionRecursively( *iter, direction );
5397 } // namespace Internal