2 * Copyright (c) 2018 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/event/actors/actor-impl.h>
27 #include <dali/devel-api/actors/layer-devel.h>
28 #include <dali/public-api/common/dali-common.h>
29 #include <dali/public-api/common/constants.h>
30 #include <dali/public-api/events/touch-data.h>
31 #include <dali/public-api/math/vector2.h>
32 #include <dali/public-api/math/vector3.h>
33 #include <dali/public-api/math/radian.h>
34 #include <dali/public-api/object/type-registry.h>
35 #include <dali/devel-api/actors/actor-devel.h>
36 #include <dali/devel-api/scripting/scripting.h>
37 #include <dali/internal/common/internal-constants.h>
38 #include <dali/internal/event/common/event-thread-services.h>
39 #include <dali/internal/event/render-tasks/render-task-impl.h>
40 #include <dali/internal/event/actors/camera-actor-impl.h>
41 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
42 #include <dali/internal/event/common/property-helper.h>
43 #include <dali/internal/event/common/stage-impl.h>
44 #include <dali/internal/event/common/type-info-impl.h>
45 #include <dali/internal/event/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( Gesture::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 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
3477 bool valueSet = true;
3481 case Dali::Actor::Property::PARENT_ORIGIN:
3483 value = GetCurrentParentOrigin();
3487 case Dali::Actor::Property::PARENT_ORIGIN_X:
3489 value = GetCurrentParentOrigin().x;
3493 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3495 value = GetCurrentParentOrigin().y;
3499 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3501 value = GetCurrentParentOrigin().z;
3505 case Dali::Actor::Property::ANCHOR_POINT:
3507 value = GetCurrentAnchorPoint();
3511 case Dali::Actor::Property::ANCHOR_POINT_X:
3513 value = GetCurrentAnchorPoint().x;
3517 case Dali::Actor::Property::ANCHOR_POINT_Y:
3519 value = GetCurrentAnchorPoint().y;
3523 case Dali::Actor::Property::ANCHOR_POINT_Z:
3525 value = GetCurrentAnchorPoint().z;
3529 case Dali::Actor::Property::SIZE:
3531 value = GetTargetSize();
3535 case Dali::Actor::Property::SIZE_WIDTH:
3537 value = GetTargetSize().width;
3541 case Dali::Actor::Property::SIZE_HEIGHT:
3543 value = GetTargetSize().height;
3547 case Dali::Actor::Property::SIZE_DEPTH:
3549 value = GetTargetSize().depth;
3553 case Dali::Actor::Property::POSITION:
3555 value = GetTargetPosition();
3559 case Dali::Actor::Property::POSITION_X:
3561 value = GetTargetPosition().x;
3565 case Dali::Actor::Property::POSITION_Y:
3567 value = GetTargetPosition().y;
3571 case Dali::Actor::Property::POSITION_Z:
3573 value = GetTargetPosition().z;
3577 case Dali::Actor::Property::ORIENTATION:
3579 value = mTargetOrientation;
3583 case Dali::Actor::Property::SCALE:
3585 value = mTargetScale;
3589 case Dali::Actor::Property::SCALE_X:
3591 value = mTargetScale.x;
3595 case Dali::Actor::Property::SCALE_Y:
3597 value = mTargetScale.y;
3601 case Dali::Actor::Property::SCALE_Z:
3603 value = mTargetScale.z;
3607 case Dali::Actor::Property::VISIBLE:
3613 case Dali::Actor::Property::COLOR:
3615 value = mTargetColor;
3619 case Dali::Actor::Property::COLOR_RED:
3621 value = mTargetColor.r;
3625 case Dali::Actor::Property::COLOR_GREEN:
3627 value = mTargetColor.g;
3631 case Dali::Actor::Property::COLOR_BLUE:
3633 value = mTargetColor.b;
3637 case Dali::Actor::Property::COLOR_ALPHA:
3638 case Dali::DevelActor::Property::OPACITY:
3640 value = mTargetColor.a;
3644 case Dali::Actor::Property::NAME:
3650 case Dali::Actor::Property::SENSITIVE:
3652 value = IsSensitive();
3656 case Dali::Actor::Property::LEAVE_REQUIRED:
3658 value = GetLeaveRequired();
3662 case Dali::Actor::Property::INHERIT_POSITION:
3664 value = IsPositionInherited();
3668 case Dali::Actor::Property::INHERIT_ORIENTATION:
3670 value = IsOrientationInherited();
3674 case Dali::Actor::Property::INHERIT_SCALE:
3676 value = IsScaleInherited();
3680 case Dali::Actor::Property::COLOR_MODE:
3682 value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
3686 case Dali::Actor::Property::DRAW_MODE:
3688 value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
3692 case Dali::Actor::Property::SIZE_MODE_FACTOR:
3694 value = GetSizeModeFactor();
3698 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
3700 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3704 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
3706 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
3710 case Dali::Actor::Property::SIZE_SCALE_POLICY:
3712 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT );
3716 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
3718 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
3722 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
3724 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
3728 case Dali::Actor::Property::PADDING:
3730 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
3731 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
3732 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
3736 case Dali::Actor::Property::MINIMUM_SIZE:
3738 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
3742 case Dali::Actor::Property::MAXIMUM_SIZE:
3744 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
3748 case Dali::Actor::Property::CLIPPING_MODE:
3750 value = mClippingMode;
3754 case Dali::DevelActor::Property::SIBLING_ORDER:
3756 value = static_cast<int>( GetSiblingOrder() );
3760 case Dali::DevelActor::Property::SCREEN_POSITION:
3762 value = GetCurrentScreenPosition();
3766 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
3768 value = mPositionUsesAnchorPoint;
3772 case Dali::Actor::Property::LAYOUT_DIRECTION:
3774 value = mLayoutDirection;
3778 case Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION:
3780 value = IsLayoutDirectionInherited();
3786 // Must be a scene-graph only property
3795 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
3797 bool valueSet = true;
3801 case Dali::Actor::Property::SIZE:
3803 value = GetCurrentSize();
3807 case Dali::Actor::Property::SIZE_WIDTH:
3809 value = GetCurrentSize().width;
3813 case Dali::Actor::Property::SIZE_HEIGHT:
3815 value = GetCurrentSize().height;
3819 case Dali::Actor::Property::SIZE_DEPTH:
3821 value = GetCurrentSize().depth;
3825 case Dali::Actor::Property::POSITION:
3827 value = GetCurrentPosition();
3831 case Dali::Actor::Property::POSITION_X:
3833 value = GetCurrentPosition().x;
3837 case Dali::Actor::Property::POSITION_Y:
3839 value = GetCurrentPosition().y;
3843 case Dali::Actor::Property::POSITION_Z:
3845 value = GetCurrentPosition().z;
3849 case Dali::Actor::Property::WORLD_POSITION:
3851 value = GetCurrentWorldPosition();
3855 case Dali::Actor::Property::WORLD_POSITION_X:
3857 value = GetCurrentWorldPosition().x;
3861 case Dali::Actor::Property::WORLD_POSITION_Y:
3863 value = GetCurrentWorldPosition().y;
3867 case Dali::Actor::Property::WORLD_POSITION_Z:
3869 value = GetCurrentWorldPosition().z;
3873 case Dali::Actor::Property::ORIENTATION:
3875 value = GetCurrentOrientation();
3879 case Dali::Actor::Property::WORLD_ORIENTATION:
3881 value = GetCurrentWorldOrientation();
3885 case Dali::Actor::Property::SCALE:
3887 value = GetCurrentScale();
3891 case Dali::Actor::Property::SCALE_X:
3893 value = GetCurrentScale().x;
3897 case Dali::Actor::Property::SCALE_Y:
3899 value = GetCurrentScale().y;
3903 case Dali::Actor::Property::SCALE_Z:
3905 value = GetCurrentScale().z;
3909 case Dali::Actor::Property::WORLD_SCALE:
3911 value = GetCurrentWorldScale();
3915 case Dali::Actor::Property::COLOR:
3917 value = GetCurrentColor();
3921 case Dali::Actor::Property::COLOR_RED:
3923 value = GetCurrentColor().r;
3927 case Dali::Actor::Property::COLOR_GREEN:
3929 value = GetCurrentColor().g;
3933 case Dali::Actor::Property::COLOR_BLUE:
3935 value = GetCurrentColor().b;
3939 case Dali::Actor::Property::COLOR_ALPHA:
3940 case Dali::DevelActor::Property::OPACITY:
3942 value = GetCurrentColor().a;
3946 case Dali::Actor::Property::WORLD_COLOR:
3948 value = GetCurrentWorldColor();
3952 case Dali::Actor::Property::WORLD_MATRIX:
3954 value = GetCurrentWorldMatrix();
3958 case Dali::Actor::Property::VISIBLE:
3960 value = IsVisible();
3964 case DevelActor::Property::CULLED:
3966 value = GetNode().IsCulled( GetEventThreadServices().GetEventBufferIndex() );
3972 // Must be an event-side only property
3981 void Actor::EnsureRelayoutData()
3983 // Assign relayout data.
3984 if( !mRelayoutData )
3986 mRelayoutData = new RelayoutData();
3990 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
3992 // Check if actor is dependent on parent
3993 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
3995 if( ( dimension & ( 1 << i ) ) )
3997 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
3998 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
4008 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
4010 // Check if actor is dependent on children
4011 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4013 if( ( dimension & ( 1 << i ) ) )
4015 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4016 switch( resizePolicy )
4018 case ResizePolicy::FIT_TO_CHILDREN:
4019 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
4035 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
4037 return Actor::RelayoutDependentOnChildren( dimension );
4040 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
4042 // Check each possible dimension and see if it is dependent on the input one
4043 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4045 if( dimension & ( 1 << i ) )
4047 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
4054 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
4056 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4058 if( dimension & ( 1 << i ) )
4060 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
4065 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
4067 // If more than one dimension is requested, just return the first one found
4068 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4070 if( ( dimension & ( 1 << i ) ) )
4072 return mRelayoutData->negotiatedDimensions[ i ];
4076 return 0.0f; // Default
4079 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
4081 EnsureRelayoutData();
4083 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4085 if( dimension & ( 1 << i ) )
4087 mRelayoutData->dimensionPadding[ i ] = padding;
4092 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4094 if ( mRelayoutData )
4096 // If more than one dimension is requested, just return the first one found
4097 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4099 if( ( dimension & ( 1 << i ) ) )
4101 return mRelayoutData->dimensionPadding[ i ];
4106 return GetDefaultDimensionPadding();
4109 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4111 EnsureRelayoutData();
4113 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4115 if( dimension & ( 1 << i ) )
4117 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4122 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4124 if ( mRelayoutData )
4126 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4128 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4138 float Actor::GetHeightForWidthBase( float width )
4140 float height = 0.0f;
4142 const Vector3 naturalSize = GetNaturalSize();
4143 if( naturalSize.width > 0.0f )
4145 height = naturalSize.height * width / naturalSize.width;
4147 else // we treat 0 as 1:1 aspect ratio
4155 float Actor::GetWidthForHeightBase( float height )
4159 const Vector3 naturalSize = GetNaturalSize();
4160 if( naturalSize.height > 0.0f )
4162 width = naturalSize.width * height / naturalSize.height;
4164 else // we treat 0 as 1:1 aspect ratio
4172 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4174 // Fill to parent, taking size mode factor into account
4175 switch( child.GetResizePolicy( dimension ) )
4177 case ResizePolicy::FILL_TO_PARENT:
4179 return GetLatestSize( dimension );
4182 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4184 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4187 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4189 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4194 return GetLatestSize( dimension );
4199 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4201 // Can be overridden in derived class
4202 return CalculateChildSizeBase( child, dimension );
4205 float Actor::GetHeightForWidth( float width )
4207 // Can be overridden in derived class
4208 return GetHeightForWidthBase( width );
4211 float Actor::GetWidthForHeight( float height )
4213 // Can be overridden in derived class
4214 return GetWidthForHeightBase( height );
4217 float Actor::GetLatestSize( Dimension::Type dimension ) const
4219 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4222 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4224 Vector2 padding = GetPadding( dimension );
4226 return GetLatestSize( dimension ) + padding.x + padding.y;
4229 float Actor::NegotiateFromParent( Dimension::Type dimension )
4231 Actor* parent = GetParent();
4234 Vector2 padding( GetPadding( dimension ) );
4235 Vector2 parentPadding( parent->GetPadding( dimension ) );
4236 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4242 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4244 float maxDimensionPoint = 0.0f;
4246 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4248 ActorPtr child = GetChildAt( i );
4250 if( !child->RelayoutDependentOnParent( dimension ) )
4252 // Calculate the min and max points that the children range across
4253 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
4254 float dimensionSize = child->GetRelayoutSize( dimension );
4255 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4259 return maxDimensionPoint;
4262 float Actor::GetSize( Dimension::Type dimension ) const
4264 return GetDimensionValue( mTargetSize, dimension );
4267 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4269 return GetDimensionValue( GetNaturalSize(), dimension );
4272 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4274 switch( GetResizePolicy( dimension ) )
4276 case ResizePolicy::USE_NATURAL_SIZE:
4278 return GetNaturalSize( dimension );
4281 case ResizePolicy::FIXED:
4283 return GetDimensionValue( GetPreferredSize(), dimension );
4286 case ResizePolicy::USE_ASSIGNED_SIZE:
4288 return GetDimensionValue( maximumSize, dimension );
4291 case ResizePolicy::FILL_TO_PARENT:
4292 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4293 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4295 return NegotiateFromParent( dimension );
4298 case ResizePolicy::FIT_TO_CHILDREN:
4300 return NegotiateFromChildren( dimension );
4303 case ResizePolicy::DIMENSION_DEPENDENCY:
4305 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4308 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4310 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4313 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4315 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4327 return 0.0f; // Default
4330 float Actor::ClampDimension( float size, Dimension::Type dimension )
4332 const float minSize = GetMinimumSize( dimension );
4333 const float maxSize = GetMaximumSize( dimension );
4335 return std::max( minSize, std::min( size, maxSize ) );
4338 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4340 // Check if it needs to be negotiated
4341 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4343 // Check that we havn't gotten into an infinite loop
4344 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4345 bool recursionFound = false;
4346 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4348 if( *it == searchActor )
4350 recursionFound = true;
4355 if( !recursionFound )
4357 // Record the path that we have taken
4358 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4360 // Dimension dependency check
4361 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4363 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4365 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4367 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4371 // Parent dependency check
4372 Actor* parent = GetParent();
4373 if( parent && RelayoutDependentOnParent( dimension ) )
4375 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4378 // Children dependency check
4379 if( RelayoutDependentOnChildren( dimension ) )
4381 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4383 ActorPtr child = GetChildAt( i );
4385 // Only relayout child first if it is not dependent on this actor
4386 if( !child->RelayoutDependentOnParent( dimension ) )
4388 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
4393 // For deriving classes
4394 OnCalculateRelayoutSize( dimension );
4396 // All dependencies checked, calculate the size and set negotiated flag
4397 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4399 SetNegotiatedDimension( newSize, dimension );
4400 SetLayoutNegotiated( true, dimension );
4402 // For deriving classes
4403 OnLayoutNegotiated( newSize, dimension );
4405 // This actor has been successfully processed, pop it off the recursion stack
4406 recursionStack.pop_back();
4410 // TODO: Break infinite loop
4411 SetLayoutNegotiated( true, dimension );
4416 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4418 // Negotiate all dimensions that require it
4419 ActorDimensionStack recursionStack;
4421 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4423 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4426 NegotiateDimension( dimension, allocatedSize, recursionStack );
4430 Vector2 Actor::ApplySizeSetPolicy( const Vector2& size )
4432 switch( mRelayoutData->sizeSetPolicy )
4434 case SizeScalePolicy::USE_SIZE_SET:
4439 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4441 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4442 const Vector3 naturalSize = GetNaturalSize();
4443 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4445 const float sizeRatio = size.width / size.height;
4446 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4448 if( naturalSizeRatio < sizeRatio )
4450 return Vector2( naturalSizeRatio * size.height, size.height );
4452 else if( naturalSizeRatio > sizeRatio )
4454 return Vector2( size.width, size.width / naturalSizeRatio );
4465 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4467 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4468 const Vector3 naturalSize = GetNaturalSize();
4469 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4471 const float sizeRatio = size.width / size.height;
4472 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4474 if( naturalSizeRatio < sizeRatio )
4476 return Vector2( size.width, size.width / naturalSizeRatio );
4478 else if( naturalSizeRatio > sizeRatio )
4480 return Vector2( naturalSizeRatio * size.height, size.height );
4499 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4501 // Do the set actor size
4502 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4504 // Adjust for size set policy
4505 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4507 // Lock the flag to stop recursive relayouts on set size
4508 mRelayoutData->insideRelayout = true;
4509 SetSize( negotiatedSize );
4510 mRelayoutData->insideRelayout = false;
4512 // Clear flags for all dimensions
4513 SetLayoutDirty( false );
4515 // Give deriving classes a chance to respond
4516 OnRelayout( negotiatedSize, container );
4518 if( !mOnRelayoutSignal.Empty() )
4520 Dali::Actor handle( this );
4521 mOnRelayoutSignal.Emit( handle );
4525 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4527 // Force a size negotiation for actors that has assigned size during relayout
4528 // This is required as otherwise the flags that force a relayout will not
4529 // necessarilly be set. This will occur if the actor has already been laid out.
4530 // The dirty flags are then cleared. Then if the actor is added back into the
4531 // relayout container afterwards, the dirty flags would still be clear...
4532 // causing a relayout to be skipped. Here we force any actors added to the
4533 // container to be relayed out.
4534 DALI_LOG_TIMER_START( NegSizeTimer1 );
4536 if( GetUseAssignedSize(Dimension::WIDTH ) )
4538 SetLayoutNegotiated( false, Dimension::WIDTH );
4540 if( GetUseAssignedSize( Dimension::HEIGHT ) )
4542 SetLayoutNegotiated( false, Dimension::HEIGHT );
4545 // Do the negotiation
4546 NegotiateDimensions( allocatedSize );
4548 // Set the actor size
4549 SetNegotiatedSize( container );
4551 // Negotiate down to children
4552 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4554 ActorPtr child = GetChildAt( i );
4556 // Forces children that have already been laid out to be relayed out
4557 // if they have assigned size during relayout.
4558 if( child->GetUseAssignedSize(Dimension::WIDTH) )
4560 child->SetLayoutNegotiated(false, Dimension::WIDTH);
4561 child->SetLayoutDirty(true, Dimension::WIDTH);
4564 if( child->GetUseAssignedSize(Dimension::HEIGHT) )
4566 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
4567 child->SetLayoutDirty(true, Dimension::HEIGHT);
4570 // Only relayout if required
4571 if( child->RelayoutRequired() )
4573 container.Add( Dali::Actor( child.Get() ), mTargetSize.GetVectorXY() );
4576 DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
4579 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
4583 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4585 if( dimension & ( 1 << i ) )
4587 mRelayoutData->useAssignedSize[ i ] = use;
4593 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
4595 if ( mRelayoutData )
4597 // If more than one dimension is requested, just return the first one found
4598 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4600 if( dimension & ( 1 << i ) )
4602 return mRelayoutData->useAssignedSize[ i ];
4610 void Actor::RelayoutRequest( Dimension::Type dimension )
4612 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
4613 if( relayoutController )
4615 Dali::Actor self( this );
4616 relayoutController->RequestRelayout( self, dimension );
4620 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
4624 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
4628 void Actor::SetPreferredSize( const Vector2& size )
4630 EnsureRelayoutData();
4632 if( size.width > 0.0f )
4634 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
4637 if( size.height > 0.0f )
4639 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
4642 mRelayoutData->preferredSize = size;
4647 Vector2 Actor::GetPreferredSize() const
4649 if ( mRelayoutData )
4651 return Vector2( mRelayoutData->preferredSize );
4654 return GetDefaultPreferredSize();
4657 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
4659 EnsureRelayoutData();
4661 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4663 if( dimension & ( 1 << i ) )
4665 mRelayoutData->minimumSize[ i ] = size;
4672 float Actor::GetMinimumSize( Dimension::Type dimension ) const
4674 if ( mRelayoutData )
4676 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4678 if( dimension & ( 1 << i ) )
4680 return mRelayoutData->minimumSize[ i ];
4685 return 0.0f; // Default
4688 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
4690 EnsureRelayoutData();
4692 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4694 if( dimension & ( 1 << i ) )
4696 mRelayoutData->maximumSize[ i ] = size;
4703 float Actor::GetMaximumSize( Dimension::Type dimension ) const
4705 if ( mRelayoutData )
4707 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4709 if( dimension & ( 1 << i ) )
4711 return mRelayoutData->maximumSize[ i ];
4716 return FLT_MAX; // Default
4719 Object* Actor::GetParentObject() const
4724 void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
4726 if( mVisible != visible )
4728 if( sendMessage == SendMessage::TRUE )
4730 // node is being used in a separate thread; queue a message to set the value & base value
4731 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible );
4736 // Emit the signal on this actor and all its children
4737 EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
4741 void Actor::SetSiblingOrder( uint32_t order )
4745 ActorContainer& siblings = *(mParent->mChildren);
4746 uint32_t currentOrder = GetSiblingOrder();
4748 if( order != currentOrder )
4754 else if( order < siblings.size() -1 )
4756 if( order > currentOrder )
4758 RaiseAbove( *siblings[order] );
4762 LowerBelow( *siblings[order] );
4773 uint32_t Actor::GetSiblingOrder() const
4779 ActorContainer& siblings = *(mParent->mChildren);
4780 for( std::size_t i = 0; i < siblings.size(); ++i )
4782 if( siblings[i] == this )
4784 order = static_cast<uint32_t>( i );
4793 void Actor::RequestRebuildDepthTree()
4799 mScene->RequestRebuildDepthTree();
4808 ActorContainer& siblings = *(mParent->mChildren);
4809 if( siblings.back() != this ) // If not already at end
4811 for( std::size_t i=0; i<siblings.size(); ++i )
4813 if( siblings[i] == this )
4816 ActorPtr next = siblings[i+1];
4817 siblings[i+1] = this;
4824 Dali::Actor handle( this );
4825 mParent->mChildOrderChangedSignal.Emit( handle );
4827 RequestRebuildDepthTree();
4831 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4839 ActorContainer& siblings = *(mParent->mChildren);
4840 if( siblings.front() != this ) // If not already at beginning
4842 for( std::size_t i=1; i<siblings.size(); ++i )
4844 if( siblings[i] == this )
4846 // Swap with previous
4847 ActorPtr previous = siblings[i-1];
4848 siblings[i-1] = this;
4849 siblings[i] = previous;
4855 Dali::Actor handle( this );
4856 mParent->mChildOrderChangedSignal.Emit( handle );
4858 RequestRebuildDepthTree();
4862 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4866 void Actor::RaiseToTop()
4870 ActorContainer& siblings = *(mParent->mChildren);
4871 if( siblings.back() != this ) // If not already at end
4873 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
4874 if( iter != siblings.end() )
4876 siblings.erase(iter);
4877 siblings.push_back(ActorPtr(this));
4881 Dali::Actor handle( this );
4882 mParent->mChildOrderChangedSignal.Emit( handle );
4884 RequestRebuildDepthTree();
4888 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4892 void Actor::LowerToBottom()
4896 ActorContainer& siblings = *(mParent->mChildren);
4897 if( siblings.front() != this ) // If not already at bottom,
4899 ActorPtr thisPtr(this); // ensure this actor remains referenced.
4901 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
4902 if( iter != siblings.end() )
4904 siblings.erase(iter);
4905 siblings.insert(siblings.begin(), thisPtr);
4909 Dali::Actor handle( this );
4910 mParent->mChildOrderChangedSignal.Emit( handle );
4912 RequestRebuildDepthTree();
4916 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4920 void Actor::RaiseAbove( Internal::Actor& target )
4924 ActorContainer& siblings = *(mParent->mChildren);
4925 if( siblings.back() != this && target.mParent == mParent ) // If not already at top
4927 ActorPtr thisPtr(this); // ensure this actor remains referenced.
4929 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
4930 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
4931 if( thisIter < targetIter )
4933 siblings.erase(thisIter);
4934 // Erasing early invalidates the targetIter. (Conversely, inserting first may also
4935 // invalidate thisIter)
4936 targetIter = std::find( siblings.begin(), siblings.end(), &target );
4938 siblings.insert(targetIter, thisPtr);
4941 Dali::Actor handle( this );
4942 mParent->mChildOrderChangedSignal.Emit( handle );
4944 RequestRebuildDepthTree();
4949 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4953 void Actor::LowerBelow( Internal::Actor& target )
4957 ActorContainer& siblings = *(mParent->mChildren);
4958 if( siblings.front() != this && target.mParent == mParent ) // If not already at bottom
4960 ActorPtr thisPtr(this); // ensure this actor remains referenced.
4962 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
4963 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
4965 if( thisIter > targetIter )
4967 siblings.erase(thisIter); // this only invalidates iterators at or after this point.
4968 siblings.insert(targetIter, thisPtr);
4971 Dali::Actor handle( this );
4972 mParent->mChildOrderChangedSignal.Emit( handle );
4974 RequestRebuildDepthTree();
4979 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
4983 void Actor::SetScene( Scene& scene )
4988 Scene& Actor::GetScene() const
4993 void Actor::SetInheritLayoutDirection( bool inherit )
4995 if( mInheritLayoutDirection != inherit )
4997 mInheritLayoutDirection = inherit;
4999 if( inherit && mParent )
5001 InheritLayoutDirectionRecursively( this, mParent->mLayoutDirection );
5006 bool Actor::IsLayoutDirectionInherited() const
5008 return mInheritLayoutDirection;
5011 void Actor::InheritLayoutDirectionRecursively( ActorPtr actor, Dali::LayoutDirection::Type direction, bool set )
5013 if( actor && ( actor->mInheritLayoutDirection || set ) )
5015 if( actor->mLayoutDirection != direction )
5017 actor->mLayoutDirection = direction;
5018 actor->EmitLayoutDirectionChangedSignal( direction );
5019 actor->RelayoutRequest();
5022 if( actor->GetChildCount() > 0 )
5024 ActorContainer& children = actor->GetChildrenInternal();
5025 for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter )
5027 InheritLayoutDirectionRecursively( *iter, direction );
5033 } // namespace Internal