2 * Copyright (c) 2019 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/event/actors/actor-impl.h>
27 #include <dali/devel-api/actors/layer-devel.h>
28 #include <dali/public-api/common/dali-common.h>
29 #include <dali/public-api/common/constants.h>
30 #include <dali/public-api/events/touch-data.h>
31 #include <dali/public-api/math/vector2.h>
32 #include <dali/public-api/math/vector3.h>
33 #include <dali/public-api/math/radian.h>
34 #include <dali/public-api/object/type-registry.h>
35 #include <dali/devel-api/actors/actor-devel.h>
36 #include <dali/devel-api/scripting/scripting.h>
37 #include <dali/internal/common/internal-constants.h>
38 #include <dali/internal/event/common/event-thread-services.h>
39 #include <dali/internal/event/render-tasks/render-task-impl.h>
40 #include <dali/internal/event/actors/camera-actor-impl.h>
41 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
42 #include <dali/internal/event/common/property-helper.h>
43 #include <dali/internal/event/common/stage-impl.h>
44 #include <dali/internal/event/common/type-info-impl.h>
45 #include <dali/internal/event/common/scene-impl.h>
46 #include <dali/internal/event/common/thread-local-storage.h>
47 #include <dali/internal/event/animation/constraint-impl.h>
48 #include <dali/internal/event/common/projection.h>
49 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
50 #include <dali/internal/update/common/animatable-property.h>
51 #include <dali/internal/update/nodes/node-messages.h>
52 #include <dali/internal/update/nodes/node-declarations.h>
53 #include <dali/internal/update/animation/scene-graph-constraint.h>
54 #include <dali/internal/event/events/actor-gesture-data.h>
55 #include <dali/internal/common/message.h>
56 #include <dali/integration-api/debug.h>
58 using Dali::Internal::SceneGraph::Node;
59 using Dali::Internal::SceneGraph::AnimatableProperty;
60 using Dali::Internal::SceneGraph::PropertyBase;
62 #if defined(DEBUG_ENABLED)
63 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_DEPTH_TIMER" );
64 Debug::Filter* gLogRelayoutFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_TIMER" );
75 /// Using a function because of library initialisation order. Vector3::ONE may not have been initialised yet.
76 inline const Vector3& GetDefaultSizeModeFactor()
81 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
82 inline const Vector2& GetDefaultPreferredSize()
87 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
88 inline const Vector2& GetDefaultDimensionPadding()
93 const SizeScalePolicy::Type DEFAULT_SIZE_SCALE_POLICY = SizeScalePolicy::USE_SIZE_SET;
95 } // unnamed namespace
98 * Struct to collect relayout variables
100 struct Actor::RelayoutData
103 : sizeModeFactor( GetDefaultSizeModeFactor() ), preferredSize( GetDefaultPreferredSize() ), sizeSetPolicy( DEFAULT_SIZE_SCALE_POLICY ), relayoutEnabled( false ), insideRelayout( false )
105 // Set size negotiation defaults
106 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
108 resizePolicies[ i ] = ResizePolicy::DEFAULT;
109 useAssignedSize[ i ] = false;
110 negotiatedDimensions[ i ] = 0.0f;
111 dimensionNegotiated[ i ] = false;
112 dimensionDirty[ i ] = false;
113 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
114 dimensionPadding[ i ] = GetDefaultDimensionPadding();
115 minimumSize[ i ] = 0.0f;
116 maximumSize[ i ] = FLT_MAX;
120 ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies
121 bool useAssignedSize[ Dimension::DIMENSION_COUNT ]; ///< The flag to specify whether the size should be assigned to the actor
123 Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies
125 Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
127 float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
129 float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be
130 float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be
132 bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated
133 bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
135 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
137 Vector2 preferredSize; ///< The preferred size of the actor
139 SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
141 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
142 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
145 namespace // unnamed namespace
151 * We want to discourage the use of property strings (minimize string comparisons),
152 * particularly for the default properties.
153 * Name Type writable animatable constraint-input enum for index-checking
155 DALI_PROPERTY_TABLE_BEGIN
156 DALI_PROPERTY( "parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
157 DALI_PROPERTY( "parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
158 DALI_PROPERTY( "parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
159 DALI_PROPERTY( "parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
160 DALI_PROPERTY( "anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
161 DALI_PROPERTY( "anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
162 DALI_PROPERTY( "anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
163 DALI_PROPERTY( "anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
164 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
165 DALI_PROPERTY( "sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
166 DALI_PROPERTY( "sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
167 DALI_PROPERTY( "sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
168 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
169 DALI_PROPERTY( "positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
170 DALI_PROPERTY( "positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
171 DALI_PROPERTY( "positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
172 DALI_PROPERTY( "worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
173 DALI_PROPERTY( "worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
174 DALI_PROPERTY( "worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
175 DALI_PROPERTY( "worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
176 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
177 DALI_PROPERTY( "worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
178 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
179 DALI_PROPERTY( "scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
180 DALI_PROPERTY( "scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
181 DALI_PROPERTY( "scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
182 DALI_PROPERTY( "worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
183 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
184 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
185 DALI_PROPERTY( "colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
186 DALI_PROPERTY( "colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
187 DALI_PROPERTY( "colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
188 DALI_PROPERTY( "colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
189 DALI_PROPERTY( "worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
190 DALI_PROPERTY( "worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
191 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
192 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
193 DALI_PROPERTY( "leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
194 DALI_PROPERTY( "inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
195 DALI_PROPERTY( "inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
196 DALI_PROPERTY( "colorMode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
197 DALI_PROPERTY( "reservedProperty01", STRING, true, false, false, Dali::Actor::Property::RESERVED_PROPERTY_01 ) // This property was removed, but to keep binary compatibility and TypeRegister test app, remain it here.
198 DALI_PROPERTY( "drawMode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
199 DALI_PROPERTY( "sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
200 DALI_PROPERTY( "widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
201 DALI_PROPERTY( "heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
202 DALI_PROPERTY( "sizeScalePolicy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
203 DALI_PROPERTY( "widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
204 DALI_PROPERTY( "heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
205 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
206 DALI_PROPERTY( "minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
207 DALI_PROPERTY( "maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
208 DALI_PROPERTY( "inheritPosition", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_POSITION )
209 DALI_PROPERTY( "clippingMode", STRING, true, false, false, Dali::Actor::Property::CLIPPING_MODE )
210 DALI_PROPERTY( "layoutDirection", STRING, true, false, false, Dali::Actor::Property::LAYOUT_DIRECTION )
211 DALI_PROPERTY( "inheritLayoutDirection", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION )
212 DALI_PROPERTY( "siblingOrder", INTEGER, true, false, false, Dali::DevelActor::Property::SIBLING_ORDER )
213 DALI_PROPERTY( "opacity", FLOAT, true, true, true, Dali::DevelActor::Property::OPACITY )
214 DALI_PROPERTY( "screenPosition", VECTOR2, false, false, false, Dali::DevelActor::Property::SCREEN_POSITION )
215 DALI_PROPERTY( "positionUsesAnchorPoint", BOOLEAN, true, false, false, Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT )
216 DALI_PROPERTY( "culled", BOOLEAN, false, false, true, Dali::DevelActor::Property::CULLED )
217 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperties )
221 const char* const SIGNAL_TOUCHED = "touched";
222 const char* const SIGNAL_HOVERED = "hovered";
223 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
224 const char* const SIGNAL_ON_STAGE = "onStage";
225 const char* const SIGNAL_OFF_STAGE = "offStage";
226 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
227 const char* const SIGNAL_TOUCH = "touch";
228 const char* const SIGNAL_VISIBILITY_CHANGED = "visibilityChanged";
229 const char* const SIGNAL_LAYOUT_DIRECTION_CHANGED = "layoutDirectionChanged";
230 const char* const SIGNAL_CHILD_ADDED = "childAdded";
231 const char* const SIGNAL_CHILD_REMOVED = "childRemoved";
235 const char* const ACTION_SHOW = "show";
236 const char* const ACTION_HIDE = "hide";
238 BaseHandle CreateActor()
240 return Dali::Actor::New();
243 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor, ActorDefaultProperties );
245 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
246 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
247 SignalConnectorType signalConnector3( mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal );
248 SignalConnectorType signalConnector4( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
249 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
250 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
251 SignalConnectorType signalConnector7( mType, SIGNAL_TOUCH, &Actor::DoConnectSignal );
252 SignalConnectorType signalConnector8( mType, SIGNAL_VISIBILITY_CHANGED, &Actor::DoConnectSignal );
253 SignalConnectorType signalConnector9( mType, SIGNAL_LAYOUT_DIRECTION_CHANGED, &Actor::DoConnectSignal );
254 SignalConnectorType signalConnector10( mType, SIGNAL_CHILD_ADDED, &Actor::DoConnectSignal );
255 SignalConnectorType signalConnector11( mType, SIGNAL_CHILD_REMOVED, &Actor::DoConnectSignal );
257 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
258 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
263 const Vector3& value;
266 DALI_ENUM_TO_STRING_TABLE_BEGIN_WITH_TYPE( AnchorValue, ANCHOR_CONSTANT )
267 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_LEFT )
268 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_CENTER )
269 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_RIGHT )
270 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_LEFT )
271 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER )
272 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_RIGHT )
273 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_LEFT )
274 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_CENTER )
275 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_RIGHT )
276 DALI_ENUM_TO_STRING_TABLE_END( ANCHOR_CONSTANT )
278 DALI_ENUM_TO_STRING_TABLE_BEGIN( COLOR_MODE )
279 DALI_ENUM_TO_STRING( USE_OWN_COLOR )
280 DALI_ENUM_TO_STRING( USE_PARENT_COLOR )
281 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_COLOR )
282 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_ALPHA )
283 DALI_ENUM_TO_STRING_TABLE_END( COLOR_MODE )
285 DALI_ENUM_TO_STRING_TABLE_BEGIN( DRAW_MODE )
286 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, NORMAL )
287 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, OVERLAY_2D )
288 DALI_ENUM_TO_STRING_TABLE_END( DRAW_MODE )
290 DALI_ENUM_TO_STRING_TABLE_BEGIN( RESIZE_POLICY )
291 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIXED )
292 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_NATURAL_SIZE )
293 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FILL_TO_PARENT )
294 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_RELATIVE_TO_PARENT )
295 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_FIXED_OFFSET_FROM_PARENT )
296 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIT_TO_CHILDREN )
297 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, DIMENSION_DEPENDENCY )
298 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_ASSIGNED_SIZE )
299 DALI_ENUM_TO_STRING_TABLE_END( RESIZE_POLICY )
301 DALI_ENUM_TO_STRING_TABLE_BEGIN( SIZE_SCALE_POLICY )
302 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, USE_SIZE_SET )
303 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FIT_WITH_ASPECT_RATIO )
304 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FILL_WITH_ASPECT_RATIO )
305 DALI_ENUM_TO_STRING_TABLE_END( SIZE_SCALE_POLICY )
307 DALI_ENUM_TO_STRING_TABLE_BEGIN( CLIPPING_MODE )
308 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, DISABLED )
309 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, CLIP_CHILDREN )
310 DALI_ENUM_TO_STRING_TABLE_END( CLIPPING_MODE )
312 DALI_ENUM_TO_STRING_TABLE_BEGIN( LAYOUT_DIRECTION )
313 DALI_ENUM_TO_STRING_WITH_SCOPE( LayoutDirection, LEFT_TO_RIGHT )
314 DALI_ENUM_TO_STRING_WITH_SCOPE( LayoutDirection, RIGHT_TO_LEFT )
315 DALI_ENUM_TO_STRING_TABLE_END( LAYOUT_DIRECTION )
317 bool GetAnchorPointConstant( const std::string& value, Vector3& anchor )
319 for( uint32_t i = 0; i < ANCHOR_CONSTANT_TABLE_COUNT; ++i )
321 uint32_t sizeIgnored = 0;
322 if( CompareTokens( value.c_str(), ANCHOR_CONSTANT_TABLE[ i ].name, sizeIgnored ) )
324 anchor = ANCHOR_CONSTANT_TABLE[ i ].value;
331 inline bool GetParentOriginConstant( const std::string& value, Vector3& parentOrigin )
333 // Values are the same so just use the same table as anchor-point
334 return GetAnchorPointConstant( value, parentOrigin );
338 * @brief Extract a given dimension from a Vector2
340 * @param[in] values The values to extract from
341 * @param[in] dimension The dimension to extract
342 * @return Return the value for the dimension
344 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
348 case Dimension::WIDTH:
352 case Dimension::HEIGHT:
354 return values.height;
365 * @brief Extract a given dimension from a Vector3
367 * @param[in] values The values to extract from
368 * @param[in] dimension The dimension to extract
369 * @return Return the value for the dimension
371 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
373 return GetDimensionValue( values.GetVectorXY(), dimension );
377 * @brief Recursively emits the visibility-changed-signal on the actor tree.
378 * @param[in] actor The actor to emit the signal on
379 * @param[in] visible The new visibility of the actor
380 * @param[in] type Whether the actor's visible property has changed or a parent's
382 void EmitVisibilityChangedSignalRecursively( ActorPtr actor, bool visible, DevelActor::VisibilityChange::Type type )
386 actor->EmitVisibilityChangedSignal( visible, type );
388 if( actor->GetChildCount() > 0 )
390 ActorContainer& children = actor->GetChildrenInternal();
391 for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter )
393 EmitVisibilityChangedSignalRecursively( *iter, visible, DevelActor::VisibilityChange::PARENT );
399 } // unnamed namespace
401 ActorPtr Actor::New()
403 // pass a reference to actor, actor does not own its node
404 ActorPtr actor( new Actor( BASIC, *CreateNode() ) );
406 // Second-phase construction
412 const SceneGraph::Node* Actor::CreateNode()
414 // create node. Nodes are owned by the update manager
415 SceneGraph::Node* node = SceneGraph::Node::New();
416 OwnerPointer< SceneGraph::Node > transferOwnership( node );
417 Internal::ThreadLocalStorage* tls = Internal::ThreadLocalStorage::GetInternal();
418 AddNodeMessage( tls->GetUpdateManager(), transferOwnership );
423 const std::string& Actor::GetName() const
428 void Actor::SetName( const std::string& name )
432 // ATTENTION: string for debug purposes is not thread safe.
433 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( &GetNode() ), name );
436 uint32_t Actor::GetId() const
438 return GetNode().GetId();
441 bool Actor::OnStage() const
446 Dali::Layer Actor::GetLayer()
450 // Short-circuit for Layer derived actors
453 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
456 // Find the immediate Layer parent
457 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
459 if( parent->IsLayer() )
461 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
468 void Actor::Add( Actor& child )
470 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
471 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
475 mChildren = new ActorContainer;
478 Actor* const oldParent( child.mParent );
480 // child might already be ours
481 if( this != oldParent )
483 // if we already have parent, unparent us first
486 oldParent->Remove( child ); // This causes OnChildRemove callback & ChildRemoved signal
488 // Old parent may need to readjust to missing child
489 if( oldParent->RelayoutDependentOnChildren() )
491 oldParent->RelayoutRequest();
495 // Guard against Add() during previous OnChildRemove callback
498 // Do this first, since user callbacks from within SetParent() may need to remove child
499 mChildren->push_back( ActorPtr( &child ) );
501 // SetParent asserts that child can be added
502 child.SetParent( this );
504 // Notification for derived classes
506 EmitChildAddedSignal( child );
508 InheritLayoutDirectionRecursively( ActorPtr( &child ), mLayoutDirection );
510 // Only put in a relayout request if there is a suitable dependency
511 if( RelayoutDependentOnChildren() )
519 void Actor::Remove( Actor& child )
521 if( (this == &child) || (!mChildren) )
523 // no children or removing itself
529 // Find the child in mChildren, and unparent it
530 ActorIter end = mChildren->end();
531 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
533 ActorPtr actor = (*iter);
535 if( actor.Get() == &child )
537 // Keep handle for OnChildRemove notification
540 // Do this first, since user callbacks from within SetParent() may need to add the child
541 mChildren->erase( iter );
543 DALI_ASSERT_DEBUG( actor->GetParent() == this );
544 actor->SetParent( NULL );
552 // Only put in a relayout request if there is a suitable dependency
553 if( RelayoutDependentOnChildren() )
559 // Notification for derived classes
560 OnChildRemove( child );
561 EmitChildRemovedSignal( child );
564 void Actor::Unparent()
568 // Remove this actor from the parent. The remove will put a relayout request in for
569 // the parent if required
570 mParent->Remove( *this );
571 // mParent is now NULL!
575 uint32_t Actor::GetChildCount() const
577 return ( NULL != mChildren ) ? static_cast<uint32_t>( mChildren->size() ) : 0; // only 4,294,967,295 children per actor
580 ActorPtr Actor::GetChildAt( uint32_t index ) const
582 DALI_ASSERT_ALWAYS( index < GetChildCount() );
584 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
587 ActorPtr Actor::FindChildByName( const std::string& actorName )
590 if( actorName == mName )
596 ActorIter end = mChildren->end();
597 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
599 child = (*iter)->FindChildByName( actorName );
610 ActorPtr Actor::FindChildById( const uint32_t id )
619 ActorIter end = mChildren->end();
620 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
622 child = (*iter)->FindChildById( id );
633 void Actor::SetParentOrigin( const Vector3& origin )
635 // node is being used in a separate thread; queue a message to set the value & base value
636 SetParentOriginMessage( GetEventThreadServices(), GetNode(), origin );
638 // Cache for event-thread access
641 // not allocated, check if different from default
642 if( ParentOrigin::DEFAULT != origin )
644 mParentOrigin = new Vector3( origin );
649 // check if different from current costs more than just set
650 *mParentOrigin = origin;
654 void Actor::SetParentOriginX( float x )
656 const Vector3& current = GetCurrentParentOrigin();
658 SetParentOrigin( Vector3( x, current.y, current.z ) );
661 void Actor::SetParentOriginY( float y )
663 const Vector3& current = GetCurrentParentOrigin();
665 SetParentOrigin( Vector3( current.x, y, current.z ) );
668 void Actor::SetParentOriginZ( float z )
670 const Vector3& current = GetCurrentParentOrigin();
672 SetParentOrigin( Vector3( current.x, current.y, z ) );
675 const Vector3& Actor::GetCurrentParentOrigin() const
677 // Cached for event-thread access
678 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
681 void Actor::SetAnchorPoint( const Vector3& anchor )
683 // node is being used in a separate thread; queue a message to set the value & base value
684 SetAnchorPointMessage( GetEventThreadServices(), GetNode(), anchor );
686 // Cache for event-thread access
689 // not allocated, check if different from default
690 if( AnchorPoint::DEFAULT != anchor )
692 mAnchorPoint = new Vector3( anchor );
697 // check if different from current costs more than just set
698 *mAnchorPoint = anchor;
702 void Actor::SetAnchorPointX( float x )
704 const Vector3& current = GetCurrentAnchorPoint();
706 SetAnchorPoint( Vector3( x, current.y, current.z ) );
709 void Actor::SetAnchorPointY( float y )
711 const Vector3& current = GetCurrentAnchorPoint();
713 SetAnchorPoint( Vector3( current.x, y, current.z ) );
716 void Actor::SetAnchorPointZ( float z )
718 const Vector3& current = GetCurrentAnchorPoint();
720 SetAnchorPoint( Vector3( current.x, current.y, z ) );
723 const Vector3& Actor::GetCurrentAnchorPoint() const
725 // Cached for event-thread access
726 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
729 void Actor::SetPosition( float x, float y )
731 SetPosition( Vector3( x, y, 0.0f ) );
734 void Actor::SetPosition( float x, float y, float z )
736 SetPosition( Vector3( x, y, z ) );
739 void Actor::SetPosition( const Vector3& position )
741 mTargetPosition = position;
743 // node is being used in a separate thread; queue a message to set the value & base value
744 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
747 void Actor::SetX( float x )
749 mTargetPosition.x = x;
751 // node is being used in a separate thread; queue a message to set the value & base value
752 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
755 void Actor::SetY( float y )
757 mTargetPosition.y = y;
759 // node is being used in a separate thread; queue a message to set the value & base value
760 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
763 void Actor::SetZ( float z )
765 mTargetPosition.z = z;
767 // node is being used in a separate thread; queue a message to set the value & base value
768 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
771 void Actor::TranslateBy( const Vector3& distance )
773 mTargetPosition += distance;
775 // node is being used in a separate thread; queue a message to set the value & base value
776 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
779 const Vector3& Actor::GetCurrentPosition() const
781 // node is being used in a separate thread; copy the value from the previous update
782 return GetNode().GetPosition(GetEventThreadServices().GetEventBufferIndex());
785 const Vector3& Actor::GetTargetPosition() const
787 return mTargetPosition;
790 const Vector3& Actor::GetCurrentWorldPosition() const
792 // node is being used in a separate thread; copy the value from the previous update
793 return GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
796 const Vector2 Actor::GetCurrentScreenPosition() const
798 if( mScene && OnStage() )
800 Vector3 worldPosition = GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
801 Vector3 cameraPosition = mScene->GetDefaultCameraActor().GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
802 worldPosition -= cameraPosition;
804 Vector3 actorSize = GetCurrentSize() * GetCurrentWorldScale();
805 Vector2 halfSceneSize( mScene->GetSize() * 0.5f ); // World position origin is center of scene
806 Vector3 halfActorSize( actorSize * 0.5f );
807 Vector3 anchorPointOffSet = halfActorSize - actorSize * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
809 return Vector2( halfSceneSize.width + worldPosition.x - anchorPointOffSet.x,
810 halfSceneSize.height + worldPosition.y - anchorPointOffSet.y );
813 return Vector2::ZERO;
816 void Actor::SetInheritPosition( bool inherit )
818 if( mInheritPosition != inherit )
820 // non animatable so keep local copy
821 mInheritPosition = inherit;
822 SetInheritPositionMessage( GetEventThreadServices(), GetNode(), inherit );
826 bool Actor::IsPositionInherited() const
828 return mInheritPosition;
831 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
833 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
834 normalizedAxis.Normalize();
836 Quaternion orientation( angle, normalizedAxis );
838 SetOrientation( orientation );
841 void Actor::SetOrientation( const Quaternion& orientation )
843 mTargetOrientation = orientation;
845 // node is being used in a separate thread; queue a message to set the value & base value
846 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation );
849 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
851 RotateBy( Quaternion(angle, axis) );
854 void Actor::RotateBy( const Quaternion& relativeRotation )
856 mTargetOrientation *= Quaternion( relativeRotation );
858 // node is being used in a separate thread; queue a message to set the value & base value
859 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
862 const Quaternion& Actor::GetCurrentOrientation() const
864 // node is being used in a separate thread; copy the value from the previous update
865 return GetNode().GetOrientation(GetEventThreadServices().GetEventBufferIndex());
868 const Quaternion& Actor::GetCurrentWorldOrientation() const
870 // node is being used in a separate thread; copy the value from the previous update
871 return GetNode().GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
874 void Actor::SetScale( float scale )
876 SetScale( Vector3( scale, scale, scale ) );
879 void Actor::SetScale( float x, float y, float z )
881 SetScale( Vector3( x, y, z ) );
884 void Actor::SetScale( const Vector3& scale )
886 mTargetScale = scale;
888 // node is being used in a separate thread; queue a message to set the value & base value
889 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
892 void Actor::SetScaleX( float x )
896 // node is being used in a separate thread; queue a message to set the value & base value
897 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
900 void Actor::SetScaleY( float y )
904 // node is being used in a separate thread; queue a message to set the value & base value
905 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
908 void Actor::SetScaleZ( float z )
912 // node is being used in a separate thread; queue a message to set the value & base value
913 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
916 void Actor::ScaleBy(const Vector3& relativeScale)
918 mTargetScale *= relativeScale;
920 // node is being used in a separate thread; queue a message to set the value & base value
921 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
924 const Vector3& Actor::GetCurrentScale() const
926 // node is being used in a separate thread; copy the value from the previous update
927 return GetNode().GetScale(GetEventThreadServices().GetEventBufferIndex());
930 const Vector3& Actor::GetCurrentWorldScale() const
932 // node is being used in a separate thread; copy the value from the previous update
933 return GetNode().GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
936 void Actor::SetInheritScale( bool inherit )
938 if( mInheritScale != inherit )
940 // non animatable so keep local copy
941 mInheritScale = inherit;
942 // node is being used in a separate thread; queue a message to set the value
943 SetInheritScaleMessage( GetEventThreadServices(), GetNode(), inherit );
947 bool Actor::IsScaleInherited() const
949 return mInheritScale;
952 Matrix Actor::GetCurrentWorldMatrix() const
954 return GetNode().GetWorldMatrix(0);
957 void Actor::SetVisible( bool visible )
959 SetVisibleInternal( visible, SendMessage::TRUE );
962 bool Actor::IsVisible() const
964 // node is being used in a separate thread; copy the value from the previous update
965 return GetNode().IsVisible( GetEventThreadServices().GetEventBufferIndex() );
968 void Actor::SetOpacity( float opacity )
970 mTargetColor.a = opacity;
972 // node is being used in a separate thread; queue a message to set the value & base value
973 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
976 float Actor::GetCurrentOpacity() const
978 // node is being used in a separate thread; copy the value from the previous update
979 return GetNode().GetOpacity(GetEventThreadServices().GetEventBufferIndex());
982 ClippingMode::Type Actor::GetClippingMode() const
984 return mClippingMode;
987 uint32_t Actor::GetSortingDepth()
992 const Vector4& Actor::GetCurrentWorldColor() const
994 return GetNode().GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
997 void Actor::SetColor( const Vector4& color )
999 mTargetColor = color;
1001 // node is being used in a separate thread; queue a message to set the value & base value
1002 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::Bake, color );
1005 void Actor::SetColorRed( float red )
1007 mTargetColor.r = red;
1009 // node is being used in a separate thread; queue a message to set the value & base value
1010 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeX, red );
1013 void Actor::SetColorGreen( float green )
1015 mTargetColor.g = green;
1017 // node is being used in a separate thread; queue a message to set the value & base value
1018 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeY, green );
1021 void Actor::SetColorBlue( float blue )
1023 mTargetColor.b = blue;
1025 // node is being used in a separate thread; queue a message to set the value & base value
1026 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1029 const Vector4& Actor::GetCurrentColor() const
1031 // node is being used in a separate thread; copy the value from the previous update
1032 return GetNode().GetColor(GetEventThreadServices().GetEventBufferIndex());
1035 void Actor::SetInheritOrientation( bool inherit )
1037 if( mInheritOrientation != inherit )
1039 // non animatable so keep local copy
1040 mInheritOrientation = inherit;
1041 // node is being used in a separate thread; queue a message to set the value
1042 SetInheritOrientationMessage( GetEventThreadServices(), GetNode(), inherit );
1046 bool Actor::IsOrientationInherited() const
1048 return mInheritOrientation;
1051 void Actor::SetSizeModeFactor( const Vector3& factor )
1053 EnsureRelayoutData();
1055 mRelayoutData->sizeModeFactor = factor;
1058 const Vector3& Actor::GetSizeModeFactor() const
1060 if ( mRelayoutData )
1062 return mRelayoutData->sizeModeFactor;
1065 return GetDefaultSizeModeFactor();
1068 void Actor::SetColorMode( ColorMode colorMode )
1070 // non animatable so keep local copy
1071 mColorMode = colorMode;
1072 // node is being used in a separate thread; queue a message to set the value
1073 SetColorModeMessage( GetEventThreadServices(), GetNode(), colorMode );
1076 ColorMode Actor::GetColorMode() const
1078 // we have cached copy
1082 void Actor::SetSize( float width, float height )
1084 SetSize( Vector2( width, height ) );
1087 void Actor::SetSize( float width, float height, float depth )
1089 SetSize( Vector3( width, height, depth ) );
1092 void Actor::SetSize( const Vector2& size )
1094 SetSize( Vector3( size.width, size.height, 0.f ) );
1097 void Actor::SetSizeInternal( const Vector2& size )
1099 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1102 void Actor::SetSize( const Vector3& size )
1104 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1106 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1107 SetPreferredSize( size.GetVectorXY() );
1111 SetSizeInternal( size );
1115 void Actor::SetSizeInternal( const Vector3& size )
1117 // dont allow recursive loop
1118 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1119 // check that we have a node AND the new size width, height or depth is at least a little bit different from the old one
1120 if( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1121 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1122 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) )
1126 // node is being used in a separate thread; queue a message to set the value & base value
1127 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
1129 // Notification for derived classes
1130 mInsideOnSizeSet = true;
1131 OnSizeSet( mTargetSize );
1132 mInsideOnSizeSet = false;
1134 // Raise a relayout request if the flag is not locked
1135 if( mRelayoutData && !mRelayoutData->insideRelayout )
1142 void Actor::SetWidth( float width )
1144 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1146 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
1147 mRelayoutData->preferredSize.width = width;
1151 mTargetSize.width = width;
1153 // node is being used in a separate thread; queue a message to set the value & base value
1154 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1160 void Actor::SetHeight( float height )
1162 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1164 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
1165 mRelayoutData->preferredSize.height = height;
1169 mTargetSize.height = height;
1171 // node is being used in a separate thread; queue a message to set the value & base value
1172 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1178 void Actor::SetDepth( float depth )
1180 mTargetSize.depth = depth;
1182 // node is being used in a separate thread; queue a message to set the value & base value
1183 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1186 Vector3 Actor::GetTargetSize() const
1188 Vector3 size = mTargetSize;
1190 // Should return preferred size if size is fixed as set by SetSize
1191 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
1193 size.width = GetPreferredSize().width;
1195 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
1197 size.height = GetPreferredSize().height;
1203 const Vector3& Actor::GetCurrentSize() const
1205 // node is being used in a separate thread; copy the value from the previous update
1206 return GetNode().GetSize( GetEventThreadServices().GetEventBufferIndex() );
1209 Vector3 Actor::GetNaturalSize() const
1211 // It is up to deriving classes to return the appropriate natural size
1212 return Vector3( 0.0f, 0.0f, 0.0f );
1215 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1217 EnsureRelayoutData();
1219 ResizePolicy::Type originalWidthPolicy = GetResizePolicy(Dimension::WIDTH);
1220 ResizePolicy::Type originalHeightPolicy = GetResizePolicy(Dimension::HEIGHT);
1222 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1224 if( dimension & ( 1 << i ) )
1226 if ( policy == ResizePolicy::USE_ASSIGNED_SIZE )
1228 mRelayoutData->useAssignedSize[ i ] = true;
1232 mRelayoutData->resizePolicies[ i ] = policy;
1233 mRelayoutData->useAssignedSize[ i ] = false;
1238 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1240 if( dimension & Dimension::WIDTH )
1242 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1245 if( dimension & Dimension::HEIGHT )
1247 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1251 // If calling SetResizePolicy, assume we want relayout enabled
1252 SetRelayoutEnabled( true );
1254 // If the resize policy is set to be FIXED, the preferred size
1255 // should be overrided by the target size. Otherwise the target
1256 // size should be overrided by the preferred size.
1258 if( dimension & Dimension::WIDTH )
1260 if( originalWidthPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1262 mRelayoutData->preferredSize.width = mTargetSize.width;
1264 else if( originalWidthPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1266 mTargetSize.width = mRelayoutData->preferredSize.width;
1270 if( dimension & Dimension::HEIGHT )
1272 if( originalHeightPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1274 mRelayoutData->preferredSize.height = mTargetSize.height;
1276 else if( originalHeightPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1278 mTargetSize.height = mRelayoutData->preferredSize.height;
1282 OnSetResizePolicy( policy, dimension );
1284 // Trigger relayout on this control
1288 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1290 if ( mRelayoutData )
1292 // If more than one dimension is requested, just return the first one found
1293 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1295 if( ( dimension & ( 1 << i ) ) )
1297 if( mRelayoutData->useAssignedSize[ i ] )
1299 return ResizePolicy::USE_ASSIGNED_SIZE;
1303 return mRelayoutData->resizePolicies[ i ];
1309 return ResizePolicy::DEFAULT;
1312 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1314 EnsureRelayoutData();
1316 mRelayoutData->sizeSetPolicy = policy;
1318 // Trigger relayout on this control
1322 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1324 if ( mRelayoutData )
1326 return mRelayoutData->sizeSetPolicy;
1329 return DEFAULT_SIZE_SCALE_POLICY;
1332 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1334 EnsureRelayoutData();
1336 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1338 if( dimension & ( 1 << i ) )
1340 mRelayoutData->dimensionDependencies[ i ] = dependency;
1345 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1347 if ( mRelayoutData )
1349 // If more than one dimension is requested, just return the first one found
1350 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1352 if( ( dimension & ( 1 << i ) ) )
1354 return mRelayoutData->dimensionDependencies[ i ];
1359 return Dimension::ALL_DIMENSIONS; // Default
1362 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1364 // If relayout data has not been allocated yet and the client is requesting
1365 // to disable it, do nothing
1366 if( mRelayoutData || relayoutEnabled )
1368 EnsureRelayoutData();
1370 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1372 mRelayoutData->relayoutEnabled = relayoutEnabled;
1376 bool Actor::IsRelayoutEnabled() const
1378 // Assume that if relayout data has not been allocated yet then
1379 // relayout is disabled
1380 return mRelayoutData && mRelayoutData->relayoutEnabled;
1383 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1385 EnsureRelayoutData();
1387 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1389 if( dimension & ( 1 << i ) )
1391 mRelayoutData->dimensionDirty[ i ] = dirty;
1396 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1398 if ( mRelayoutData )
1400 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1402 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1412 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1414 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1417 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1419 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1422 uint32_t Actor::AddRenderer( Renderer& renderer )
1426 mRenderers = new RendererContainer;
1429 uint32_t index = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1430 RendererPtr rendererPtr = RendererPtr( &renderer );
1431 mRenderers->push_back( rendererPtr );
1432 AttachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1436 uint32_t Actor::GetRendererCount() const
1438 uint32_t rendererCount(0);
1441 rendererCount = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1444 return rendererCount;
1447 RendererPtr Actor::GetRendererAt( uint32_t index )
1449 RendererPtr renderer;
1450 if( index < GetRendererCount() )
1452 renderer = ( *mRenderers )[ index ];
1458 void Actor::RemoveRenderer( Renderer& renderer )
1462 RendererIter end = mRenderers->end();
1463 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1465 if( (*iter).Get() == &renderer )
1467 mRenderers->erase( iter );
1468 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1475 void Actor::RemoveRenderer( uint32_t index )
1477 if( index < GetRendererCount() )
1479 RendererPtr renderer = ( *mRenderers )[ index ];
1480 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.Get()->GetRendererSceneObject() );
1481 mRenderers->erase( mRenderers->begin()+index );
1485 bool Actor::IsOverlay() const
1487 return ( DrawMode::OVERLAY_2D == mDrawMode );
1490 void Actor::SetDrawMode( DrawMode::Type drawMode )
1492 // this flag is not animatable so keep the value
1493 mDrawMode = drawMode;
1495 // node is being used in a separate thread; queue a message to set the value
1496 SetDrawModeMessage( GetEventThreadServices(), GetNode(), drawMode );
1499 DrawMode::Type Actor::GetDrawMode() const
1504 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1506 // only valid when on-stage
1507 if( mScene && OnStage() )
1509 const RenderTaskList& taskList = mScene->GetRenderTaskList();
1511 Vector2 converted( screenX, screenY );
1513 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1514 uint32_t taskCount = taskList.GetTaskCount();
1515 for( uint32_t i = taskCount; i > 0; --i )
1517 RenderTaskPtr task = taskList.GetTask( i - 1 );
1518 if( ScreenToLocal( *task, localX, localY, screenX, screenY ) )
1520 // found a task where this conversion was ok so return
1528 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1530 bool retval = false;
1531 // only valid when on-stage
1534 CameraActor* camera = renderTask.GetCameraActor();
1538 renderTask.GetViewport( viewport );
1540 // need to translate coordinates to render tasks coordinate space
1541 Vector2 converted( screenX, screenY );
1542 if( renderTask.TranslateCoordinates( converted ) )
1544 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1551 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1553 // Early-out if not on stage
1559 // Get the ModelView matrix
1561 Matrix::Multiply( modelView, GetNode().GetWorldMatrix(0), viewMatrix );
1563 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1564 Matrix invertedMvp( false/*don't init*/);
1565 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1566 bool success = invertedMvp.Invert();
1568 // Convert to GL coordinates
1569 Vector4 screenPos( screenX - static_cast<float>( viewport.x ), static_cast<float>( viewport.height ) - screenY - static_cast<float>( viewport.y ), 0.f, 1.f );
1574 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), nearPos );
1581 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), farPos );
1587 if( XyPlaneIntersect( nearPos, farPos, local ) )
1589 Vector3 size = GetCurrentSize();
1590 localX = local.x + size.x * 0.5f;
1591 localY = local.y + size.y * 0.5f;
1602 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1605 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1607 Mathematical Formulation
1609 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1611 ( p - c ) dot ( p - c ) = r^2
1613 Given a ray with a point of origin 'o', and a direction vector 'd':
1615 ray(t) = o + td, t >= 0
1617 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1619 (o + td - c ) dot ( o + td - c ) = r^2
1621 To solve for t we first expand the above into a more recognisable quadratic equation form
1623 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1632 B = 2( o - c ) dot d
1633 C = ( o - c ) dot ( o - c ) - r^2
1635 which can be solved using a standard quadratic formula.
1637 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1639 Practical Simplification
1641 In a renderer, we often differentiate between world space and object space. In the object space
1642 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1643 into object space, the mathematical solution presented above can be simplified significantly.
1645 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1649 and we can find the t at which the (transformed) ray intersects the sphere by
1651 ( o + td ) dot ( o + td ) = r^2
1653 According to the reasoning above, we expand the above quadratic equation into the general form
1657 which now has coefficients:
1664 // Early-out if not on stage
1670 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1672 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1673 const Vector3& translation( GetNode().GetWorldPosition( bufferIndex ) );
1674 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1676 // Compute the radius is not needed, square radius it's enough.
1677 const Vector3& size( GetNode().GetSize( bufferIndex ) );
1679 // Scale the sphere.
1680 const Vector3& scale( GetNode().GetWorldScale( bufferIndex ) );
1682 const float width = size.width * scale.width;
1683 const float height = size.height * scale.height;
1685 float squareSphereRadius = 0.5f * ( width * width + height * height );
1687 float a = rayDir.Dot( rayDir ); // a
1688 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1689 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1691 return ( b2 * b2 - a * c ) >= 0.f;
1694 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector2& hitPointLocal, float& distance ) const
1700 // Transforms the ray to the local reference system.
1701 // Calculate the inverse of Model matrix
1702 Matrix invModelMatrix( false/*don't init*/);
1704 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1705 invModelMatrix = GetNode().GetWorldMatrix(0);
1706 invModelMatrix.Invert();
1708 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1709 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1711 // Test with the actor's XY plane (Normal = 0 0 1 1).
1713 float a = -rayOriginLocal.z;
1714 float b = rayDirLocal.z;
1716 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1718 // Ray travels distance * rayDirLocal to intersect with plane.
1721 const Vector3& size = GetNode().GetSize( bufferIndex );
1723 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1724 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1726 // Test with the actor's geometry.
1727 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1734 void Actor::SetLeaveRequired( bool required )
1736 mLeaveRequired = required;
1739 bool Actor::GetLeaveRequired() const
1741 return mLeaveRequired;
1744 void Actor::SetKeyboardFocusable( bool focusable )
1746 mKeyboardFocusable = focusable;
1749 bool Actor::IsKeyboardFocusable() const
1751 return mKeyboardFocusable;
1754 bool Actor::GetTouchRequired() const
1756 return !mTouchedSignal.Empty() || !mTouchSignal.Empty() || mDerivedRequiresTouch;
1759 bool Actor::GetHoverRequired() const
1761 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1764 bool Actor::GetWheelEventRequired() const
1766 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1769 bool Actor::IsHittable() const
1771 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1774 ActorGestureData& Actor::GetGestureData()
1776 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1777 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1778 if( NULL == mGestureData )
1780 mGestureData = new ActorGestureData;
1782 return *mGestureData;
1785 bool Actor::IsGestureRequred( DevelGesture::Type type ) const
1787 return mGestureData && mGestureData->IsGestureRequred( type );
1790 bool Actor::EmitTouchEventSignal( const TouchEvent& event, const Dali::TouchData& touch )
1792 bool consumed = false;
1794 if( !mTouchSignal.Empty() )
1796 Dali::Actor handle( this );
1797 consumed = mTouchSignal.Emit( handle, touch );
1800 if( !mTouchedSignal.Empty() )
1802 Dali::Actor handle( this );
1803 consumed |= mTouchedSignal.Emit( handle, event );
1808 // Notification for derived classes
1809 consumed = OnTouchEvent( event ); // TODO
1815 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1817 bool consumed = false;
1819 if( !mHoveredSignal.Empty() )
1821 Dali::Actor handle( this );
1822 consumed = mHoveredSignal.Emit( handle, event );
1827 // Notification for derived classes
1828 consumed = OnHoverEvent( event );
1834 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1836 bool consumed = false;
1838 if( !mWheelEventSignal.Empty() )
1840 Dali::Actor handle( this );
1841 consumed = mWheelEventSignal.Emit( handle, event );
1846 // Notification for derived classes
1847 consumed = OnWheelEvent( event );
1853 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
1855 if( ! mVisibilityChangedSignal.Empty() )
1857 Dali::Actor handle( this );
1858 mVisibilityChangedSignal.Emit( handle, visible, type );
1862 void Actor::EmitLayoutDirectionChangedSignal( LayoutDirection::Type type )
1864 if( ! mLayoutDirectionChangedSignal.Empty() )
1866 Dali::Actor handle( this );
1867 mLayoutDirectionChangedSignal.Emit( handle, type );
1871 void Actor::EmitChildAddedSignal( Actor& child )
1873 if( ! mChildAddedSignal.Empty() )
1875 Dali::Actor handle( &child );
1876 mChildAddedSignal.Emit( handle );
1880 void Actor::EmitChildRemovedSignal( Actor& child )
1882 if( ! mChildRemovedSignal.Empty() )
1884 Dali::Actor handle( &child );
1885 mChildRemovedSignal.Emit( handle );
1889 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
1891 return mTouchedSignal;
1894 Dali::Actor::TouchDataSignalType& Actor::TouchSignal()
1896 return mTouchSignal;
1899 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
1901 return mHoveredSignal;
1904 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
1906 return mWheelEventSignal;
1909 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
1911 return mOnStageSignal;
1914 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
1916 return mOffStageSignal;
1919 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
1921 return mOnRelayoutSignal;
1924 DevelActor::VisibilityChangedSignalType& Actor::VisibilityChangedSignal()
1926 return mVisibilityChangedSignal;
1929 Dali::Actor::LayoutDirectionChangedSignalType& Actor::LayoutDirectionChangedSignal()
1931 return mLayoutDirectionChangedSignal;
1934 DevelActor::ChildChangedSignalType& Actor::ChildAddedSignal()
1936 return mChildAddedSignal;
1939 DevelActor::ChildChangedSignalType& Actor::ChildRemovedSignal()
1941 return mChildRemovedSignal;
1944 DevelActor::ChildOrderChangedSignalType& Actor::ChildOrderChangedSignal()
1946 return mChildOrderChangedSignal;
1949 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1951 bool connected( true );
1952 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
1954 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1956 actor->TouchedSignal().Connect( tracker, functor );
1958 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1960 actor->HoveredSignal().Connect( tracker, functor );
1962 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1964 actor->WheelEventSignal().Connect( tracker, functor );
1966 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
1968 actor->OnStageSignal().Connect( tracker, functor );
1970 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
1972 actor->OffStageSignal().Connect( tracker, functor );
1974 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
1976 actor->OnRelayoutSignal().Connect( tracker, functor );
1978 else if( 0 == signalName.compare( SIGNAL_TOUCH ) )
1980 actor->TouchSignal().Connect( tracker, functor );
1982 else if( 0 == signalName.compare( SIGNAL_VISIBILITY_CHANGED ) )
1984 actor->VisibilityChangedSignal().Connect( tracker, functor );
1986 else if( 0 == signalName.compare( SIGNAL_LAYOUT_DIRECTION_CHANGED ) )
1988 actor->LayoutDirectionChangedSignal().Connect( tracker, functor );
1990 else if( 0 == signalName.compare( SIGNAL_CHILD_ADDED ) )
1992 actor->ChildAddedSignal().Connect( tracker, functor );
1994 else if( 0 == signalName.compare( SIGNAL_CHILD_REMOVED ) )
1996 actor->ChildRemovedSignal().Connect( tracker, functor );
2000 // signalName does not match any signal
2007 Actor::Actor( DerivedType derivedType, const SceneGraph::Node& node )
2013 mParentOrigin( NULL ),
2014 mAnchorPoint( NULL ),
2015 mRelayoutData( NULL ),
2016 mGestureData( NULL ),
2020 mWheelEventSignal(),
2023 mOnRelayoutSignal(),
2024 mVisibilityChangedSignal(),
2025 mLayoutDirectionChangedSignal(),
2026 mChildAddedSignal(),
2027 mChildRemovedSignal(),
2028 mChildOrderChangedSignal(),
2029 mTargetOrientation( Quaternion::IDENTITY ),
2030 mTargetColor( Color::WHITE ),
2031 mTargetSize( Vector3::ZERO ),
2032 mTargetPosition( Vector3::ZERO ),
2033 mTargetScale( Vector3::ONE ),
2037 mIsRoot( ROOT_LAYER == derivedType ),
2038 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2039 mIsOnStage( false ),
2041 mLeaveRequired( false ),
2042 mKeyboardFocusable( false ),
2043 mDerivedRequiresTouch( false ),
2044 mDerivedRequiresHover( false ),
2045 mDerivedRequiresWheelEvent( false ),
2046 mOnStageSignalled( false ),
2047 mInsideOnSizeSet( false ),
2048 mInheritPosition( true ),
2049 mInheritOrientation( true ),
2050 mInheritScale( true ),
2051 mPositionUsesAnchorPoint( true ),
2053 mInheritLayoutDirection( true ),
2054 mLayoutDirection( LayoutDirection::LEFT_TO_RIGHT ),
2055 mDrawMode( DrawMode::NORMAL ),
2056 mColorMode( Node::DEFAULT_COLOR_MODE ),
2057 mClippingMode( ClippingMode::DISABLED )
2061 void Actor::Initialize()
2065 GetEventThreadServices().RegisterObject( this );
2070 // Remove mParent pointers from children even if we're destroying core,
2071 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2074 ActorConstIter endIter = mChildren->end();
2075 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2077 (*iter)->SetParent( NULL );
2083 // Guard to allow handle destruction after Core has been destroyed
2084 if( EventThreadServices::IsCoreRunning() )
2086 // Root layer will destroy its node in its own destructor
2089 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
2091 GetEventThreadServices().UnregisterObject( this );
2095 // Cleanup optional gesture data
2096 delete mGestureData;
2098 // Cleanup optional parent origin and anchor
2099 delete mParentOrigin;
2100 delete mAnchorPoint;
2102 // Delete optional relayout data
2103 delete mRelayoutData;
2106 void Actor::ConnectToStage( uint32_t parentDepth )
2108 // This container is used instead of walking the Actor hierarchy.
2109 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
2110 ActorContainer connectionList;
2114 mScene->RequestRebuildDepthTree();
2117 // This stage is atomic i.e. not interrupted by user callbacks.
2118 RecursiveConnectToStage( connectionList, parentDepth + 1 );
2120 // Notify applications about the newly connected actors.
2121 const ActorIter endIter = connectionList.end();
2122 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2124 (*iter)->NotifyStageConnection();
2130 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, uint32_t depth )
2132 DALI_ASSERT_ALWAYS( !OnStage() );
2135 mDepth = static_cast< uint16_t >( depth ); // overflow ignored, not expected in practice
2137 ConnectToSceneGraph();
2139 // Notification for internal derived classes
2140 OnStageConnectionInternal();
2142 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2143 connectionList.push_back( ActorPtr( this ) );
2145 // Recursively connect children
2148 ActorConstIter endIter = mChildren->end();
2149 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2151 (*iter)->SetScene( *mScene );
2152 (*iter)->RecursiveConnectToStage( connectionList, depth + 1 );
2158 * This method is called when the Actor is connected to the Stage.
2159 * The parent must have added its Node to the scene-graph.
2160 * The child must connect its Node to the parent's Node.
2161 * This is recursive; the child calls ConnectToStage() for its children.
2163 void Actor::ConnectToSceneGraph()
2165 DALI_ASSERT_DEBUG( mParent != NULL);
2167 // Reparent Node in next Update
2168 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), mParent->GetNode(), GetNode() );
2170 // Request relayout on all actors that are added to the scenegraph
2173 // Notification for Object::Observers
2177 void Actor::NotifyStageConnection()
2179 // Actors can be removed (in a callback), before the on-stage stage is reported.
2180 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2181 if( OnStage() && !mOnStageSignalled )
2183 // Notification for external (CustomActor) derived classes
2184 OnStageConnectionExternal( mDepth );
2186 if( !mOnStageSignal.Empty() )
2188 Dali::Actor handle( this );
2189 mOnStageSignal.Emit( handle );
2192 // Guard against Remove during callbacks
2195 mOnStageSignalled = true; // signal required next time Actor is removed
2200 void Actor::DisconnectFromStage()
2202 // This container is used instead of walking the Actor hierachy.
2203 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2204 ActorContainer disconnectionList;
2208 mScene->RequestRebuildDepthTree();
2211 // This stage is atomic i.e. not interrupted by user callbacks
2212 RecursiveDisconnectFromStage( disconnectionList );
2214 // Notify applications about the newly disconnected actors.
2215 const ActorIter endIter = disconnectionList.end();
2216 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2218 (*iter)->NotifyStageDisconnection();
2222 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2224 // need to change state first so that internals relying on IsOnStage() inside OnStageDisconnectionInternal() get the correct value
2227 // Recursively disconnect children
2230 ActorConstIter endIter = mChildren->end();
2231 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2233 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2237 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2238 disconnectionList.push_back( ActorPtr( this ) );
2240 // Notification for internal derived classes
2241 OnStageDisconnectionInternal();
2243 DisconnectFromSceneGraph();
2247 * This method is called by an actor or its parent, before a node removal message is sent.
2248 * This is recursive; the child calls DisconnectFromStage() for its children.
2250 void Actor::DisconnectFromSceneGraph()
2252 // Notification for Object::Observers
2253 OnSceneObjectRemove();
2256 void Actor::NotifyStageDisconnection()
2258 // Actors can be added (in a callback), before the off-stage state is reported.
2259 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2260 // only do this step if there is a stage, i.e. Core is not being shut down
2261 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2263 // Notification for external (CustomeActor) derived classes
2264 OnStageDisconnectionExternal();
2266 if( !mOffStageSignal.Empty() )
2268 Dali::Actor handle( this );
2269 mOffStageSignal.Emit( handle );
2272 // Guard against Add during callbacks
2275 mOnStageSignalled = false; // signal required next time Actor is added
2280 bool Actor::IsNodeConnected() const
2282 bool connected( false );
2286 if( IsRoot() || GetNode().GetParent() )
2295 // This method initiates traversal of the actor tree using depth-first
2296 // traversal to set a depth index based on traversal order. It sends a
2297 // single message to update manager to update all the actor's nodes in
2298 // this tree with the depth index. The sceneGraphNodeDepths vector's
2299 // elements are ordered by depth, and could be used to reduce sorting
2300 // in the update thread.
2301 void Actor::RebuildDepthTree()
2303 DALI_LOG_TIMER_START(depthTimer);
2305 // Vector of scene-graph nodes and their depths to send to UpdateManager
2306 // in a single message
2307 OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths( new SceneGraph::NodeDepths() );
2309 int32_t depthIndex = 1;
2310 DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
2312 SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths );
2313 DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
2316 void Actor::DepthTraverseActorTree( OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths, int32_t& depthIndex )
2318 mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
2319 sceneGraphNodeDepths->Add( const_cast<SceneGraph::Node*>( &GetNode() ), mSortedDepth );
2321 // Create/add to children of this node
2324 for( ActorContainer::iterator it = mChildren->begin(); it != mChildren->end(); ++it )
2326 Actor* childActor = (*it).Get();
2328 childActor->DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
2333 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2337 case Dali::Actor::Property::PARENT_ORIGIN:
2339 Property::Type type = property.GetType();
2340 if( type == Property::VECTOR3 )
2342 SetParentOrigin( property.Get< Vector3 >() );
2344 else if ( type == Property::STRING )
2346 std::string parentOriginString;
2347 property.Get( parentOriginString );
2348 Vector3 parentOrigin;
2349 if( GetParentOriginConstant( parentOriginString, parentOrigin ) )
2351 SetParentOrigin( parentOrigin );
2357 case Dali::Actor::Property::PARENT_ORIGIN_X:
2359 SetParentOriginX( property.Get< float >() );
2363 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2365 SetParentOriginY( property.Get< float >() );
2369 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2371 SetParentOriginZ( property.Get< float >() );
2375 case Dali::Actor::Property::ANCHOR_POINT:
2377 Property::Type type = property.GetType();
2378 if( type == Property::VECTOR3 )
2380 SetAnchorPoint( property.Get< Vector3 >() );
2382 else if ( type == Property::STRING )
2384 std::string anchorPointString;
2385 property.Get( anchorPointString );
2387 if( GetAnchorPointConstant( anchorPointString, anchor ) )
2389 SetAnchorPoint( anchor );
2395 case Dali::Actor::Property::ANCHOR_POINT_X:
2397 SetAnchorPointX( property.Get< float >() );
2401 case Dali::Actor::Property::ANCHOR_POINT_Y:
2403 SetAnchorPointY( property.Get< float >() );
2407 case Dali::Actor::Property::ANCHOR_POINT_Z:
2409 SetAnchorPointZ( property.Get< float >() );
2413 case Dali::Actor::Property::SIZE:
2415 SetSize( property.Get< Vector3 >() );
2419 case Dali::Actor::Property::SIZE_WIDTH:
2421 SetWidth( property.Get< float >() );
2425 case Dali::Actor::Property::SIZE_HEIGHT:
2427 SetHeight( property.Get< float >() );
2431 case Dali::Actor::Property::SIZE_DEPTH:
2433 SetDepth( property.Get< float >() );
2437 case Dali::Actor::Property::POSITION:
2439 SetPosition( property.Get< Vector3 >() );
2443 case Dali::Actor::Property::POSITION_X:
2445 SetX( property.Get< float >() );
2449 case Dali::Actor::Property::POSITION_Y:
2451 SetY( property.Get< float >() );
2455 case Dali::Actor::Property::POSITION_Z:
2457 SetZ( property.Get< float >() );
2461 case Dali::Actor::Property::ORIENTATION:
2463 SetOrientation( property.Get< Quaternion >() );
2467 case Dali::Actor::Property::SCALE:
2469 SetScale( property.Get< Vector3 >() );
2473 case Dali::Actor::Property::SCALE_X:
2475 SetScaleX( property.Get< float >() );
2479 case Dali::Actor::Property::SCALE_Y:
2481 SetScaleY( property.Get< float >() );
2485 case Dali::Actor::Property::SCALE_Z:
2487 SetScaleZ( property.Get< float >() );
2491 case Dali::Actor::Property::VISIBLE:
2493 SetVisible( property.Get< bool >() );
2497 case Dali::Actor::Property::COLOR:
2499 SetColor( property.Get< Vector4 >() );
2503 case Dali::Actor::Property::COLOR_RED:
2505 SetColorRed( property.Get< float >() );
2509 case Dali::Actor::Property::COLOR_GREEN:
2511 SetColorGreen( property.Get< float >() );
2515 case Dali::Actor::Property::COLOR_BLUE:
2517 SetColorBlue( property.Get< float >() );
2521 case Dali::Actor::Property::COLOR_ALPHA:
2522 case Dali::DevelActor::Property::OPACITY:
2525 if( property.Get( value ) )
2527 SetOpacity( value );
2532 case Dali::Actor::Property::NAME:
2534 SetName( property.Get< std::string >() );
2538 case Dali::Actor::Property::SENSITIVE:
2540 SetSensitive( property.Get< bool >() );
2544 case Dali::Actor::Property::LEAVE_REQUIRED:
2546 SetLeaveRequired( property.Get< bool >() );
2550 case Dali::Actor::Property::INHERIT_POSITION:
2552 SetInheritPosition( property.Get< bool >() );
2556 case Dali::Actor::Property::INHERIT_ORIENTATION:
2558 SetInheritOrientation( property.Get< bool >() );
2562 case Dali::Actor::Property::INHERIT_SCALE:
2564 SetInheritScale( property.Get< bool >() );
2568 case Dali::Actor::Property::COLOR_MODE:
2570 ColorMode mode = mColorMode;
2571 if ( Scripting::GetEnumerationProperty< ColorMode >( property, COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT, mode ) )
2573 SetColorMode( mode );
2578 case Dali::Actor::Property::DRAW_MODE:
2580 DrawMode::Type mode = mDrawMode;
2581 if( Scripting::GetEnumerationProperty< DrawMode::Type >( property, DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT, mode ) )
2583 SetDrawMode( mode );
2588 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2590 SetSizeModeFactor( property.Get< Vector3 >() );
2594 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2596 ResizePolicy::Type type = GetResizePolicy( Dimension::WIDTH );
2597 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2599 SetResizePolicy( type, Dimension::WIDTH );
2604 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2606 ResizePolicy::Type type = GetResizePolicy( Dimension::HEIGHT );
2607 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2609 SetResizePolicy( type, Dimension::HEIGHT );
2614 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2616 SizeScalePolicy::Type type = GetSizeScalePolicy();
2617 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT, type ) )
2619 SetSizeScalePolicy( type );
2624 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2626 if( property.Get< bool >() )
2628 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2633 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2635 if( property.Get< bool >() )
2637 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2642 case Dali::Actor::Property::PADDING:
2644 Vector4 padding = property.Get< Vector4 >();
2645 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2646 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2650 case Dali::Actor::Property::MINIMUM_SIZE:
2652 Vector2 size = property.Get< Vector2 >();
2653 SetMinimumSize( size.x, Dimension::WIDTH );
2654 SetMinimumSize( size.y, Dimension::HEIGHT );
2658 case Dali::Actor::Property::MAXIMUM_SIZE:
2660 Vector2 size = property.Get< Vector2 >();
2661 SetMaximumSize( size.x, Dimension::WIDTH );
2662 SetMaximumSize( size.y, Dimension::HEIGHT );
2666 case Dali::DevelActor::Property::SIBLING_ORDER:
2670 if( property.Get( value ) )
2672 SetSiblingOrder( value );
2677 case Dali::Actor::Property::CLIPPING_MODE:
2679 ClippingMode::Type convertedValue = mClippingMode;
2680 if( Scripting::GetEnumerationProperty< ClippingMode::Type >( property, CLIPPING_MODE_TABLE, CLIPPING_MODE_TABLE_COUNT, convertedValue ) )
2682 mClippingMode = convertedValue;
2683 SetClippingModeMessage( GetEventThreadServices(), GetNode(), mClippingMode );
2688 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
2691 if( property.Get( value ) && value != mPositionUsesAnchorPoint )
2693 mPositionUsesAnchorPoint = value;
2694 SetPositionUsesAnchorPointMessage( GetEventThreadServices(), GetNode(), mPositionUsesAnchorPoint );
2699 case Dali::Actor::Property::LAYOUT_DIRECTION:
2701 Dali::LayoutDirection::Type direction = mLayoutDirection;
2702 mInheritLayoutDirection = false;
2704 if( Scripting::GetEnumerationProperty< LayoutDirection::Type >( property, LAYOUT_DIRECTION_TABLE, LAYOUT_DIRECTION_TABLE_COUNT, direction ) )
2706 InheritLayoutDirectionRecursively( this, direction, true );
2711 case Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION:
2714 if( property.Get( value ) )
2716 SetInheritLayoutDirection( value );
2723 // this can happen in the case of a non-animatable default property so just do nothing
2729 // TODO: This method needs to be removed
2730 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2732 switch( entry.GetType() )
2734 case Property::BOOLEAN:
2736 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2737 DALI_ASSERT_DEBUG( NULL != property );
2739 // property is being used in a separate thread; queue a message to set the property
2740 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
2745 case Property::INTEGER:
2747 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
2748 DALI_ASSERT_DEBUG( NULL != property );
2750 // property is being used in a separate thread; queue a message to set the property
2751 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<int>::Bake, value.Get<int>() );
2756 case Property::FLOAT:
2758 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
2759 DALI_ASSERT_DEBUG( NULL != property );
2761 // property is being used in a separate thread; queue a message to set the property
2762 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<float>::Bake, value.Get<float>() );
2767 case Property::VECTOR2:
2769 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
2770 DALI_ASSERT_DEBUG( NULL != property );
2772 // property is being used in a separate thread; queue a message to set the property
2773 if(entry.componentIndex == 0)
2775 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
2777 else if(entry.componentIndex == 1)
2779 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
2783 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
2789 case Property::VECTOR3:
2791 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
2792 DALI_ASSERT_DEBUG( NULL != property );
2794 // property is being used in a separate thread; queue a message to set the property
2795 if(entry.componentIndex == 0)
2797 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
2799 else if(entry.componentIndex == 1)
2801 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
2803 else if(entry.componentIndex == 2)
2805 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
2809 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
2815 case Property::VECTOR4:
2817 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
2818 DALI_ASSERT_DEBUG( NULL != property );
2820 // property is being used in a separate thread; queue a message to set the property
2821 if(entry.componentIndex == 0)
2823 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
2825 else if(entry.componentIndex == 1)
2827 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
2829 else if(entry.componentIndex == 2)
2831 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
2833 else if(entry.componentIndex == 3)
2835 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
2839 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
2845 case Property::ROTATION:
2847 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
2848 DALI_ASSERT_DEBUG( NULL != property );
2850 // property is being used in a separate thread; queue a message to set the property
2851 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
2856 case Property::MATRIX:
2858 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
2859 DALI_ASSERT_DEBUG( NULL != property );
2861 // property is being used in a separate thread; queue a message to set the property
2862 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), &GetNode(), property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
2867 case Property::MATRIX3:
2869 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
2870 DALI_ASSERT_DEBUG( NULL != property );
2872 // property is being used in a separate thread; queue a message to set the property
2873 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), &GetNode(), property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
2880 // nothing to do for other types
2885 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
2887 Property::Value value;
2889 if( ! GetCachedPropertyValue( index, value ) )
2891 // If property value is not stored in the event-side, then it must be a scene-graph only property
2892 GetCurrentPropertyValue( index, value );
2898 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
2900 Property::Value value;
2902 if( ! GetCurrentPropertyValue( index, value ) )
2904 // If unable to retrieve scene-graph property value, then it must be an event-side only property
2905 GetCachedPropertyValue( index, value );
2911 void Actor::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
2913 switch( animationType )
2916 case Animation::BETWEEN:
2920 case Dali::Actor::Property::SIZE:
2922 if( value.Get( mTargetSize ) )
2924 // Notify deriving classes
2925 OnSizeAnimation( animation, mTargetSize );
2930 case Dali::Actor::Property::SIZE_WIDTH:
2932 if( value.Get( mTargetSize.width ) )
2934 // Notify deriving classes
2935 OnSizeAnimation( animation, mTargetSize );
2940 case Dali::Actor::Property::SIZE_HEIGHT:
2942 if( value.Get( mTargetSize.height ) )
2944 // Notify deriving classes
2945 OnSizeAnimation( animation, mTargetSize );
2950 case Dali::Actor::Property::SIZE_DEPTH:
2952 if( value.Get( mTargetSize.depth ) )
2954 // Notify deriving classes
2955 OnSizeAnimation( animation, mTargetSize );
2960 case Dali::Actor::Property::POSITION:
2962 value.Get( mTargetPosition );
2966 case Dali::Actor::Property::POSITION_X:
2968 value.Get( mTargetPosition.x );
2972 case Dali::Actor::Property::POSITION_Y:
2974 value.Get( mTargetPosition.y );
2978 case Dali::Actor::Property::POSITION_Z:
2980 value.Get( mTargetPosition.z );
2984 case Dali::Actor::Property::ORIENTATION:
2986 value.Get( mTargetOrientation );
2990 case Dali::Actor::Property::SCALE:
2992 value.Get( mTargetScale );
2996 case Dali::Actor::Property::SCALE_X:
2998 value.Get( mTargetScale.x );
3002 case Dali::Actor::Property::SCALE_Y:
3004 value.Get( mTargetScale.y );
3008 case Dali::Actor::Property::SCALE_Z:
3010 value.Get( mTargetScale.z );
3014 case Dali::Actor::Property::VISIBLE:
3016 SetVisibleInternal( value.Get< bool >(), SendMessage::FALSE );
3020 case Dali::Actor::Property::COLOR:
3022 value.Get( mTargetColor );
3026 case Dali::Actor::Property::COLOR_RED:
3028 value.Get( mTargetColor.r );
3032 case Dali::Actor::Property::COLOR_GREEN:
3034 value.Get( mTargetColor.g );
3038 case Dali::Actor::Property::COLOR_BLUE:
3040 value.Get( mTargetColor.b );
3044 case Dali::Actor::Property::COLOR_ALPHA:
3045 case Dali::DevelActor::Property::OPACITY:
3047 value.Get( mTargetColor.a );
3053 // Not an animatable property. Do nothing.
3064 case Dali::Actor::Property::SIZE:
3066 if( AdjustValue< Vector3 >( mTargetSize, value ) )
3068 // Notify deriving classes
3069 OnSizeAnimation( animation, mTargetSize );
3074 case Dali::Actor::Property::SIZE_WIDTH:
3076 if( AdjustValue< float >( mTargetSize.width, value ) )
3078 // Notify deriving classes
3079 OnSizeAnimation( animation, mTargetSize );
3084 case Dali::Actor::Property::SIZE_HEIGHT:
3086 if( AdjustValue< float >( mTargetSize.height, value ) )
3088 // Notify deriving classes
3089 OnSizeAnimation( animation, mTargetSize );
3094 case Dali::Actor::Property::SIZE_DEPTH:
3096 if( AdjustValue< float >( mTargetSize.depth, value ) )
3098 // Notify deriving classes
3099 OnSizeAnimation( animation, mTargetSize );
3104 case Dali::Actor::Property::POSITION:
3106 AdjustValue< Vector3 >( mTargetPosition, value );
3110 case Dali::Actor::Property::POSITION_X:
3112 AdjustValue< float >( mTargetPosition.x, value );
3116 case Dali::Actor::Property::POSITION_Y:
3118 AdjustValue< float >( mTargetPosition.y, value );
3122 case Dali::Actor::Property::POSITION_Z:
3124 AdjustValue< float >( mTargetPosition.z, value );
3128 case Dali::Actor::Property::ORIENTATION:
3130 Quaternion relativeValue;
3131 if( value.Get( relativeValue ) )
3133 mTargetOrientation *= relativeValue;
3138 case Dali::Actor::Property::SCALE:
3140 AdjustValue< Vector3 >( mTargetScale, value );
3144 case Dali::Actor::Property::SCALE_X:
3146 AdjustValue< float >( mTargetScale.x, value );
3150 case Dali::Actor::Property::SCALE_Y:
3152 AdjustValue< float >( mTargetScale.y, value );
3156 case Dali::Actor::Property::SCALE_Z:
3158 AdjustValue< float >( mTargetScale.z, value );
3162 case Dali::Actor::Property::VISIBLE:
3164 bool relativeValue = false;
3165 if( value.Get( relativeValue ) )
3167 bool visible = mVisible || relativeValue;
3168 SetVisibleInternal( visible, SendMessage::FALSE );
3173 case Dali::Actor::Property::COLOR:
3175 AdjustValue< Vector4 >( mTargetColor, value );
3179 case Dali::Actor::Property::COLOR_RED:
3181 AdjustValue< float >( mTargetColor.r, value );
3185 case Dali::Actor::Property::COLOR_GREEN:
3187 AdjustValue< float >( mTargetColor.g, value );
3191 case Dali::Actor::Property::COLOR_BLUE:
3193 AdjustValue< float >( mTargetColor.b, value );
3197 case Dali::Actor::Property::COLOR_ALPHA:
3198 case Dali::DevelActor::Property::OPACITY:
3200 AdjustValue< float >( mTargetColor.a, value );
3206 // Not an animatable property. Do nothing.
3215 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3217 const PropertyBase* property( NULL );
3221 case Dali::Actor::Property::SIZE: // FALLTHROUGH
3222 case Dali::Actor::Property::SIZE_WIDTH: // FALLTHROUGH
3223 case Dali::Actor::Property::SIZE_HEIGHT: // FALLTHROUGH
3224 case Dali::Actor::Property::SIZE_DEPTH:
3226 property = &GetNode().mSize;
3229 case Dali::Actor::Property::POSITION: // FALLTHROUGH
3230 case Dali::Actor::Property::POSITION_X: // FALLTHROUGH
3231 case Dali::Actor::Property::POSITION_Y: // FALLTHROUGH
3232 case Dali::Actor::Property::POSITION_Z:
3234 property = &GetNode().mPosition;
3237 case Dali::Actor::Property::ORIENTATION:
3239 property = &GetNode().mOrientation;
3242 case Dali::Actor::Property::SCALE: // FALLTHROUGH
3243 case Dali::Actor::Property::SCALE_X: // FALLTHROUGH
3244 case Dali::Actor::Property::SCALE_Y: // FALLTHROUGH
3245 case Dali::Actor::Property::SCALE_Z:
3247 property = &GetNode().mScale;
3250 case Dali::Actor::Property::VISIBLE:
3252 property = &GetNode().mVisible;
3255 case Dali::Actor::Property::COLOR: // FALLTHROUGH
3256 case Dali::Actor::Property::COLOR_RED: // FALLTHROUGH
3257 case Dali::Actor::Property::COLOR_GREEN: // FALLTHROUGH
3258 case Dali::Actor::Property::COLOR_BLUE: // FALLTHROUGH
3259 case Dali::Actor::Property::COLOR_ALPHA: // FALLTHROUGH
3260 case Dali::DevelActor::Property::OPACITY:
3262 property = &GetNode().mColor;
3272 // not our property, ask base
3273 property = Object::GetSceneObjectAnimatableProperty( index );
3279 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3281 const PropertyInputImpl* property( NULL );
3285 case Dali::Actor::Property::PARENT_ORIGIN: // FALLTHROUGH
3286 case Dali::Actor::Property::PARENT_ORIGIN_X: // FALLTHROUGH
3287 case Dali::Actor::Property::PARENT_ORIGIN_Y: // FALLTHROUGH
3288 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3290 property = &GetNode().mParentOrigin;
3293 case Dali::Actor::Property::ANCHOR_POINT: // FALLTHROUGH
3294 case Dali::Actor::Property::ANCHOR_POINT_X: // FALLTHROUGH
3295 case Dali::Actor::Property::ANCHOR_POINT_Y: // FALLTHROUGH
3296 case Dali::Actor::Property::ANCHOR_POINT_Z:
3298 property = &GetNode().mAnchorPoint;
3301 case Dali::Actor::Property::WORLD_POSITION: // FALLTHROUGH
3302 case Dali::Actor::Property::WORLD_POSITION_X: // FALLTHROUGH
3303 case Dali::Actor::Property::WORLD_POSITION_Y: // FALLTHROUGH
3304 case Dali::Actor::Property::WORLD_POSITION_Z:
3306 property = &GetNode().mWorldPosition;
3309 case Dali::Actor::Property::WORLD_ORIENTATION:
3311 property = &GetNode().mWorldOrientation;
3314 case Dali::Actor::Property::WORLD_SCALE:
3316 property = &GetNode().mWorldScale;
3319 case Dali::Actor::Property::WORLD_COLOR:
3321 property = &GetNode().mWorldColor;
3324 case Dali::Actor::Property::WORLD_MATRIX:
3326 property = &GetNode().mWorldMatrix;
3329 case Dali::DevelActor::Property::CULLED:
3331 property = &GetNode().mCulled;
3341 // reuse animatable property getter as animatable properties are inputs as well
3342 // animatable property chains back to Object::GetSceneObjectInputProperty() so all properties get covered
3343 property = GetSceneObjectAnimatableProperty( index );
3349 int32_t Actor::GetPropertyComponentIndex( Property::Index index ) const
3351 int32_t componentIndex = Property::INVALID_COMPONENT_INDEX;
3355 case Dali::Actor::Property::PARENT_ORIGIN_X:
3356 case Dali::Actor::Property::ANCHOR_POINT_X:
3357 case Dali::Actor::Property::SIZE_WIDTH:
3358 case Dali::Actor::Property::POSITION_X:
3359 case Dali::Actor::Property::WORLD_POSITION_X:
3360 case Dali::Actor::Property::SCALE_X:
3361 case Dali::Actor::Property::COLOR_RED:
3367 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3368 case Dali::Actor::Property::ANCHOR_POINT_Y:
3369 case Dali::Actor::Property::SIZE_HEIGHT:
3370 case Dali::Actor::Property::POSITION_Y:
3371 case Dali::Actor::Property::WORLD_POSITION_Y:
3372 case Dali::Actor::Property::SCALE_Y:
3373 case Dali::Actor::Property::COLOR_GREEN:
3379 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3380 case Dali::Actor::Property::ANCHOR_POINT_Z:
3381 case Dali::Actor::Property::SIZE_DEPTH:
3382 case Dali::Actor::Property::POSITION_Z:
3383 case Dali::Actor::Property::WORLD_POSITION_Z:
3384 case Dali::Actor::Property::SCALE_Z:
3385 case Dali::Actor::Property::COLOR_BLUE:
3391 case Dali::Actor::Property::COLOR_ALPHA:
3392 case Dali::DevelActor::Property::OPACITY:
3404 if( Property::INVALID_COMPONENT_INDEX == componentIndex )
3407 componentIndex = Object::GetPropertyComponentIndex( index );
3410 return componentIndex;
3413 void Actor::SetParent( Actor* parent )
3417 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3421 mScene = parent->mScene;
3423 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3426 // Instruct each actor to create a corresponding node in the scene graph
3427 ConnectToStage( parent->GetHierarchyDepth() );
3430 // Resolve the name and index for the child properties if any
3431 ResolveChildProperties();
3433 else // parent being set to NULL
3435 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3439 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3442 // Disconnect the Node & its children from the scene-graph.
3443 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
3445 // Instruct each actor to discard pointers to the scene-graph
3446 DisconnectFromStage();
3453 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3456 Actor* actor = dynamic_cast< Actor* >( object );
3460 if( 0 == actionName.compare( ACTION_SHOW ) )
3462 actor->SetVisible( true );
3465 else if( 0 == actionName.compare( ACTION_HIDE ) )
3467 actor->SetVisible( false );
3475 Rect<> Actor::CalculateScreenExtents( ) const
3477 auto screenPosition = GetCurrentScreenPosition();
3478 Vector3 size = GetCurrentSize() * GetCurrentWorldScale();
3479 Vector3 anchorPointOffSet = size * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
3480 Vector2 position = Vector2( screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y );
3481 return { position.x, position.y, size.x, size.y };
3484 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
3486 bool valueSet = true;
3490 case Dali::Actor::Property::PARENT_ORIGIN:
3492 value = GetCurrentParentOrigin();
3496 case Dali::Actor::Property::PARENT_ORIGIN_X:
3498 value = GetCurrentParentOrigin().x;
3502 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3504 value = GetCurrentParentOrigin().y;
3508 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3510 value = GetCurrentParentOrigin().z;
3514 case Dali::Actor::Property::ANCHOR_POINT:
3516 value = GetCurrentAnchorPoint();
3520 case Dali::Actor::Property::ANCHOR_POINT_X:
3522 value = GetCurrentAnchorPoint().x;
3526 case Dali::Actor::Property::ANCHOR_POINT_Y:
3528 value = GetCurrentAnchorPoint().y;
3532 case Dali::Actor::Property::ANCHOR_POINT_Z:
3534 value = GetCurrentAnchorPoint().z;
3538 case Dali::Actor::Property::SIZE:
3540 value = GetTargetSize();
3544 case Dali::Actor::Property::SIZE_WIDTH:
3546 value = GetTargetSize().width;
3550 case Dali::Actor::Property::SIZE_HEIGHT:
3552 value = GetTargetSize().height;
3556 case Dali::Actor::Property::SIZE_DEPTH:
3558 value = GetTargetSize().depth;
3562 case Dali::Actor::Property::POSITION:
3564 value = GetTargetPosition();
3568 case Dali::Actor::Property::POSITION_X:
3570 value = GetTargetPosition().x;
3574 case Dali::Actor::Property::POSITION_Y:
3576 value = GetTargetPosition().y;
3580 case Dali::Actor::Property::POSITION_Z:
3582 value = GetTargetPosition().z;
3586 case Dali::Actor::Property::ORIENTATION:
3588 value = mTargetOrientation;
3592 case Dali::Actor::Property::SCALE:
3594 value = mTargetScale;
3598 case Dali::Actor::Property::SCALE_X:
3600 value = mTargetScale.x;
3604 case Dali::Actor::Property::SCALE_Y:
3606 value = mTargetScale.y;
3610 case Dali::Actor::Property::SCALE_Z:
3612 value = mTargetScale.z;
3616 case Dali::Actor::Property::VISIBLE:
3622 case Dali::Actor::Property::COLOR:
3624 value = mTargetColor;
3628 case Dali::Actor::Property::COLOR_RED:
3630 value = mTargetColor.r;
3634 case Dali::Actor::Property::COLOR_GREEN:
3636 value = mTargetColor.g;
3640 case Dali::Actor::Property::COLOR_BLUE:
3642 value = mTargetColor.b;
3646 case Dali::Actor::Property::COLOR_ALPHA:
3647 case Dali::DevelActor::Property::OPACITY:
3649 value = mTargetColor.a;
3653 case Dali::Actor::Property::NAME:
3659 case Dali::Actor::Property::SENSITIVE:
3661 value = IsSensitive();
3665 case Dali::Actor::Property::LEAVE_REQUIRED:
3667 value = GetLeaveRequired();
3671 case Dali::Actor::Property::INHERIT_POSITION:
3673 value = IsPositionInherited();
3677 case Dali::Actor::Property::INHERIT_ORIENTATION:
3679 value = IsOrientationInherited();
3683 case Dali::Actor::Property::INHERIT_SCALE:
3685 value = IsScaleInherited();
3689 case Dali::Actor::Property::COLOR_MODE:
3691 value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
3695 case Dali::Actor::Property::DRAW_MODE:
3697 value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
3701 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3703 value = GetSizeModeFactor();
3707 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3709 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3713 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3715 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3719 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3721 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT );
3725 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3727 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3731 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3733 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3737 case Dali::Actor::Property::PADDING:
3739 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3740 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3741 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3745 case Dali::Actor::Property::MINIMUM_SIZE:
3747 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3751 case Dali::Actor::Property::MAXIMUM_SIZE:
3753 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3757 case Dali::Actor::Property::CLIPPING_MODE:
3759 value = mClippingMode;
3763 case Dali::DevelActor::Property::SIBLING_ORDER:
3765 value = static_cast<int>( GetSiblingOrder() );
3769 case Dali::DevelActor::Property::SCREEN_POSITION:
3771 value = GetCurrentScreenPosition();
3775 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
3777 value = mPositionUsesAnchorPoint;
3781 case Dali::Actor::Property::LAYOUT_DIRECTION:
3783 value = mLayoutDirection;
3787 case Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION:
3789 value = IsLayoutDirectionInherited();
3795 // Must be a scene-graph only property
3804 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
3806 bool valueSet = true;
3810 case Dali::Actor::Property::SIZE:
3812 value = GetCurrentSize();
3816 case Dali::Actor::Property::SIZE_WIDTH:
3818 value = GetCurrentSize().width;
3822 case Dali::Actor::Property::SIZE_HEIGHT:
3824 value = GetCurrentSize().height;
3828 case Dali::Actor::Property::SIZE_DEPTH:
3830 value = GetCurrentSize().depth;
3834 case Dali::Actor::Property::POSITION:
3836 value = GetCurrentPosition();
3840 case Dali::Actor::Property::POSITION_X:
3842 value = GetCurrentPosition().x;
3846 case Dali::Actor::Property::POSITION_Y:
3848 value = GetCurrentPosition().y;
3852 case Dali::Actor::Property::POSITION_Z:
3854 value = GetCurrentPosition().z;
3858 case Dali::Actor::Property::WORLD_POSITION:
3860 value = GetCurrentWorldPosition();
3864 case Dali::Actor::Property::WORLD_POSITION_X:
3866 value = GetCurrentWorldPosition().x;
3870 case Dali::Actor::Property::WORLD_POSITION_Y:
3872 value = GetCurrentWorldPosition().y;
3876 case Dali::Actor::Property::WORLD_POSITION_Z:
3878 value = GetCurrentWorldPosition().z;
3882 case Dali::Actor::Property::ORIENTATION:
3884 value = GetCurrentOrientation();
3888 case Dali::Actor::Property::WORLD_ORIENTATION:
3890 value = GetCurrentWorldOrientation();
3894 case Dali::Actor::Property::SCALE:
3896 value = GetCurrentScale();
3900 case Dali::Actor::Property::SCALE_X:
3902 value = GetCurrentScale().x;
3906 case Dali::Actor::Property::SCALE_Y:
3908 value = GetCurrentScale().y;
3912 case Dali::Actor::Property::SCALE_Z:
3914 value = GetCurrentScale().z;
3918 case Dali::Actor::Property::WORLD_SCALE:
3920 value = GetCurrentWorldScale();
3924 case Dali::Actor::Property::COLOR:
3926 value = GetCurrentColor();
3930 case Dali::Actor::Property::COLOR_RED:
3932 value = GetCurrentColor().r;
3936 case Dali::Actor::Property::COLOR_GREEN:
3938 value = GetCurrentColor().g;
3942 case Dali::Actor::Property::COLOR_BLUE:
3944 value = GetCurrentColor().b;
3948 case Dali::Actor::Property::COLOR_ALPHA:
3949 case Dali::DevelActor::Property::OPACITY:
3951 value = GetCurrentColor().a;
3955 case Dali::Actor::Property::WORLD_COLOR:
3957 value = GetCurrentWorldColor();
3961 case Dali::Actor::Property::WORLD_MATRIX:
3963 value = GetCurrentWorldMatrix();
3967 case Dali::Actor::Property::VISIBLE:
3969 value = IsVisible();
3973 case DevelActor::Property::CULLED:
3975 value = GetNode().IsCulled( GetEventThreadServices().GetEventBufferIndex() );
3981 // Must be an event-side only property
3990 void Actor::EnsureRelayoutData()
3992 // Assign relayout data.
3993 if( !mRelayoutData )
3995 mRelayoutData = new RelayoutData();
3999 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
4001 // Check if actor is dependent on parent
4002 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4004 if( ( dimension & ( 1 << i ) ) )
4006 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4007 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
4017 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
4019 // Check if actor is dependent on children
4020 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4022 if( ( dimension & ( 1 << i ) ) )
4024 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4025 switch( resizePolicy )
4027 case ResizePolicy::FIT_TO_CHILDREN:
4028 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
4044 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
4046 return Actor::RelayoutDependentOnChildren( dimension );
4049 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
4051 // Check each possible dimension and see if it is dependent on the input one
4052 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4054 if( dimension & ( 1 << i ) )
4056 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
4063 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
4065 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4067 if( dimension & ( 1 << i ) )
4069 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
4074 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
4076 // If more than one dimension is requested, just return the first one found
4077 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4079 if( ( dimension & ( 1 << i ) ) )
4081 return mRelayoutData->negotiatedDimensions[ i ];
4085 return 0.0f; // Default
4088 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
4090 EnsureRelayoutData();
4092 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4094 if( dimension & ( 1 << i ) )
4096 mRelayoutData->dimensionPadding[ i ] = padding;
4101 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4103 if ( mRelayoutData )
4105 // If more than one dimension is requested, just return the first one found
4106 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4108 if( ( dimension & ( 1 << i ) ) )
4110 return mRelayoutData->dimensionPadding[ i ];
4115 return GetDefaultDimensionPadding();
4118 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4120 EnsureRelayoutData();
4122 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4124 if( dimension & ( 1 << i ) )
4126 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4131 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4133 if ( mRelayoutData )
4135 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4137 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4147 float Actor::GetHeightForWidthBase( float width )
4149 float height = 0.0f;
4151 const Vector3 naturalSize = GetNaturalSize();
4152 if( naturalSize.width > 0.0f )
4154 height = naturalSize.height * width / naturalSize.width;
4156 else // we treat 0 as 1:1 aspect ratio
4164 float Actor::GetWidthForHeightBase( float height )
4168 const Vector3 naturalSize = GetNaturalSize();
4169 if( naturalSize.height > 0.0f )
4171 width = naturalSize.width * height / naturalSize.height;
4173 else // we treat 0 as 1:1 aspect ratio
4181 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4183 // Fill to parent, taking size mode factor into account
4184 switch( child.GetResizePolicy( dimension ) )
4186 case ResizePolicy::FILL_TO_PARENT:
4188 return GetLatestSize( dimension );
4191 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4193 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4196 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4198 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4203 return GetLatestSize( dimension );
4208 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4210 // Can be overridden in derived class
4211 return CalculateChildSizeBase( child, dimension );
4214 float Actor::GetHeightForWidth( float width )
4216 // Can be overridden in derived class
4217 return GetHeightForWidthBase( width );
4220 float Actor::GetWidthForHeight( float height )
4222 // Can be overridden in derived class
4223 return GetWidthForHeightBase( height );
4226 float Actor::GetLatestSize( Dimension::Type dimension ) const
4228 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4231 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4233 Vector2 padding = GetPadding( dimension );
4235 return GetLatestSize( dimension ) + padding.x + padding.y;
4238 float Actor::NegotiateFromParent( Dimension::Type dimension )
4240 Actor* parent = GetParent();
4243 Vector2 padding( GetPadding( dimension ) );
4244 Vector2 parentPadding( parent->GetPadding( dimension ) );
4245 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4251 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4253 float maxDimensionPoint = 0.0f;
4255 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4257 ActorPtr child = GetChildAt( i );
4259 if( !child->RelayoutDependentOnParent( dimension ) )
4261 // Calculate the min and max points that the children range across
4262 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
4263 float dimensionSize = child->GetRelayoutSize( dimension );
4264 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4268 return maxDimensionPoint;
4271 float Actor::GetSize( Dimension::Type dimension ) const
4273 return GetDimensionValue( mTargetSize, dimension );
4276 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4278 return GetDimensionValue( GetNaturalSize(), dimension );
4281 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4283 switch( GetResizePolicy( dimension ) )
4285 case ResizePolicy::USE_NATURAL_SIZE:
4287 return GetNaturalSize( dimension );
4290 case ResizePolicy::FIXED:
4292 return GetDimensionValue( GetPreferredSize(), dimension );
4295 case ResizePolicy::USE_ASSIGNED_SIZE:
4297 return GetDimensionValue( maximumSize, dimension );
4300 case ResizePolicy::FILL_TO_PARENT:
4301 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4302 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4304 return NegotiateFromParent( dimension );
4307 case ResizePolicy::FIT_TO_CHILDREN:
4309 return NegotiateFromChildren( dimension );
4312 case ResizePolicy::DIMENSION_DEPENDENCY:
4314 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4317 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4319 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4322 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4324 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4336 return 0.0f; // Default
4339 float Actor::ClampDimension( float size, Dimension::Type dimension )
4341 const float minSize = GetMinimumSize( dimension );
4342 const float maxSize = GetMaximumSize( dimension );
4344 return std::max( minSize, std::min( size, maxSize ) );
4347 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4349 // Check if it needs to be negotiated
4350 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4352 // Check that we havn't gotten into an infinite loop
4353 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4354 bool recursionFound = false;
4355 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4357 if( *it == searchActor )
4359 recursionFound = true;
4364 if( !recursionFound )
4366 // Record the path that we have taken
4367 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4369 // Dimension dependency check
4370 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4372 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4374 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4376 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4380 // Parent dependency check
4381 Actor* parent = GetParent();
4382 if( parent && RelayoutDependentOnParent( dimension ) )
4384 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4387 // Children dependency check
4388 if( RelayoutDependentOnChildren( dimension ) )
4390 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4392 ActorPtr child = GetChildAt( i );
4394 // Only relayout child first if it is not dependent on this actor
4395 if( !child->RelayoutDependentOnParent( dimension ) )
4397 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
4402 // For deriving classes
4403 OnCalculateRelayoutSize( dimension );
4405 // All dependencies checked, calculate the size and set negotiated flag
4406 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4408 SetNegotiatedDimension( newSize, dimension );
4409 SetLayoutNegotiated( true, dimension );
4411 // For deriving classes
4412 OnLayoutNegotiated( newSize, dimension );
4414 // This actor has been successfully processed, pop it off the recursion stack
4415 recursionStack.pop_back();
4419 // TODO: Break infinite loop
4420 SetLayoutNegotiated( true, dimension );
4425 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4427 // Negotiate all dimensions that require it
4428 ActorDimensionStack recursionStack;
4430 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4432 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4435 NegotiateDimension( dimension, allocatedSize, recursionStack );
4439 Vector2 Actor::ApplySizeSetPolicy( const Vector2& size )
4441 switch( mRelayoutData->sizeSetPolicy )
4443 case SizeScalePolicy::USE_SIZE_SET:
4448 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4450 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4451 const Vector3 naturalSize = GetNaturalSize();
4452 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4454 const float sizeRatio = size.width / size.height;
4455 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4457 if( naturalSizeRatio < sizeRatio )
4459 return Vector2( naturalSizeRatio * size.height, size.height );
4461 else if( naturalSizeRatio > sizeRatio )
4463 return Vector2( size.width, size.width / naturalSizeRatio );
4474 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4476 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4477 const Vector3 naturalSize = GetNaturalSize();
4478 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4480 const float sizeRatio = size.width / size.height;
4481 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4483 if( naturalSizeRatio < sizeRatio )
4485 return Vector2( size.width, size.width / naturalSizeRatio );
4487 else if( naturalSizeRatio > sizeRatio )
4489 return Vector2( naturalSizeRatio * size.height, size.height );
4508 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4510 // Do the set actor size
4511 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4513 // Adjust for size set policy
4514 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4516 // Lock the flag to stop recursive relayouts on set size
4517 mRelayoutData->insideRelayout = true;
4518 SetSize( negotiatedSize );
4519 mRelayoutData->insideRelayout = false;
4521 // Clear flags for all dimensions
4522 SetLayoutDirty( false );
4524 // Give deriving classes a chance to respond
4525 OnRelayout( negotiatedSize, container );
4527 if( !mOnRelayoutSignal.Empty() )
4529 Dali::Actor handle( this );
4530 mOnRelayoutSignal.Emit( handle );
4534 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4536 // Force a size negotiation for actors that has assigned size during relayout
4537 // This is required as otherwise the flags that force a relayout will not
4538 // necessarilly be set. This will occur if the actor has already been laid out.
4539 // The dirty flags are then cleared. Then if the actor is added back into the
4540 // relayout container afterwards, the dirty flags would still be clear...
4541 // causing a relayout to be skipped. Here we force any actors added to the
4542 // container to be relayed out.
4543 DALI_LOG_TIMER_START( NegSizeTimer1 );
4545 if( GetUseAssignedSize(Dimension::WIDTH ) )
4547 SetLayoutNegotiated( false, Dimension::WIDTH );
4549 if( GetUseAssignedSize( Dimension::HEIGHT ) )
4551 SetLayoutNegotiated( false, Dimension::HEIGHT );
4554 // Do the negotiation
4555 NegotiateDimensions( allocatedSize );
4557 // Set the actor size
4558 SetNegotiatedSize( container );
4560 // Negotiate down to children
4561 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4563 ActorPtr child = GetChildAt( i );
4565 // Forces children that have already been laid out to be relayed out
4566 // if they have assigned size during relayout.
4567 if( child->GetUseAssignedSize(Dimension::WIDTH) )
4569 child->SetLayoutNegotiated(false, Dimension::WIDTH);
4570 child->SetLayoutDirty(true, Dimension::WIDTH);
4573 if( child->GetUseAssignedSize(Dimension::HEIGHT) )
4575 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
4576 child->SetLayoutDirty(true, Dimension::HEIGHT);
4579 // Only relayout if required
4580 if( child->RelayoutRequired() )
4582 container.Add( Dali::Actor( child.Get() ), mTargetSize.GetVectorXY() );
4585 DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
4588 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
4592 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4594 if( dimension & ( 1 << i ) )
4596 mRelayoutData->useAssignedSize[ i ] = use;
4602 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
4604 if ( mRelayoutData )
4606 // If more than one dimension is requested, just return the first one found
4607 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4609 if( dimension & ( 1 << i ) )
4611 return mRelayoutData->useAssignedSize[ i ];
4619 void Actor::RelayoutRequest( Dimension::Type dimension )
4621 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4622 if( relayoutController )
4624 Dali::Actor self( this );
4625 relayoutController->RequestRelayout( self, dimension );
4629 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4633 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4637 void Actor::SetPreferredSize( const Vector2& size )
4639 EnsureRelayoutData();
4641 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4642 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4644 mRelayoutData->preferredSize = size;
4649 Vector2 Actor::GetPreferredSize() const
4651 if ( mRelayoutData )
4653 return Vector2( mRelayoutData->preferredSize );
4656 return GetDefaultPreferredSize();
4659 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4661 EnsureRelayoutData();
4663 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4665 if( dimension & ( 1 << i ) )
4667 mRelayoutData->minimumSize[ i ] = size;
4674 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4676 if ( mRelayoutData )
4678 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4680 if( dimension & ( 1 << i ) )
4682 return mRelayoutData->minimumSize[ i ];
4687 return 0.0f; // Default
4690 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4692 EnsureRelayoutData();
4694 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4696 if( dimension & ( 1 << i ) )
4698 mRelayoutData->maximumSize[ i ] = size;
4705 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4707 if ( mRelayoutData )
4709 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4711 if( dimension & ( 1 << i ) )
4713 return mRelayoutData->maximumSize[ i ];
4718 return FLT_MAX; // Default
4721 Object* Actor::GetParentObject() const
4726 void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
4728 if( mVisible != visible )
4730 if( sendMessage == SendMessage::TRUE )
4732 // node is being used in a separate thread; queue a message to set the value & base value
4733 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible );
4738 // Emit the signal on this actor and all its children
4739 EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
4743 void Actor::SetSiblingOrder( uint32_t order )
4747 ActorContainer& siblings = *(mParent->mChildren);
4748 uint32_t currentOrder = GetSiblingOrder();
4750 if( order != currentOrder )
4756 else if( order < siblings.size() -1 )
4758 if( order > currentOrder )
4760 RaiseAbove( *siblings[order] );
4764 LowerBelow( *siblings[order] );
4775 uint32_t Actor::GetSiblingOrder() const
4781 ActorContainer& siblings = *(mParent->mChildren);
4782 for( std::size_t i = 0; i < siblings.size(); ++i )
4784 if( siblings[i] == this )
4786 order = static_cast<uint32_t>( i );
4795 void Actor::RequestRebuildDepthTree()
4801 mScene->RequestRebuildDepthTree();
4810 ActorContainer& siblings = *(mParent->mChildren);
4811 if( siblings.back() != this ) // If not already at end
4813 for( std::size_t i=0; i<siblings.size(); ++i )
4815 if( siblings[i] == this )
4818 ActorPtr next = siblings[i+1];
4819 siblings[i+1] = this;
4826 Dali::Actor handle( this );
4827 mParent->mChildOrderChangedSignal.Emit( handle );
4829 RequestRebuildDepthTree();
4833 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4841 ActorContainer& siblings = *(mParent->mChildren);
4842 if( siblings.front() != this ) // If not already at beginning
4844 for( std::size_t i=1; i<siblings.size(); ++i )
4846 if( siblings[i] == this )
4848 // Swap with previous
4849 ActorPtr previous = siblings[i-1];
4850 siblings[i-1] = this;
4851 siblings[i] = previous;
4857 Dali::Actor handle( this );
4858 mParent->mChildOrderChangedSignal.Emit( handle );
4860 RequestRebuildDepthTree();
4864 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4868 void Actor::RaiseToTop()
4872 ActorContainer& siblings = *(mParent->mChildren);
4873 if( siblings.back() != this ) // If not already at end
4875 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
4876 if( iter != siblings.end() )
4878 siblings.erase(iter);
4879 siblings.push_back(ActorPtr(this));
4883 Dali::Actor handle( this );
4884 mParent->mChildOrderChangedSignal.Emit( handle );
4886 RequestRebuildDepthTree();
4890 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4894 void Actor::LowerToBottom()
4898 ActorContainer& siblings = *(mParent->mChildren);
4899 if( siblings.front() != this ) // If not already at bottom,
4901 ActorPtr thisPtr(this); // ensure this actor remains referenced.
4903 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
4904 if( iter != siblings.end() )
4906 siblings.erase(iter);
4907 siblings.insert(siblings.begin(), thisPtr);
4911 Dali::Actor handle( this );
4912 mParent->mChildOrderChangedSignal.Emit( handle );
4914 RequestRebuildDepthTree();
4918 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4922 void Actor::RaiseAbove( Internal::Actor& target )
4926 ActorContainer& siblings = *(mParent->mChildren);
4927 if( siblings.back() != this && target.mParent == mParent ) // If not already at top
4929 ActorPtr thisPtr(this); // ensure this actor remains referenced.
4931 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
4932 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
4933 if( thisIter < targetIter )
4935 siblings.erase(thisIter);
4936 // Erasing early invalidates the targetIter. (Conversely, inserting first may also
4937 // invalidate thisIter)
4938 targetIter = std::find( siblings.begin(), siblings.end(), &target );
4940 siblings.insert(targetIter, thisPtr);
4943 Dali::Actor handle( this );
4944 mParent->mChildOrderChangedSignal.Emit( handle );
4946 RequestRebuildDepthTree();
4951 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4955 void Actor::LowerBelow( Internal::Actor& target )
4959 ActorContainer& siblings = *(mParent->mChildren);
4960 if( siblings.front() != this && target.mParent == mParent ) // If not already at bottom
4962 ActorPtr thisPtr(this); // ensure this actor remains referenced.
4964 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
4965 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
4967 if( thisIter > targetIter )
4969 siblings.erase(thisIter); // this only invalidates iterators at or after this point.
4970 siblings.insert(targetIter, thisPtr);
4973 Dali::Actor handle( this );
4974 mParent->mChildOrderChangedSignal.Emit( handle );
4976 RequestRebuildDepthTree();
4981 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4985 void Actor::SetScene( Scene& scene )
4990 Scene& Actor::GetScene() const
4995 void Actor::SetInheritLayoutDirection( bool inherit )
4997 if( mInheritLayoutDirection != inherit )
4999 mInheritLayoutDirection = inherit;
5001 if( inherit && mParent )
5003 InheritLayoutDirectionRecursively( this, mParent->mLayoutDirection );
5008 bool Actor::IsLayoutDirectionInherited() const
5010 return mInheritLayoutDirection;
5013 void Actor::InheritLayoutDirectionRecursively( ActorPtr actor, Dali::LayoutDirection::Type direction, bool set )
5015 if( actor && ( actor->mInheritLayoutDirection || set ) )
5017 if( actor->mLayoutDirection != direction )
5019 actor->mLayoutDirection = direction;
5020 actor->EmitLayoutDirectionChangedSignal( direction );
5021 actor->RelayoutRequest();
5024 if( actor->GetChildCount() > 0 )
5026 ActorContainer& children = actor->GetChildrenInternal();
5027 for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter )
5029 InheritLayoutDirectionRecursively( *iter, direction );
5035 } // namespace Internal