2 * Copyright (c) 2018 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/event/actors/actor-impl.h>
27 #include <dali/devel-api/actors/layer-devel.h>
28 #include <dali/public-api/common/dali-common.h>
29 #include <dali/public-api/common/constants.h>
30 #include <dali/public-api/events/touch-data.h>
31 #include <dali/public-api/math/vector2.h>
32 #include <dali/public-api/math/vector3.h>
33 #include <dali/public-api/math/radian.h>
34 #include <dali/public-api/object/type-registry.h>
35 #include <dali/devel-api/actors/actor-devel.h>
36 #include <dali/devel-api/scripting/scripting.h>
37 #include <dali/internal/common/internal-constants.h>
38 #include <dali/internal/event/common/event-thread-services.h>
39 #include <dali/internal/event/render-tasks/render-task-impl.h>
40 #include <dali/internal/event/actors/camera-actor-impl.h>
41 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
42 #include <dali/internal/event/common/property-helper.h>
43 #include <dali/internal/event/common/stage-impl.h>
44 #include <dali/internal/event/common/type-info-impl.h>
45 #include <dali/internal/event/animation/constraint-impl.h>
46 #include <dali/internal/event/common/projection.h>
47 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
48 #include <dali/internal/update/common/animatable-property.h>
49 #include <dali/internal/update/nodes/node-messages.h>
50 #include <dali/internal/update/nodes/node-declarations.h>
51 #include <dali/internal/update/animation/scene-graph-constraint.h>
52 #include <dali/internal/event/events/actor-gesture-data.h>
53 #include <dali/internal/common/message.h>
54 #include <dali/integration-api/debug.h>
56 using Dali::Internal::SceneGraph::Node;
57 using Dali::Internal::SceneGraph::AnimatableProperty;
58 using Dali::Internal::SceneGraph::PropertyBase;
60 #if defined(DEBUG_ENABLED)
61 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_DEPTH_TIMER" );
62 Debug::Filter* gLogRelayoutFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_TIMER" );
73 /// Using a function because of library initialisation order. Vector3::ONE may not have been initialised yet.
74 inline const Vector3& GetDefaultSizeModeFactor()
79 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
80 inline const Vector2& GetDefaultPreferredSize()
85 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
86 inline const Vector2& GetDefaultDimensionPadding()
91 const SizeScalePolicy::Type DEFAULT_SIZE_SCALE_POLICY = SizeScalePolicy::USE_SIZE_SET;
93 } // unnamed namespace
96 * Struct to collect relayout variables
98 struct Actor::RelayoutData
101 : sizeModeFactor( GetDefaultSizeModeFactor() ), preferredSize( GetDefaultPreferredSize() ), sizeSetPolicy( DEFAULT_SIZE_SCALE_POLICY ), relayoutEnabled( false ), insideRelayout( false )
103 // Set size negotiation defaults
104 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
106 resizePolicies[ i ] = ResizePolicy::DEFAULT;
107 useAssignedSize[ i ] = false;
108 negotiatedDimensions[ i ] = 0.0f;
109 dimensionNegotiated[ i ] = false;
110 dimensionDirty[ i ] = false;
111 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
112 dimensionPadding[ i ] = GetDefaultDimensionPadding();
113 minimumSize[ i ] = 0.0f;
114 maximumSize[ i ] = FLT_MAX;
118 ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies
119 bool useAssignedSize[ Dimension::DIMENSION_COUNT ]; ///< The flag to specify whether the size should be assigned to the actor
121 Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies
123 Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
125 float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
127 float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be
128 float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be
130 bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated
131 bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
133 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
135 Vector2 preferredSize; ///< The preferred size of the actor
137 SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
139 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
140 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
143 namespace // unnamed namespace
149 * We want to discourage the use of property strings (minimize string comparisons),
150 * particularly for the default properties.
151 * Name Type writable animatable constraint-input enum for index-checking
153 DALI_PROPERTY_TABLE_BEGIN
154 DALI_PROPERTY( "parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
155 DALI_PROPERTY( "parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
156 DALI_PROPERTY( "parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
157 DALI_PROPERTY( "parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
158 DALI_PROPERTY( "anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
159 DALI_PROPERTY( "anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
160 DALI_PROPERTY( "anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
161 DALI_PROPERTY( "anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
162 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
163 DALI_PROPERTY( "sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
164 DALI_PROPERTY( "sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
165 DALI_PROPERTY( "sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
166 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
167 DALI_PROPERTY( "positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
168 DALI_PROPERTY( "positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
169 DALI_PROPERTY( "positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
170 DALI_PROPERTY( "worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
171 DALI_PROPERTY( "worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
172 DALI_PROPERTY( "worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
173 DALI_PROPERTY( "worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
174 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
175 DALI_PROPERTY( "worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
176 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
177 DALI_PROPERTY( "scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
178 DALI_PROPERTY( "scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
179 DALI_PROPERTY( "scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
180 DALI_PROPERTY( "worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
181 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
182 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
183 DALI_PROPERTY( "colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
184 DALI_PROPERTY( "colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
185 DALI_PROPERTY( "colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
186 DALI_PROPERTY( "colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
187 DALI_PROPERTY( "worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
188 DALI_PROPERTY( "worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
189 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
190 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
191 DALI_PROPERTY( "leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
192 DALI_PROPERTY( "inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
193 DALI_PROPERTY( "inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
194 DALI_PROPERTY( "colorMode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
195 DALI_PROPERTY( "drawMode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
196 DALI_PROPERTY( "sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
197 DALI_PROPERTY( "widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
198 DALI_PROPERTY( "heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
199 DALI_PROPERTY( "sizeScalePolicy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
200 DALI_PROPERTY( "widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
201 DALI_PROPERTY( "heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
202 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
203 DALI_PROPERTY( "minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
204 DALI_PROPERTY( "maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
205 DALI_PROPERTY( "inheritPosition", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_POSITION )
206 DALI_PROPERTY( "clippingMode", STRING, true, false, false, Dali::Actor::Property::CLIPPING_MODE )
207 DALI_PROPERTY( "layoutDirection", STRING, true, false, false, Dali::Actor::Property::LAYOUT_DIRECTION )
208 DALI_PROPERTY( "inheritLayoutDirection", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION )
209 DALI_PROPERTY( "siblingOrder", INTEGER, true, false, false, Dali::DevelActor::Property::SIBLING_ORDER )
210 DALI_PROPERTY( "opacity", FLOAT, true, true, true, Dali::DevelActor::Property::OPACITY )
211 DALI_PROPERTY( "screenPosition", VECTOR2, false, false, false, Dali::DevelActor::Property::SCREEN_POSITION )
212 DALI_PROPERTY( "positionUsesAnchorPoint", BOOLEAN, true, false, false, Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT )
213 DALI_PROPERTY( "culled", BOOLEAN, false, false, true, Dali::DevelActor::Property::CULLED )
214 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperties )
218 const char* const SIGNAL_TOUCHED = "touched";
219 const char* const SIGNAL_HOVERED = "hovered";
220 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
221 const char* const SIGNAL_ON_STAGE = "onStage";
222 const char* const SIGNAL_OFF_STAGE = "offStage";
223 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
224 const char* const SIGNAL_TOUCH = "touch";
225 const char* const SIGNAL_VISIBILITY_CHANGED = "visibilityChanged";
226 const char* const SIGNAL_LAYOUT_DIRECTION_CHANGED = "layoutDirectionChanged";
227 const char* const SIGNAL_CHILD_ADDED = "childAdded";
228 const char* const SIGNAL_CHILD_REMOVED = "childRemoved";
232 const char* const ACTION_SHOW = "show";
233 const char* const ACTION_HIDE = "hide";
235 BaseHandle CreateActor()
237 return Dali::Actor::New();
240 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor, ActorDefaultProperties );
242 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
243 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
244 SignalConnectorType signalConnector3( mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal );
245 SignalConnectorType signalConnector4( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
246 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
247 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
248 SignalConnectorType signalConnector7( mType, SIGNAL_TOUCH, &Actor::DoConnectSignal );
249 SignalConnectorType signalConnector8( mType, SIGNAL_VISIBILITY_CHANGED, &Actor::DoConnectSignal );
250 SignalConnectorType signalConnector9( mType, SIGNAL_LAYOUT_DIRECTION_CHANGED, &Actor::DoConnectSignal );
251 SignalConnectorType signalConnector10( mType, SIGNAL_CHILD_ADDED, &Actor::DoConnectSignal );
252 SignalConnectorType signalConnector11( mType, SIGNAL_CHILD_REMOVED, &Actor::DoConnectSignal );
254 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
255 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
260 const Vector3& value;
263 DALI_ENUM_TO_STRING_TABLE_BEGIN_WITH_TYPE( AnchorValue, ANCHOR_CONSTANT )
264 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_LEFT )
265 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_CENTER )
266 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_RIGHT )
267 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_LEFT )
268 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER )
269 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_RIGHT )
270 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_LEFT )
271 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_CENTER )
272 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_RIGHT )
273 DALI_ENUM_TO_STRING_TABLE_END( ANCHOR_CONSTANT )
275 DALI_ENUM_TO_STRING_TABLE_BEGIN( COLOR_MODE )
276 DALI_ENUM_TO_STRING( USE_OWN_COLOR )
277 DALI_ENUM_TO_STRING( USE_PARENT_COLOR )
278 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_COLOR )
279 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_ALPHA )
280 DALI_ENUM_TO_STRING_TABLE_END( COLOR_MODE )
282 DALI_ENUM_TO_STRING_TABLE_BEGIN( DRAW_MODE )
283 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, NORMAL )
284 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, OVERLAY_2D )
285 DALI_ENUM_TO_STRING_TABLE_END( DRAW_MODE )
287 DALI_ENUM_TO_STRING_TABLE_BEGIN( RESIZE_POLICY )
288 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIXED )
289 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_NATURAL_SIZE )
290 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FILL_TO_PARENT )
291 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_RELATIVE_TO_PARENT )
292 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_FIXED_OFFSET_FROM_PARENT )
293 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIT_TO_CHILDREN )
294 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, DIMENSION_DEPENDENCY )
295 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_ASSIGNED_SIZE )
296 DALI_ENUM_TO_STRING_TABLE_END( RESIZE_POLICY )
298 DALI_ENUM_TO_STRING_TABLE_BEGIN( SIZE_SCALE_POLICY )
299 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, USE_SIZE_SET )
300 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FIT_WITH_ASPECT_RATIO )
301 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FILL_WITH_ASPECT_RATIO )
302 DALI_ENUM_TO_STRING_TABLE_END( SIZE_SCALE_POLICY )
304 DALI_ENUM_TO_STRING_TABLE_BEGIN( CLIPPING_MODE )
305 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, DISABLED )
306 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, CLIP_CHILDREN )
307 DALI_ENUM_TO_STRING_TABLE_END( CLIPPING_MODE )
309 DALI_ENUM_TO_STRING_TABLE_BEGIN( LAYOUT_DIRECTION )
310 DALI_ENUM_TO_STRING_WITH_SCOPE( LayoutDirection, LEFT_TO_RIGHT )
311 DALI_ENUM_TO_STRING_WITH_SCOPE( LayoutDirection, RIGHT_TO_LEFT )
312 DALI_ENUM_TO_STRING_TABLE_END( LAYOUT_DIRECTION )
314 bool GetAnchorPointConstant( const std::string& value, Vector3& anchor )
316 for( uint32_t i = 0; i < ANCHOR_CONSTANT_TABLE_COUNT; ++i )
318 uint32_t sizeIgnored = 0;
319 if( CompareTokens( value.c_str(), ANCHOR_CONSTANT_TABLE[ i ].name, sizeIgnored ) )
321 anchor = ANCHOR_CONSTANT_TABLE[ i ].value;
328 inline bool GetParentOriginConstant( const std::string& value, Vector3& parentOrigin )
330 // Values are the same so just use the same table as anchor-point
331 return GetAnchorPointConstant( value, parentOrigin );
335 * @brief Extract a given dimension from a Vector2
337 * @param[in] values The values to extract from
338 * @param[in] dimension The dimension to extract
339 * @return Return the value for the dimension
341 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
345 case Dimension::WIDTH:
349 case Dimension::HEIGHT:
351 return values.height;
362 * @brief Extract a given dimension from a Vector3
364 * @param[in] values The values to extract from
365 * @param[in] dimension The dimension to extract
366 * @return Return the value for the dimension
368 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
370 return GetDimensionValue( values.GetVectorXY(), dimension );
374 * @brief Recursively emits the visibility-changed-signal on the actor tree.
375 * @param[in] actor The actor to emit the signal on
376 * @param[in] visible The new visibility of the actor
377 * @param[in] type Whether the actor's visible property has changed or a parent's
379 void EmitVisibilityChangedSignalRecursively( ActorPtr actor, bool visible, DevelActor::VisibilityChange::Type type )
383 actor->EmitVisibilityChangedSignal( visible, type );
385 if( actor->GetChildCount() > 0 )
387 ActorContainer& children = actor->GetChildrenInternal();
388 for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter )
390 EmitVisibilityChangedSignalRecursively( *iter, visible, DevelActor::VisibilityChange::PARENT );
396 } // unnamed namespace
398 ActorPtr Actor::New()
400 // pass a reference to actor, actor does not own its node
401 ActorPtr actor( new Actor( BASIC, *CreateNode() ) );
403 // Second-phase construction
409 const SceneGraph::Node* Actor::CreateNode()
411 // create node. Nodes are owned by the update manager
412 SceneGraph::Node* node = SceneGraph::Node::New();
413 OwnerPointer< SceneGraph::Node > transferOwnership( node );
414 AddNodeMessage( Stage::GetCurrent()->GetUpdateManager(), transferOwnership );
419 const std::string& Actor::GetName() const
424 void Actor::SetName( const std::string& name )
428 // ATTENTION: string for debug purposes is not thread safe.
429 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( &GetNode() ), name );
432 uint32_t Actor::GetId() const
434 return GetNode().GetId();
437 bool Actor::OnStage() const
442 Dali::Layer Actor::GetLayer()
446 // Short-circuit for Layer derived actors
449 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
452 // Find the immediate Layer parent
453 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
455 if( parent->IsLayer() )
457 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
464 void Actor::Add( Actor& child )
466 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
467 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
471 mChildren = new ActorContainer;
474 Actor* const oldParent( child.mParent );
476 // child might already be ours
477 if( this != oldParent )
479 // if we already have parent, unparent us first
482 oldParent->Remove( child ); // This causes OnChildRemove callback & ChildRemoved signal
484 // Old parent may need to readjust to missing child
485 if( oldParent->RelayoutDependentOnChildren() )
487 oldParent->RelayoutRequest();
491 // Guard against Add() during previous OnChildRemove callback
494 // Do this first, since user callbacks from within SetParent() may need to remove child
495 mChildren->push_back( ActorPtr( &child ) );
497 // SetParent asserts that child can be added
498 child.SetParent( this );
500 // Notification for derived classes
502 EmitChildAddedSignal( child );
504 InheritLayoutDirectionRecursively( ActorPtr( &child ), mLayoutDirection );
506 // Only put in a relayout request if there is a suitable dependency
507 if( RelayoutDependentOnChildren() )
515 void Actor::Remove( Actor& child )
517 if( (this == &child) || (!mChildren) )
519 // no children or removing itself
525 // Find the child in mChildren, and unparent it
526 ActorIter end = mChildren->end();
527 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
529 ActorPtr actor = (*iter);
531 if( actor.Get() == &child )
533 // Keep handle for OnChildRemove notification
536 // Do this first, since user callbacks from within SetParent() may need to add the child
537 mChildren->erase( iter );
539 DALI_ASSERT_DEBUG( actor->GetParent() == this );
540 actor->SetParent( NULL );
548 // Only put in a relayout request if there is a suitable dependency
549 if( RelayoutDependentOnChildren() )
555 // Notification for derived classes
556 OnChildRemove( child );
557 EmitChildRemovedSignal( child );
560 void Actor::Unparent()
564 // Remove this actor from the parent. The remove will put a relayout request in for
565 // the parent if required
566 mParent->Remove( *this );
567 // mParent is now NULL!
571 uint32_t Actor::GetChildCount() const
573 return ( NULL != mChildren ) ? static_cast<uint32_t>( mChildren->size() ) : 0; // only 4,294,967,295 children per actor
576 ActorPtr Actor::GetChildAt( uint32_t index ) const
578 DALI_ASSERT_ALWAYS( index < GetChildCount() );
580 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
583 ActorPtr Actor::FindChildByName( const std::string& actorName )
586 if( actorName == mName )
592 ActorIter end = mChildren->end();
593 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
595 child = (*iter)->FindChildByName( actorName );
606 ActorPtr Actor::FindChildById( const uint32_t id )
615 ActorIter end = mChildren->end();
616 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
618 child = (*iter)->FindChildById( id );
629 void Actor::SetParentOrigin( const Vector3& origin )
631 // node is being used in a separate thread; queue a message to set the value & base value
632 SetParentOriginMessage( GetEventThreadServices(), GetNode(), origin );
634 // Cache for event-thread access
637 // not allocated, check if different from default
638 if( ParentOrigin::DEFAULT != origin )
640 mParentOrigin = new Vector3( origin );
645 // check if different from current costs more than just set
646 *mParentOrigin = origin;
650 void Actor::SetParentOriginX( float x )
652 const Vector3& current = GetCurrentParentOrigin();
654 SetParentOrigin( Vector3( x, current.y, current.z ) );
657 void Actor::SetParentOriginY( float y )
659 const Vector3& current = GetCurrentParentOrigin();
661 SetParentOrigin( Vector3( current.x, y, current.z ) );
664 void Actor::SetParentOriginZ( float z )
666 const Vector3& current = GetCurrentParentOrigin();
668 SetParentOrigin( Vector3( current.x, current.y, z ) );
671 const Vector3& Actor::GetCurrentParentOrigin() const
673 // Cached for event-thread access
674 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
677 void Actor::SetAnchorPoint( const Vector3& anchor )
679 // node is being used in a separate thread; queue a message to set the value & base value
680 SetAnchorPointMessage( GetEventThreadServices(), GetNode(), anchor );
682 // Cache for event-thread access
685 // not allocated, check if different from default
686 if( AnchorPoint::DEFAULT != anchor )
688 mAnchorPoint = new Vector3( anchor );
693 // check if different from current costs more than just set
694 *mAnchorPoint = anchor;
698 void Actor::SetAnchorPointX( float x )
700 const Vector3& current = GetCurrentAnchorPoint();
702 SetAnchorPoint( Vector3( x, current.y, current.z ) );
705 void Actor::SetAnchorPointY( float y )
707 const Vector3& current = GetCurrentAnchorPoint();
709 SetAnchorPoint( Vector3( current.x, y, current.z ) );
712 void Actor::SetAnchorPointZ( float z )
714 const Vector3& current = GetCurrentAnchorPoint();
716 SetAnchorPoint( Vector3( current.x, current.y, z ) );
719 const Vector3& Actor::GetCurrentAnchorPoint() const
721 // Cached for event-thread access
722 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
725 void Actor::SetPosition( float x, float y )
727 SetPosition( Vector3( x, y, 0.0f ) );
730 void Actor::SetPosition( float x, float y, float z )
732 SetPosition( Vector3( x, y, z ) );
735 void Actor::SetPosition( const Vector3& position )
737 mTargetPosition = position;
739 // node is being used in a separate thread; queue a message to set the value & base value
740 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
743 void Actor::SetX( float x )
745 mTargetPosition.x = x;
747 // node is being used in a separate thread; queue a message to set the value & base value
748 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
751 void Actor::SetY( float y )
753 mTargetPosition.y = y;
755 // node is being used in a separate thread; queue a message to set the value & base value
756 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
759 void Actor::SetZ( float z )
761 mTargetPosition.z = z;
763 // node is being used in a separate thread; queue a message to set the value & base value
764 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
767 void Actor::TranslateBy( const Vector3& distance )
769 mTargetPosition += distance;
771 // node is being used in a separate thread; queue a message to set the value & base value
772 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
775 const Vector3& Actor::GetCurrentPosition() const
777 // node is being used in a separate thread; copy the value from the previous update
778 return GetNode().GetPosition(GetEventThreadServices().GetEventBufferIndex());
781 const Vector3& Actor::GetTargetPosition() const
783 return mTargetPosition;
786 const Vector3& Actor::GetCurrentWorldPosition() const
788 // node is being used in a separate thread; copy the value from the previous update
789 return GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
792 const Vector2 Actor::GetCurrentScreenPosition() const
794 StagePtr stage = Stage::GetCurrent();
795 if( stage && OnStage() )
797 Vector3 worldPosition = GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
798 Vector3 cameraPosition = stage->GetDefaultCameraActor().GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
799 worldPosition -= cameraPosition;
801 Vector3 actorSize = GetCurrentSize() * GetCurrentWorldScale();
802 Vector2 halfStageSize( stage->GetSize() * 0.5f ); // World position origin is center of stage
803 Vector3 halfActorSize( actorSize * 0.5f );
804 Vector3 anchorPointOffSet = halfActorSize - actorSize * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
806 return Vector2( halfStageSize.width + worldPosition.x - anchorPointOffSet.x,
807 halfStageSize.height + worldPosition.y - anchorPointOffSet.y );
810 return Vector2::ZERO;
813 void Actor::SetInheritPosition( bool inherit )
815 if( mInheritPosition != inherit )
817 // non animatable so keep local copy
818 mInheritPosition = inherit;
819 SetInheritPositionMessage( GetEventThreadServices(), GetNode(), inherit );
823 bool Actor::IsPositionInherited() const
825 return mInheritPosition;
828 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
830 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
831 normalizedAxis.Normalize();
833 Quaternion orientation( angle, normalizedAxis );
835 SetOrientation( orientation );
838 void Actor::SetOrientation( const Quaternion& orientation )
840 mTargetOrientation = orientation;
842 // node is being used in a separate thread; queue a message to set the value & base value
843 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation );
846 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
848 RotateBy( Quaternion(angle, axis) );
851 void Actor::RotateBy( const Quaternion& relativeRotation )
853 mTargetOrientation *= Quaternion( relativeRotation );
855 // node is being used in a separate thread; queue a message to set the value & base value
856 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
859 const Quaternion& Actor::GetCurrentOrientation() const
861 // node is being used in a separate thread; copy the value from the previous update
862 return GetNode().GetOrientation(GetEventThreadServices().GetEventBufferIndex());
865 const Quaternion& Actor::GetCurrentWorldOrientation() const
867 // node is being used in a separate thread; copy the value from the previous update
868 return GetNode().GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
871 void Actor::SetScale( float scale )
873 SetScale( Vector3( scale, scale, scale ) );
876 void Actor::SetScale( float x, float y, float z )
878 SetScale( Vector3( x, y, z ) );
881 void Actor::SetScale( const Vector3& scale )
883 mTargetScale = scale;
885 // node is being used in a separate thread; queue a message to set the value & base value
886 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
889 void Actor::SetScaleX( float x )
893 // node is being used in a separate thread; queue a message to set the value & base value
894 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
897 void Actor::SetScaleY( float y )
901 // node is being used in a separate thread; queue a message to set the value & base value
902 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
905 void Actor::SetScaleZ( float z )
909 // node is being used in a separate thread; queue a message to set the value & base value
910 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
913 void Actor::ScaleBy(const Vector3& relativeScale)
915 mTargetScale *= relativeScale;
917 // node is being used in a separate thread; queue a message to set the value & base value
918 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
921 const Vector3& Actor::GetCurrentScale() const
923 // node is being used in a separate thread; copy the value from the previous update
924 return GetNode().GetScale(GetEventThreadServices().GetEventBufferIndex());
927 const Vector3& Actor::GetCurrentWorldScale() const
929 // node is being used in a separate thread; copy the value from the previous update
930 return GetNode().GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
933 void Actor::SetInheritScale( bool inherit )
935 if( mInheritScale != inherit )
937 // non animatable so keep local copy
938 mInheritScale = inherit;
939 // node is being used in a separate thread; queue a message to set the value
940 SetInheritScaleMessage( GetEventThreadServices(), GetNode(), inherit );
944 bool Actor::IsScaleInherited() const
946 return mInheritScale;
949 Matrix Actor::GetCurrentWorldMatrix() const
951 return GetNode().GetWorldMatrix(0);
954 void Actor::SetVisible( bool visible )
956 SetVisibleInternal( visible, SendMessage::TRUE );
959 bool Actor::IsVisible() const
961 // node is being used in a separate thread; copy the value from the previous update
962 return GetNode().IsVisible( GetEventThreadServices().GetEventBufferIndex() );
965 void Actor::SetOpacity( float opacity )
967 mTargetColor.a = opacity;
969 // node is being used in a separate thread; queue a message to set the value & base value
970 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
973 float Actor::GetCurrentOpacity() const
975 // node is being used in a separate thread; copy the value from the previous update
976 return GetNode().GetOpacity(GetEventThreadServices().GetEventBufferIndex());
979 ClippingMode::Type Actor::GetClippingMode() const
981 return mClippingMode;
984 uint32_t Actor::GetSortingDepth()
989 const Vector4& Actor::GetCurrentWorldColor() const
991 return GetNode().GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
994 void Actor::SetColor( const Vector4& color )
996 mTargetColor = color;
998 // node is being used in a separate thread; queue a message to set the value & base value
999 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::Bake, color );
1002 void Actor::SetColorRed( float red )
1004 mTargetColor.r = red;
1006 // node is being used in a separate thread; queue a message to set the value & base value
1007 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeX, red );
1010 void Actor::SetColorGreen( float green )
1012 mTargetColor.g = green;
1014 // node is being used in a separate thread; queue a message to set the value & base value
1015 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeY, green );
1018 void Actor::SetColorBlue( float blue )
1020 mTargetColor.b = blue;
1022 // node is being used in a separate thread; queue a message to set the value & base value
1023 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1026 const Vector4& Actor::GetCurrentColor() const
1028 // node is being used in a separate thread; copy the value from the previous update
1029 return GetNode().GetColor(GetEventThreadServices().GetEventBufferIndex());
1032 void Actor::SetInheritOrientation( bool inherit )
1034 if( mInheritOrientation != inherit )
1036 // non animatable so keep local copy
1037 mInheritOrientation = inherit;
1038 // node is being used in a separate thread; queue a message to set the value
1039 SetInheritOrientationMessage( GetEventThreadServices(), GetNode(), inherit );
1043 bool Actor::IsOrientationInherited() const
1045 return mInheritOrientation;
1048 void Actor::SetSizeModeFactor( const Vector3& factor )
1050 EnsureRelayoutData();
1052 mRelayoutData->sizeModeFactor = factor;
1055 const Vector3& Actor::GetSizeModeFactor() const
1057 if ( mRelayoutData )
1059 return mRelayoutData->sizeModeFactor;
1062 return GetDefaultSizeModeFactor();
1065 void Actor::SetColorMode( ColorMode colorMode )
1067 // non animatable so keep local copy
1068 mColorMode = colorMode;
1069 // node is being used in a separate thread; queue a message to set the value
1070 SetColorModeMessage( GetEventThreadServices(), GetNode(), colorMode );
1073 ColorMode Actor::GetColorMode() const
1075 // we have cached copy
1079 void Actor::SetSize( float width, float height )
1081 SetSize( Vector2( width, height ) );
1084 void Actor::SetSize( float width, float height, float depth )
1086 SetSize( Vector3( width, height, depth ) );
1089 void Actor::SetSize( const Vector2& size )
1091 SetSize( Vector3( size.width, size.height, 0.f ) );
1094 void Actor::SetSizeInternal( const Vector2& size )
1096 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1099 void Actor::SetSize( const Vector3& size )
1101 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1103 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1104 SetPreferredSize( size.GetVectorXY() );
1108 SetSizeInternal( size );
1112 void Actor::SetSizeInternal( const Vector3& size )
1114 // dont allow recursive loop
1115 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1116 // 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
1117 if( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1118 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1119 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) )
1123 // node is being used in a separate thread; queue a message to set the value & base value
1124 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
1126 // Notification for derived classes
1127 mInsideOnSizeSet = true;
1128 OnSizeSet( mTargetSize );
1129 mInsideOnSizeSet = false;
1131 // Raise a relayout request if the flag is not locked
1132 if( mRelayoutData && !mRelayoutData->insideRelayout )
1139 void Actor::SetWidth( float width )
1141 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1143 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
1144 mRelayoutData->preferredSize.width = width;
1148 mTargetSize.width = width;
1150 // node is being used in a separate thread; queue a message to set the value & base value
1151 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1157 void Actor::SetHeight( float height )
1159 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1161 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
1162 mRelayoutData->preferredSize.height = height;
1166 mTargetSize.height = height;
1168 // node is being used in a separate thread; queue a message to set the value & base value
1169 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1175 void Actor::SetDepth( float depth )
1177 mTargetSize.depth = depth;
1179 // node is being used in a separate thread; queue a message to set the value & base value
1180 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1183 Vector3 Actor::GetTargetSize() const
1185 Vector3 size = mTargetSize;
1187 // Should return preferred size if size is fixed as set by SetSize
1188 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
1190 size.width = GetPreferredSize().width;
1192 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
1194 size.height = GetPreferredSize().height;
1200 const Vector3& Actor::GetCurrentSize() const
1202 // node is being used in a separate thread; copy the value from the previous update
1203 return GetNode().GetSize( GetEventThreadServices().GetEventBufferIndex() );
1206 Vector3 Actor::GetNaturalSize() const
1208 // It is up to deriving classes to return the appropriate natural size
1209 return Vector3( 0.0f, 0.0f, 0.0f );
1212 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1214 EnsureRelayoutData();
1216 ResizePolicy::Type originalWidthPolicy = GetResizePolicy(Dimension::WIDTH);
1217 ResizePolicy::Type originalHeightPolicy = GetResizePolicy(Dimension::HEIGHT);
1219 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1221 if( dimension & ( 1 << i ) )
1223 if ( policy == ResizePolicy::USE_ASSIGNED_SIZE )
1225 mRelayoutData->useAssignedSize[ i ] = true;
1229 mRelayoutData->resizePolicies[ i ] = policy;
1230 mRelayoutData->useAssignedSize[ i ] = false;
1235 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1237 if( dimension & Dimension::WIDTH )
1239 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1242 if( dimension & Dimension::HEIGHT )
1244 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1248 // If calling SetResizePolicy, assume we want relayout enabled
1249 SetRelayoutEnabled( true );
1251 // If the resize policy is set to be FIXED, the preferred size
1252 // should be overrided by the target size. Otherwise the target
1253 // size should be overrided by the preferred size.
1255 if( dimension & Dimension::WIDTH )
1257 if( originalWidthPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1259 mRelayoutData->preferredSize.width = mTargetSize.width;
1261 else if( originalWidthPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1263 mTargetSize.width = mRelayoutData->preferredSize.width;
1267 if( dimension & Dimension::HEIGHT )
1269 if( originalHeightPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1271 mRelayoutData->preferredSize.height = mTargetSize.height;
1273 else if( originalHeightPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1275 mTargetSize.height = mRelayoutData->preferredSize.height;
1279 OnSetResizePolicy( policy, dimension );
1281 // Trigger relayout on this control
1285 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1287 if ( mRelayoutData )
1289 // If more than one dimension is requested, just return the first one found
1290 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1292 if( ( dimension & ( 1 << i ) ) )
1294 if( mRelayoutData->useAssignedSize[ i ] )
1296 return ResizePolicy::USE_ASSIGNED_SIZE;
1300 return mRelayoutData->resizePolicies[ i ];
1306 return ResizePolicy::DEFAULT;
1309 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1311 EnsureRelayoutData();
1313 mRelayoutData->sizeSetPolicy = policy;
1316 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1318 if ( mRelayoutData )
1320 return mRelayoutData->sizeSetPolicy;
1323 return DEFAULT_SIZE_SCALE_POLICY;
1326 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1328 EnsureRelayoutData();
1330 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1332 if( dimension & ( 1 << i ) )
1334 mRelayoutData->dimensionDependencies[ i ] = dependency;
1339 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1341 if ( mRelayoutData )
1343 // If more than one dimension is requested, just return the first one found
1344 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1346 if( ( dimension & ( 1 << i ) ) )
1348 return mRelayoutData->dimensionDependencies[ i ];
1353 return Dimension::ALL_DIMENSIONS; // Default
1356 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1358 // If relayout data has not been allocated yet and the client is requesting
1359 // to disable it, do nothing
1360 if( mRelayoutData || relayoutEnabled )
1362 EnsureRelayoutData();
1364 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1366 mRelayoutData->relayoutEnabled = relayoutEnabled;
1370 bool Actor::IsRelayoutEnabled() const
1372 // Assume that if relayout data has not been allocated yet then
1373 // relayout is disabled
1374 return mRelayoutData && mRelayoutData->relayoutEnabled;
1377 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1379 EnsureRelayoutData();
1381 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1383 if( dimension & ( 1 << i ) )
1385 mRelayoutData->dimensionDirty[ i ] = dirty;
1390 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1392 if ( mRelayoutData )
1394 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1396 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1406 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1408 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1411 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1413 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1416 uint32_t Actor::AddRenderer( Renderer& renderer )
1420 mRenderers = new RendererContainer;
1423 uint32_t index = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1424 RendererPtr rendererPtr = RendererPtr( &renderer );
1425 mRenderers->push_back( rendererPtr );
1426 AttachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1430 uint32_t Actor::GetRendererCount() const
1432 uint32_t rendererCount(0);
1435 rendererCount = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1438 return rendererCount;
1441 RendererPtr Actor::GetRendererAt( uint32_t index )
1443 RendererPtr renderer;
1444 if( index < GetRendererCount() )
1446 renderer = ( *mRenderers )[ index ];
1452 void Actor::RemoveRenderer( Renderer& renderer )
1456 RendererIter end = mRenderers->end();
1457 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1459 if( (*iter).Get() == &renderer )
1461 mRenderers->erase( iter );
1462 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1469 void Actor::RemoveRenderer( uint32_t index )
1471 if( index < GetRendererCount() )
1473 RendererPtr renderer = ( *mRenderers )[ index ];
1474 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.Get()->GetRendererSceneObject() );
1475 mRenderers->erase( mRenderers->begin()+index );
1479 bool Actor::IsOverlay() const
1481 return ( DrawMode::OVERLAY_2D == mDrawMode );
1484 void Actor::SetDrawMode( DrawMode::Type drawMode )
1486 // this flag is not animatable so keep the value
1487 mDrawMode = drawMode;
1489 // node is being used in a separate thread; queue a message to set the value
1490 SetDrawModeMessage( GetEventThreadServices(), GetNode(), drawMode );
1493 DrawMode::Type Actor::GetDrawMode() const
1498 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1500 // only valid when on-stage
1501 StagePtr stage = Stage::GetCurrent();
1502 if( stage && OnStage() )
1504 const RenderTaskList& taskList = stage->GetRenderTaskList();
1506 Vector2 converted( screenX, screenY );
1508 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1509 uint32_t taskCount = taskList.GetTaskCount();
1510 for( uint32_t i = taskCount; i > 0; --i )
1512 RenderTaskPtr task = taskList.GetTask( i - 1 );
1513 if( ScreenToLocal( *task, localX, localY, screenX, screenY ) )
1515 // found a task where this conversion was ok so return
1523 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1525 bool retval = false;
1526 // only valid when on-stage
1529 CameraActor* camera = renderTask.GetCameraActor();
1533 renderTask.GetViewport( viewport );
1535 // need to translate coordinates to render tasks coordinate space
1536 Vector2 converted( screenX, screenY );
1537 if( renderTask.TranslateCoordinates( converted ) )
1539 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1546 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1548 // Early-out if not on stage
1554 // Get the ModelView matrix
1556 Matrix::Multiply( modelView, GetNode().GetWorldMatrix(0), viewMatrix );
1558 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1559 Matrix invertedMvp( false/*don't init*/);
1560 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1561 bool success = invertedMvp.Invert();
1563 // Convert to GL coordinates
1564 Vector4 screenPos( screenX - static_cast<float>( viewport.x ), static_cast<float>( viewport.height ) - screenY - static_cast<float>( viewport.y ), 0.f, 1.f );
1569 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), nearPos );
1576 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), farPos );
1582 if( XyPlaneIntersect( nearPos, farPos, local ) )
1584 Vector3 size = GetCurrentSize();
1585 localX = local.x + size.x * 0.5f;
1586 localY = local.y + size.y * 0.5f;
1597 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1600 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1602 Mathematical Formulation
1604 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1606 ( p - c ) dot ( p - c ) = r^2
1608 Given a ray with a point of origin 'o', and a direction vector 'd':
1610 ray(t) = o + td, t >= 0
1612 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1614 (o + td - c ) dot ( o + td - c ) = r^2
1616 To solve for t we first expand the above into a more recognisable quadratic equation form
1618 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1627 B = 2( o - c ) dot d
1628 C = ( o - c ) dot ( o - c ) - r^2
1630 which can be solved using a standard quadratic formula.
1632 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1634 Practical Simplification
1636 In a renderer, we often differentiate between world space and object space. In the object space
1637 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1638 into object space, the mathematical solution presented above can be simplified significantly.
1640 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1644 and we can find the t at which the (transformed) ray intersects the sphere by
1646 ( o + td ) dot ( o + td ) = r^2
1648 According to the reasoning above, we expand the above quadratic equation into the general form
1652 which now has coefficients:
1659 // Early-out if not on stage
1665 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1667 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1668 const Vector3& translation( GetNode().GetWorldPosition( bufferIndex ) );
1669 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1671 // Compute the radius is not needed, square radius it's enough.
1672 const Vector3& size( GetNode().GetSize( bufferIndex ) );
1674 // Scale the sphere.
1675 const Vector3& scale( GetNode().GetWorldScale( bufferIndex ) );
1677 const float width = size.width * scale.width;
1678 const float height = size.height * scale.height;
1680 float squareSphereRadius = 0.5f * ( width * width + height * height );
1682 float a = rayDir.Dot( rayDir ); // a
1683 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1684 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1686 return ( b2 * b2 - a * c ) >= 0.f;
1689 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector2& hitPointLocal, float& distance ) const
1695 // Transforms the ray to the local reference system.
1696 // Calculate the inverse of Model matrix
1697 Matrix invModelMatrix( false/*don't init*/);
1699 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1700 invModelMatrix = GetNode().GetWorldMatrix(0);
1701 invModelMatrix.Invert();
1703 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1704 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1706 // Test with the actor's XY plane (Normal = 0 0 1 1).
1708 float a = -rayOriginLocal.z;
1709 float b = rayDirLocal.z;
1711 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1713 // Ray travels distance * rayDirLocal to intersect with plane.
1716 const Vector3& size = GetNode().GetSize( bufferIndex );
1718 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1719 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1721 // Test with the actor's geometry.
1722 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1729 void Actor::SetLeaveRequired( bool required )
1731 mLeaveRequired = required;
1734 bool Actor::GetLeaveRequired() const
1736 return mLeaveRequired;
1739 void Actor::SetKeyboardFocusable( bool focusable )
1741 mKeyboardFocusable = focusable;
1744 bool Actor::IsKeyboardFocusable() const
1746 return mKeyboardFocusable;
1749 bool Actor::GetTouchRequired() const
1751 return !mTouchedSignal.Empty() || !mTouchSignal.Empty() || mDerivedRequiresTouch;
1754 bool Actor::GetHoverRequired() const
1756 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1759 bool Actor::GetWheelEventRequired() const
1761 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1764 bool Actor::IsHittable() const
1766 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1769 ActorGestureData& Actor::GetGestureData()
1771 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1772 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1773 if( NULL == mGestureData )
1775 mGestureData = new ActorGestureData;
1777 return *mGestureData;
1780 bool Actor::IsGestureRequred( Gesture::Type type ) const
1782 return mGestureData && mGestureData->IsGestureRequred( type );
1785 bool Actor::EmitTouchEventSignal( const TouchEvent& event, const Dali::TouchData& touch )
1787 bool consumed = false;
1789 if( !mTouchSignal.Empty() )
1791 Dali::Actor handle( this );
1792 consumed = mTouchSignal.Emit( handle, touch );
1795 if( !mTouchedSignal.Empty() )
1797 Dali::Actor handle( this );
1798 consumed |= mTouchedSignal.Emit( handle, event );
1803 // Notification for derived classes
1804 consumed = OnTouchEvent( event ); // TODO
1810 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1812 bool consumed = false;
1814 if( !mHoveredSignal.Empty() )
1816 Dali::Actor handle( this );
1817 consumed = mHoveredSignal.Emit( handle, event );
1822 // Notification for derived classes
1823 consumed = OnHoverEvent( event );
1829 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1831 bool consumed = false;
1833 if( !mWheelEventSignal.Empty() )
1835 Dali::Actor handle( this );
1836 consumed = mWheelEventSignal.Emit( handle, event );
1841 // Notification for derived classes
1842 consumed = OnWheelEvent( event );
1848 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
1850 if( ! mVisibilityChangedSignal.Empty() )
1852 Dali::Actor handle( this );
1853 mVisibilityChangedSignal.Emit( handle, visible, type );
1857 void Actor::EmitLayoutDirectionChangedSignal( LayoutDirection::Type type )
1859 if( ! mLayoutDirectionChangedSignal.Empty() )
1861 Dali::Actor handle( this );
1862 mLayoutDirectionChangedSignal.Emit( handle, type );
1866 void Actor::EmitChildAddedSignal( Actor& child )
1868 if( ! mChildAddedSignal.Empty() )
1870 Dali::Actor handle( &child );
1871 mChildAddedSignal.Emit( handle );
1875 void Actor::EmitChildRemovedSignal( Actor& child )
1877 if( ! mChildRemovedSignal.Empty() )
1879 Dali::Actor handle( &child );
1880 mChildRemovedSignal.Emit( handle );
1884 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
1886 return mTouchedSignal;
1889 Dali::Actor::TouchDataSignalType& Actor::TouchSignal()
1891 return mTouchSignal;
1894 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
1896 return mHoveredSignal;
1899 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
1901 return mWheelEventSignal;
1904 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
1906 return mOnStageSignal;
1909 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
1911 return mOffStageSignal;
1914 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
1916 return mOnRelayoutSignal;
1919 DevelActor::VisibilityChangedSignalType& Actor::VisibilityChangedSignal()
1921 return mVisibilityChangedSignal;
1924 Dali::Actor::LayoutDirectionChangedSignalType& Actor::LayoutDirectionChangedSignal()
1926 return mLayoutDirectionChangedSignal;
1929 DevelActor::ChildChangedSignalType& Actor::ChildAddedSignal()
1931 return mChildAddedSignal;
1934 DevelActor::ChildChangedSignalType& Actor::ChildRemovedSignal()
1936 return mChildRemovedSignal;
1939 DevelActor::ChildOrderChangedSignalType& Actor::ChildOrderChangedSignal()
1941 return mChildOrderChangedSignal;
1944 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1946 bool connected( true );
1947 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
1949 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1951 actor->TouchedSignal().Connect( tracker, functor );
1953 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1955 actor->HoveredSignal().Connect( tracker, functor );
1957 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1959 actor->WheelEventSignal().Connect( tracker, functor );
1961 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
1963 actor->OnStageSignal().Connect( tracker, functor );
1965 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
1967 actor->OffStageSignal().Connect( tracker, functor );
1969 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
1971 actor->OnRelayoutSignal().Connect( tracker, functor );
1973 else if( 0 == signalName.compare( SIGNAL_TOUCH ) )
1975 actor->TouchSignal().Connect( tracker, functor );
1977 else if( 0 == signalName.compare( SIGNAL_VISIBILITY_CHANGED ) )
1979 actor->VisibilityChangedSignal().Connect( tracker, functor );
1981 else if( 0 == signalName.compare( SIGNAL_LAYOUT_DIRECTION_CHANGED ) )
1983 actor->LayoutDirectionChangedSignal().Connect( tracker, functor );
1985 else if( 0 == signalName.compare( SIGNAL_CHILD_ADDED ) )
1987 actor->ChildAddedSignal().Connect( tracker, functor );
1989 else if( 0 == signalName.compare( SIGNAL_CHILD_REMOVED ) )
1991 actor->ChildRemovedSignal().Connect( tracker, functor );
1995 // signalName does not match any signal
2002 Actor::Actor( DerivedType derivedType, const SceneGraph::Node& node )
2007 mParentOrigin( NULL ),
2008 mAnchorPoint( NULL ),
2009 mRelayoutData( NULL ),
2010 mGestureData( NULL ),
2014 mWheelEventSignal(),
2017 mOnRelayoutSignal(),
2018 mVisibilityChangedSignal(),
2019 mLayoutDirectionChangedSignal(),
2020 mChildAddedSignal(),
2021 mChildRemovedSignal(),
2022 mChildOrderChangedSignal(),
2023 mTargetOrientation( Quaternion::IDENTITY ),
2024 mTargetColor( Color::WHITE ),
2025 mTargetSize( Vector3::ZERO ),
2026 mTargetPosition( Vector3::ZERO ),
2027 mTargetScale( Vector3::ONE ),
2031 mIsRoot( ROOT_LAYER == derivedType ),
2032 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2033 mIsOnStage( false ),
2035 mLeaveRequired( false ),
2036 mKeyboardFocusable( false ),
2037 mDerivedRequiresTouch( false ),
2038 mDerivedRequiresHover( false ),
2039 mDerivedRequiresWheelEvent( false ),
2040 mOnStageSignalled( false ),
2041 mInsideOnSizeSet( false ),
2042 mInheritPosition( true ),
2043 mInheritOrientation( true ),
2044 mInheritScale( true ),
2045 mPositionUsesAnchorPoint( true ),
2047 mInheritLayoutDirection( true ),
2048 mLayoutDirection( LayoutDirection::LEFT_TO_RIGHT ),
2049 mDrawMode( DrawMode::NORMAL ),
2050 mColorMode( Node::DEFAULT_COLOR_MODE ),
2051 mClippingMode( ClippingMode::DISABLED )
2055 void Actor::Initialize()
2059 GetEventThreadServices().RegisterObject( this );
2064 // Remove mParent pointers from children even if we're destroying core,
2065 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2068 ActorConstIter endIter = mChildren->end();
2069 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2071 (*iter)->SetParent( NULL );
2077 // Guard to allow handle destruction after Core has been destroyed
2078 if( EventThreadServices::IsCoreRunning() )
2080 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
2082 GetEventThreadServices().UnregisterObject( this );
2085 // Cleanup optional gesture data
2086 delete mGestureData;
2088 // Cleanup optional parent origin and anchor
2089 delete mParentOrigin;
2090 delete mAnchorPoint;
2092 // Delete optional relayout data
2093 delete mRelayoutData;
2096 void Actor::ConnectToStage( uint32_t parentDepth )
2098 // This container is used instead of walking the Actor hierarchy.
2099 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
2100 ActorContainer connectionList;
2102 StagePtr stage = Stage::GetCurrent();
2105 stage->RequestRebuildDepthTree();
2108 // This stage is atomic i.e. not interrupted by user callbacks.
2109 RecursiveConnectToStage( connectionList, parentDepth + 1 );
2111 // Notify applications about the newly connected actors.
2112 const ActorIter endIter = connectionList.end();
2113 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2115 (*iter)->NotifyStageConnection();
2121 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, uint32_t depth )
2123 DALI_ASSERT_ALWAYS( !OnStage() );
2126 mDepth = static_cast< uint16_t >( depth ); // overflow ignored, not expected in practice
2128 ConnectToSceneGraph();
2130 // Notification for internal derived classes
2131 OnStageConnectionInternal();
2133 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2134 connectionList.push_back( ActorPtr( this ) );
2136 // Recursively connect children
2139 ActorConstIter endIter = mChildren->end();
2140 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2142 (*iter)->RecursiveConnectToStage( connectionList, depth + 1 );
2148 * This method is called when the Actor is connected to the Stage.
2149 * The parent must have added its Node to the scene-graph.
2150 * The child must connect its Node to the parent's Node.
2151 * This is recursive; the child calls ConnectToStage() for its children.
2153 void Actor::ConnectToSceneGraph()
2155 DALI_ASSERT_DEBUG( mParent != NULL);
2157 // Reparent Node in next Update
2158 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), mParent->GetNode(), GetNode() );
2160 // Request relayout on all actors that are added to the scenegraph
2163 // Notification for Object::Observers
2167 void Actor::NotifyStageConnection()
2169 // Actors can be removed (in a callback), before the on-stage stage is reported.
2170 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2171 if( OnStage() && !mOnStageSignalled )
2173 // Notification for external (CustomActor) derived classes
2174 OnStageConnectionExternal( mDepth );
2176 if( !mOnStageSignal.Empty() )
2178 Dali::Actor handle( this );
2179 mOnStageSignal.Emit( handle );
2182 // Guard against Remove during callbacks
2185 mOnStageSignalled = true; // signal required next time Actor is removed
2190 void Actor::DisconnectFromStage()
2192 // This container is used instead of walking the Actor hierachy.
2193 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2194 ActorContainer disconnectionList;
2196 StagePtr stage = Stage::GetCurrent();
2199 stage->RequestRebuildDepthTree();
2202 // This stage is atomic i.e. not interrupted by user callbacks
2203 RecursiveDisconnectFromStage( disconnectionList );
2205 // Notify applications about the newly disconnected actors.
2206 const ActorIter endIter = disconnectionList.end();
2207 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2209 (*iter)->NotifyStageDisconnection();
2213 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2215 // need to change state first so that internals relying on IsOnStage() inside OnStageDisconnectionInternal() get the correct value
2218 // Recursively disconnect children
2221 ActorConstIter endIter = mChildren->end();
2222 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2224 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2228 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2229 disconnectionList.push_back( ActorPtr( this ) );
2231 // Notification for internal derived classes
2232 OnStageDisconnectionInternal();
2234 DisconnectFromSceneGraph();
2238 * This method is called by an actor or its parent, before a node removal message is sent.
2239 * This is recursive; the child calls DisconnectFromStage() for its children.
2241 void Actor::DisconnectFromSceneGraph()
2243 // Notification for Object::Observers
2244 OnSceneObjectRemove();
2247 void Actor::NotifyStageDisconnection()
2249 // Actors can be added (in a callback), before the off-stage state is reported.
2250 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2251 // only do this step if there is a stage, i.e. Core is not being shut down
2252 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2254 // Notification for external (CustomeActor) derived classes
2255 OnStageDisconnectionExternal();
2257 if( !mOffStageSignal.Empty() )
2259 Dali::Actor handle( this );
2260 mOffStageSignal.Emit( handle );
2263 // Guard against Add during callbacks
2266 mOnStageSignalled = false; // signal required next time Actor is added
2271 bool Actor::IsNodeConnected() const
2273 bool connected( false );
2277 if( IsRoot() || GetNode().GetParent() )
2286 // This method initiates traversal of the actor tree using depth-first
2287 // traversal to set a depth index based on traversal order. It sends a
2288 // single message to update manager to update all the actor's nodes in
2289 // this tree with the depth index. The sceneGraphNodeDepths vector's
2290 // elements are ordered by depth, and could be used to reduce sorting
2291 // in the update thread.
2292 void Actor::RebuildDepthTree()
2294 DALI_LOG_TIMER_START(depthTimer);
2296 // Vector of scene-graph nodes and their depths to send to UpdateManager
2297 // in a single message
2298 OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths( new SceneGraph::NodeDepths() );
2300 int32_t depthIndex = 1;
2301 DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
2303 SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths );
2304 DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
2307 void Actor::DepthTraverseActorTree( OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths, int32_t& depthIndex )
2309 mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
2310 sceneGraphNodeDepths->Add( const_cast<SceneGraph::Node*>( &GetNode() ), mSortedDepth );
2312 // Create/add to children of this node
2315 for( ActorContainer::iterator it = mChildren->begin(); it != mChildren->end(); ++it )
2317 Actor* childActor = (*it).Get();
2319 childActor->DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
2324 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2328 case Dali::Actor::Property::PARENT_ORIGIN:
2330 Property::Type type = property.GetType();
2331 if( type == Property::VECTOR3 )
2333 SetParentOrigin( property.Get< Vector3 >() );
2335 else if ( type == Property::STRING )
2337 std::string parentOriginString;
2338 property.Get( parentOriginString );
2339 Vector3 parentOrigin;
2340 if( GetParentOriginConstant( parentOriginString, parentOrigin ) )
2342 SetParentOrigin( parentOrigin );
2348 case Dali::Actor::Property::PARENT_ORIGIN_X:
2350 SetParentOriginX( property.Get< float >() );
2354 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2356 SetParentOriginY( property.Get< float >() );
2360 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2362 SetParentOriginZ( property.Get< float >() );
2366 case Dali::Actor::Property::ANCHOR_POINT:
2368 Property::Type type = property.GetType();
2369 if( type == Property::VECTOR3 )
2371 SetAnchorPoint( property.Get< Vector3 >() );
2373 else if ( type == Property::STRING )
2375 std::string anchorPointString;
2376 property.Get( anchorPointString );
2378 if( GetAnchorPointConstant( anchorPointString, anchor ) )
2380 SetAnchorPoint( anchor );
2386 case Dali::Actor::Property::ANCHOR_POINT_X:
2388 SetAnchorPointX( property.Get< float >() );
2392 case Dali::Actor::Property::ANCHOR_POINT_Y:
2394 SetAnchorPointY( property.Get< float >() );
2398 case Dali::Actor::Property::ANCHOR_POINT_Z:
2400 SetAnchorPointZ( property.Get< float >() );
2404 case Dali::Actor::Property::SIZE:
2406 SetSize( property.Get< Vector3 >() );
2410 case Dali::Actor::Property::SIZE_WIDTH:
2412 SetWidth( property.Get< float >() );
2416 case Dali::Actor::Property::SIZE_HEIGHT:
2418 SetHeight( property.Get< float >() );
2422 case Dali::Actor::Property::SIZE_DEPTH:
2424 SetDepth( property.Get< float >() );
2428 case Dali::Actor::Property::POSITION:
2430 SetPosition( property.Get< Vector3 >() );
2434 case Dali::Actor::Property::POSITION_X:
2436 SetX( property.Get< float >() );
2440 case Dali::Actor::Property::POSITION_Y:
2442 SetY( property.Get< float >() );
2446 case Dali::Actor::Property::POSITION_Z:
2448 SetZ( property.Get< float >() );
2452 case Dali::Actor::Property::ORIENTATION:
2454 SetOrientation( property.Get< Quaternion >() );
2458 case Dali::Actor::Property::SCALE:
2460 SetScale( property.Get< Vector3 >() );
2464 case Dali::Actor::Property::SCALE_X:
2466 SetScaleX( property.Get< float >() );
2470 case Dali::Actor::Property::SCALE_Y:
2472 SetScaleY( property.Get< float >() );
2476 case Dali::Actor::Property::SCALE_Z:
2478 SetScaleZ( property.Get< float >() );
2482 case Dali::Actor::Property::VISIBLE:
2484 SetVisible( property.Get< bool >() );
2488 case Dali::Actor::Property::COLOR:
2490 SetColor( property.Get< Vector4 >() );
2494 case Dali::Actor::Property::COLOR_RED:
2496 SetColorRed( property.Get< float >() );
2500 case Dali::Actor::Property::COLOR_GREEN:
2502 SetColorGreen( property.Get< float >() );
2506 case Dali::Actor::Property::COLOR_BLUE:
2508 SetColorBlue( property.Get< float >() );
2512 case Dali::Actor::Property::COLOR_ALPHA:
2513 case Dali::DevelActor::Property::OPACITY:
2516 if( property.Get( value ) )
2518 SetOpacity( value );
2523 case Dali::Actor::Property::NAME:
2525 SetName( property.Get< std::string >() );
2529 case Dali::Actor::Property::SENSITIVE:
2531 SetSensitive( property.Get< bool >() );
2535 case Dali::Actor::Property::LEAVE_REQUIRED:
2537 SetLeaveRequired( property.Get< bool >() );
2541 case Dali::Actor::Property::INHERIT_POSITION:
2543 SetInheritPosition( property.Get< bool >() );
2547 case Dali::Actor::Property::INHERIT_ORIENTATION:
2549 SetInheritOrientation( property.Get< bool >() );
2553 case Dali::Actor::Property::INHERIT_SCALE:
2555 SetInheritScale( property.Get< bool >() );
2559 case Dali::Actor::Property::COLOR_MODE:
2561 ColorMode mode = mColorMode;
2562 if ( Scripting::GetEnumerationProperty< ColorMode >( property, COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT, mode ) )
2564 SetColorMode( mode );
2569 case Dali::Actor::Property::DRAW_MODE:
2571 DrawMode::Type mode = mDrawMode;
2572 if( Scripting::GetEnumerationProperty< DrawMode::Type >( property, DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT, mode ) )
2574 SetDrawMode( mode );
2579 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2581 SetSizeModeFactor( property.Get< Vector3 >() );
2585 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2587 ResizePolicy::Type type = GetResizePolicy( Dimension::WIDTH );
2588 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2590 SetResizePolicy( type, Dimension::WIDTH );
2595 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2597 ResizePolicy::Type type = GetResizePolicy( Dimension::HEIGHT );
2598 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2600 SetResizePolicy( type, Dimension::HEIGHT );
2605 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2607 SizeScalePolicy::Type type = GetSizeScalePolicy();
2608 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT, type ) )
2610 SetSizeScalePolicy( type );
2615 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2617 if( property.Get< bool >() )
2619 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2624 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2626 if( property.Get< bool >() )
2628 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2633 case Dali::Actor::Property::PADDING:
2635 Vector4 padding = property.Get< Vector4 >();
2636 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2637 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2641 case Dali::Actor::Property::MINIMUM_SIZE:
2643 Vector2 size = property.Get< Vector2 >();
2644 SetMinimumSize( size.x, Dimension::WIDTH );
2645 SetMinimumSize( size.y, Dimension::HEIGHT );
2649 case Dali::Actor::Property::MAXIMUM_SIZE:
2651 Vector2 size = property.Get< Vector2 >();
2652 SetMaximumSize( size.x, Dimension::WIDTH );
2653 SetMaximumSize( size.y, Dimension::HEIGHT );
2657 case Dali::DevelActor::Property::SIBLING_ORDER:
2661 if( property.Get( value ) )
2663 SetSiblingOrder( value );
2668 case Dali::Actor::Property::CLIPPING_MODE:
2670 ClippingMode::Type convertedValue = mClippingMode;
2671 if( Scripting::GetEnumerationProperty< ClippingMode::Type >( property, CLIPPING_MODE_TABLE, CLIPPING_MODE_TABLE_COUNT, convertedValue ) )
2673 mClippingMode = convertedValue;
2674 SetClippingModeMessage( GetEventThreadServices(), GetNode(), mClippingMode );
2679 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
2682 if( property.Get( value ) && value != mPositionUsesAnchorPoint )
2684 mPositionUsesAnchorPoint = value;
2685 SetPositionUsesAnchorPointMessage( GetEventThreadServices(), GetNode(), mPositionUsesAnchorPoint );
2690 case Dali::Actor::Property::LAYOUT_DIRECTION:
2692 Dali::LayoutDirection::Type direction = mLayoutDirection;
2693 mInheritLayoutDirection = false;
2695 if( Scripting::GetEnumerationProperty< LayoutDirection::Type >( property, LAYOUT_DIRECTION_TABLE, LAYOUT_DIRECTION_TABLE_COUNT, direction ) )
2697 InheritLayoutDirectionRecursively( this, direction, true );
2702 case Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION:
2705 if( property.Get( value ) )
2707 SetInheritLayoutDirection( value );
2714 // this can happen in the case of a non-animatable default property so just do nothing
2720 // TODO: This method needs to be removed
2721 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2723 switch( entry.GetType() )
2725 case Property::BOOLEAN:
2727 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2728 DALI_ASSERT_DEBUG( NULL != property );
2730 // property is being used in a separate thread; queue a message to set the property
2731 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2736 case Property::INTEGER:
2738 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2739 DALI_ASSERT_DEBUG( NULL != property );
2741 // property is being used in a separate thread; queue a message to set the property
2742 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2747 case Property::FLOAT:
2749 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2750 DALI_ASSERT_DEBUG( NULL != property );
2752 // property is being used in a separate thread; queue a message to set the property
2753 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2758 case Property::VECTOR2:
2760 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2761 DALI_ASSERT_DEBUG( NULL != property );
2763 // property is being used in a separate thread; queue a message to set the property
2764 if(entry.componentIndex == 0)
2766 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2768 else if(entry.componentIndex == 1)
2770 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2774 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2780 case Property::VECTOR3:
2782 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2783 DALI_ASSERT_DEBUG( NULL != property );
2785 // property is being used in a separate thread; queue a message to set the property
2786 if(entry.componentIndex == 0)
2788 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2790 else if(entry.componentIndex == 1)
2792 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2794 else if(entry.componentIndex == 2)
2796 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2800 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2806 case Property::VECTOR4:
2808 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2809 DALI_ASSERT_DEBUG( NULL != property );
2811 // property is being used in a separate thread; queue a message to set the property
2812 if(entry.componentIndex == 0)
2814 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
2816 else if(entry.componentIndex == 1)
2818 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
2820 else if(entry.componentIndex == 2)
2822 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
2824 else if(entry.componentIndex == 3)
2826 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
2830 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2836 case Property::ROTATION:
2838 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
2839 DALI_ASSERT_DEBUG( NULL != property );
2841 // property is being used in a separate thread; queue a message to set the property
2842 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
2847 case Property::MATRIX:
2849 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
2850 DALI_ASSERT_DEBUG( NULL != property );
2852 // property is being used in a separate thread; queue a message to set the property
2853 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), &GetNode(), property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
2858 case Property::MATRIX3:
2860 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
2861 DALI_ASSERT_DEBUG( NULL != property );
2863 // property is being used in a separate thread; queue a message to set the property
2864 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), &GetNode(), property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
2871 // nothing to do for other types
2876 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
2878 Property::Value value;
2880 if( ! GetCachedPropertyValue( index, value ) )
2882 // If property value is not stored in the event-side, then it must be a scene-graph only property
2883 GetCurrentPropertyValue( index, value );
2889 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
2891 Property::Value value;
2893 if( ! GetCurrentPropertyValue( index, value ) )
2895 // If unable to retrieve scene-graph property value, then it must be an event-side only property
2896 GetCachedPropertyValue( index, value );
2902 void Actor::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
2904 switch( animationType )
2907 case Animation::BETWEEN:
2911 case Dali::Actor::Property::SIZE:
2913 if( value.Get( mTargetSize ) )
2915 // Notify deriving classes
2916 OnSizeAnimation( animation, mTargetSize );
2921 case Dali::Actor::Property::SIZE_WIDTH:
2923 if( value.Get( mTargetSize.width ) )
2925 // Notify deriving classes
2926 OnSizeAnimation( animation, mTargetSize );
2931 case Dali::Actor::Property::SIZE_HEIGHT:
2933 if( value.Get( mTargetSize.height ) )
2935 // Notify deriving classes
2936 OnSizeAnimation( animation, mTargetSize );
2941 case Dali::Actor::Property::SIZE_DEPTH:
2943 if( value.Get( mTargetSize.depth ) )
2945 // Notify deriving classes
2946 OnSizeAnimation( animation, mTargetSize );
2951 case Dali::Actor::Property::POSITION:
2953 value.Get( mTargetPosition );
2957 case Dali::Actor::Property::POSITION_X:
2959 value.Get( mTargetPosition.x );
2963 case Dali::Actor::Property::POSITION_Y:
2965 value.Get( mTargetPosition.y );
2969 case Dali::Actor::Property::POSITION_Z:
2971 value.Get( mTargetPosition.z );
2975 case Dali::Actor::Property::ORIENTATION:
2977 value.Get( mTargetOrientation );
2981 case Dali::Actor::Property::SCALE:
2983 value.Get( mTargetScale );
2987 case Dali::Actor::Property::SCALE_X:
2989 value.Get( mTargetScale.x );
2993 case Dali::Actor::Property::SCALE_Y:
2995 value.Get( mTargetScale.y );
2999 case Dali::Actor::Property::SCALE_Z:
3001 value.Get( mTargetScale.z );
3005 case Dali::Actor::Property::VISIBLE:
3007 SetVisibleInternal( value.Get< bool >(), SendMessage::FALSE );
3011 case Dali::Actor::Property::COLOR:
3013 value.Get( mTargetColor );
3017 case Dali::Actor::Property::COLOR_RED:
3019 value.Get( mTargetColor.r );
3023 case Dali::Actor::Property::COLOR_GREEN:
3025 value.Get( mTargetColor.g );
3029 case Dali::Actor::Property::COLOR_BLUE:
3031 value.Get( mTargetColor.b );
3035 case Dali::Actor::Property::COLOR_ALPHA:
3036 case Dali::DevelActor::Property::OPACITY:
3038 value.Get( mTargetColor.a );
3044 // Not an animatable property. Do nothing.
3055 case Dali::Actor::Property::SIZE:
3057 if( AdjustValue< Vector3 >( mTargetSize, value ) )
3059 // Notify deriving classes
3060 OnSizeAnimation( animation, mTargetSize );
3065 case Dali::Actor::Property::SIZE_WIDTH:
3067 if( AdjustValue< float >( mTargetSize.width, value ) )
3069 // Notify deriving classes
3070 OnSizeAnimation( animation, mTargetSize );
3075 case Dali::Actor::Property::SIZE_HEIGHT:
3077 if( AdjustValue< float >( mTargetSize.height, value ) )
3079 // Notify deriving classes
3080 OnSizeAnimation( animation, mTargetSize );
3085 case Dali::Actor::Property::SIZE_DEPTH:
3087 if( AdjustValue< float >( mTargetSize.depth, value ) )
3089 // Notify deriving classes
3090 OnSizeAnimation( animation, mTargetSize );
3095 case Dali::Actor::Property::POSITION:
3097 AdjustValue< Vector3 >( mTargetPosition, value );
3101 case Dali::Actor::Property::POSITION_X:
3103 AdjustValue< float >( mTargetPosition.x, value );
3107 case Dali::Actor::Property::POSITION_Y:
3109 AdjustValue< float >( mTargetPosition.y, value );
3113 case Dali::Actor::Property::POSITION_Z:
3115 AdjustValue< float >( mTargetPosition.z, value );
3119 case Dali::Actor::Property::ORIENTATION:
3121 Quaternion relativeValue;
3122 if( value.Get( relativeValue ) )
3124 mTargetOrientation *= relativeValue;
3129 case Dali::Actor::Property::SCALE:
3131 AdjustValue< Vector3 >( mTargetScale, value );
3135 case Dali::Actor::Property::SCALE_X:
3137 AdjustValue< float >( mTargetScale.x, value );
3141 case Dali::Actor::Property::SCALE_Y:
3143 AdjustValue< float >( mTargetScale.y, value );
3147 case Dali::Actor::Property::SCALE_Z:
3149 AdjustValue< float >( mTargetScale.z, value );
3153 case Dali::Actor::Property::VISIBLE:
3155 bool relativeValue = false;
3156 if( value.Get( relativeValue ) )
3158 bool visible = mVisible || relativeValue;
3159 SetVisibleInternal( visible, SendMessage::FALSE );
3164 case Dali::Actor::Property::COLOR:
3166 AdjustValue< Vector4 >( mTargetColor, value );
3170 case Dali::Actor::Property::COLOR_RED:
3172 AdjustValue< float >( mTargetColor.r, value );
3176 case Dali::Actor::Property::COLOR_GREEN:
3178 AdjustValue< float >( mTargetColor.g, value );
3182 case Dali::Actor::Property::COLOR_BLUE:
3184 AdjustValue< float >( mTargetColor.b, value );
3188 case Dali::Actor::Property::COLOR_ALPHA:
3189 case Dali::DevelActor::Property::OPACITY:
3191 AdjustValue< float >( mTargetColor.a, value );
3197 // Not an animatable property. Do nothing.
3206 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3208 const PropertyBase* property( NULL );
3212 case Dali::Actor::Property::SIZE: // FALLTHROUGH
3213 case Dali::Actor::Property::SIZE_WIDTH: // FALLTHROUGH
3214 case Dali::Actor::Property::SIZE_HEIGHT: // FALLTHROUGH
3215 case Dali::Actor::Property::SIZE_DEPTH:
3217 property = &GetNode().mSize;
3220 case Dali::Actor::Property::POSITION: // FALLTHROUGH
3221 case Dali::Actor::Property::POSITION_X: // FALLTHROUGH
3222 case Dali::Actor::Property::POSITION_Y: // FALLTHROUGH
3223 case Dali::Actor::Property::POSITION_Z:
3225 property = &GetNode().mPosition;
3228 case Dali::Actor::Property::ORIENTATION:
3230 property = &GetNode().mOrientation;
3233 case Dali::Actor::Property::SCALE: // FALLTHROUGH
3234 case Dali::Actor::Property::SCALE_X: // FALLTHROUGH
3235 case Dali::Actor::Property::SCALE_Y: // FALLTHROUGH
3236 case Dali::Actor::Property::SCALE_Z:
3238 property = &GetNode().mScale;
3241 case Dali::Actor::Property::VISIBLE:
3243 property = &GetNode().mVisible;
3246 case Dali::Actor::Property::COLOR: // FALLTHROUGH
3247 case Dali::Actor::Property::COLOR_RED: // FALLTHROUGH
3248 case Dali::Actor::Property::COLOR_GREEN: // FALLTHROUGH
3249 case Dali::Actor::Property::COLOR_BLUE: // FALLTHROUGH
3250 case Dali::Actor::Property::COLOR_ALPHA: // FALLTHROUGH
3251 case Dali::DevelActor::Property::OPACITY:
3253 property = &GetNode().mColor;
3263 // not our property, ask base
3264 property = Object::GetSceneObjectAnimatableProperty( index );
3270 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3272 const PropertyInputImpl* property( NULL );
3276 case Dali::Actor::Property::PARENT_ORIGIN: // FALLTHROUGH
3277 case Dali::Actor::Property::PARENT_ORIGIN_X: // FALLTHROUGH
3278 case Dali::Actor::Property::PARENT_ORIGIN_Y: // FALLTHROUGH
3279 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3281 property = &GetNode().mParentOrigin;
3284 case Dali::Actor::Property::ANCHOR_POINT: // FALLTHROUGH
3285 case Dali::Actor::Property::ANCHOR_POINT_X: // FALLTHROUGH
3286 case Dali::Actor::Property::ANCHOR_POINT_Y: // FALLTHROUGH
3287 case Dali::Actor::Property::ANCHOR_POINT_Z:
3289 property = &GetNode().mAnchorPoint;
3292 case Dali::Actor::Property::WORLD_POSITION: // FALLTHROUGH
3293 case Dali::Actor::Property::WORLD_POSITION_X: // FALLTHROUGH
3294 case Dali::Actor::Property::WORLD_POSITION_Y: // FALLTHROUGH
3295 case Dali::Actor::Property::WORLD_POSITION_Z:
3297 property = &GetNode().mWorldPosition;
3300 case Dali::Actor::Property::WORLD_ORIENTATION:
3302 property = &GetNode().mWorldOrientation;
3305 case Dali::Actor::Property::WORLD_SCALE:
3307 property = &GetNode().mWorldScale;
3310 case Dali::Actor::Property::WORLD_COLOR:
3312 property = &GetNode().mWorldColor;
3315 case Dali::Actor::Property::WORLD_MATRIX:
3317 property = &GetNode().mWorldMatrix;
3320 case Dali::DevelActor::Property::CULLED:
3322 property = &GetNode().mCulled;
3332 // reuse animatable property getter as animatable properties are inputs as well
3333 // animatable property chains back to Object::GetSceneObjectInputProperty() so all properties get covered
3334 property = GetSceneObjectAnimatableProperty( index );
3340 int32_t Actor::GetPropertyComponentIndex( Property::Index index ) const
3342 int32_t componentIndex = Property::INVALID_COMPONENT_INDEX;
3346 case Dali::Actor::Property::PARENT_ORIGIN_X:
3347 case Dali::Actor::Property::ANCHOR_POINT_X:
3348 case Dali::Actor::Property::SIZE_WIDTH:
3349 case Dali::Actor::Property::POSITION_X:
3350 case Dali::Actor::Property::WORLD_POSITION_X:
3351 case Dali::Actor::Property::SCALE_X:
3352 case Dali::Actor::Property::COLOR_RED:
3358 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3359 case Dali::Actor::Property::ANCHOR_POINT_Y:
3360 case Dali::Actor::Property::SIZE_HEIGHT:
3361 case Dali::Actor::Property::POSITION_Y:
3362 case Dali::Actor::Property::WORLD_POSITION_Y:
3363 case Dali::Actor::Property::SCALE_Y:
3364 case Dali::Actor::Property::COLOR_GREEN:
3370 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3371 case Dali::Actor::Property::ANCHOR_POINT_Z:
3372 case Dali::Actor::Property::SIZE_DEPTH:
3373 case Dali::Actor::Property::POSITION_Z:
3374 case Dali::Actor::Property::WORLD_POSITION_Z:
3375 case Dali::Actor::Property::SCALE_Z:
3376 case Dali::Actor::Property::COLOR_BLUE:
3382 case Dali::Actor::Property::COLOR_ALPHA:
3383 case Dali::DevelActor::Property::OPACITY:
3395 if( Property::INVALID_COMPONENT_INDEX == componentIndex )
3398 componentIndex = Object::GetPropertyComponentIndex( index );
3401 return componentIndex;
3404 void Actor::SetParent( Actor* parent )
3408 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3412 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3415 // Instruct each actor to create a corresponding node in the scene graph
3416 ConnectToStage( parent->GetHierarchyDepth() );
3419 // Resolve the name and index for the child properties if any
3420 ResolveChildProperties();
3422 else // parent being set to NULL
3424 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3428 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3431 // Disconnect the Node & its children from the scene-graph.
3432 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
3434 // Instruct each actor to discard pointers to the scene-graph
3435 DisconnectFromStage();
3440 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3443 Actor* actor = dynamic_cast< Actor* >( object );
3447 if( 0 == actionName.compare( ACTION_SHOW ) )
3449 actor->SetVisible( true );
3452 else if( 0 == actionName.compare( ACTION_HIDE ) )
3454 actor->SetVisible( false );
3462 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
3464 bool valueSet = true;
3468 case Dali::Actor::Property::PARENT_ORIGIN:
3470 value = GetCurrentParentOrigin();
3474 case Dali::Actor::Property::PARENT_ORIGIN_X:
3476 value = GetCurrentParentOrigin().x;
3480 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3482 value = GetCurrentParentOrigin().y;
3486 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3488 value = GetCurrentParentOrigin().z;
3492 case Dali::Actor::Property::ANCHOR_POINT:
3494 value = GetCurrentAnchorPoint();
3498 case Dali::Actor::Property::ANCHOR_POINT_X:
3500 value = GetCurrentAnchorPoint().x;
3504 case Dali::Actor::Property::ANCHOR_POINT_Y:
3506 value = GetCurrentAnchorPoint().y;
3510 case Dali::Actor::Property::ANCHOR_POINT_Z:
3512 value = GetCurrentAnchorPoint().z;
3516 case Dali::Actor::Property::SIZE:
3518 value = GetTargetSize();
3522 case Dali::Actor::Property::SIZE_WIDTH:
3524 value = GetTargetSize().width;
3528 case Dali::Actor::Property::SIZE_HEIGHT:
3530 value = GetTargetSize().height;
3534 case Dali::Actor::Property::SIZE_DEPTH:
3536 value = GetTargetSize().depth;
3540 case Dali::Actor::Property::POSITION:
3542 value = GetTargetPosition();
3546 case Dali::Actor::Property::POSITION_X:
3548 value = GetTargetPosition().x;
3552 case Dali::Actor::Property::POSITION_Y:
3554 value = GetTargetPosition().y;
3558 case Dali::Actor::Property::POSITION_Z:
3560 value = GetTargetPosition().z;
3564 case Dali::Actor::Property::ORIENTATION:
3566 value = mTargetOrientation;
3570 case Dali::Actor::Property::SCALE:
3572 value = mTargetScale;
3576 case Dali::Actor::Property::SCALE_X:
3578 value = mTargetScale.x;
3582 case Dali::Actor::Property::SCALE_Y:
3584 value = mTargetScale.y;
3588 case Dali::Actor::Property::SCALE_Z:
3590 value = mTargetScale.z;
3594 case Dali::Actor::Property::VISIBLE:
3600 case Dali::Actor::Property::COLOR:
3602 value = mTargetColor;
3606 case Dali::Actor::Property::COLOR_RED:
3608 value = mTargetColor.r;
3612 case Dali::Actor::Property::COLOR_GREEN:
3614 value = mTargetColor.g;
3618 case Dali::Actor::Property::COLOR_BLUE:
3620 value = mTargetColor.b;
3624 case Dali::Actor::Property::COLOR_ALPHA:
3625 case Dali::DevelActor::Property::OPACITY:
3627 value = mTargetColor.a;
3631 case Dali::Actor::Property::NAME:
3637 case Dali::Actor::Property::SENSITIVE:
3639 value = IsSensitive();
3643 case Dali::Actor::Property::LEAVE_REQUIRED:
3645 value = GetLeaveRequired();
3649 case Dali::Actor::Property::INHERIT_POSITION:
3651 value = IsPositionInherited();
3655 case Dali::Actor::Property::INHERIT_ORIENTATION:
3657 value = IsOrientationInherited();
3661 case Dali::Actor::Property::INHERIT_SCALE:
3663 value = IsScaleInherited();
3667 case Dali::Actor::Property::COLOR_MODE:
3669 value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
3673 case Dali::Actor::Property::DRAW_MODE:
3675 value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
3679 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3681 value = GetSizeModeFactor();
3685 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3687 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3691 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3693 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3697 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3699 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT );
3703 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3705 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3709 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3711 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3715 case Dali::Actor::Property::PADDING:
3717 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3718 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3719 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3723 case Dali::Actor::Property::MINIMUM_SIZE:
3725 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3729 case Dali::Actor::Property::MAXIMUM_SIZE:
3731 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3735 case Dali::Actor::Property::CLIPPING_MODE:
3737 value = mClippingMode;
3741 case Dali::DevelActor::Property::SIBLING_ORDER:
3743 value = static_cast<int>( GetSiblingOrder() );
3747 case Dali::DevelActor::Property::SCREEN_POSITION:
3749 value = GetCurrentScreenPosition();
3753 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
3755 value = mPositionUsesAnchorPoint;
3759 case Dali::Actor::Property::LAYOUT_DIRECTION:
3761 value = mLayoutDirection;
3765 case Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION:
3767 value = IsLayoutDirectionInherited();
3773 // Must be a scene-graph only property
3782 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
3784 bool valueSet = true;
3788 case Dali::Actor::Property::SIZE:
3790 value = GetCurrentSize();
3794 case Dali::Actor::Property::SIZE_WIDTH:
3796 value = GetCurrentSize().width;
3800 case Dali::Actor::Property::SIZE_HEIGHT:
3802 value = GetCurrentSize().height;
3806 case Dali::Actor::Property::SIZE_DEPTH:
3808 value = GetCurrentSize().depth;
3812 case Dali::Actor::Property::POSITION:
3814 value = GetCurrentPosition();
3818 case Dali::Actor::Property::POSITION_X:
3820 value = GetCurrentPosition().x;
3824 case Dali::Actor::Property::POSITION_Y:
3826 value = GetCurrentPosition().y;
3830 case Dali::Actor::Property::POSITION_Z:
3832 value = GetCurrentPosition().z;
3836 case Dali::Actor::Property::WORLD_POSITION:
3838 value = GetCurrentWorldPosition();
3842 case Dali::Actor::Property::WORLD_POSITION_X:
3844 value = GetCurrentWorldPosition().x;
3848 case Dali::Actor::Property::WORLD_POSITION_Y:
3850 value = GetCurrentWorldPosition().y;
3854 case Dali::Actor::Property::WORLD_POSITION_Z:
3856 value = GetCurrentWorldPosition().z;
3860 case Dali::Actor::Property::ORIENTATION:
3862 value = GetCurrentOrientation();
3866 case Dali::Actor::Property::WORLD_ORIENTATION:
3868 value = GetCurrentWorldOrientation();
3872 case Dali::Actor::Property::SCALE:
3874 value = GetCurrentScale();
3878 case Dali::Actor::Property::SCALE_X:
3880 value = GetCurrentScale().x;
3884 case Dali::Actor::Property::SCALE_Y:
3886 value = GetCurrentScale().y;
3890 case Dali::Actor::Property::SCALE_Z:
3892 value = GetCurrentScale().z;
3896 case Dali::Actor::Property::WORLD_SCALE:
3898 value = GetCurrentWorldScale();
3902 case Dali::Actor::Property::COLOR:
3904 value = GetCurrentColor();
3908 case Dali::Actor::Property::COLOR_RED:
3910 value = GetCurrentColor().r;
3914 case Dali::Actor::Property::COLOR_GREEN:
3916 value = GetCurrentColor().g;
3920 case Dali::Actor::Property::COLOR_BLUE:
3922 value = GetCurrentColor().b;
3926 case Dali::Actor::Property::COLOR_ALPHA:
3927 case Dali::DevelActor::Property::OPACITY:
3929 value = GetCurrentColor().a;
3933 case Dali::Actor::Property::WORLD_COLOR:
3935 value = GetCurrentWorldColor();
3939 case Dali::Actor::Property::WORLD_MATRIX:
3941 value = GetCurrentWorldMatrix();
3945 case Dali::Actor::Property::VISIBLE:
3947 value = IsVisible();
3951 case DevelActor::Property::CULLED:
3953 value = GetNode().IsCulled( GetEventThreadServices().GetEventBufferIndex() );
3959 // Must be an event-side only property
3968 void Actor::EnsureRelayoutData()
3970 // Assign relayout data.
3971 if( !mRelayoutData )
3973 mRelayoutData = new RelayoutData();
3977 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3979 // Check if actor is dependent on parent
3980 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3982 if( ( dimension & ( 1 << i ) ) )
3984 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3985 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3995 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3997 // Check if actor is dependent on children
3998 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4000 if( ( dimension & ( 1 << i ) ) )
4002 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4003 switch( resizePolicy )
4005 case ResizePolicy::FIT_TO_CHILDREN:
4006 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
4022 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
4024 return Actor::RelayoutDependentOnChildren( dimension );
4027 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
4029 // Check each possible dimension and see if it is dependent on the input one
4030 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4032 if( dimension & ( 1 << i ) )
4034 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
4041 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
4043 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4045 if( dimension & ( 1 << i ) )
4047 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
4052 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
4054 // If more than one dimension is requested, just return the first one found
4055 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4057 if( ( dimension & ( 1 << i ) ) )
4059 return mRelayoutData->negotiatedDimensions[ i ];
4063 return 0.0f; // Default
4066 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
4068 EnsureRelayoutData();
4070 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4072 if( dimension & ( 1 << i ) )
4074 mRelayoutData->dimensionPadding[ i ] = padding;
4079 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4081 if ( mRelayoutData )
4083 // If more than one dimension is requested, just return the first one found
4084 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4086 if( ( dimension & ( 1 << i ) ) )
4088 return mRelayoutData->dimensionPadding[ i ];
4093 return GetDefaultDimensionPadding();
4096 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4098 EnsureRelayoutData();
4100 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4102 if( dimension & ( 1 << i ) )
4104 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4109 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4111 if ( mRelayoutData )
4113 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4115 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4125 float Actor::GetHeightForWidthBase( float width )
4127 float height = 0.0f;
4129 const Vector3 naturalSize = GetNaturalSize();
4130 if( naturalSize.width > 0.0f )
4132 height = naturalSize.height * width / naturalSize.width;
4134 else // we treat 0 as 1:1 aspect ratio
4142 float Actor::GetWidthForHeightBase( float height )
4146 const Vector3 naturalSize = GetNaturalSize();
4147 if( naturalSize.height > 0.0f )
4149 width = naturalSize.width * height / naturalSize.height;
4151 else // we treat 0 as 1:1 aspect ratio
4159 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4161 // Fill to parent, taking size mode factor into account
4162 switch( child.GetResizePolicy( dimension ) )
4164 case ResizePolicy::FILL_TO_PARENT:
4166 return GetLatestSize( dimension );
4169 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4171 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4174 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4176 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4181 return GetLatestSize( dimension );
4186 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4188 // Can be overridden in derived class
4189 return CalculateChildSizeBase( child, dimension );
4192 float Actor::GetHeightForWidth( float width )
4194 // Can be overridden in derived class
4195 return GetHeightForWidthBase( width );
4198 float Actor::GetWidthForHeight( float height )
4200 // Can be overridden in derived class
4201 return GetWidthForHeightBase( height );
4204 float Actor::GetLatestSize( Dimension::Type dimension ) const
4206 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4209 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4211 Vector2 padding = GetPadding( dimension );
4213 return GetLatestSize( dimension ) + padding.x + padding.y;
4216 float Actor::NegotiateFromParent( Dimension::Type dimension )
4218 Actor* parent = GetParent();
4221 Vector2 padding( GetPadding( dimension ) );
4222 Vector2 parentPadding( parent->GetPadding( dimension ) );
4223 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4229 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4231 float maxDimensionPoint = 0.0f;
4233 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4235 ActorPtr child = GetChildAt( i );
4237 if( !child->RelayoutDependentOnParent( dimension ) )
4239 // Calculate the min and max points that the children range across
4240 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
4241 float dimensionSize = child->GetRelayoutSize( dimension );
4242 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4246 return maxDimensionPoint;
4249 float Actor::GetSize( Dimension::Type dimension ) const
4251 return GetDimensionValue( mTargetSize, dimension );
4254 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4256 return GetDimensionValue( GetNaturalSize(), dimension );
4259 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4261 switch( GetResizePolicy( dimension ) )
4263 case ResizePolicy::USE_NATURAL_SIZE:
4265 return GetNaturalSize( dimension );
4268 case ResizePolicy::FIXED:
4270 return GetDimensionValue( GetPreferredSize(), dimension );
4273 case ResizePolicy::USE_ASSIGNED_SIZE:
4275 return GetDimensionValue( maximumSize, dimension );
4278 case ResizePolicy::FILL_TO_PARENT:
4279 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4280 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4282 return NegotiateFromParent( dimension );
4285 case ResizePolicy::FIT_TO_CHILDREN:
4287 return NegotiateFromChildren( dimension );
4290 case ResizePolicy::DIMENSION_DEPENDENCY:
4292 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4295 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4297 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4300 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4302 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4314 return 0.0f; // Default
4317 float Actor::ClampDimension( float size, Dimension::Type dimension )
4319 const float minSize = GetMinimumSize( dimension );
4320 const float maxSize = GetMaximumSize( dimension );
4322 return std::max( minSize, std::min( size, maxSize ) );
4325 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4327 // Check if it needs to be negotiated
4328 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4330 // Check that we havn't gotten into an infinite loop
4331 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4332 bool recursionFound = false;
4333 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4335 if( *it == searchActor )
4337 recursionFound = true;
4342 if( !recursionFound )
4344 // Record the path that we have taken
4345 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4347 // Dimension dependency check
4348 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4350 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4352 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4354 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4358 // Parent dependency check
4359 Actor* parent = GetParent();
4360 if( parent && RelayoutDependentOnParent( dimension ) )
4362 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4365 // Children dependency check
4366 if( RelayoutDependentOnChildren( dimension ) )
4368 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4370 ActorPtr child = GetChildAt( i );
4372 // Only relayout child first if it is not dependent on this actor
4373 if( !child->RelayoutDependentOnParent( dimension ) )
4375 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
4380 // For deriving classes
4381 OnCalculateRelayoutSize( dimension );
4383 // All dependencies checked, calculate the size and set negotiated flag
4384 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4386 SetNegotiatedDimension( newSize, dimension );
4387 SetLayoutNegotiated( true, dimension );
4389 // For deriving classes
4390 OnLayoutNegotiated( newSize, dimension );
4392 // This actor has been successfully processed, pop it off the recursion stack
4393 recursionStack.pop_back();
4397 // TODO: Break infinite loop
4398 SetLayoutNegotiated( true, dimension );
4403 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4405 // Negotiate all dimensions that require it
4406 ActorDimensionStack recursionStack;
4408 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4410 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4413 NegotiateDimension( dimension, allocatedSize, recursionStack );
4417 Vector2 Actor::ApplySizeSetPolicy( const Vector2& size )
4419 switch( mRelayoutData->sizeSetPolicy )
4421 case SizeScalePolicy::USE_SIZE_SET:
4426 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4428 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4429 const Vector3 naturalSize = GetNaturalSize();
4430 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4432 const float sizeRatio = size.width / size.height;
4433 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4435 if( naturalSizeRatio < sizeRatio )
4437 return Vector2( naturalSizeRatio * size.height, size.height );
4439 else if( naturalSizeRatio > sizeRatio )
4441 return Vector2( size.width, size.width / naturalSizeRatio );
4452 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4454 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4455 const Vector3 naturalSize = GetNaturalSize();
4456 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4458 const float sizeRatio = size.width / size.height;
4459 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4461 if( naturalSizeRatio < sizeRatio )
4463 return Vector2( size.width, size.width / naturalSizeRatio );
4465 else if( naturalSizeRatio > sizeRatio )
4467 return Vector2( naturalSizeRatio * size.height, size.height );
4486 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4488 // Do the set actor size
4489 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4491 // Adjust for size set policy
4492 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4494 // Lock the flag to stop recursive relayouts on set size
4495 mRelayoutData->insideRelayout = true;
4496 SetSize( negotiatedSize );
4497 mRelayoutData->insideRelayout = false;
4499 // Clear flags for all dimensions
4500 SetLayoutDirty( false );
4502 // Give deriving classes a chance to respond
4503 OnRelayout( negotiatedSize, container );
4505 if( !mOnRelayoutSignal.Empty() )
4507 Dali::Actor handle( this );
4508 mOnRelayoutSignal.Emit( handle );
4512 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4514 // Force a size negotiation for actors that has assigned size during relayout
4515 // This is required as otherwise the flags that force a relayout will not
4516 // necessarilly be set. This will occur if the actor has already been laid out.
4517 // The dirty flags are then cleared. Then if the actor is added back into the
4518 // relayout container afterwards, the dirty flags would still be clear...
4519 // causing a relayout to be skipped. Here we force any actors added to the
4520 // container to be relayed out.
4521 DALI_LOG_TIMER_START( NegSizeTimer1 );
4523 if( GetUseAssignedSize(Dimension::WIDTH ) )
4525 SetLayoutNegotiated( false, Dimension::WIDTH );
4527 if( GetUseAssignedSize( Dimension::HEIGHT ) )
4529 SetLayoutNegotiated( false, Dimension::HEIGHT );
4532 // Do the negotiation
4533 NegotiateDimensions( allocatedSize );
4535 // Set the actor size
4536 SetNegotiatedSize( container );
4538 // Negotiate down to children
4539 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4541 ActorPtr child = GetChildAt( i );
4543 // Forces children that have already been laid out to be relayed out
4544 // if they have assigned size during relayout.
4545 if( child->GetUseAssignedSize(Dimension::WIDTH) )
4547 child->SetLayoutNegotiated(false, Dimension::WIDTH);
4548 child->SetLayoutDirty(true, Dimension::WIDTH);
4551 if( child->GetUseAssignedSize(Dimension::HEIGHT) )
4553 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
4554 child->SetLayoutDirty(true, Dimension::HEIGHT);
4557 // Only relayout if required
4558 if( child->RelayoutRequired() )
4560 container.Add( Dali::Actor( child.Get() ), mTargetSize.GetVectorXY() );
4563 DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
4566 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
4570 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4572 if( dimension & ( 1 << i ) )
4574 mRelayoutData->useAssignedSize[ i ] = use;
4580 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
4582 if ( mRelayoutData )
4584 // If more than one dimension is requested, just return the first one found
4585 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4587 if( dimension & ( 1 << i ) )
4589 return mRelayoutData->useAssignedSize[ i ];
4597 void Actor::RelayoutRequest( Dimension::Type dimension )
4599 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4600 if( relayoutController )
4602 Dali::Actor self( this );
4603 relayoutController->RequestRelayout( self, dimension );
4607 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4611 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4615 void Actor::SetPreferredSize( const Vector2& size )
4617 EnsureRelayoutData();
4619 if( size.width > 0.0f )
4621 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4624 if( size.height > 0.0f )
4626 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4629 mRelayoutData->preferredSize = size;
4634 Vector2 Actor::GetPreferredSize() const
4636 if ( mRelayoutData )
4638 return Vector2( mRelayoutData->preferredSize );
4641 return GetDefaultPreferredSize();
4644 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4646 EnsureRelayoutData();
4648 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4650 if( dimension & ( 1 << i ) )
4652 mRelayoutData->minimumSize[ i ] = size;
4659 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4661 if ( mRelayoutData )
4663 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4665 if( dimension & ( 1 << i ) )
4667 return mRelayoutData->minimumSize[ i ];
4672 return 0.0f; // Default
4675 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4677 EnsureRelayoutData();
4679 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4681 if( dimension & ( 1 << i ) )
4683 mRelayoutData->maximumSize[ i ] = size;
4690 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4692 if ( mRelayoutData )
4694 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4696 if( dimension & ( 1 << i ) )
4698 return mRelayoutData->maximumSize[ i ];
4703 return FLT_MAX; // Default
4706 Object* Actor::GetParentObject() const
4711 void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
4713 if( mVisible != visible )
4715 if( sendMessage == SendMessage::TRUE )
4717 // node is being used in a separate thread; queue a message to set the value & base value
4718 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible );
4723 // Emit the signal on this actor and all its children
4724 EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
4728 void Actor::SetSiblingOrder( uint32_t order )
4732 ActorContainer& siblings = *(mParent->mChildren);
4733 uint32_t currentOrder = GetSiblingOrder();
4735 if( order != currentOrder )
4741 else if( order < siblings.size() -1 )
4743 if( order > currentOrder )
4745 RaiseAbove( *siblings[order] );
4749 LowerBelow( *siblings[order] );
4760 uint32_t Actor::GetSiblingOrder() const
4766 ActorContainer& siblings = *(mParent->mChildren);
4767 for( std::size_t i = 0; i < siblings.size(); ++i )
4769 if( siblings[i] == this )
4771 order = static_cast<uint32_t>( i );
4780 void Actor::RequestRebuildDepthTree()
4784 StagePtr stage = Stage::GetCurrent();
4787 stage->RequestRebuildDepthTree();
4796 ActorContainer& siblings = *(mParent->mChildren);
4797 if( siblings.back() != this ) // If not already at end
4799 for( std::size_t i=0; i<siblings.size(); ++i )
4801 if( siblings[i] == this )
4804 ActorPtr next = siblings[i+1];
4805 siblings[i+1] = this;
4812 Dali::Actor handle( this );
4813 mParent->mChildOrderChangedSignal.Emit( handle );
4815 RequestRebuildDepthTree();
4819 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4827 ActorContainer& siblings = *(mParent->mChildren);
4828 if( siblings.front() != this ) // If not already at beginning
4830 for( std::size_t i=1; i<siblings.size(); ++i )
4832 if( siblings[i] == this )
4834 // Swap with previous
4835 ActorPtr previous = siblings[i-1];
4836 siblings[i-1] = this;
4837 siblings[i] = previous;
4843 Dali::Actor handle( this );
4844 mParent->mChildOrderChangedSignal.Emit( handle );
4846 RequestRebuildDepthTree();
4850 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4854 void Actor::RaiseToTop()
4858 ActorContainer& siblings = *(mParent->mChildren);
4859 if( siblings.back() != this ) // If not already at end
4861 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
4862 if( iter != siblings.end() )
4864 siblings.erase(iter);
4865 siblings.push_back(ActorPtr(this));
4869 Dali::Actor handle( this );
4870 mParent->mChildOrderChangedSignal.Emit( handle );
4872 RequestRebuildDepthTree();
4876 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4880 void Actor::LowerToBottom()
4884 ActorContainer& siblings = *(mParent->mChildren);
4885 if( siblings.front() != this ) // If not already at bottom,
4887 ActorPtr thisPtr(this); // ensure this actor remains referenced.
4889 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
4890 if( iter != siblings.end() )
4892 siblings.erase(iter);
4893 siblings.insert(siblings.begin(), thisPtr);
4897 Dali::Actor handle( this );
4898 mParent->mChildOrderChangedSignal.Emit( handle );
4900 RequestRebuildDepthTree();
4904 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4908 void Actor::RaiseAbove( Internal::Actor& target )
4912 ActorContainer& siblings = *(mParent->mChildren);
4913 if( siblings.back() != this && target.mParent == mParent ) // If not already at top
4915 ActorPtr thisPtr(this); // ensure this actor remains referenced.
4917 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
4918 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
4919 if( thisIter < targetIter )
4921 siblings.erase(thisIter);
4922 // Erasing early invalidates the targetIter. (Conversely, inserting first may also
4923 // invalidate thisIter)
4924 targetIter = std::find( siblings.begin(), siblings.end(), &target );
4926 siblings.insert(targetIter, thisPtr);
4929 Dali::Actor handle( this );
4930 mParent->mChildOrderChangedSignal.Emit( handle );
4932 RequestRebuildDepthTree();
4937 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4941 void Actor::LowerBelow( Internal::Actor& target )
4945 ActorContainer& siblings = *(mParent->mChildren);
4946 if( siblings.front() != this && target.mParent == mParent ) // If not already at bottom
4948 ActorPtr thisPtr(this); // ensure this actor remains referenced.
4950 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
4951 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
4953 if( thisIter > targetIter )
4955 siblings.erase(thisIter); // this only invalidates iterators at or after this point.
4956 siblings.insert(targetIter, thisPtr);
4959 Dali::Actor handle( this );
4960 mParent->mChildOrderChangedSignal.Emit( handle );
4962 RequestRebuildDepthTree();
4967 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4971 void Actor::SetInheritLayoutDirection( bool inherit )
4973 if( mInheritLayoutDirection != inherit )
4975 mInheritLayoutDirection = inherit;
4977 if( inherit && mParent )
4979 InheritLayoutDirectionRecursively( this, mParent->mLayoutDirection );
4984 bool Actor::IsLayoutDirectionInherited() const
4986 return mInheritLayoutDirection;
4989 void Actor::InheritLayoutDirectionRecursively( ActorPtr actor, Dali::LayoutDirection::Type direction, bool set )
4991 if( actor && ( actor->mInheritLayoutDirection || set ) )
4993 if( actor->mLayoutDirection != direction )
4995 actor->mLayoutDirection = direction;
4996 actor->EmitLayoutDirectionChangedSignal( direction );
4997 actor->RelayoutRequest();
5000 if( actor->GetChildCount() > 0 )
5002 ActorContainer& children = actor->GetChildrenInternal();
5003 for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter )
5005 InheritLayoutDirectionRecursively( *iter, direction );
5011 } // namespace Internal