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( "reservedProperty01", STRING, true, false, false, Dali::Actor::Property::RESERVED_PROPERTY_01 ) // This property was removed, but to keep binary compatibility and TypeRegister test app, remain it here.
196 DALI_PROPERTY( "drawMode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
197 DALI_PROPERTY( "sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
198 DALI_PROPERTY( "widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
199 DALI_PROPERTY( "heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
200 DALI_PROPERTY( "sizeScalePolicy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
201 DALI_PROPERTY( "widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
202 DALI_PROPERTY( "heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
203 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
204 DALI_PROPERTY( "minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
205 DALI_PROPERTY( "maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
206 DALI_PROPERTY( "inheritPosition", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_POSITION )
207 DALI_PROPERTY( "clippingMode", STRING, true, false, false, Dali::Actor::Property::CLIPPING_MODE )
208 DALI_PROPERTY( "layoutDirection", STRING, true, false, false, Dali::Actor::Property::LAYOUT_DIRECTION )
209 DALI_PROPERTY( "inheritLayoutDirection", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION )
210 DALI_PROPERTY( "siblingOrder", INTEGER, true, false, false, Dali::DevelActor::Property::SIBLING_ORDER )
211 DALI_PROPERTY( "opacity", FLOAT, true, true, true, Dali::DevelActor::Property::OPACITY )
212 DALI_PROPERTY( "screenPosition", VECTOR2, false, false, false, Dali::DevelActor::Property::SCREEN_POSITION )
213 DALI_PROPERTY( "positionUsesAnchorPoint", BOOLEAN, true, false, false, Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT )
214 DALI_PROPERTY( "culled", BOOLEAN, false, false, true, Dali::DevelActor::Property::CULLED )
215 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperties )
219 const char* const SIGNAL_TOUCHED = "touched";
220 const char* const SIGNAL_HOVERED = "hovered";
221 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
222 const char* const SIGNAL_ON_STAGE = "onStage";
223 const char* const SIGNAL_OFF_STAGE = "offStage";
224 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
225 const char* const SIGNAL_TOUCH = "touch";
226 const char* const SIGNAL_VISIBILITY_CHANGED = "visibilityChanged";
227 const char* const SIGNAL_LAYOUT_DIRECTION_CHANGED = "layoutDirectionChanged";
228 const char* const SIGNAL_CHILD_ADDED = "childAdded";
229 const char* const SIGNAL_CHILD_REMOVED = "childRemoved";
233 const char* const ACTION_SHOW = "show";
234 const char* const ACTION_HIDE = "hide";
236 BaseHandle CreateActor()
238 return Dali::Actor::New();
241 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor, ActorDefaultProperties );
243 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
244 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
245 SignalConnectorType signalConnector3( mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal );
246 SignalConnectorType signalConnector4( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
247 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
248 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
249 SignalConnectorType signalConnector7( mType, SIGNAL_TOUCH, &Actor::DoConnectSignal );
250 SignalConnectorType signalConnector8( mType, SIGNAL_VISIBILITY_CHANGED, &Actor::DoConnectSignal );
251 SignalConnectorType signalConnector9( mType, SIGNAL_LAYOUT_DIRECTION_CHANGED, &Actor::DoConnectSignal );
252 SignalConnectorType signalConnector10( mType, SIGNAL_CHILD_ADDED, &Actor::DoConnectSignal );
253 SignalConnectorType signalConnector11( mType, SIGNAL_CHILD_REMOVED, &Actor::DoConnectSignal );
255 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
256 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
261 const Vector3& value;
264 DALI_ENUM_TO_STRING_TABLE_BEGIN_WITH_TYPE( AnchorValue, ANCHOR_CONSTANT )
265 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_LEFT )
266 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_CENTER )
267 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_RIGHT )
268 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_LEFT )
269 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER )
270 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_RIGHT )
271 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_LEFT )
272 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_CENTER )
273 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_RIGHT )
274 DALI_ENUM_TO_STRING_TABLE_END( ANCHOR_CONSTANT )
276 DALI_ENUM_TO_STRING_TABLE_BEGIN( COLOR_MODE )
277 DALI_ENUM_TO_STRING( USE_OWN_COLOR )
278 DALI_ENUM_TO_STRING( USE_PARENT_COLOR )
279 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_COLOR )
280 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_ALPHA )
281 DALI_ENUM_TO_STRING_TABLE_END( COLOR_MODE )
283 DALI_ENUM_TO_STRING_TABLE_BEGIN( DRAW_MODE )
284 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, NORMAL )
285 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, OVERLAY_2D )
286 DALI_ENUM_TO_STRING_TABLE_END( DRAW_MODE )
288 DALI_ENUM_TO_STRING_TABLE_BEGIN( RESIZE_POLICY )
289 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIXED )
290 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_NATURAL_SIZE )
291 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FILL_TO_PARENT )
292 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_RELATIVE_TO_PARENT )
293 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_FIXED_OFFSET_FROM_PARENT )
294 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIT_TO_CHILDREN )
295 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, DIMENSION_DEPENDENCY )
296 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_ASSIGNED_SIZE )
297 DALI_ENUM_TO_STRING_TABLE_END( RESIZE_POLICY )
299 DALI_ENUM_TO_STRING_TABLE_BEGIN( SIZE_SCALE_POLICY )
300 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, USE_SIZE_SET )
301 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FIT_WITH_ASPECT_RATIO )
302 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FILL_WITH_ASPECT_RATIO )
303 DALI_ENUM_TO_STRING_TABLE_END( SIZE_SCALE_POLICY )
305 DALI_ENUM_TO_STRING_TABLE_BEGIN( CLIPPING_MODE )
306 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, DISABLED )
307 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, CLIP_CHILDREN )
308 DALI_ENUM_TO_STRING_TABLE_END( CLIPPING_MODE )
310 DALI_ENUM_TO_STRING_TABLE_BEGIN( LAYOUT_DIRECTION )
311 DALI_ENUM_TO_STRING_WITH_SCOPE( LayoutDirection, LEFT_TO_RIGHT )
312 DALI_ENUM_TO_STRING_WITH_SCOPE( LayoutDirection, RIGHT_TO_LEFT )
313 DALI_ENUM_TO_STRING_TABLE_END( LAYOUT_DIRECTION )
315 bool GetAnchorPointConstant( const std::string& value, Vector3& anchor )
317 for( uint32_t i = 0; i < ANCHOR_CONSTANT_TABLE_COUNT; ++i )
319 uint32_t sizeIgnored = 0;
320 if( CompareTokens( value.c_str(), ANCHOR_CONSTANT_TABLE[ i ].name, sizeIgnored ) )
322 anchor = ANCHOR_CONSTANT_TABLE[ i ].value;
329 inline bool GetParentOriginConstant( const std::string& value, Vector3& parentOrigin )
331 // Values are the same so just use the same table as anchor-point
332 return GetAnchorPointConstant( value, parentOrigin );
336 * @brief Extract a given dimension from a Vector2
338 * @param[in] values The values to extract from
339 * @param[in] dimension The dimension to extract
340 * @return Return the value for the dimension
342 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
346 case Dimension::WIDTH:
350 case Dimension::HEIGHT:
352 return values.height;
363 * @brief Extract a given dimension from a Vector3
365 * @param[in] values The values to extract from
366 * @param[in] dimension The dimension to extract
367 * @return Return the value for the dimension
369 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
371 return GetDimensionValue( values.GetVectorXY(), dimension );
375 * @brief Recursively emits the visibility-changed-signal on the actor tree.
376 * @param[in] actor The actor to emit the signal on
377 * @param[in] visible The new visibility of the actor
378 * @param[in] type Whether the actor's visible property has changed or a parent's
380 void EmitVisibilityChangedSignalRecursively( ActorPtr actor, bool visible, DevelActor::VisibilityChange::Type type )
384 actor->EmitVisibilityChangedSignal( visible, type );
386 if( actor->GetChildCount() > 0 )
388 ActorContainer& children = actor->GetChildrenInternal();
389 for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter )
391 EmitVisibilityChangedSignalRecursively( *iter, visible, DevelActor::VisibilityChange::PARENT );
397 } // unnamed namespace
399 ActorPtr Actor::New()
401 // pass a reference to actor, actor does not own its node
402 ActorPtr actor( new Actor( BASIC, *CreateNode() ) );
404 // Second-phase construction
410 const SceneGraph::Node* Actor::CreateNode()
412 // create node. Nodes are owned by the update manager
413 SceneGraph::Node* node = SceneGraph::Node::New();
414 OwnerPointer< SceneGraph::Node > transferOwnership( node );
415 AddNodeMessage( Stage::GetCurrent()->GetUpdateManager(), transferOwnership );
420 const std::string& Actor::GetName() const
425 void Actor::SetName( const std::string& name )
429 // ATTENTION: string for debug purposes is not thread safe.
430 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( &GetNode() ), name );
433 uint32_t Actor::GetId() const
435 return GetNode().GetId();
438 bool Actor::OnStage() const
443 Dali::Layer Actor::GetLayer()
447 // Short-circuit for Layer derived actors
450 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
453 // Find the immediate Layer parent
454 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
456 if( parent->IsLayer() )
458 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
465 void Actor::Add( Actor& child )
467 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
468 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
472 mChildren = new ActorContainer;
475 Actor* const oldParent( child.mParent );
477 // child might already be ours
478 if( this != oldParent )
480 // if we already have parent, unparent us first
483 oldParent->Remove( child ); // This causes OnChildRemove callback & ChildRemoved signal
485 // Old parent may need to readjust to missing child
486 if( oldParent->RelayoutDependentOnChildren() )
488 oldParent->RelayoutRequest();
492 // Guard against Add() during previous OnChildRemove callback
495 // Do this first, since user callbacks from within SetParent() may need to remove child
496 mChildren->push_back( ActorPtr( &child ) );
498 // SetParent asserts that child can be added
499 child.SetParent( this );
501 // Notification for derived classes
503 EmitChildAddedSignal( child );
505 InheritLayoutDirectionRecursively( ActorPtr( &child ), mLayoutDirection );
507 // Only put in a relayout request if there is a suitable dependency
508 if( RelayoutDependentOnChildren() )
516 void Actor::Remove( Actor& child )
518 if( (this == &child) || (!mChildren) )
520 // no children or removing itself
526 // Find the child in mChildren, and unparent it
527 ActorIter end = mChildren->end();
528 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
530 ActorPtr actor = (*iter);
532 if( actor.Get() == &child )
534 // Keep handle for OnChildRemove notification
537 // Do this first, since user callbacks from within SetParent() may need to add the child
538 mChildren->erase( iter );
540 DALI_ASSERT_DEBUG( actor->GetParent() == this );
541 actor->SetParent( NULL );
549 // Only put in a relayout request if there is a suitable dependency
550 if( RelayoutDependentOnChildren() )
556 // Notification for derived classes
557 OnChildRemove( child );
558 EmitChildRemovedSignal( child );
561 void Actor::Unparent()
565 // Remove this actor from the parent. The remove will put a relayout request in for
566 // the parent if required
567 mParent->Remove( *this );
568 // mParent is now NULL!
572 uint32_t Actor::GetChildCount() const
574 return ( NULL != mChildren ) ? static_cast<uint32_t>( mChildren->size() ) : 0; // only 4,294,967,295 children per actor
577 ActorPtr Actor::GetChildAt( uint32_t index ) const
579 DALI_ASSERT_ALWAYS( index < GetChildCount() );
581 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
584 ActorPtr Actor::FindChildByName( const std::string& actorName )
587 if( actorName == mName )
593 ActorIter end = mChildren->end();
594 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
596 child = (*iter)->FindChildByName( actorName );
607 ActorPtr Actor::FindChildById( const uint32_t id )
616 ActorIter end = mChildren->end();
617 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
619 child = (*iter)->FindChildById( id );
630 void Actor::SetParentOrigin( const Vector3& origin )
632 // node is being used in a separate thread; queue a message to set the value & base value
633 SetParentOriginMessage( GetEventThreadServices(), GetNode(), origin );
635 // Cache for event-thread access
638 // not allocated, check if different from default
639 if( ParentOrigin::DEFAULT != origin )
641 mParentOrigin = new Vector3( origin );
646 // check if different from current costs more than just set
647 *mParentOrigin = origin;
651 void Actor::SetParentOriginX( float x )
653 const Vector3& current = GetCurrentParentOrigin();
655 SetParentOrigin( Vector3( x, current.y, current.z ) );
658 void Actor::SetParentOriginY( float y )
660 const Vector3& current = GetCurrentParentOrigin();
662 SetParentOrigin( Vector3( current.x, y, current.z ) );
665 void Actor::SetParentOriginZ( float z )
667 const Vector3& current = GetCurrentParentOrigin();
669 SetParentOrigin( Vector3( current.x, current.y, z ) );
672 const Vector3& Actor::GetCurrentParentOrigin() const
674 // Cached for event-thread access
675 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
678 void Actor::SetAnchorPoint( const Vector3& anchor )
680 // node is being used in a separate thread; queue a message to set the value & base value
681 SetAnchorPointMessage( GetEventThreadServices(), GetNode(), anchor );
683 // Cache for event-thread access
686 // not allocated, check if different from default
687 if( AnchorPoint::DEFAULT != anchor )
689 mAnchorPoint = new Vector3( anchor );
694 // check if different from current costs more than just set
695 *mAnchorPoint = anchor;
699 void Actor::SetAnchorPointX( float x )
701 const Vector3& current = GetCurrentAnchorPoint();
703 SetAnchorPoint( Vector3( x, current.y, current.z ) );
706 void Actor::SetAnchorPointY( float y )
708 const Vector3& current = GetCurrentAnchorPoint();
710 SetAnchorPoint( Vector3( current.x, y, current.z ) );
713 void Actor::SetAnchorPointZ( float z )
715 const Vector3& current = GetCurrentAnchorPoint();
717 SetAnchorPoint( Vector3( current.x, current.y, z ) );
720 const Vector3& Actor::GetCurrentAnchorPoint() const
722 // Cached for event-thread access
723 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
726 void Actor::SetPosition( float x, float y )
728 SetPosition( Vector3( x, y, 0.0f ) );
731 void Actor::SetPosition( float x, float y, float z )
733 SetPosition( Vector3( x, y, z ) );
736 void Actor::SetPosition( const Vector3& position )
738 mTargetPosition = position;
740 // node is being used in a separate thread; queue a message to set the value & base value
741 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
744 void Actor::SetX( float x )
746 mTargetPosition.x = x;
748 // node is being used in a separate thread; queue a message to set the value & base value
749 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
752 void Actor::SetY( float y )
754 mTargetPosition.y = y;
756 // node is being used in a separate thread; queue a message to set the value & base value
757 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
760 void Actor::SetZ( float z )
762 mTargetPosition.z = z;
764 // node is being used in a separate thread; queue a message to set the value & base value
765 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
768 void Actor::TranslateBy( const Vector3& distance )
770 mTargetPosition += distance;
772 // node is being used in a separate thread; queue a message to set the value & base value
773 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
776 const Vector3& Actor::GetCurrentPosition() const
778 // node is being used in a separate thread; copy the value from the previous update
779 return GetNode().GetPosition(GetEventThreadServices().GetEventBufferIndex());
782 const Vector3& Actor::GetTargetPosition() const
784 return mTargetPosition;
787 const Vector3& Actor::GetCurrentWorldPosition() const
789 // node is being used in a separate thread; copy the value from the previous update
790 return GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
793 const Vector2 Actor::GetCurrentScreenPosition() const
795 StagePtr stage = Stage::GetCurrent();
796 if( stage && OnStage() )
798 Vector3 worldPosition = GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
799 Vector3 cameraPosition = stage->GetDefaultCameraActor().GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
800 worldPosition -= cameraPosition;
802 Vector3 actorSize = GetCurrentSize() * GetCurrentWorldScale();
803 Vector2 halfStageSize( stage->GetSize() * 0.5f ); // World position origin is center of stage
804 Vector3 halfActorSize( actorSize * 0.5f );
805 Vector3 anchorPointOffSet = halfActorSize - actorSize * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
807 return Vector2( halfStageSize.width + worldPosition.x - anchorPointOffSet.x,
808 halfStageSize.height + worldPosition.y - anchorPointOffSet.y );
811 return Vector2::ZERO;
814 void Actor::SetInheritPosition( bool inherit )
816 if( mInheritPosition != inherit )
818 // non animatable so keep local copy
819 mInheritPosition = inherit;
820 SetInheritPositionMessage( GetEventThreadServices(), GetNode(), inherit );
824 bool Actor::IsPositionInherited() const
826 return mInheritPosition;
829 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
831 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
832 normalizedAxis.Normalize();
834 Quaternion orientation( angle, normalizedAxis );
836 SetOrientation( orientation );
839 void Actor::SetOrientation( const Quaternion& orientation )
841 mTargetOrientation = orientation;
843 // node is being used in a separate thread; queue a message to set the value & base value
844 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation );
847 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
849 RotateBy( Quaternion(angle, axis) );
852 void Actor::RotateBy( const Quaternion& relativeRotation )
854 mTargetOrientation *= Quaternion( relativeRotation );
856 // node is being used in a separate thread; queue a message to set the value & base value
857 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
860 const Quaternion& Actor::GetCurrentOrientation() const
862 // node is being used in a separate thread; copy the value from the previous update
863 return GetNode().GetOrientation(GetEventThreadServices().GetEventBufferIndex());
866 const Quaternion& Actor::GetCurrentWorldOrientation() const
868 // node is being used in a separate thread; copy the value from the previous update
869 return GetNode().GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
872 void Actor::SetScale( float scale )
874 SetScale( Vector3( scale, scale, scale ) );
877 void Actor::SetScale( float x, float y, float z )
879 SetScale( Vector3( x, y, z ) );
882 void Actor::SetScale( const Vector3& scale )
884 mTargetScale = scale;
886 // node is being used in a separate thread; queue a message to set the value & base value
887 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
890 void Actor::SetScaleX( float x )
894 // node is being used in a separate thread; queue a message to set the value & base value
895 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
898 void Actor::SetScaleY( float y )
902 // node is being used in a separate thread; queue a message to set the value & base value
903 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
906 void Actor::SetScaleZ( float z )
910 // node is being used in a separate thread; queue a message to set the value & base value
911 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
914 void Actor::ScaleBy(const Vector3& relativeScale)
916 mTargetScale *= relativeScale;
918 // node is being used in a separate thread; queue a message to set the value & base value
919 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
922 const Vector3& Actor::GetCurrentScale() const
924 // node is being used in a separate thread; copy the value from the previous update
925 return GetNode().GetScale(GetEventThreadServices().GetEventBufferIndex());
928 const Vector3& Actor::GetCurrentWorldScale() const
930 // node is being used in a separate thread; copy the value from the previous update
931 return GetNode().GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
934 void Actor::SetInheritScale( bool inherit )
936 if( mInheritScale != inherit )
938 // non animatable so keep local copy
939 mInheritScale = inherit;
940 // node is being used in a separate thread; queue a message to set the value
941 SetInheritScaleMessage( GetEventThreadServices(), GetNode(), inherit );
945 bool Actor::IsScaleInherited() const
947 return mInheritScale;
950 Matrix Actor::GetCurrentWorldMatrix() const
952 return GetNode().GetWorldMatrix(0);
955 void Actor::SetVisible( bool visible )
957 SetVisibleInternal( visible, SendMessage::TRUE );
960 bool Actor::IsVisible() const
962 // node is being used in a separate thread; copy the value from the previous update
963 return GetNode().IsVisible( GetEventThreadServices().GetEventBufferIndex() );
966 void Actor::SetOpacity( float opacity )
968 mTargetColor.a = opacity;
970 // node is being used in a separate thread; queue a message to set the value & base value
971 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
974 float Actor::GetCurrentOpacity() const
976 // node is being used in a separate thread; copy the value from the previous update
977 return GetNode().GetOpacity(GetEventThreadServices().GetEventBufferIndex());
980 ClippingMode::Type Actor::GetClippingMode() const
982 return mClippingMode;
985 uint32_t Actor::GetSortingDepth()
990 const Vector4& Actor::GetCurrentWorldColor() const
992 return GetNode().GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
995 void Actor::SetColor( const Vector4& color )
997 mTargetColor = color;
999 // node is being used in a separate thread; queue a message to set the value & base value
1000 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::Bake, color );
1003 void Actor::SetColorRed( float red )
1005 mTargetColor.r = red;
1007 // node is being used in a separate thread; queue a message to set the value & base value
1008 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeX, red );
1011 void Actor::SetColorGreen( float green )
1013 mTargetColor.g = green;
1015 // node is being used in a separate thread; queue a message to set the value & base value
1016 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeY, green );
1019 void Actor::SetColorBlue( float blue )
1021 mTargetColor.b = blue;
1023 // node is being used in a separate thread; queue a message to set the value & base value
1024 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1027 const Vector4& Actor::GetCurrentColor() const
1029 // node is being used in a separate thread; copy the value from the previous update
1030 return GetNode().GetColor(GetEventThreadServices().GetEventBufferIndex());
1033 void Actor::SetInheritOrientation( bool inherit )
1035 if( mInheritOrientation != inherit )
1037 // non animatable so keep local copy
1038 mInheritOrientation = inherit;
1039 // node is being used in a separate thread; queue a message to set the value
1040 SetInheritOrientationMessage( GetEventThreadServices(), GetNode(), inherit );
1044 bool Actor::IsOrientationInherited() const
1046 return mInheritOrientation;
1049 void Actor::SetSizeModeFactor( const Vector3& factor )
1051 EnsureRelayoutData();
1053 mRelayoutData->sizeModeFactor = factor;
1056 const Vector3& Actor::GetSizeModeFactor() const
1058 if ( mRelayoutData )
1060 return mRelayoutData->sizeModeFactor;
1063 return GetDefaultSizeModeFactor();
1066 void Actor::SetColorMode( ColorMode colorMode )
1068 // non animatable so keep local copy
1069 mColorMode = colorMode;
1070 // node is being used in a separate thread; queue a message to set the value
1071 SetColorModeMessage( GetEventThreadServices(), GetNode(), colorMode );
1074 ColorMode Actor::GetColorMode() const
1076 // we have cached copy
1080 void Actor::SetSize( float width, float height )
1082 SetSize( Vector2( width, height ) );
1085 void Actor::SetSize( float width, float height, float depth )
1087 SetSize( Vector3( width, height, depth ) );
1090 void Actor::SetSize( const Vector2& size )
1092 SetSize( Vector3( size.width, size.height, 0.f ) );
1095 void Actor::SetSizeInternal( const Vector2& size )
1097 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1100 void Actor::SetSize( const Vector3& size )
1102 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1104 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1105 SetPreferredSize( size.GetVectorXY() );
1109 SetSizeInternal( size );
1113 void Actor::SetSizeInternal( const Vector3& size )
1115 // dont allow recursive loop
1116 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1117 // 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
1118 if( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1119 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1120 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) )
1124 // node is being used in a separate thread; queue a message to set the value & base value
1125 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
1127 // Notification for derived classes
1128 mInsideOnSizeSet = true;
1129 OnSizeSet( mTargetSize );
1130 mInsideOnSizeSet = false;
1132 // Raise a relayout request if the flag is not locked
1133 if( mRelayoutData && !mRelayoutData->insideRelayout )
1140 void Actor::SetWidth( float width )
1142 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1144 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
1145 mRelayoutData->preferredSize.width = width;
1149 mTargetSize.width = width;
1151 // node is being used in a separate thread; queue a message to set the value & base value
1152 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1158 void Actor::SetHeight( float height )
1160 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1162 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
1163 mRelayoutData->preferredSize.height = height;
1167 mTargetSize.height = height;
1169 // node is being used in a separate thread; queue a message to set the value & base value
1170 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1176 void Actor::SetDepth( float depth )
1178 mTargetSize.depth = depth;
1180 // node is being used in a separate thread; queue a message to set the value & base value
1181 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1184 Vector3 Actor::GetTargetSize() const
1186 Vector3 size = mTargetSize;
1188 // Should return preferred size if size is fixed as set by SetSize
1189 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
1191 size.width = GetPreferredSize().width;
1193 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
1195 size.height = GetPreferredSize().height;
1201 const Vector3& Actor::GetCurrentSize() const
1203 // node is being used in a separate thread; copy the value from the previous update
1204 return GetNode().GetSize( GetEventThreadServices().GetEventBufferIndex() );
1207 Vector3 Actor::GetNaturalSize() const
1209 // It is up to deriving classes to return the appropriate natural size
1210 return Vector3( 0.0f, 0.0f, 0.0f );
1213 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1215 EnsureRelayoutData();
1217 ResizePolicy::Type originalWidthPolicy = GetResizePolicy(Dimension::WIDTH);
1218 ResizePolicy::Type originalHeightPolicy = GetResizePolicy(Dimension::HEIGHT);
1220 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1222 if( dimension & ( 1 << i ) )
1224 if ( policy == ResizePolicy::USE_ASSIGNED_SIZE )
1226 mRelayoutData->useAssignedSize[ i ] = true;
1230 mRelayoutData->resizePolicies[ i ] = policy;
1231 mRelayoutData->useAssignedSize[ i ] = false;
1236 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1238 if( dimension & Dimension::WIDTH )
1240 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1243 if( dimension & Dimension::HEIGHT )
1245 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1249 // If calling SetResizePolicy, assume we want relayout enabled
1250 SetRelayoutEnabled( true );
1252 // If the resize policy is set to be FIXED, the preferred size
1253 // should be overrided by the target size. Otherwise the target
1254 // size should be overrided by the preferred size.
1256 if( dimension & Dimension::WIDTH )
1258 if( originalWidthPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1260 mRelayoutData->preferredSize.width = mTargetSize.width;
1262 else if( originalWidthPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1264 mTargetSize.width = mRelayoutData->preferredSize.width;
1268 if( dimension & Dimension::HEIGHT )
1270 if( originalHeightPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1272 mRelayoutData->preferredSize.height = mTargetSize.height;
1274 else if( originalHeightPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1276 mTargetSize.height = mRelayoutData->preferredSize.height;
1280 OnSetResizePolicy( policy, dimension );
1282 // Trigger relayout on this control
1286 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1288 if ( mRelayoutData )
1290 // If more than one dimension is requested, just return the first one found
1291 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1293 if( ( dimension & ( 1 << i ) ) )
1295 if( mRelayoutData->useAssignedSize[ i ] )
1297 return ResizePolicy::USE_ASSIGNED_SIZE;
1301 return mRelayoutData->resizePolicies[ i ];
1307 return ResizePolicy::DEFAULT;
1310 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1312 EnsureRelayoutData();
1314 mRelayoutData->sizeSetPolicy = policy;
1317 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1319 if ( mRelayoutData )
1321 return mRelayoutData->sizeSetPolicy;
1324 return DEFAULT_SIZE_SCALE_POLICY;
1327 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1329 EnsureRelayoutData();
1331 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1333 if( dimension & ( 1 << i ) )
1335 mRelayoutData->dimensionDependencies[ i ] = dependency;
1340 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1342 if ( mRelayoutData )
1344 // If more than one dimension is requested, just return the first one found
1345 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1347 if( ( dimension & ( 1 << i ) ) )
1349 return mRelayoutData->dimensionDependencies[ i ];
1354 return Dimension::ALL_DIMENSIONS; // Default
1357 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1359 // If relayout data has not been allocated yet and the client is requesting
1360 // to disable it, do nothing
1361 if( mRelayoutData || relayoutEnabled )
1363 EnsureRelayoutData();
1365 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1367 mRelayoutData->relayoutEnabled = relayoutEnabled;
1371 bool Actor::IsRelayoutEnabled() const
1373 // Assume that if relayout data has not been allocated yet then
1374 // relayout is disabled
1375 return mRelayoutData && mRelayoutData->relayoutEnabled;
1378 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1380 EnsureRelayoutData();
1382 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1384 if( dimension & ( 1 << i ) )
1386 mRelayoutData->dimensionDirty[ i ] = dirty;
1391 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1393 if ( mRelayoutData )
1395 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1397 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1407 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1409 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1412 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1414 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1417 uint32_t Actor::AddRenderer( Renderer& renderer )
1421 mRenderers = new RendererContainer;
1424 uint32_t index = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1425 RendererPtr rendererPtr = RendererPtr( &renderer );
1426 mRenderers->push_back( rendererPtr );
1427 AttachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1431 uint32_t Actor::GetRendererCount() const
1433 uint32_t rendererCount(0);
1436 rendererCount = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1439 return rendererCount;
1442 RendererPtr Actor::GetRendererAt( uint32_t index )
1444 RendererPtr renderer;
1445 if( index < GetRendererCount() )
1447 renderer = ( *mRenderers )[ index ];
1453 void Actor::RemoveRenderer( Renderer& renderer )
1457 RendererIter end = mRenderers->end();
1458 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1460 if( (*iter).Get() == &renderer )
1462 mRenderers->erase( iter );
1463 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1470 void Actor::RemoveRenderer( uint32_t index )
1472 if( index < GetRendererCount() )
1474 RendererPtr renderer = ( *mRenderers )[ index ];
1475 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.Get()->GetRendererSceneObject() );
1476 mRenderers->erase( mRenderers->begin()+index );
1480 bool Actor::IsOverlay() const
1482 return ( DrawMode::OVERLAY_2D == mDrawMode );
1485 void Actor::SetDrawMode( DrawMode::Type drawMode )
1487 // this flag is not animatable so keep the value
1488 mDrawMode = drawMode;
1490 // node is being used in a separate thread; queue a message to set the value
1491 SetDrawModeMessage( GetEventThreadServices(), GetNode(), drawMode );
1494 DrawMode::Type Actor::GetDrawMode() const
1499 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1501 // only valid when on-stage
1502 StagePtr stage = Stage::GetCurrent();
1503 if( stage && OnStage() )
1505 const RenderTaskList& taskList = stage->GetRenderTaskList();
1507 Vector2 converted( screenX, screenY );
1509 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1510 uint32_t taskCount = taskList.GetTaskCount();
1511 for( uint32_t i = taskCount; i > 0; --i )
1513 RenderTaskPtr task = taskList.GetTask( i - 1 );
1514 if( ScreenToLocal( *task, localX, localY, screenX, screenY ) )
1516 // found a task where this conversion was ok so return
1524 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1526 bool retval = false;
1527 // only valid when on-stage
1530 CameraActor* camera = renderTask.GetCameraActor();
1534 renderTask.GetViewport( viewport );
1536 // need to translate coordinates to render tasks coordinate space
1537 Vector2 converted( screenX, screenY );
1538 if( renderTask.TranslateCoordinates( converted ) )
1540 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1547 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1549 // Early-out if not on stage
1555 // Get the ModelView matrix
1557 Matrix::Multiply( modelView, GetNode().GetWorldMatrix(0), viewMatrix );
1559 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1560 Matrix invertedMvp( false/*don't init*/);
1561 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1562 bool success = invertedMvp.Invert();
1564 // Convert to GL coordinates
1565 Vector4 screenPos( screenX - static_cast<float>( viewport.x ), static_cast<float>( viewport.height ) - screenY - static_cast<float>( viewport.y ), 0.f, 1.f );
1570 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), nearPos );
1577 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), farPos );
1583 if( XyPlaneIntersect( nearPos, farPos, local ) )
1585 Vector3 size = GetCurrentSize();
1586 localX = local.x + size.x * 0.5f;
1587 localY = local.y + size.y * 0.5f;
1598 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1601 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1603 Mathematical Formulation
1605 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1607 ( p - c ) dot ( p - c ) = r^2
1609 Given a ray with a point of origin 'o', and a direction vector 'd':
1611 ray(t) = o + td, t >= 0
1613 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1615 (o + td - c ) dot ( o + td - c ) = r^2
1617 To solve for t we first expand the above into a more recognisable quadratic equation form
1619 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1628 B = 2( o - c ) dot d
1629 C = ( o - c ) dot ( o - c ) - r^2
1631 which can be solved using a standard quadratic formula.
1633 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1635 Practical Simplification
1637 In a renderer, we often differentiate between world space and object space. In the object space
1638 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1639 into object space, the mathematical solution presented above can be simplified significantly.
1641 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1645 and we can find the t at which the (transformed) ray intersects the sphere by
1647 ( o + td ) dot ( o + td ) = r^2
1649 According to the reasoning above, we expand the above quadratic equation into the general form
1653 which now has coefficients:
1660 // Early-out if not on stage
1666 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1668 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1669 const Vector3& translation( GetNode().GetWorldPosition( bufferIndex ) );
1670 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1672 // Compute the radius is not needed, square radius it's enough.
1673 const Vector3& size( GetNode().GetSize( bufferIndex ) );
1675 // Scale the sphere.
1676 const Vector3& scale( GetNode().GetWorldScale( bufferIndex ) );
1678 const float width = size.width * scale.width;
1679 const float height = size.height * scale.height;
1681 float squareSphereRadius = 0.5f * ( width * width + height * height );
1683 float a = rayDir.Dot( rayDir ); // a
1684 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1685 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1687 return ( b2 * b2 - a * c ) >= 0.f;
1690 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector2& hitPointLocal, float& distance ) const
1696 // Transforms the ray to the local reference system.
1697 // Calculate the inverse of Model matrix
1698 Matrix invModelMatrix( false/*don't init*/);
1700 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1701 invModelMatrix = GetNode().GetWorldMatrix(0);
1702 invModelMatrix.Invert();
1704 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1705 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1707 // Test with the actor's XY plane (Normal = 0 0 1 1).
1709 float a = -rayOriginLocal.z;
1710 float b = rayDirLocal.z;
1712 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1714 // Ray travels distance * rayDirLocal to intersect with plane.
1717 const Vector3& size = GetNode().GetSize( bufferIndex );
1719 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1720 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1722 // Test with the actor's geometry.
1723 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1730 void Actor::SetLeaveRequired( bool required )
1732 mLeaveRequired = required;
1735 bool Actor::GetLeaveRequired() const
1737 return mLeaveRequired;
1740 void Actor::SetKeyboardFocusable( bool focusable )
1742 mKeyboardFocusable = focusable;
1745 bool Actor::IsKeyboardFocusable() const
1747 return mKeyboardFocusable;
1750 bool Actor::GetTouchRequired() const
1752 return !mTouchedSignal.Empty() || !mTouchSignal.Empty() || mDerivedRequiresTouch;
1755 bool Actor::GetHoverRequired() const
1757 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1760 bool Actor::GetWheelEventRequired() const
1762 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1765 bool Actor::IsHittable() const
1767 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1770 ActorGestureData& Actor::GetGestureData()
1772 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1773 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1774 if( NULL == mGestureData )
1776 mGestureData = new ActorGestureData;
1778 return *mGestureData;
1781 bool Actor::IsGestureRequred( Gesture::Type type ) const
1783 return mGestureData && mGestureData->IsGestureRequred( type );
1786 bool Actor::EmitTouchEventSignal( const TouchEvent& event, const Dali::TouchData& touch )
1788 bool consumed = false;
1790 if( !mTouchSignal.Empty() )
1792 Dali::Actor handle( this );
1793 consumed = mTouchSignal.Emit( handle, touch );
1796 if( !mTouchedSignal.Empty() )
1798 Dali::Actor handle( this );
1799 consumed |= mTouchedSignal.Emit( handle, event );
1804 // Notification for derived classes
1805 consumed = OnTouchEvent( event ); // TODO
1811 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1813 bool consumed = false;
1815 if( !mHoveredSignal.Empty() )
1817 Dali::Actor handle( this );
1818 consumed = mHoveredSignal.Emit( handle, event );
1823 // Notification for derived classes
1824 consumed = OnHoverEvent( event );
1830 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1832 bool consumed = false;
1834 if( !mWheelEventSignal.Empty() )
1836 Dali::Actor handle( this );
1837 consumed = mWheelEventSignal.Emit( handle, event );
1842 // Notification for derived classes
1843 consumed = OnWheelEvent( event );
1849 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
1851 if( ! mVisibilityChangedSignal.Empty() )
1853 Dali::Actor handle( this );
1854 mVisibilityChangedSignal.Emit( handle, visible, type );
1858 void Actor::EmitLayoutDirectionChangedSignal( LayoutDirection::Type type )
1860 if( ! mLayoutDirectionChangedSignal.Empty() )
1862 Dali::Actor handle( this );
1863 mLayoutDirectionChangedSignal.Emit( handle, type );
1867 void Actor::EmitChildAddedSignal( Actor& child )
1869 if( ! mChildAddedSignal.Empty() )
1871 Dali::Actor handle( &child );
1872 mChildAddedSignal.Emit( handle );
1876 void Actor::EmitChildRemovedSignal( Actor& child )
1878 if( ! mChildRemovedSignal.Empty() )
1880 Dali::Actor handle( &child );
1881 mChildRemovedSignal.Emit( handle );
1885 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
1887 return mTouchedSignal;
1890 Dali::Actor::TouchDataSignalType& Actor::TouchSignal()
1892 return mTouchSignal;
1895 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
1897 return mHoveredSignal;
1900 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
1902 return mWheelEventSignal;
1905 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
1907 return mOnStageSignal;
1910 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
1912 return mOffStageSignal;
1915 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
1917 return mOnRelayoutSignal;
1920 DevelActor::VisibilityChangedSignalType& Actor::VisibilityChangedSignal()
1922 return mVisibilityChangedSignal;
1925 Dali::Actor::LayoutDirectionChangedSignalType& Actor::LayoutDirectionChangedSignal()
1927 return mLayoutDirectionChangedSignal;
1930 DevelActor::ChildChangedSignalType& Actor::ChildAddedSignal()
1932 return mChildAddedSignal;
1935 DevelActor::ChildChangedSignalType& Actor::ChildRemovedSignal()
1937 return mChildRemovedSignal;
1940 DevelActor::ChildOrderChangedSignalType& Actor::ChildOrderChangedSignal()
1942 return mChildOrderChangedSignal;
1945 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1947 bool connected( true );
1948 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
1950 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1952 actor->TouchedSignal().Connect( tracker, functor );
1954 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1956 actor->HoveredSignal().Connect( tracker, functor );
1958 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1960 actor->WheelEventSignal().Connect( tracker, functor );
1962 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
1964 actor->OnStageSignal().Connect( tracker, functor );
1966 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
1968 actor->OffStageSignal().Connect( tracker, functor );
1970 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
1972 actor->OnRelayoutSignal().Connect( tracker, functor );
1974 else if( 0 == signalName.compare( SIGNAL_TOUCH ) )
1976 actor->TouchSignal().Connect( tracker, functor );
1978 else if( 0 == signalName.compare( SIGNAL_VISIBILITY_CHANGED ) )
1980 actor->VisibilityChangedSignal().Connect( tracker, functor );
1982 else if( 0 == signalName.compare( SIGNAL_LAYOUT_DIRECTION_CHANGED ) )
1984 actor->LayoutDirectionChangedSignal().Connect( tracker, functor );
1986 else if( 0 == signalName.compare( SIGNAL_CHILD_ADDED ) )
1988 actor->ChildAddedSignal().Connect( tracker, functor );
1990 else if( 0 == signalName.compare( SIGNAL_CHILD_REMOVED ) )
1992 actor->ChildRemovedSignal().Connect( tracker, functor );
1996 // signalName does not match any signal
2003 Actor::Actor( DerivedType derivedType, const SceneGraph::Node& node )
2008 mParentOrigin( NULL ),
2009 mAnchorPoint( NULL ),
2010 mRelayoutData( NULL ),
2011 mGestureData( NULL ),
2015 mWheelEventSignal(),
2018 mOnRelayoutSignal(),
2019 mVisibilityChangedSignal(),
2020 mLayoutDirectionChangedSignal(),
2021 mChildAddedSignal(),
2022 mChildRemovedSignal(),
2023 mChildOrderChangedSignal(),
2024 mTargetOrientation( Quaternion::IDENTITY ),
2025 mTargetColor( Color::WHITE ),
2026 mTargetSize( Vector3::ZERO ),
2027 mTargetPosition( Vector3::ZERO ),
2028 mTargetScale( Vector3::ONE ),
2032 mIsRoot( ROOT_LAYER == derivedType ),
2033 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2034 mIsOnStage( false ),
2036 mLeaveRequired( false ),
2037 mKeyboardFocusable( false ),
2038 mDerivedRequiresTouch( false ),
2039 mDerivedRequiresHover( false ),
2040 mDerivedRequiresWheelEvent( false ),
2041 mOnStageSignalled( false ),
2042 mInsideOnSizeSet( false ),
2043 mInheritPosition( true ),
2044 mInheritOrientation( true ),
2045 mInheritScale( true ),
2046 mPositionUsesAnchorPoint( true ),
2048 mInheritLayoutDirection( true ),
2049 mLayoutDirection( LayoutDirection::LEFT_TO_RIGHT ),
2050 mDrawMode( DrawMode::NORMAL ),
2051 mColorMode( Node::DEFAULT_COLOR_MODE ),
2052 mClippingMode( ClippingMode::DISABLED )
2056 void Actor::Initialize()
2060 GetEventThreadServices().RegisterObject( this );
2065 // Remove mParent pointers from children even if we're destroying core,
2066 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2069 ActorConstIter endIter = mChildren->end();
2070 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2072 (*iter)->SetParent( NULL );
2078 // Guard to allow handle destruction after Core has been destroyed
2079 if( EventThreadServices::IsCoreRunning() )
2081 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
2083 GetEventThreadServices().UnregisterObject( this );
2086 // Cleanup optional gesture data
2087 delete mGestureData;
2089 // Cleanup optional parent origin and anchor
2090 delete mParentOrigin;
2091 delete mAnchorPoint;
2093 // Delete optional relayout data
2094 delete mRelayoutData;
2097 void Actor::ConnectToStage( uint32_t parentDepth )
2099 // This container is used instead of walking the Actor hierarchy.
2100 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
2101 ActorContainer connectionList;
2103 StagePtr stage = Stage::GetCurrent();
2106 stage->RequestRebuildDepthTree();
2109 // This stage is atomic i.e. not interrupted by user callbacks.
2110 RecursiveConnectToStage( connectionList, parentDepth + 1 );
2112 // Notify applications about the newly connected actors.
2113 const ActorIter endIter = connectionList.end();
2114 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2116 (*iter)->NotifyStageConnection();
2122 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, uint32_t depth )
2124 DALI_ASSERT_ALWAYS( !OnStage() );
2127 mDepth = static_cast< uint16_t >( depth ); // overflow ignored, not expected in practice
2129 ConnectToSceneGraph();
2131 // Notification for internal derived classes
2132 OnStageConnectionInternal();
2134 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2135 connectionList.push_back( ActorPtr( this ) );
2137 // Recursively connect children
2140 ActorConstIter endIter = mChildren->end();
2141 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2143 (*iter)->RecursiveConnectToStage( connectionList, depth + 1 );
2149 * This method is called when the Actor is connected to the Stage.
2150 * The parent must have added its Node to the scene-graph.
2151 * The child must connect its Node to the parent's Node.
2152 * This is recursive; the child calls ConnectToStage() for its children.
2154 void Actor::ConnectToSceneGraph()
2156 DALI_ASSERT_DEBUG( mParent != NULL);
2158 // Reparent Node in next Update
2159 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), mParent->GetNode(), GetNode() );
2161 // Request relayout on all actors that are added to the scenegraph
2164 // Notification for Object::Observers
2168 void Actor::NotifyStageConnection()
2170 // Actors can be removed (in a callback), before the on-stage stage is reported.
2171 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2172 if( OnStage() && !mOnStageSignalled )
2174 // Notification for external (CustomActor) derived classes
2175 OnStageConnectionExternal( mDepth );
2177 if( !mOnStageSignal.Empty() )
2179 Dali::Actor handle( this );
2180 mOnStageSignal.Emit( handle );
2183 // Guard against Remove during callbacks
2186 mOnStageSignalled = true; // signal required next time Actor is removed
2191 void Actor::DisconnectFromStage()
2193 // This container is used instead of walking the Actor hierachy.
2194 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2195 ActorContainer disconnectionList;
2197 StagePtr stage = Stage::GetCurrent();
2200 stage->RequestRebuildDepthTree();
2203 // This stage is atomic i.e. not interrupted by user callbacks
2204 RecursiveDisconnectFromStage( disconnectionList );
2206 // Notify applications about the newly disconnected actors.
2207 const ActorIter endIter = disconnectionList.end();
2208 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2210 (*iter)->NotifyStageDisconnection();
2214 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2216 // need to change state first so that internals relying on IsOnStage() inside OnStageDisconnectionInternal() get the correct value
2219 // Recursively disconnect children
2222 ActorConstIter endIter = mChildren->end();
2223 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2225 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2229 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2230 disconnectionList.push_back( ActorPtr( this ) );
2232 // Notification for internal derived classes
2233 OnStageDisconnectionInternal();
2235 DisconnectFromSceneGraph();
2239 * This method is called by an actor or its parent, before a node removal message is sent.
2240 * This is recursive; the child calls DisconnectFromStage() for its children.
2242 void Actor::DisconnectFromSceneGraph()
2244 // Notification for Object::Observers
2245 OnSceneObjectRemove();
2248 void Actor::NotifyStageDisconnection()
2250 // Actors can be added (in a callback), before the off-stage state is reported.
2251 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2252 // only do this step if there is a stage, i.e. Core is not being shut down
2253 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2255 // Notification for external (CustomeActor) derived classes
2256 OnStageDisconnectionExternal();
2258 if( !mOffStageSignal.Empty() )
2260 Dali::Actor handle( this );
2261 mOffStageSignal.Emit( handle );
2264 // Guard against Add during callbacks
2267 mOnStageSignalled = false; // signal required next time Actor is added
2272 bool Actor::IsNodeConnected() const
2274 bool connected( false );
2278 if( IsRoot() || GetNode().GetParent() )
2287 // This method initiates traversal of the actor tree using depth-first
2288 // traversal to set a depth index based on traversal order. It sends a
2289 // single message to update manager to update all the actor's nodes in
2290 // this tree with the depth index. The sceneGraphNodeDepths vector's
2291 // elements are ordered by depth, and could be used to reduce sorting
2292 // in the update thread.
2293 void Actor::RebuildDepthTree()
2295 DALI_LOG_TIMER_START(depthTimer);
2297 // Vector of scene-graph nodes and their depths to send to UpdateManager
2298 // in a single message
2299 OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths( new SceneGraph::NodeDepths() );
2301 int32_t depthIndex = 1;
2302 DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
2304 SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths );
2305 DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
2308 void Actor::DepthTraverseActorTree( OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths, int32_t& depthIndex )
2310 mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
2311 sceneGraphNodeDepths->Add( const_cast<SceneGraph::Node*>( &GetNode() ), mSortedDepth );
2313 // Create/add to children of this node
2316 for( ActorContainer::iterator it = mChildren->begin(); it != mChildren->end(); ++it )
2318 Actor* childActor = (*it).Get();
2320 childActor->DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
2325 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2329 case Dali::Actor::Property::PARENT_ORIGIN:
2331 Property::Type type = property.GetType();
2332 if( type == Property::VECTOR3 )
2334 SetParentOrigin( property.Get< Vector3 >() );
2336 else if ( type == Property::STRING )
2338 std::string parentOriginString;
2339 property.Get( parentOriginString );
2340 Vector3 parentOrigin;
2341 if( GetParentOriginConstant( parentOriginString, parentOrigin ) )
2343 SetParentOrigin( parentOrigin );
2349 case Dali::Actor::Property::PARENT_ORIGIN_X:
2351 SetParentOriginX( property.Get< float >() );
2355 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2357 SetParentOriginY( property.Get< float >() );
2361 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2363 SetParentOriginZ( property.Get< float >() );
2367 case Dali::Actor::Property::ANCHOR_POINT:
2369 Property::Type type = property.GetType();
2370 if( type == Property::VECTOR3 )
2372 SetAnchorPoint( property.Get< Vector3 >() );
2374 else if ( type == Property::STRING )
2376 std::string anchorPointString;
2377 property.Get( anchorPointString );
2379 if( GetAnchorPointConstant( anchorPointString, anchor ) )
2381 SetAnchorPoint( anchor );
2387 case Dali::Actor::Property::ANCHOR_POINT_X:
2389 SetAnchorPointX( property.Get< float >() );
2393 case Dali::Actor::Property::ANCHOR_POINT_Y:
2395 SetAnchorPointY( property.Get< float >() );
2399 case Dali::Actor::Property::ANCHOR_POINT_Z:
2401 SetAnchorPointZ( property.Get< float >() );
2405 case Dali::Actor::Property::SIZE:
2407 SetSize( property.Get< Vector3 >() );
2411 case Dali::Actor::Property::SIZE_WIDTH:
2413 SetWidth( property.Get< float >() );
2417 case Dali::Actor::Property::SIZE_HEIGHT:
2419 SetHeight( property.Get< float >() );
2423 case Dali::Actor::Property::SIZE_DEPTH:
2425 SetDepth( property.Get< float >() );
2429 case Dali::Actor::Property::POSITION:
2431 SetPosition( property.Get< Vector3 >() );
2435 case Dali::Actor::Property::POSITION_X:
2437 SetX( property.Get< float >() );
2441 case Dali::Actor::Property::POSITION_Y:
2443 SetY( property.Get< float >() );
2447 case Dali::Actor::Property::POSITION_Z:
2449 SetZ( property.Get< float >() );
2453 case Dali::Actor::Property::ORIENTATION:
2455 SetOrientation( property.Get< Quaternion >() );
2459 case Dali::Actor::Property::SCALE:
2461 SetScale( property.Get< Vector3 >() );
2465 case Dali::Actor::Property::SCALE_X:
2467 SetScaleX( property.Get< float >() );
2471 case Dali::Actor::Property::SCALE_Y:
2473 SetScaleY( property.Get< float >() );
2477 case Dali::Actor::Property::SCALE_Z:
2479 SetScaleZ( property.Get< float >() );
2483 case Dali::Actor::Property::VISIBLE:
2485 SetVisible( property.Get< bool >() );
2489 case Dali::Actor::Property::COLOR:
2491 SetColor( property.Get< Vector4 >() );
2495 case Dali::Actor::Property::COLOR_RED:
2497 SetColorRed( property.Get< float >() );
2501 case Dali::Actor::Property::COLOR_GREEN:
2503 SetColorGreen( property.Get< float >() );
2507 case Dali::Actor::Property::COLOR_BLUE:
2509 SetColorBlue( property.Get< float >() );
2513 case Dali::Actor::Property::COLOR_ALPHA:
2514 case Dali::DevelActor::Property::OPACITY:
2517 if( property.Get( value ) )
2519 SetOpacity( value );
2524 case Dali::Actor::Property::NAME:
2526 SetName( property.Get< std::string >() );
2530 case Dali::Actor::Property::SENSITIVE:
2532 SetSensitive( property.Get< bool >() );
2536 case Dali::Actor::Property::LEAVE_REQUIRED:
2538 SetLeaveRequired( property.Get< bool >() );
2542 case Dali::Actor::Property::INHERIT_POSITION:
2544 SetInheritPosition( property.Get< bool >() );
2548 case Dali::Actor::Property::INHERIT_ORIENTATION:
2550 SetInheritOrientation( property.Get< bool >() );
2554 case Dali::Actor::Property::INHERIT_SCALE:
2556 SetInheritScale( property.Get< bool >() );
2560 case Dali::Actor::Property::COLOR_MODE:
2562 ColorMode mode = mColorMode;
2563 if ( Scripting::GetEnumerationProperty< ColorMode >( property, COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT, mode ) )
2565 SetColorMode( mode );
2570 case Dali::Actor::Property::DRAW_MODE:
2572 DrawMode::Type mode = mDrawMode;
2573 if( Scripting::GetEnumerationProperty< DrawMode::Type >( property, DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT, mode ) )
2575 SetDrawMode( mode );
2580 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2582 SetSizeModeFactor( property.Get< Vector3 >() );
2586 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2588 ResizePolicy::Type type = GetResizePolicy( Dimension::WIDTH );
2589 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2591 SetResizePolicy( type, Dimension::WIDTH );
2596 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2598 ResizePolicy::Type type = GetResizePolicy( Dimension::HEIGHT );
2599 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2601 SetResizePolicy( type, Dimension::HEIGHT );
2606 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2608 SizeScalePolicy::Type type = GetSizeScalePolicy();
2609 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT, type ) )
2611 SetSizeScalePolicy( type );
2616 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2618 if( property.Get< bool >() )
2620 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2625 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2627 if( property.Get< bool >() )
2629 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2634 case Dali::Actor::Property::PADDING:
2636 Vector4 padding = property.Get< Vector4 >();
2637 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2638 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2642 case Dali::Actor::Property::MINIMUM_SIZE:
2644 Vector2 size = property.Get< Vector2 >();
2645 SetMinimumSize( size.x, Dimension::WIDTH );
2646 SetMinimumSize( size.y, Dimension::HEIGHT );
2650 case Dali::Actor::Property::MAXIMUM_SIZE:
2652 Vector2 size = property.Get< Vector2 >();
2653 SetMaximumSize( size.x, Dimension::WIDTH );
2654 SetMaximumSize( size.y, Dimension::HEIGHT );
2658 case Dali::DevelActor::Property::SIBLING_ORDER:
2662 if( property.Get( value ) )
2664 SetSiblingOrder( value );
2669 case Dali::Actor::Property::CLIPPING_MODE:
2671 ClippingMode::Type convertedValue = mClippingMode;
2672 if( Scripting::GetEnumerationProperty< ClippingMode::Type >( property, CLIPPING_MODE_TABLE, CLIPPING_MODE_TABLE_COUNT, convertedValue ) )
2674 mClippingMode = convertedValue;
2675 SetClippingModeMessage( GetEventThreadServices(), GetNode(), mClippingMode );
2680 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
2683 if( property.Get( value ) && value != mPositionUsesAnchorPoint )
2685 mPositionUsesAnchorPoint = value;
2686 SetPositionUsesAnchorPointMessage( GetEventThreadServices(), GetNode(), mPositionUsesAnchorPoint );
2691 case Dali::Actor::Property::LAYOUT_DIRECTION:
2693 Dali::LayoutDirection::Type direction = mLayoutDirection;
2694 mInheritLayoutDirection = false;
2696 if( Scripting::GetEnumerationProperty< LayoutDirection::Type >( property, LAYOUT_DIRECTION_TABLE, LAYOUT_DIRECTION_TABLE_COUNT, direction ) )
2698 InheritLayoutDirectionRecursively( this, direction, true );
2703 case Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION:
2706 if( property.Get( value ) )
2708 SetInheritLayoutDirection( value );
2715 // this can happen in the case of a non-animatable default property so just do nothing
2721 // TODO: This method needs to be removed
2722 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2724 switch( entry.GetType() )
2726 case Property::BOOLEAN:
2728 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2729 DALI_ASSERT_DEBUG( NULL != property );
2731 // property is being used in a separate thread; queue a message to set the property
2732 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2737 case Property::INTEGER:
2739 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2740 DALI_ASSERT_DEBUG( NULL != property );
2742 // property is being used in a separate thread; queue a message to set the property
2743 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2748 case Property::FLOAT:
2750 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2751 DALI_ASSERT_DEBUG( NULL != property );
2753 // property is being used in a separate thread; queue a message to set the property
2754 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2759 case Property::VECTOR2:
2761 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2762 DALI_ASSERT_DEBUG( NULL != property );
2764 // property is being used in a separate thread; queue a message to set the property
2765 if(entry.componentIndex == 0)
2767 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2769 else if(entry.componentIndex == 1)
2771 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2775 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2781 case Property::VECTOR3:
2783 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2784 DALI_ASSERT_DEBUG( NULL != property );
2786 // property is being used in a separate thread; queue a message to set the property
2787 if(entry.componentIndex == 0)
2789 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2791 else if(entry.componentIndex == 1)
2793 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2795 else if(entry.componentIndex == 2)
2797 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2801 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2807 case Property::VECTOR4:
2809 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2810 DALI_ASSERT_DEBUG( NULL != property );
2812 // property is being used in a separate thread; queue a message to set the property
2813 if(entry.componentIndex == 0)
2815 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
2817 else if(entry.componentIndex == 1)
2819 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
2821 else if(entry.componentIndex == 2)
2823 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
2825 else if(entry.componentIndex == 3)
2827 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
2831 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2837 case Property::ROTATION:
2839 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
2840 DALI_ASSERT_DEBUG( NULL != property );
2842 // property is being used in a separate thread; queue a message to set the property
2843 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
2848 case Property::MATRIX:
2850 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
2851 DALI_ASSERT_DEBUG( NULL != property );
2853 // property is being used in a separate thread; queue a message to set the property
2854 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), &GetNode(), property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
2859 case Property::MATRIX3:
2861 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
2862 DALI_ASSERT_DEBUG( NULL != property );
2864 // property is being used in a separate thread; queue a message to set the property
2865 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), &GetNode(), property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
2872 // nothing to do for other types
2877 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
2879 Property::Value value;
2881 if( ! GetCachedPropertyValue( index, value ) )
2883 // If property value is not stored in the event-side, then it must be a scene-graph only property
2884 GetCurrentPropertyValue( index, value );
2890 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
2892 Property::Value value;
2894 if( ! GetCurrentPropertyValue( index, value ) )
2896 // If unable to retrieve scene-graph property value, then it must be an event-side only property
2897 GetCachedPropertyValue( index, value );
2903 void Actor::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
2905 switch( animationType )
2908 case Animation::BETWEEN:
2912 case Dali::Actor::Property::SIZE:
2914 if( value.Get( mTargetSize ) )
2916 // Notify deriving classes
2917 OnSizeAnimation( animation, mTargetSize );
2922 case Dali::Actor::Property::SIZE_WIDTH:
2924 if( value.Get( mTargetSize.width ) )
2926 // Notify deriving classes
2927 OnSizeAnimation( animation, mTargetSize );
2932 case Dali::Actor::Property::SIZE_HEIGHT:
2934 if( value.Get( mTargetSize.height ) )
2936 // Notify deriving classes
2937 OnSizeAnimation( animation, mTargetSize );
2942 case Dali::Actor::Property::SIZE_DEPTH:
2944 if( value.Get( mTargetSize.depth ) )
2946 // Notify deriving classes
2947 OnSizeAnimation( animation, mTargetSize );
2952 case Dali::Actor::Property::POSITION:
2954 value.Get( mTargetPosition );
2958 case Dali::Actor::Property::POSITION_X:
2960 value.Get( mTargetPosition.x );
2964 case Dali::Actor::Property::POSITION_Y:
2966 value.Get( mTargetPosition.y );
2970 case Dali::Actor::Property::POSITION_Z:
2972 value.Get( mTargetPosition.z );
2976 case Dali::Actor::Property::ORIENTATION:
2978 value.Get( mTargetOrientation );
2982 case Dali::Actor::Property::SCALE:
2984 value.Get( mTargetScale );
2988 case Dali::Actor::Property::SCALE_X:
2990 value.Get( mTargetScale.x );
2994 case Dali::Actor::Property::SCALE_Y:
2996 value.Get( mTargetScale.y );
3000 case Dali::Actor::Property::SCALE_Z:
3002 value.Get( mTargetScale.z );
3006 case Dali::Actor::Property::VISIBLE:
3008 SetVisibleInternal( value.Get< bool >(), SendMessage::FALSE );
3012 case Dali::Actor::Property::COLOR:
3014 value.Get( mTargetColor );
3018 case Dali::Actor::Property::COLOR_RED:
3020 value.Get( mTargetColor.r );
3024 case Dali::Actor::Property::COLOR_GREEN:
3026 value.Get( mTargetColor.g );
3030 case Dali::Actor::Property::COLOR_BLUE:
3032 value.Get( mTargetColor.b );
3036 case Dali::Actor::Property::COLOR_ALPHA:
3037 case Dali::DevelActor::Property::OPACITY:
3039 value.Get( mTargetColor.a );
3045 // Not an animatable property. Do nothing.
3056 case Dali::Actor::Property::SIZE:
3058 if( AdjustValue< Vector3 >( mTargetSize, value ) )
3060 // Notify deriving classes
3061 OnSizeAnimation( animation, mTargetSize );
3066 case Dali::Actor::Property::SIZE_WIDTH:
3068 if( AdjustValue< float >( mTargetSize.width, value ) )
3070 // Notify deriving classes
3071 OnSizeAnimation( animation, mTargetSize );
3076 case Dali::Actor::Property::SIZE_HEIGHT:
3078 if( AdjustValue< float >( mTargetSize.height, value ) )
3080 // Notify deriving classes
3081 OnSizeAnimation( animation, mTargetSize );
3086 case Dali::Actor::Property::SIZE_DEPTH:
3088 if( AdjustValue< float >( mTargetSize.depth, value ) )
3090 // Notify deriving classes
3091 OnSizeAnimation( animation, mTargetSize );
3096 case Dali::Actor::Property::POSITION:
3098 AdjustValue< Vector3 >( mTargetPosition, value );
3102 case Dali::Actor::Property::POSITION_X:
3104 AdjustValue< float >( mTargetPosition.x, value );
3108 case Dali::Actor::Property::POSITION_Y:
3110 AdjustValue< float >( mTargetPosition.y, value );
3114 case Dali::Actor::Property::POSITION_Z:
3116 AdjustValue< float >( mTargetPosition.z, value );
3120 case Dali::Actor::Property::ORIENTATION:
3122 Quaternion relativeValue;
3123 if( value.Get( relativeValue ) )
3125 mTargetOrientation *= relativeValue;
3130 case Dali::Actor::Property::SCALE:
3132 AdjustValue< Vector3 >( mTargetScale, value );
3136 case Dali::Actor::Property::SCALE_X:
3138 AdjustValue< float >( mTargetScale.x, value );
3142 case Dali::Actor::Property::SCALE_Y:
3144 AdjustValue< float >( mTargetScale.y, value );
3148 case Dali::Actor::Property::SCALE_Z:
3150 AdjustValue< float >( mTargetScale.z, value );
3154 case Dali::Actor::Property::VISIBLE:
3156 bool relativeValue = false;
3157 if( value.Get( relativeValue ) )
3159 bool visible = mVisible || relativeValue;
3160 SetVisibleInternal( visible, SendMessage::FALSE );
3165 case Dali::Actor::Property::COLOR:
3167 AdjustValue< Vector4 >( mTargetColor, value );
3171 case Dali::Actor::Property::COLOR_RED:
3173 AdjustValue< float >( mTargetColor.r, value );
3177 case Dali::Actor::Property::COLOR_GREEN:
3179 AdjustValue< float >( mTargetColor.g, value );
3183 case Dali::Actor::Property::COLOR_BLUE:
3185 AdjustValue< float >( mTargetColor.b, value );
3189 case Dali::Actor::Property::COLOR_ALPHA:
3190 case Dali::DevelActor::Property::OPACITY:
3192 AdjustValue< float >( mTargetColor.a, value );
3198 // Not an animatable property. Do nothing.
3207 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3209 const PropertyBase* property( NULL );
3213 case Dali::Actor::Property::SIZE: // FALLTHROUGH
3214 case Dali::Actor::Property::SIZE_WIDTH: // FALLTHROUGH
3215 case Dali::Actor::Property::SIZE_HEIGHT: // FALLTHROUGH
3216 case Dali::Actor::Property::SIZE_DEPTH:
3218 property = &GetNode().mSize;
3221 case Dali::Actor::Property::POSITION: // FALLTHROUGH
3222 case Dali::Actor::Property::POSITION_X: // FALLTHROUGH
3223 case Dali::Actor::Property::POSITION_Y: // FALLTHROUGH
3224 case Dali::Actor::Property::POSITION_Z:
3226 property = &GetNode().mPosition;
3229 case Dali::Actor::Property::ORIENTATION:
3231 property = &GetNode().mOrientation;
3234 case Dali::Actor::Property::SCALE: // FALLTHROUGH
3235 case Dali::Actor::Property::SCALE_X: // FALLTHROUGH
3236 case Dali::Actor::Property::SCALE_Y: // FALLTHROUGH
3237 case Dali::Actor::Property::SCALE_Z:
3239 property = &GetNode().mScale;
3242 case Dali::Actor::Property::VISIBLE:
3244 property = &GetNode().mVisible;
3247 case Dali::Actor::Property::COLOR: // FALLTHROUGH
3248 case Dali::Actor::Property::COLOR_RED: // FALLTHROUGH
3249 case Dali::Actor::Property::COLOR_GREEN: // FALLTHROUGH
3250 case Dali::Actor::Property::COLOR_BLUE: // FALLTHROUGH
3251 case Dali::Actor::Property::COLOR_ALPHA: // FALLTHROUGH
3252 case Dali::DevelActor::Property::OPACITY:
3254 property = &GetNode().mColor;
3264 // not our property, ask base
3265 property = Object::GetSceneObjectAnimatableProperty( index );
3271 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3273 const PropertyInputImpl* property( NULL );
3277 case Dali::Actor::Property::PARENT_ORIGIN: // FALLTHROUGH
3278 case Dali::Actor::Property::PARENT_ORIGIN_X: // FALLTHROUGH
3279 case Dali::Actor::Property::PARENT_ORIGIN_Y: // FALLTHROUGH
3280 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3282 property = &GetNode().mParentOrigin;
3285 case Dali::Actor::Property::ANCHOR_POINT: // FALLTHROUGH
3286 case Dali::Actor::Property::ANCHOR_POINT_X: // FALLTHROUGH
3287 case Dali::Actor::Property::ANCHOR_POINT_Y: // FALLTHROUGH
3288 case Dali::Actor::Property::ANCHOR_POINT_Z:
3290 property = &GetNode().mAnchorPoint;
3293 case Dali::Actor::Property::WORLD_POSITION: // FALLTHROUGH
3294 case Dali::Actor::Property::WORLD_POSITION_X: // FALLTHROUGH
3295 case Dali::Actor::Property::WORLD_POSITION_Y: // FALLTHROUGH
3296 case Dali::Actor::Property::WORLD_POSITION_Z:
3298 property = &GetNode().mWorldPosition;
3301 case Dali::Actor::Property::WORLD_ORIENTATION:
3303 property = &GetNode().mWorldOrientation;
3306 case Dali::Actor::Property::WORLD_SCALE:
3308 property = &GetNode().mWorldScale;
3311 case Dali::Actor::Property::WORLD_COLOR:
3313 property = &GetNode().mWorldColor;
3316 case Dali::Actor::Property::WORLD_MATRIX:
3318 property = &GetNode().mWorldMatrix;
3321 case Dali::DevelActor::Property::CULLED:
3323 property = &GetNode().mCulled;
3333 // reuse animatable property getter as animatable properties are inputs as well
3334 // animatable property chains back to Object::GetSceneObjectInputProperty() so all properties get covered
3335 property = GetSceneObjectAnimatableProperty( index );
3341 int32_t Actor::GetPropertyComponentIndex( Property::Index index ) const
3343 int32_t componentIndex = Property::INVALID_COMPONENT_INDEX;
3347 case Dali::Actor::Property::PARENT_ORIGIN_X:
3348 case Dali::Actor::Property::ANCHOR_POINT_X:
3349 case Dali::Actor::Property::SIZE_WIDTH:
3350 case Dali::Actor::Property::POSITION_X:
3351 case Dali::Actor::Property::WORLD_POSITION_X:
3352 case Dali::Actor::Property::SCALE_X:
3353 case Dali::Actor::Property::COLOR_RED:
3359 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3360 case Dali::Actor::Property::ANCHOR_POINT_Y:
3361 case Dali::Actor::Property::SIZE_HEIGHT:
3362 case Dali::Actor::Property::POSITION_Y:
3363 case Dali::Actor::Property::WORLD_POSITION_Y:
3364 case Dali::Actor::Property::SCALE_Y:
3365 case Dali::Actor::Property::COLOR_GREEN:
3371 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3372 case Dali::Actor::Property::ANCHOR_POINT_Z:
3373 case Dali::Actor::Property::SIZE_DEPTH:
3374 case Dali::Actor::Property::POSITION_Z:
3375 case Dali::Actor::Property::WORLD_POSITION_Z:
3376 case Dali::Actor::Property::SCALE_Z:
3377 case Dali::Actor::Property::COLOR_BLUE:
3383 case Dali::Actor::Property::COLOR_ALPHA:
3384 case Dali::DevelActor::Property::OPACITY:
3396 if( Property::INVALID_COMPONENT_INDEX == componentIndex )
3399 componentIndex = Object::GetPropertyComponentIndex( index );
3402 return componentIndex;
3405 void Actor::SetParent( Actor* parent )
3409 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3413 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3416 // Instruct each actor to create a corresponding node in the scene graph
3417 ConnectToStage( parent->GetHierarchyDepth() );
3420 // Resolve the name and index for the child properties if any
3421 ResolveChildProperties();
3423 else // parent being set to NULL
3425 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3429 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3432 // Disconnect the Node & its children from the scene-graph.
3433 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
3435 // Instruct each actor to discard pointers to the scene-graph
3436 DisconnectFromStage();
3441 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3444 Actor* actor = dynamic_cast< Actor* >( object );
3448 if( 0 == actionName.compare( ACTION_SHOW ) )
3450 actor->SetVisible( true );
3453 else if( 0 == actionName.compare( ACTION_HIDE ) )
3455 actor->SetVisible( false );
3463 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
3465 bool valueSet = true;
3469 case Dali::Actor::Property::PARENT_ORIGIN:
3471 value = GetCurrentParentOrigin();
3475 case Dali::Actor::Property::PARENT_ORIGIN_X:
3477 value = GetCurrentParentOrigin().x;
3481 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3483 value = GetCurrentParentOrigin().y;
3487 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3489 value = GetCurrentParentOrigin().z;
3493 case Dali::Actor::Property::ANCHOR_POINT:
3495 value = GetCurrentAnchorPoint();
3499 case Dali::Actor::Property::ANCHOR_POINT_X:
3501 value = GetCurrentAnchorPoint().x;
3505 case Dali::Actor::Property::ANCHOR_POINT_Y:
3507 value = GetCurrentAnchorPoint().y;
3511 case Dali::Actor::Property::ANCHOR_POINT_Z:
3513 value = GetCurrentAnchorPoint().z;
3517 case Dali::Actor::Property::SIZE:
3519 value = GetTargetSize();
3523 case Dali::Actor::Property::SIZE_WIDTH:
3525 value = GetTargetSize().width;
3529 case Dali::Actor::Property::SIZE_HEIGHT:
3531 value = GetTargetSize().height;
3535 case Dali::Actor::Property::SIZE_DEPTH:
3537 value = GetTargetSize().depth;
3541 case Dali::Actor::Property::POSITION:
3543 value = GetTargetPosition();
3547 case Dali::Actor::Property::POSITION_X:
3549 value = GetTargetPosition().x;
3553 case Dali::Actor::Property::POSITION_Y:
3555 value = GetTargetPosition().y;
3559 case Dali::Actor::Property::POSITION_Z:
3561 value = GetTargetPosition().z;
3565 case Dali::Actor::Property::ORIENTATION:
3567 value = mTargetOrientation;
3571 case Dali::Actor::Property::SCALE:
3573 value = mTargetScale;
3577 case Dali::Actor::Property::SCALE_X:
3579 value = mTargetScale.x;
3583 case Dali::Actor::Property::SCALE_Y:
3585 value = mTargetScale.y;
3589 case Dali::Actor::Property::SCALE_Z:
3591 value = mTargetScale.z;
3595 case Dali::Actor::Property::VISIBLE:
3601 case Dali::Actor::Property::COLOR:
3603 value = mTargetColor;
3607 case Dali::Actor::Property::COLOR_RED:
3609 value = mTargetColor.r;
3613 case Dali::Actor::Property::COLOR_GREEN:
3615 value = mTargetColor.g;
3619 case Dali::Actor::Property::COLOR_BLUE:
3621 value = mTargetColor.b;
3625 case Dali::Actor::Property::COLOR_ALPHA:
3626 case Dali::DevelActor::Property::OPACITY:
3628 value = mTargetColor.a;
3632 case Dali::Actor::Property::NAME:
3638 case Dali::Actor::Property::SENSITIVE:
3640 value = IsSensitive();
3644 case Dali::Actor::Property::LEAVE_REQUIRED:
3646 value = GetLeaveRequired();
3650 case Dali::Actor::Property::INHERIT_POSITION:
3652 value = IsPositionInherited();
3656 case Dali::Actor::Property::INHERIT_ORIENTATION:
3658 value = IsOrientationInherited();
3662 case Dali::Actor::Property::INHERIT_SCALE:
3664 value = IsScaleInherited();
3668 case Dali::Actor::Property::COLOR_MODE:
3670 value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
3674 case Dali::Actor::Property::DRAW_MODE:
3676 value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
3680 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3682 value = GetSizeModeFactor();
3686 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3688 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3692 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3694 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3698 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3700 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT );
3704 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3706 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3710 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3712 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3716 case Dali::Actor::Property::PADDING:
3718 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3719 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3720 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3724 case Dali::Actor::Property::MINIMUM_SIZE:
3726 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3730 case Dali::Actor::Property::MAXIMUM_SIZE:
3732 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3736 case Dali::Actor::Property::CLIPPING_MODE:
3738 value = mClippingMode;
3742 case Dali::DevelActor::Property::SIBLING_ORDER:
3744 value = static_cast<int>( GetSiblingOrder() );
3748 case Dali::DevelActor::Property::SCREEN_POSITION:
3750 value = GetCurrentScreenPosition();
3754 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
3756 value = mPositionUsesAnchorPoint;
3760 case Dali::Actor::Property::LAYOUT_DIRECTION:
3762 value = mLayoutDirection;
3766 case Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION:
3768 value = IsLayoutDirectionInherited();
3774 // Must be a scene-graph only property
3783 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
3785 bool valueSet = true;
3789 case Dali::Actor::Property::SIZE:
3791 value = GetCurrentSize();
3795 case Dali::Actor::Property::SIZE_WIDTH:
3797 value = GetCurrentSize().width;
3801 case Dali::Actor::Property::SIZE_HEIGHT:
3803 value = GetCurrentSize().height;
3807 case Dali::Actor::Property::SIZE_DEPTH:
3809 value = GetCurrentSize().depth;
3813 case Dali::Actor::Property::POSITION:
3815 value = GetCurrentPosition();
3819 case Dali::Actor::Property::POSITION_X:
3821 value = GetCurrentPosition().x;
3825 case Dali::Actor::Property::POSITION_Y:
3827 value = GetCurrentPosition().y;
3831 case Dali::Actor::Property::POSITION_Z:
3833 value = GetCurrentPosition().z;
3837 case Dali::Actor::Property::WORLD_POSITION:
3839 value = GetCurrentWorldPosition();
3843 case Dali::Actor::Property::WORLD_POSITION_X:
3845 value = GetCurrentWorldPosition().x;
3849 case Dali::Actor::Property::WORLD_POSITION_Y:
3851 value = GetCurrentWorldPosition().y;
3855 case Dali::Actor::Property::WORLD_POSITION_Z:
3857 value = GetCurrentWorldPosition().z;
3861 case Dali::Actor::Property::ORIENTATION:
3863 value = GetCurrentOrientation();
3867 case Dali::Actor::Property::WORLD_ORIENTATION:
3869 value = GetCurrentWorldOrientation();
3873 case Dali::Actor::Property::SCALE:
3875 value = GetCurrentScale();
3879 case Dali::Actor::Property::SCALE_X:
3881 value = GetCurrentScale().x;
3885 case Dali::Actor::Property::SCALE_Y:
3887 value = GetCurrentScale().y;
3891 case Dali::Actor::Property::SCALE_Z:
3893 value = GetCurrentScale().z;
3897 case Dali::Actor::Property::WORLD_SCALE:
3899 value = GetCurrentWorldScale();
3903 case Dali::Actor::Property::COLOR:
3905 value = GetCurrentColor();
3909 case Dali::Actor::Property::COLOR_RED:
3911 value = GetCurrentColor().r;
3915 case Dali::Actor::Property::COLOR_GREEN:
3917 value = GetCurrentColor().g;
3921 case Dali::Actor::Property::COLOR_BLUE:
3923 value = GetCurrentColor().b;
3927 case Dali::Actor::Property::COLOR_ALPHA:
3928 case Dali::DevelActor::Property::OPACITY:
3930 value = GetCurrentColor().a;
3934 case Dali::Actor::Property::WORLD_COLOR:
3936 value = GetCurrentWorldColor();
3940 case Dali::Actor::Property::WORLD_MATRIX:
3942 value = GetCurrentWorldMatrix();
3946 case Dali::Actor::Property::VISIBLE:
3948 value = IsVisible();
3952 case DevelActor::Property::CULLED:
3954 value = GetNode().IsCulled( GetEventThreadServices().GetEventBufferIndex() );
3960 // Must be an event-side only property
3969 void Actor::EnsureRelayoutData()
3971 // Assign relayout data.
3972 if( !mRelayoutData )
3974 mRelayoutData = new RelayoutData();
3978 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3980 // Check if actor is dependent on parent
3981 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3983 if( ( dimension & ( 1 << i ) ) )
3985 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3986 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
3996 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
3998 // Check if actor is dependent on children
3999 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4001 if( ( dimension & ( 1 << i ) ) )
4003 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4004 switch( resizePolicy )
4006 case ResizePolicy::FIT_TO_CHILDREN:
4007 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
4023 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
4025 return Actor::RelayoutDependentOnChildren( dimension );
4028 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
4030 // Check each possible dimension and see if it is dependent on the input one
4031 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4033 if( dimension & ( 1 << i ) )
4035 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
4042 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
4044 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4046 if( dimension & ( 1 << i ) )
4048 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
4053 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
4055 // If more than one dimension is requested, just return the first one found
4056 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4058 if( ( dimension & ( 1 << i ) ) )
4060 return mRelayoutData->negotiatedDimensions[ i ];
4064 return 0.0f; // Default
4067 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
4069 EnsureRelayoutData();
4071 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4073 if( dimension & ( 1 << i ) )
4075 mRelayoutData->dimensionPadding[ i ] = padding;
4080 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4082 if ( mRelayoutData )
4084 // If more than one dimension is requested, just return the first one found
4085 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4087 if( ( dimension & ( 1 << i ) ) )
4089 return mRelayoutData->dimensionPadding[ i ];
4094 return GetDefaultDimensionPadding();
4097 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4099 EnsureRelayoutData();
4101 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4103 if( dimension & ( 1 << i ) )
4105 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4110 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4112 if ( mRelayoutData )
4114 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4116 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4126 float Actor::GetHeightForWidthBase( float width )
4128 float height = 0.0f;
4130 const Vector3 naturalSize = GetNaturalSize();
4131 if( naturalSize.width > 0.0f )
4133 height = naturalSize.height * width / naturalSize.width;
4135 else // we treat 0 as 1:1 aspect ratio
4143 float Actor::GetWidthForHeightBase( float height )
4147 const Vector3 naturalSize = GetNaturalSize();
4148 if( naturalSize.height > 0.0f )
4150 width = naturalSize.width * height / naturalSize.height;
4152 else // we treat 0 as 1:1 aspect ratio
4160 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4162 // Fill to parent, taking size mode factor into account
4163 switch( child.GetResizePolicy( dimension ) )
4165 case ResizePolicy::FILL_TO_PARENT:
4167 return GetLatestSize( dimension );
4170 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4172 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4175 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4177 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4182 return GetLatestSize( dimension );
4187 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4189 // Can be overridden in derived class
4190 return CalculateChildSizeBase( child, dimension );
4193 float Actor::GetHeightForWidth( float width )
4195 // Can be overridden in derived class
4196 return GetHeightForWidthBase( width );
4199 float Actor::GetWidthForHeight( float height )
4201 // Can be overridden in derived class
4202 return GetWidthForHeightBase( height );
4205 float Actor::GetLatestSize( Dimension::Type dimension ) const
4207 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4210 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4212 Vector2 padding = GetPadding( dimension );
4214 return GetLatestSize( dimension ) + padding.x + padding.y;
4217 float Actor::NegotiateFromParent( Dimension::Type dimension )
4219 Actor* parent = GetParent();
4222 Vector2 padding( GetPadding( dimension ) );
4223 Vector2 parentPadding( parent->GetPadding( dimension ) );
4224 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4230 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4232 float maxDimensionPoint = 0.0f;
4234 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4236 ActorPtr child = GetChildAt( i );
4238 if( !child->RelayoutDependentOnParent( dimension ) )
4240 // Calculate the min and max points that the children range across
4241 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
4242 float dimensionSize = child->GetRelayoutSize( dimension );
4243 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4247 return maxDimensionPoint;
4250 float Actor::GetSize( Dimension::Type dimension ) const
4252 return GetDimensionValue( mTargetSize, dimension );
4255 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4257 return GetDimensionValue( GetNaturalSize(), dimension );
4260 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4262 switch( GetResizePolicy( dimension ) )
4264 case ResizePolicy::USE_NATURAL_SIZE:
4266 return GetNaturalSize( dimension );
4269 case ResizePolicy::FIXED:
4271 return GetDimensionValue( GetPreferredSize(), dimension );
4274 case ResizePolicy::USE_ASSIGNED_SIZE:
4276 return GetDimensionValue( maximumSize, dimension );
4279 case ResizePolicy::FILL_TO_PARENT:
4280 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4281 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4283 return NegotiateFromParent( dimension );
4286 case ResizePolicy::FIT_TO_CHILDREN:
4288 return NegotiateFromChildren( dimension );
4291 case ResizePolicy::DIMENSION_DEPENDENCY:
4293 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4296 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4298 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4301 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4303 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4315 return 0.0f; // Default
4318 float Actor::ClampDimension( float size, Dimension::Type dimension )
4320 const float minSize = GetMinimumSize( dimension );
4321 const float maxSize = GetMaximumSize( dimension );
4323 return std::max( minSize, std::min( size, maxSize ) );
4326 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4328 // Check if it needs to be negotiated
4329 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4331 // Check that we havn't gotten into an infinite loop
4332 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4333 bool recursionFound = false;
4334 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4336 if( *it == searchActor )
4338 recursionFound = true;
4343 if( !recursionFound )
4345 // Record the path that we have taken
4346 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4348 // Dimension dependency check
4349 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4351 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4353 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4355 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4359 // Parent dependency check
4360 Actor* parent = GetParent();
4361 if( parent && RelayoutDependentOnParent( dimension ) )
4363 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4366 // Children dependency check
4367 if( RelayoutDependentOnChildren( dimension ) )
4369 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4371 ActorPtr child = GetChildAt( i );
4373 // Only relayout child first if it is not dependent on this actor
4374 if( !child->RelayoutDependentOnParent( dimension ) )
4376 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
4381 // For deriving classes
4382 OnCalculateRelayoutSize( dimension );
4384 // All dependencies checked, calculate the size and set negotiated flag
4385 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4387 SetNegotiatedDimension( newSize, dimension );
4388 SetLayoutNegotiated( true, dimension );
4390 // For deriving classes
4391 OnLayoutNegotiated( newSize, dimension );
4393 // This actor has been successfully processed, pop it off the recursion stack
4394 recursionStack.pop_back();
4398 // TODO: Break infinite loop
4399 SetLayoutNegotiated( true, dimension );
4404 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4406 // Negotiate all dimensions that require it
4407 ActorDimensionStack recursionStack;
4409 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4411 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4414 NegotiateDimension( dimension, allocatedSize, recursionStack );
4418 Vector2 Actor::ApplySizeSetPolicy( const Vector2& size )
4420 switch( mRelayoutData->sizeSetPolicy )
4422 case SizeScalePolicy::USE_SIZE_SET:
4427 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4429 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4430 const Vector3 naturalSize = GetNaturalSize();
4431 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4433 const float sizeRatio = size.width / size.height;
4434 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4436 if( naturalSizeRatio < sizeRatio )
4438 return Vector2( naturalSizeRatio * size.height, size.height );
4440 else if( naturalSizeRatio > sizeRatio )
4442 return Vector2( size.width, size.width / naturalSizeRatio );
4453 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4455 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4456 const Vector3 naturalSize = GetNaturalSize();
4457 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4459 const float sizeRatio = size.width / size.height;
4460 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4462 if( naturalSizeRatio < sizeRatio )
4464 return Vector2( size.width, size.width / naturalSizeRatio );
4466 else if( naturalSizeRatio > sizeRatio )
4468 return Vector2( naturalSizeRatio * size.height, size.height );
4487 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4489 // Do the set actor size
4490 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4492 // Adjust for size set policy
4493 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4495 // Lock the flag to stop recursive relayouts on set size
4496 mRelayoutData->insideRelayout = true;
4497 SetSize( negotiatedSize );
4498 mRelayoutData->insideRelayout = false;
4500 // Clear flags for all dimensions
4501 SetLayoutDirty( false );
4503 // Give deriving classes a chance to respond
4504 OnRelayout( negotiatedSize, container );
4506 if( !mOnRelayoutSignal.Empty() )
4508 Dali::Actor handle( this );
4509 mOnRelayoutSignal.Emit( handle );
4513 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4515 // Force a size negotiation for actors that has assigned size during relayout
4516 // This is required as otherwise the flags that force a relayout will not
4517 // necessarilly be set. This will occur if the actor has already been laid out.
4518 // The dirty flags are then cleared. Then if the actor is added back into the
4519 // relayout container afterwards, the dirty flags would still be clear...
4520 // causing a relayout to be skipped. Here we force any actors added to the
4521 // container to be relayed out.
4522 DALI_LOG_TIMER_START( NegSizeTimer1 );
4524 if( GetUseAssignedSize(Dimension::WIDTH ) )
4526 SetLayoutNegotiated( false, Dimension::WIDTH );
4528 if( GetUseAssignedSize( Dimension::HEIGHT ) )
4530 SetLayoutNegotiated( false, Dimension::HEIGHT );
4533 // Do the negotiation
4534 NegotiateDimensions( allocatedSize );
4536 // Set the actor size
4537 SetNegotiatedSize( container );
4539 // Negotiate down to children
4540 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4542 ActorPtr child = GetChildAt( i );
4544 // Forces children that have already been laid out to be relayed out
4545 // if they have assigned size during relayout.
4546 if( child->GetUseAssignedSize(Dimension::WIDTH) )
4548 child->SetLayoutNegotiated(false, Dimension::WIDTH);
4549 child->SetLayoutDirty(true, Dimension::WIDTH);
4552 if( child->GetUseAssignedSize(Dimension::HEIGHT) )
4554 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
4555 child->SetLayoutDirty(true, Dimension::HEIGHT);
4558 // Only relayout if required
4559 if( child->RelayoutRequired() )
4561 container.Add( Dali::Actor( child.Get() ), mTargetSize.GetVectorXY() );
4564 DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
4567 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
4571 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4573 if( dimension & ( 1 << i ) )
4575 mRelayoutData->useAssignedSize[ i ] = use;
4581 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
4583 if ( mRelayoutData )
4585 // If more than one dimension is requested, just return the first one found
4586 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4588 if( dimension & ( 1 << i ) )
4590 return mRelayoutData->useAssignedSize[ i ];
4598 void Actor::RelayoutRequest( Dimension::Type dimension )
4600 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4601 if( relayoutController )
4603 Dali::Actor self( this );
4604 relayoutController->RequestRelayout( self, dimension );
4608 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4612 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4616 void Actor::SetPreferredSize( const Vector2& size )
4618 EnsureRelayoutData();
4620 if( size.width > 0.0f )
4622 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4625 if( size.height > 0.0f )
4627 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4630 mRelayoutData->preferredSize = size;
4635 Vector2 Actor::GetPreferredSize() const
4637 if ( mRelayoutData )
4639 return Vector2( mRelayoutData->preferredSize );
4642 return GetDefaultPreferredSize();
4645 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4647 EnsureRelayoutData();
4649 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4651 if( dimension & ( 1 << i ) )
4653 mRelayoutData->minimumSize[ i ] = size;
4660 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4662 if ( mRelayoutData )
4664 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4666 if( dimension & ( 1 << i ) )
4668 return mRelayoutData->minimumSize[ i ];
4673 return 0.0f; // Default
4676 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4678 EnsureRelayoutData();
4680 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4682 if( dimension & ( 1 << i ) )
4684 mRelayoutData->maximumSize[ i ] = size;
4691 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4693 if ( mRelayoutData )
4695 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4697 if( dimension & ( 1 << i ) )
4699 return mRelayoutData->maximumSize[ i ];
4704 return FLT_MAX; // Default
4707 Object* Actor::GetParentObject() const
4712 void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
4714 if( mVisible != visible )
4716 if( sendMessage == SendMessage::TRUE )
4718 // node is being used in a separate thread; queue a message to set the value & base value
4719 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible );
4724 // Emit the signal on this actor and all its children
4725 EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
4729 void Actor::SetSiblingOrder( uint32_t order )
4733 ActorContainer& siblings = *(mParent->mChildren);
4734 uint32_t currentOrder = GetSiblingOrder();
4736 if( order != currentOrder )
4742 else if( order < siblings.size() -1 )
4744 if( order > currentOrder )
4746 RaiseAbove( *siblings[order] );
4750 LowerBelow( *siblings[order] );
4761 uint32_t Actor::GetSiblingOrder() const
4767 ActorContainer& siblings = *(mParent->mChildren);
4768 for( std::size_t i = 0; i < siblings.size(); ++i )
4770 if( siblings[i] == this )
4772 order = static_cast<uint32_t>( i );
4781 void Actor::RequestRebuildDepthTree()
4785 StagePtr stage = Stage::GetCurrent();
4788 stage->RequestRebuildDepthTree();
4797 ActorContainer& siblings = *(mParent->mChildren);
4798 if( siblings.back() != this ) // If not already at end
4800 for( std::size_t i=0; i<siblings.size(); ++i )
4802 if( siblings[i] == this )
4805 ActorPtr next = siblings[i+1];
4806 siblings[i+1] = this;
4813 Dali::Actor handle( this );
4814 mParent->mChildOrderChangedSignal.Emit( handle );
4816 RequestRebuildDepthTree();
4820 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4828 ActorContainer& siblings = *(mParent->mChildren);
4829 if( siblings.front() != this ) // If not already at beginning
4831 for( std::size_t i=1; i<siblings.size(); ++i )
4833 if( siblings[i] == this )
4835 // Swap with previous
4836 ActorPtr previous = siblings[i-1];
4837 siblings[i-1] = this;
4838 siblings[i] = previous;
4844 Dali::Actor handle( this );
4845 mParent->mChildOrderChangedSignal.Emit( handle );
4847 RequestRebuildDepthTree();
4851 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4855 void Actor::RaiseToTop()
4859 ActorContainer& siblings = *(mParent->mChildren);
4860 if( siblings.back() != this ) // If not already at end
4862 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
4863 if( iter != siblings.end() )
4865 siblings.erase(iter);
4866 siblings.push_back(ActorPtr(this));
4870 Dali::Actor handle( this );
4871 mParent->mChildOrderChangedSignal.Emit( handle );
4873 RequestRebuildDepthTree();
4877 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4881 void Actor::LowerToBottom()
4885 ActorContainer& siblings = *(mParent->mChildren);
4886 if( siblings.front() != this ) // If not already at bottom,
4888 ActorPtr thisPtr(this); // ensure this actor remains referenced.
4890 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
4891 if( iter != siblings.end() )
4893 siblings.erase(iter);
4894 siblings.insert(siblings.begin(), thisPtr);
4898 Dali::Actor handle( this );
4899 mParent->mChildOrderChangedSignal.Emit( handle );
4901 RequestRebuildDepthTree();
4905 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4909 void Actor::RaiseAbove( Internal::Actor& target )
4913 ActorContainer& siblings = *(mParent->mChildren);
4914 if( siblings.back() != this && target.mParent == mParent ) // If not already at top
4916 ActorPtr thisPtr(this); // ensure this actor remains referenced.
4918 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
4919 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
4920 if( thisIter < targetIter )
4922 siblings.erase(thisIter);
4923 // Erasing early invalidates the targetIter. (Conversely, inserting first may also
4924 // invalidate thisIter)
4925 targetIter = std::find( siblings.begin(), siblings.end(), &target );
4927 siblings.insert(targetIter, thisPtr);
4930 Dali::Actor handle( this );
4931 mParent->mChildOrderChangedSignal.Emit( handle );
4933 RequestRebuildDepthTree();
4938 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4942 void Actor::LowerBelow( Internal::Actor& target )
4946 ActorContainer& siblings = *(mParent->mChildren);
4947 if( siblings.front() != this && target.mParent == mParent ) // If not already at bottom
4949 ActorPtr thisPtr(this); // ensure this actor remains referenced.
4951 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
4952 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
4954 if( thisIter > targetIter )
4956 siblings.erase(thisIter); // this only invalidates iterators at or after this point.
4957 siblings.insert(targetIter, thisPtr);
4960 Dali::Actor handle( this );
4961 mParent->mChildOrderChangedSignal.Emit( handle );
4963 RequestRebuildDepthTree();
4968 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4972 void Actor::SetInheritLayoutDirection( bool inherit )
4974 if( mInheritLayoutDirection != inherit )
4976 mInheritLayoutDirection = inherit;
4978 if( inherit && mParent )
4980 InheritLayoutDirectionRecursively( this, mParent->mLayoutDirection );
4985 bool Actor::IsLayoutDirectionInherited() const
4987 return mInheritLayoutDirection;
4990 void Actor::InheritLayoutDirectionRecursively( ActorPtr actor, Dali::LayoutDirection::Type direction, bool set )
4992 if( actor && ( actor->mInheritLayoutDirection || set ) )
4994 if( actor->mLayoutDirection != direction )
4996 actor->mLayoutDirection = direction;
4997 actor->EmitLayoutDirectionChangedSignal( direction );
4998 actor->RelayoutRequest();
5001 if( actor->GetChildCount() > 0 )
5003 ActorContainer& children = actor->GetChildrenInternal();
5004 for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter )
5006 InheritLayoutDirectionRecursively( *iter, direction );
5012 } // namespace Internal