2 * Copyright (c) 2018 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/event/actors/actor-impl.h>
27 #include <dali/devel-api/actors/layer-devel.h>
28 #include <dali/public-api/common/dali-common.h>
29 #include <dali/public-api/common/constants.h>
30 #include <dali/public-api/events/touch-data.h>
31 #include <dali/public-api/math/vector2.h>
32 #include <dali/public-api/math/vector3.h>
33 #include <dali/public-api/math/radian.h>
34 #include <dali/public-api/object/type-registry.h>
35 #include <dali/devel-api/actors/actor-devel.h>
36 #include <dali/devel-api/scripting/scripting.h>
37 #include <dali/internal/common/internal-constants.h>
38 #include <dali/internal/event/common/event-thread-services.h>
39 #include <dali/internal/event/render-tasks/render-task-impl.h>
40 #include <dali/internal/event/actors/camera-actor-impl.h>
41 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
42 #include <dali/internal/event/common/property-helper.h>
43 #include <dali/internal/event/common/stage-impl.h>
44 #include <dali/internal/event/common/type-info-impl.h>
45 #include <dali/internal/event/animation/constraint-impl.h>
46 #include <dali/internal/event/common/projection.h>
47 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
48 #include <dali/internal/update/common/animatable-property.h>
49 #include <dali/internal/update/nodes/node-messages.h>
50 #include <dali/internal/update/nodes/node-declarations.h>
51 #include <dali/internal/update/animation/scene-graph-constraint.h>
52 #include <dali/internal/event/events/actor-gesture-data.h>
53 #include <dali/internal/common/message.h>
54 #include <dali/integration-api/debug.h>
56 using Dali::Internal::SceneGraph::Node;
57 using Dali::Internal::SceneGraph::AnimatableProperty;
58 using Dali::Internal::SceneGraph::PropertyBase;
60 #if defined(DEBUG_ENABLED)
61 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_DEPTH_TIMER" );
62 Debug::Filter* gLogRelayoutFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_TIMER" );
71 unsigned int Actor::mActorCounter = 0;
75 /// Using a function because of library initialisation order. Vector3::ONE may not have been initialised yet.
76 inline const Vector3& GetDefaultSizeModeFactor()
81 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
82 inline const Vector2& GetDefaultPreferredSize()
87 /// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
88 inline const Vector2& GetDefaultDimensionPadding()
93 const SizeScalePolicy::Type DEFAULT_SIZE_SCALE_POLICY = SizeScalePolicy::USE_SIZE_SET;
95 } // unnamed namespace
98 * Struct to collect relayout variables
100 struct Actor::RelayoutData
103 : sizeModeFactor( GetDefaultSizeModeFactor() ), preferredSize( GetDefaultPreferredSize() ), sizeSetPolicy( DEFAULT_SIZE_SCALE_POLICY ), relayoutEnabled( false ), insideRelayout( false )
105 // Set size negotiation defaults
106 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
108 resizePolicies[ i ] = ResizePolicy::DEFAULT;
109 useAssignedSize[ i ] = false;
110 negotiatedDimensions[ i ] = 0.0f;
111 dimensionNegotiated[ i ] = false;
112 dimensionDirty[ i ] = false;
113 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
114 dimensionPadding[ i ] = GetDefaultDimensionPadding();
115 minimumSize[ i ] = 0.0f;
116 maximumSize[ i ] = FLT_MAX;
120 ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies
121 bool useAssignedSize[ Dimension::DIMENSION_COUNT ]; ///< The flag to specify whether the size should be assigned to the actor
123 Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies
125 Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
127 float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
129 float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be
130 float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be
132 bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated
133 bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
135 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
137 Vector2 preferredSize; ///< The preferred size of the actor
139 SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
141 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
142 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
145 namespace // unnamed namespace
151 * We want to discourage the use of property strings (minimize string comparisons),
152 * particularly for the default properties.
153 * Name Type writable animatable constraint-input enum for index-checking
155 DALI_PROPERTY_TABLE_BEGIN
156 DALI_PROPERTY( "parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
157 DALI_PROPERTY( "parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
158 DALI_PROPERTY( "parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
159 DALI_PROPERTY( "parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
160 DALI_PROPERTY( "anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
161 DALI_PROPERTY( "anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
162 DALI_PROPERTY( "anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
163 DALI_PROPERTY( "anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
164 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
165 DALI_PROPERTY( "sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
166 DALI_PROPERTY( "sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
167 DALI_PROPERTY( "sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
168 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
169 DALI_PROPERTY( "positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
170 DALI_PROPERTY( "positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
171 DALI_PROPERTY( "positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
172 DALI_PROPERTY( "worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
173 DALI_PROPERTY( "worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
174 DALI_PROPERTY( "worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
175 DALI_PROPERTY( "worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
176 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
177 DALI_PROPERTY( "worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
178 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
179 DALI_PROPERTY( "scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
180 DALI_PROPERTY( "scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
181 DALI_PROPERTY( "scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
182 DALI_PROPERTY( "worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
183 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
184 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
185 DALI_PROPERTY( "colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
186 DALI_PROPERTY( "colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
187 DALI_PROPERTY( "colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
188 DALI_PROPERTY( "colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
189 DALI_PROPERTY( "worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
190 DALI_PROPERTY( "worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
191 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
192 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
193 DALI_PROPERTY( "leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
194 DALI_PROPERTY( "inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
195 DALI_PROPERTY( "inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
196 DALI_PROPERTY( "colorMode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
197 DALI_PROPERTY( "positionInheritance", STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE )
198 DALI_PROPERTY( "drawMode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE )
199 DALI_PROPERTY( "sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
200 DALI_PROPERTY( "widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
201 DALI_PROPERTY( "heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
202 DALI_PROPERTY( "sizeScalePolicy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
203 DALI_PROPERTY( "widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
204 DALI_PROPERTY( "heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
205 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
206 DALI_PROPERTY( "minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
207 DALI_PROPERTY( "maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
208 DALI_PROPERTY( "inheritPosition", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_POSITION )
209 DALI_PROPERTY( "clippingMode", STRING, true, false, false, Dali::Actor::Property::CLIPPING_MODE )
210 DALI_PROPERTY( "layoutDirection", STRING, true, false, false, Dali::Actor::Property::LAYOUT_DIRECTION )
211 DALI_PROPERTY( "inheritLayoutDirection", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION )
212 DALI_PROPERTY( "siblingOrder", INTEGER, true, false, false, Dali::DevelActor::Property::SIBLING_ORDER )
213 DALI_PROPERTY( "opacity", FLOAT, true, true, true, Dali::DevelActor::Property::OPACITY )
214 DALI_PROPERTY( "screenPosition", VECTOR2, false, false, false, Dali::DevelActor::Property::SCREEN_POSITION )
215 DALI_PROPERTY( "positionUsesAnchorPoint", BOOLEAN, true, false, false, Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT )
216 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
220 const char* const SIGNAL_TOUCHED = "touched";
221 const char* const SIGNAL_HOVERED = "hovered";
222 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
223 const char* const SIGNAL_ON_STAGE = "onStage";
224 const char* const SIGNAL_OFF_STAGE = "offStage";
225 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
226 const char* const SIGNAL_TOUCH = "touch";
227 const char* const SIGNAL_VISIBILITY_CHANGED = "visibilityChanged";
228 const char* const SIGNAL_LAYOUT_DIRECTION_CHANGED = "layoutDirectionChanged";
229 const char* const SIGNAL_CHILD_ADDED = "childAdded";
230 const char* const SIGNAL_CHILD_REMOVED = "childRemoved";
234 const char* const ACTION_SHOW = "show";
235 const char* const ACTION_HIDE = "hide";
237 BaseHandle CreateActor()
239 return Dali::Actor::New();
242 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
244 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
245 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
246 SignalConnectorType signalConnector3( mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal );
247 SignalConnectorType signalConnector4( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
248 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
249 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
250 SignalConnectorType signalConnector7( mType, SIGNAL_TOUCH, &Actor::DoConnectSignal );
251 SignalConnectorType signalConnector8( mType, SIGNAL_VISIBILITY_CHANGED, &Actor::DoConnectSignal );
252 SignalConnectorType signalConnector9( mType, SIGNAL_LAYOUT_DIRECTION_CHANGED, &Actor::DoConnectSignal );
253 SignalConnectorType signalConnector10( mType, SIGNAL_CHILD_ADDED, &Actor::DoConnectSignal );
254 SignalConnectorType signalConnector11( mType, SIGNAL_CHILD_REMOVED, &Actor::DoConnectSignal );
256 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
257 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
262 const Vector3& value;
265 DALI_ENUM_TO_STRING_TABLE_BEGIN_WITH_TYPE( AnchorValue, ANCHOR_CONSTANT )
266 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_LEFT )
267 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_CENTER )
268 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_RIGHT )
269 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_LEFT )
270 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER )
271 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_RIGHT )
272 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_LEFT )
273 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_CENTER )
274 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_RIGHT )
275 DALI_ENUM_TO_STRING_TABLE_END( ANCHOR_CONSTANT )
277 DALI_ENUM_TO_STRING_TABLE_BEGIN( COLOR_MODE )
278 DALI_ENUM_TO_STRING( USE_OWN_COLOR )
279 DALI_ENUM_TO_STRING( USE_PARENT_COLOR )
280 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_COLOR )
281 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_ALPHA )
282 DALI_ENUM_TO_STRING_TABLE_END( COLOR_MODE )
284 DALI_ENUM_TO_STRING_TABLE_BEGIN( POSITION_INHERITANCE_MODE )
285 DALI_ENUM_TO_STRING( INHERIT_PARENT_POSITION )
286 DALI_ENUM_TO_STRING( USE_PARENT_POSITION )
287 DALI_ENUM_TO_STRING( USE_PARENT_POSITION_PLUS_LOCAL_POSITION )
288 DALI_ENUM_TO_STRING( DONT_INHERIT_POSITION )
289 DALI_ENUM_TO_STRING_TABLE_END( POSITION_INHERITANCE_MODE )
291 DALI_ENUM_TO_STRING_TABLE_BEGIN( DRAW_MODE )
292 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, NORMAL )
293 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, OVERLAY_2D )
294 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, STENCIL )
295 DALI_ENUM_TO_STRING_TABLE_END( DRAW_MODE )
297 DALI_ENUM_TO_STRING_TABLE_BEGIN( RESIZE_POLICY )
298 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIXED )
299 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_NATURAL_SIZE )
300 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FILL_TO_PARENT )
301 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_RELATIVE_TO_PARENT )
302 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_FIXED_OFFSET_FROM_PARENT )
303 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIT_TO_CHILDREN )
304 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, DIMENSION_DEPENDENCY )
305 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_ASSIGNED_SIZE )
306 DALI_ENUM_TO_STRING_TABLE_END( RESIZE_POLICY )
308 DALI_ENUM_TO_STRING_TABLE_BEGIN( SIZE_SCALE_POLICY )
309 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, USE_SIZE_SET )
310 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FIT_WITH_ASPECT_RATIO )
311 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FILL_WITH_ASPECT_RATIO )
312 DALI_ENUM_TO_STRING_TABLE_END( SIZE_SCALE_POLICY )
314 DALI_ENUM_TO_STRING_TABLE_BEGIN( CLIPPING_MODE )
315 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, DISABLED )
316 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, CLIP_CHILDREN )
317 DALI_ENUM_TO_STRING_TABLE_END( CLIPPING_MODE )
319 DALI_ENUM_TO_STRING_TABLE_BEGIN( LAYOUT_DIRECTION )
320 DALI_ENUM_TO_STRING_WITH_SCOPE( LayoutDirection, LEFT_TO_RIGHT )
321 DALI_ENUM_TO_STRING_WITH_SCOPE( LayoutDirection, RIGHT_TO_LEFT )
322 DALI_ENUM_TO_STRING_TABLE_END( LAYOUT_DIRECTION )
324 bool GetAnchorPointConstant( const std::string& value, Vector3& anchor )
326 for( unsigned int i = 0; i < ANCHOR_CONSTANT_TABLE_COUNT; ++i )
328 size_t sizeIgnored = 0;
329 if( CompareTokens( value.c_str(), ANCHOR_CONSTANT_TABLE[ i ].name, sizeIgnored ) )
331 anchor = ANCHOR_CONSTANT_TABLE[ i ].value;
338 inline bool GetParentOriginConstant( const std::string& value, Vector3& parentOrigin )
340 // Values are the same so just use the same table as anchor-point
341 return GetAnchorPointConstant( value, parentOrigin );
345 * @brief Extract a given dimension from a Vector2
347 * @param[in] values The values to extract from
348 * @param[in] dimension The dimension to extract
349 * @return Return the value for the dimension
351 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
355 case Dimension::WIDTH:
359 case Dimension::HEIGHT:
361 return values.height;
372 * @brief Extract a given dimension from a Vector3
374 * @param[in] values The values to extract from
375 * @param[in] dimension The dimension to extract
376 * @return Return the value for the dimension
378 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
380 return GetDimensionValue( values.GetVectorXY(), dimension );
384 * @brief Recursively emits the visibility-changed-signal on the actor tree.
385 * @param[in] actor The actor to emit the signal on
386 * @param[in] visible The new visibility of the actor
387 * @param[in] type Whether the actor's visible property has changed or a parent's
389 void EmitVisibilityChangedSignalRecursively( ActorPtr actor, bool visible, DevelActor::VisibilityChange::Type type )
393 actor->EmitVisibilityChangedSignal( visible, type );
395 if( actor->GetChildCount() > 0 )
397 ActorContainer& children = actor->GetChildrenInternal();
398 for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter )
400 EmitVisibilityChangedSignalRecursively( *iter, visible, DevelActor::VisibilityChange::PARENT );
406 } // unnamed namespace
408 ActorPtr Actor::New()
410 ActorPtr actor( new Actor( BASIC ) );
412 // Second-phase construction
418 const std::string& Actor::GetName() const
423 void Actor::SetName( const std::string& name )
429 // ATTENTION: string for debug purposes is not thread safe.
430 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
434 unsigned int Actor::GetId() const
439 bool Actor::OnStage() const
444 Dali::Layer Actor::GetLayer()
448 // Short-circuit for Layer derived actors
451 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
454 // Find the immediate Layer parent
455 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
457 if( parent->IsLayer() )
459 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
466 void Actor::Add( Actor& child )
468 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
469 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
473 mChildren = new ActorContainer;
476 Actor* const oldParent( child.mParent );
478 // child might already be ours
479 if( this != oldParent )
481 // if we already have parent, unparent us first
484 oldParent->Remove( child ); // This causes OnChildRemove callback & ChildRemoved signal
486 // Old parent may need to readjust to missing child
487 if( oldParent->RelayoutDependentOnChildren() )
489 oldParent->RelayoutRequest();
493 // Guard against Add() during previous OnChildRemove callback
496 // Do this first, since user callbacks from within SetParent() may need to remove child
497 mChildren->push_back( ActorPtr( &child ) );
499 // SetParent asserts that child can be added
500 child.SetParent( this );
502 // Notification for derived classes
504 EmitChildAddedSignal( child );
506 InheritLayoutDirectionRecursively( ActorPtr( &child ), mLayoutDirection );
508 // Only put in a relayout request if there is a suitable dependency
509 if( RelayoutDependentOnChildren() )
517 void Actor::Remove( Actor& child )
519 if( (this == &child) || (!mChildren) )
521 // no children or removing itself
527 // Find the child in mChildren, and unparent it
528 ActorIter end = mChildren->end();
529 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
531 ActorPtr actor = (*iter);
533 if( actor.Get() == &child )
535 // Keep handle for OnChildRemove notification
538 // Do this first, since user callbacks from within SetParent() may need to add the child
539 mChildren->erase( iter );
541 DALI_ASSERT_DEBUG( actor->GetParent() == this );
542 actor->SetParent( NULL );
550 // Only put in a relayout request if there is a suitable dependency
551 if( RelayoutDependentOnChildren() )
557 // Notification for derived classes
558 OnChildRemove( child );
559 EmitChildRemovedSignal( child );
562 void Actor::Unparent()
566 // Remove this actor from the parent. The remove will put a relayout request in for
567 // the parent if required
568 mParent->Remove( *this );
569 // mParent is now NULL!
573 unsigned int Actor::GetChildCount() const
575 return ( NULL != mChildren ) ? mChildren->size() : 0;
578 ActorPtr Actor::GetChildAt( unsigned int index ) const
580 DALI_ASSERT_ALWAYS( index < GetChildCount() );
582 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
585 ActorPtr Actor::FindChildByName( const std::string& actorName )
588 if( actorName == mName )
594 ActorIter end = mChildren->end();
595 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
597 child = (*iter)->FindChildByName( actorName );
608 ActorPtr Actor::FindChildById( const unsigned int id )
617 ActorIter end = mChildren->end();
618 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
620 child = (*iter)->FindChildById( id );
631 void Actor::SetParentOrigin( const Vector3& origin )
635 // mNode is being used in a separate thread; queue a message to set the value & base value
636 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
639 // Cache for event-thread access
642 // not allocated, check if different from default
643 if( ParentOrigin::DEFAULT != origin )
645 mParentOrigin = new Vector3( origin );
650 // check if different from current costs more than just set
651 *mParentOrigin = origin;
655 void Actor::SetParentOriginX( float x )
657 const Vector3& current = GetCurrentParentOrigin();
659 SetParentOrigin( Vector3( x, current.y, current.z ) );
662 void Actor::SetParentOriginY( float y )
664 const Vector3& current = GetCurrentParentOrigin();
666 SetParentOrigin( Vector3( current.x, y, current.z ) );
669 void Actor::SetParentOriginZ( float z )
671 const Vector3& current = GetCurrentParentOrigin();
673 SetParentOrigin( Vector3( current.x, current.y, z ) );
676 const Vector3& Actor::GetCurrentParentOrigin() const
678 // Cached for event-thread access
679 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
682 void Actor::SetAnchorPoint( const Vector3& anchor )
686 // mNode is being used in a separate thread; queue a message to set the value & base value
687 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
690 // Cache for event-thread access
693 // not allocated, check if different from default
694 if( AnchorPoint::DEFAULT != anchor )
696 mAnchorPoint = new Vector3( anchor );
701 // check if different from current costs more than just set
702 *mAnchorPoint = anchor;
706 void Actor::SetAnchorPointX( float x )
708 const Vector3& current = GetCurrentAnchorPoint();
710 SetAnchorPoint( Vector3( x, current.y, current.z ) );
713 void Actor::SetAnchorPointY( float y )
715 const Vector3& current = GetCurrentAnchorPoint();
717 SetAnchorPoint( Vector3( current.x, y, current.z ) );
720 void Actor::SetAnchorPointZ( float z )
722 const Vector3& current = GetCurrentAnchorPoint();
724 SetAnchorPoint( Vector3( current.x, current.y, z ) );
727 const Vector3& Actor::GetCurrentAnchorPoint() const
729 // Cached for event-thread access
730 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
733 void Actor::SetPosition( float x, float y )
735 SetPosition( Vector3( x, y, 0.0f ) );
738 void Actor::SetPosition( float x, float y, float z )
740 SetPosition( Vector3( x, y, z ) );
743 void Actor::SetPosition( const Vector3& position )
745 mTargetPosition = position;
749 // mNode is being used in a separate thread; queue a message to set the value & base value
750 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
754 void Actor::SetX( float x )
756 mTargetPosition.x = x;
760 // mNode is being used in a separate thread; queue a message to set the value & base value
761 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
765 void Actor::SetY( float y )
767 mTargetPosition.y = y;
771 // mNode is being used in a separate thread; queue a message to set the value & base value
772 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
776 void Actor::SetZ( float z )
778 mTargetPosition.z = z;
782 // mNode is being used in a separate thread; queue a message to set the value & base value
783 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
787 void Actor::TranslateBy( const Vector3& distance )
789 mTargetPosition += distance;
793 // mNode is being used in a separate thread; queue a message to set the value & base value
794 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
798 const Vector3& Actor::GetCurrentPosition() const
802 // mNode is being used in a separate thread; copy the value from the previous update
803 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
806 return Vector3::ZERO;
809 const Vector3& Actor::GetTargetPosition() const
811 return mTargetPosition;
814 const Vector3& Actor::GetCurrentWorldPosition() const
818 // mNode is being used in a separate thread; copy the value from the previous update
819 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
822 return Vector3::ZERO;
825 const Vector2 Actor::GetCurrentScreenPosition() const
827 StagePtr stage = Stage::GetCurrent();
828 if( stage && OnStage() && NULL != mNode )
830 Vector3 worldPosition = mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
831 Vector3 cameraPosition = stage->GetDefaultCameraActor().mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
832 worldPosition -= cameraPosition;
834 Vector3 actorSize = GetCurrentSize() * GetCurrentWorldScale();
835 Vector2 halfStageSize( stage->GetSize() * 0.5f ); // World position origin is center of stage
836 Vector3 halfActorSize( actorSize * 0.5f );
837 Vector3 anchorPointOffSet = halfActorSize - actorSize * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
839 return Vector2( halfStageSize.width + worldPosition.x - anchorPointOffSet.x,
840 halfStageSize.height + worldPosition.y - anchorPointOffSet.y );
843 return Vector2::ZERO;
846 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
848 // this flag is not animatable so keep the value
849 mPositionInheritanceMode = mode;
852 // mNode is being used in a separate thread; queue a message to set the value
853 SetInheritPositionMessage( GetEventThreadServices(), *mNode, mode == INHERIT_PARENT_POSITION );
857 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
859 // Cached for event-thread access
860 return mPositionInheritanceMode;
863 void Actor::SetInheritPosition( bool inherit )
865 if( mInheritPosition != inherit && NULL != mNode )
867 // non animateable so keep local copy
868 mInheritPosition = inherit;
869 SetInheritPositionMessage( GetEventThreadServices(), *mNode, inherit );
873 bool Actor::IsPositionInherited() const
875 return mInheritPosition;
878 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
880 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
881 normalizedAxis.Normalize();
883 Quaternion orientation( angle, normalizedAxis );
885 SetOrientation( orientation );
888 void Actor::SetOrientation( const Quaternion& orientation )
890 mTargetOrientation = orientation;
894 // mNode is being used in a separate thread; queue a message to set the value & base value
895 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation );
899 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
901 RotateBy( Quaternion(angle, axis) );
904 void Actor::RotateBy( const Quaternion& relativeRotation )
906 mTargetOrientation *= Quaternion( relativeRotation );
910 // mNode is being used in a separate thread; queue a message to set the value & base value
911 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
915 const Quaternion& Actor::GetCurrentOrientation() const
919 // mNode is being used in a separate thread; copy the value from the previous update
920 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
923 return Quaternion::IDENTITY;
926 const Quaternion& Actor::GetCurrentWorldOrientation() const
930 // mNode is being used in a separate thread; copy the value from the previous update
931 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
934 return Quaternion::IDENTITY;
937 void Actor::SetScale( float scale )
939 SetScale( Vector3( scale, scale, scale ) );
942 void Actor::SetScale( float x, float y, float z )
944 SetScale( Vector3( x, y, z ) );
947 void Actor::SetScale( const Vector3& scale )
949 mTargetScale = scale;
953 // mNode is being used in a separate thread; queue a message to set the value & base value
954 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
958 void Actor::SetScaleX( float x )
964 // mNode is being used in a separate thread; queue a message to set the value & base value
965 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
969 void Actor::SetScaleY( float y )
975 // mNode is being used in a separate thread; queue a message to set the value & base value
976 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
980 void Actor::SetScaleZ( float z )
986 // mNode is being used in a separate thread; queue a message to set the value & base value
987 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
991 void Actor::ScaleBy(const Vector3& relativeScale)
993 mTargetScale *= relativeScale;
997 // mNode is being used in a separate thread; queue a message to set the value & base value
998 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
1002 const Vector3& Actor::GetCurrentScale() const
1006 // mNode is being used in a separate thread; copy the value from the previous update
1007 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
1010 return Vector3::ONE;
1013 const Vector3& Actor::GetCurrentWorldScale() const
1017 // mNode is being used in a separate thread; copy the value from the previous update
1018 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
1021 return Vector3::ONE;
1024 void Actor::SetInheritScale( bool inherit )
1027 if( mInheritScale != inherit && NULL != mNode )
1029 // non animateable so keep local copy
1030 mInheritScale = inherit;
1031 // mNode is being used in a separate thread; queue a message to set the value
1032 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
1036 bool Actor::IsScaleInherited() const
1038 return mInheritScale;
1041 Matrix Actor::GetCurrentWorldMatrix() const
1045 return mNode->GetWorldMatrix(0);
1048 return Matrix::IDENTITY;
1051 void Actor::SetVisible( bool visible )
1053 SetVisibleInternal( visible, SendMessage::TRUE );
1056 bool Actor::IsVisible() const
1060 // mNode is being used in a separate thread; copy the value from the previous update
1061 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
1067 void Actor::SetOpacity( float opacity )
1069 mTargetColor.a = opacity;
1073 // mNode is being used in a separate thread; queue a message to set the value & base value
1074 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
1078 float Actor::GetCurrentOpacity() const
1082 // mNode is being used in a separate thread; copy the value from the previous update
1083 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1089 ClippingMode::Type Actor::GetClippingMode() const
1091 return mClippingMode;
1094 unsigned int Actor::GetSortingDepth()
1096 return mSortedDepth;
1099 const Vector4& Actor::GetCurrentWorldColor() const
1103 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1106 return Color::WHITE;
1109 void Actor::SetColor( const Vector4& color )
1111 mTargetColor = color;
1115 // mNode is being used in a separate thread; queue a message to set the value & base value
1116 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1120 void Actor::SetColorRed( float red )
1122 mTargetColor.r = red;
1126 // mNode is being used in a separate thread; queue a message to set the value & base value
1127 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1131 void Actor::SetColorGreen( float green )
1133 mTargetColor.g = green;
1137 // mNode is being used in a separate thread; queue a message to set the value & base value
1138 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1142 void Actor::SetColorBlue( float blue )
1144 mTargetColor.b = blue;
1148 // mNode is being used in a separate thread; queue a message to set the value & base value
1149 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1153 const Vector4& Actor::GetCurrentColor() const
1157 // mNode is being used in a separate thread; copy the value from the previous update
1158 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1161 return Color::WHITE;
1164 void Actor::SetInheritOrientation( bool inherit )
1166 if( mInheritOrientation != inherit && NULL != mNode)
1168 // non animateable so keep local copy
1169 mInheritOrientation = inherit;
1170 // mNode is being used in a separate thread; queue a message to set the value
1171 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1175 bool Actor::IsOrientationInherited() const
1177 return mInheritOrientation;
1180 void Actor::SetSizeModeFactor( const Vector3& factor )
1182 EnsureRelayoutData();
1184 mRelayoutData->sizeModeFactor = factor;
1187 const Vector3& Actor::GetSizeModeFactor() const
1189 if ( mRelayoutData )
1191 return mRelayoutData->sizeModeFactor;
1194 return GetDefaultSizeModeFactor();
1197 void Actor::SetColorMode( ColorMode colorMode )
1199 // non animateable so keep local copy
1200 mColorMode = colorMode;
1203 // mNode is being used in a separate thread; queue a message to set the value
1204 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1208 ColorMode Actor::GetColorMode() const
1210 // we have cached copy
1214 void Actor::SetSize( float width, float height )
1216 SetSize( Vector2( width, height ) );
1219 void Actor::SetSize( float width, float height, float depth )
1221 SetSize( Vector3( width, height, depth ) );
1224 void Actor::SetSize( const Vector2& size )
1226 SetSize( Vector3( size.width, size.height, 0.f ) );
1229 void Actor::SetSizeInternal( const Vector2& size )
1231 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1234 void Actor::SetSize( const Vector3& size )
1236 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1238 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1239 SetPreferredSize( size.GetVectorXY() );
1243 SetSizeInternal( size );
1247 void Actor::SetSizeInternal( const Vector3& size )
1249 // dont allow recursive loop
1250 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1251 // 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
1252 if( ( NULL != mNode )&&
1253 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1254 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1255 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1259 // mNode is being used in a separate thread; queue a message to set the value & base value
1260 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
1262 // Notification for derived classes
1263 mInsideOnSizeSet = true;
1264 OnSizeSet( mTargetSize );
1265 mInsideOnSizeSet = false;
1267 // Raise a relayout request if the flag is not locked
1268 if( mRelayoutData && !mRelayoutData->insideRelayout )
1275 void Actor::SetWidth( float width )
1277 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1279 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
1280 mRelayoutData->preferredSize.width = width;
1284 mTargetSize.width = width;
1288 // mNode is being used in a separate thread; queue a message to set the value & base value
1289 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1296 void Actor::SetHeight( float height )
1298 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1300 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
1301 mRelayoutData->preferredSize.height = height;
1305 mTargetSize.height = height;
1309 // mNode is being used in a separate thread; queue a message to set the value & base value
1310 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1317 void Actor::SetDepth( float depth )
1319 mTargetSize.depth = depth;
1323 // mNode is being used in a separate thread; queue a message to set the value & base value
1324 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1328 Vector3 Actor::GetTargetSize() const
1330 Vector3 size = mTargetSize;
1332 // Should return preferred size if size is fixed as set by SetSize
1333 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
1335 size.width = GetPreferredSize().width;
1337 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
1339 size.height = GetPreferredSize().height;
1345 const Vector3& Actor::GetCurrentSize() const
1349 // mNode is being used in a separate thread; copy the value from the previous update
1350 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1353 return Vector3::ZERO;
1356 Vector3 Actor::GetNaturalSize() const
1358 // It is up to deriving classes to return the appropriate natural size
1359 return Vector3( 0.0f, 0.0f, 0.0f );
1362 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1364 EnsureRelayoutData();
1366 ResizePolicy::Type originalWidthPolicy = GetResizePolicy(Dimension::WIDTH);
1367 ResizePolicy::Type originalHeightPolicy = GetResizePolicy(Dimension::HEIGHT);
1369 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1371 if( dimension & ( 1 << i ) )
1373 if ( policy == ResizePolicy::USE_ASSIGNED_SIZE )
1375 mRelayoutData->useAssignedSize[ i ] = true;
1379 mRelayoutData->resizePolicies[ i ] = policy;
1380 mRelayoutData->useAssignedSize[ i ] = false;
1385 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1387 if( dimension & Dimension::WIDTH )
1389 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1392 if( dimension & Dimension::HEIGHT )
1394 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1398 // If calling SetResizePolicy, assume we want relayout enabled
1399 SetRelayoutEnabled( true );
1401 // If the resize policy is set to be FIXED, the preferred size
1402 // should be overrided by the target size. Otherwise the target
1403 // size should be overrided by the preferred size.
1405 if( dimension & Dimension::WIDTH )
1407 if( originalWidthPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1409 mRelayoutData->preferredSize.width = mTargetSize.width;
1411 else if( originalWidthPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1413 mTargetSize.width = mRelayoutData->preferredSize.width;
1417 if( dimension & Dimension::HEIGHT )
1419 if( originalHeightPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1421 mRelayoutData->preferredSize.height = mTargetSize.height;
1423 else if( originalHeightPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1425 mTargetSize.height = mRelayoutData->preferredSize.height;
1429 OnSetResizePolicy( policy, dimension );
1431 // Trigger relayout on this control
1435 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1437 if ( mRelayoutData )
1439 // If more than one dimension is requested, just return the first one found
1440 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1442 if( ( dimension & ( 1 << i ) ) )
1444 if( mRelayoutData->useAssignedSize[ i ] )
1446 return ResizePolicy::USE_ASSIGNED_SIZE;
1450 return mRelayoutData->resizePolicies[ i ];
1456 return ResizePolicy::DEFAULT;
1459 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1461 EnsureRelayoutData();
1463 mRelayoutData->sizeSetPolicy = policy;
1466 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1468 if ( mRelayoutData )
1470 return mRelayoutData->sizeSetPolicy;
1473 return DEFAULT_SIZE_SCALE_POLICY;
1476 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1478 EnsureRelayoutData();
1480 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1482 if( dimension & ( 1 << i ) )
1484 mRelayoutData->dimensionDependencies[ i ] = dependency;
1489 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1491 if ( mRelayoutData )
1493 // If more than one dimension is requested, just return the first one found
1494 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1496 if( ( dimension & ( 1 << i ) ) )
1498 return mRelayoutData->dimensionDependencies[ i ];
1503 return Dimension::ALL_DIMENSIONS; // Default
1506 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1508 // If relayout data has not been allocated yet and the client is requesting
1509 // to disable it, do nothing
1510 if( mRelayoutData || relayoutEnabled )
1512 EnsureRelayoutData();
1514 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1516 mRelayoutData->relayoutEnabled = relayoutEnabled;
1520 bool Actor::IsRelayoutEnabled() const
1522 // Assume that if relayout data has not been allocated yet then
1523 // relayout is disabled
1524 return mRelayoutData && mRelayoutData->relayoutEnabled;
1527 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1529 EnsureRelayoutData();
1531 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1533 if( dimension & ( 1 << i ) )
1535 mRelayoutData->dimensionDirty[ i ] = dirty;
1540 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1542 if ( mRelayoutData )
1544 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1546 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1556 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1558 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1561 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1563 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1566 unsigned int Actor::AddRenderer( Renderer& renderer )
1570 mRenderers = new RendererContainer;
1573 unsigned int index = mRenderers->size();
1574 RendererPtr rendererPtr = RendererPtr( &renderer );
1575 mRenderers->push_back( rendererPtr );
1576 AddRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1580 unsigned int Actor::GetRendererCount() const
1582 unsigned int rendererCount(0);
1585 rendererCount = mRenderers->size();
1588 return rendererCount;
1591 RendererPtr Actor::GetRendererAt( unsigned int index )
1593 RendererPtr renderer;
1594 if( index < GetRendererCount() )
1596 renderer = ( *mRenderers )[ index ];
1602 void Actor::RemoveRenderer( Renderer& renderer )
1606 RendererIter end = mRenderers->end();
1607 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1609 if( (*iter).Get() == &renderer )
1611 mRenderers->erase( iter );
1612 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1619 void Actor::RemoveRenderer( unsigned int index )
1621 if( index < GetRendererCount() )
1623 RendererPtr renderer = ( *mRenderers )[ index ];
1624 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.Get()->GetRendererSceneObject() );
1625 mRenderers->erase( mRenderers->begin()+index );
1629 bool Actor::IsOverlay() const
1631 return ( DrawMode::OVERLAY_2D == mDrawMode );
1634 void Actor::SetDrawMode( DrawMode::Type drawMode )
1636 // this flag is not animatable so keep the value
1637 mDrawMode = drawMode;
1638 if( ( NULL != mNode ) && ( drawMode != DrawMode::STENCIL ) )
1640 // mNode is being used in a separate thread; queue a message to set the value
1641 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1645 DrawMode::Type Actor::GetDrawMode() const
1650 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1652 // only valid when on-stage
1653 StagePtr stage = Stage::GetCurrent();
1654 if( stage && OnStage() )
1656 const RenderTaskList& taskList = stage->GetRenderTaskList();
1658 Vector2 converted( screenX, screenY );
1660 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1661 const int taskCount = taskList.GetTaskCount();
1662 for( int i = taskCount - 1; i >= 0; --i )
1664 Dali::RenderTask task = taskList.GetTask( i );
1665 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1667 // found a task where this conversion was ok so return
1675 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1677 bool retval = false;
1678 // only valid when on-stage
1681 CameraActor* camera = renderTask.GetCameraActor();
1685 renderTask.GetViewport( viewport );
1687 // need to translate coordinates to render tasks coordinate space
1688 Vector2 converted( screenX, screenY );
1689 if( renderTask.TranslateCoordinates( converted ) )
1691 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1698 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1700 // Early-out if mNode is NULL
1706 // Get the ModelView matrix
1708 Matrix::Multiply( modelView, mNode->GetWorldMatrix(0), viewMatrix );
1710 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1711 Matrix invertedMvp( false/*don't init*/);
1712 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1713 bool success = invertedMvp.Invert();
1715 // Convert to GL coordinates
1716 Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
1721 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
1728 success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
1734 if( XyPlaneIntersect( nearPos, farPos, local ) )
1736 Vector3 size = GetCurrentSize();
1737 localX = local.x + size.x * 0.5f;
1738 localY = local.y + size.y * 0.5f;
1749 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1752 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1754 Mathematical Formulation
1756 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1758 ( p - c ) dot ( p - c ) = r^2
1760 Given a ray with a point of origin 'o', and a direction vector 'd':
1762 ray(t) = o + td, t >= 0
1764 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1766 (o + td - c ) dot ( o + td - c ) = r^2
1768 To solve for t we first expand the above into a more recognisable quadratic equation form
1770 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1779 B = 2( o - c ) dot d
1780 C = ( o - c ) dot ( o - c ) - r^2
1782 which can be solved using a standard quadratic formula.
1784 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1786 Practical Simplification
1788 In a renderer, we often differentiate between world space and object space. In the object space
1789 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1790 into object space, the mathematical solution presented above can be simplified significantly.
1792 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1796 and we can find the t at which the (transformed) ray intersects the sphere by
1798 ( o + td ) dot ( o + td ) = r^2
1800 According to the reasoning above, we expand the above quadratic equation into the general form
1804 which now has coefficients:
1811 // Early out if mNode is NULL
1817 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1819 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1820 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1821 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1823 // Compute the radius is not needed, square radius it's enough.
1824 const Vector3& size( mNode->GetSize( bufferIndex ) );
1826 // Scale the sphere.
1827 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1829 const float width = size.width * scale.width;
1830 const float height = size.height * scale.height;
1832 float squareSphereRadius = 0.5f * ( width * width + height * height );
1834 float a = rayDir.Dot( rayDir ); // a
1835 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1836 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1838 return ( b2 * b2 - a * c ) >= 0.f;
1841 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector2& hitPointLocal, float& distance ) const
1845 if( OnStage() && NULL != mNode )
1847 // Transforms the ray to the local reference system.
1848 // Calculate the inverse of Model matrix
1849 Matrix invModelMatrix( false/*don't init*/);
1851 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1852 invModelMatrix = mNode->GetWorldMatrix(0);
1853 invModelMatrix.Invert();
1855 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1856 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1858 // Test with the actor's XY plane (Normal = 0 0 1 1).
1860 float a = -rayOriginLocal.z;
1861 float b = rayDirLocal.z;
1863 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1865 // Ray travels distance * rayDirLocal to intersect with plane.
1868 const Vector3& size = mNode->GetSize( bufferIndex );
1870 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1871 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1873 // Test with the actor's geometry.
1874 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1881 void Actor::SetLeaveRequired( bool required )
1883 mLeaveRequired = required;
1886 bool Actor::GetLeaveRequired() const
1888 return mLeaveRequired;
1891 void Actor::SetKeyboardFocusable( bool focusable )
1893 mKeyboardFocusable = focusable;
1896 bool Actor::IsKeyboardFocusable() const
1898 return mKeyboardFocusable;
1901 bool Actor::GetTouchRequired() const
1903 return !mTouchedSignal.Empty() || !mTouchSignal.Empty() || mDerivedRequiresTouch;
1906 bool Actor::GetHoverRequired() const
1908 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1911 bool Actor::GetWheelEventRequired() const
1913 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1916 bool Actor::IsHittable() const
1918 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1921 ActorGestureData& Actor::GetGestureData()
1923 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1924 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1925 if( NULL == mGestureData )
1927 mGestureData = new ActorGestureData;
1929 return *mGestureData;
1932 bool Actor::IsGestureRequred( Gesture::Type type ) const
1934 return mGestureData && mGestureData->IsGestureRequred( type );
1937 bool Actor::EmitTouchEventSignal( const TouchEvent& event, const Dali::TouchData& touch )
1939 bool consumed = false;
1941 if( !mTouchSignal.Empty() )
1943 Dali::Actor handle( this );
1944 consumed = mTouchSignal.Emit( handle, touch );
1947 if( !mTouchedSignal.Empty() )
1949 Dali::Actor handle( this );
1950 consumed |= mTouchedSignal.Emit( handle, event );
1955 // Notification for derived classes
1956 consumed = OnTouchEvent( event ); // TODO
1962 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1964 bool consumed = false;
1966 if( !mHoveredSignal.Empty() )
1968 Dali::Actor handle( this );
1969 consumed = mHoveredSignal.Emit( handle, event );
1974 // Notification for derived classes
1975 consumed = OnHoverEvent( event );
1981 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1983 bool consumed = false;
1985 if( !mWheelEventSignal.Empty() )
1987 Dali::Actor handle( this );
1988 consumed = mWheelEventSignal.Emit( handle, event );
1993 // Notification for derived classes
1994 consumed = OnWheelEvent( event );
2000 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
2002 if( ! mVisibilityChangedSignal.Empty() )
2004 Dali::Actor handle( this );
2005 mVisibilityChangedSignal.Emit( handle, visible, type );
2009 void Actor::EmitLayoutDirectionChangedSignal( LayoutDirection::Type type )
2011 if( ! mLayoutDirectionChangedSignal.Empty() )
2013 Dali::Actor handle( this );
2014 mLayoutDirectionChangedSignal.Emit( handle, type );
2018 void Actor::EmitChildAddedSignal( Actor& child )
2020 if( ! mChildAddedSignal.Empty() )
2022 Dali::Actor handle( &child );
2023 mChildAddedSignal.Emit( handle );
2027 void Actor::EmitChildRemovedSignal( Actor& child )
2029 if( ! mChildRemovedSignal.Empty() )
2031 Dali::Actor handle( &child );
2032 mChildRemovedSignal.Emit( handle );
2036 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
2038 return mTouchedSignal;
2041 Dali::Actor::TouchDataSignalType& Actor::TouchSignal()
2043 return mTouchSignal;
2046 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
2048 return mHoveredSignal;
2051 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
2053 return mWheelEventSignal;
2056 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
2058 return mOnStageSignal;
2061 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
2063 return mOffStageSignal;
2066 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
2068 return mOnRelayoutSignal;
2071 DevelActor::VisibilityChangedSignalType& Actor::VisibilityChangedSignal()
2073 return mVisibilityChangedSignal;
2076 Dali::Actor::LayoutDirectionChangedSignalType& Actor::LayoutDirectionChangedSignal()
2078 return mLayoutDirectionChangedSignal;
2081 DevelActor::ChildChangedSignalType& Actor::ChildAddedSignal()
2083 return mChildAddedSignal;
2086 DevelActor::ChildChangedSignalType& Actor::ChildRemovedSignal()
2088 return mChildRemovedSignal;
2091 DevelActor::ChildOrderChangedSignalType& Actor::ChildOrderChangedSignal()
2093 return mChildOrderChangedSignal;
2096 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
2098 bool connected( true );
2099 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
2101 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
2103 actor->TouchedSignal().Connect( tracker, functor );
2105 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
2107 actor->HoveredSignal().Connect( tracker, functor );
2109 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
2111 actor->WheelEventSignal().Connect( tracker, functor );
2113 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
2115 actor->OnStageSignal().Connect( tracker, functor );
2117 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
2119 actor->OffStageSignal().Connect( tracker, functor );
2121 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
2123 actor->OnRelayoutSignal().Connect( tracker, functor );
2125 else if( 0 == signalName.compare( SIGNAL_TOUCH ) )
2127 actor->TouchSignal().Connect( tracker, functor );
2129 else if( 0 == signalName.compare( SIGNAL_VISIBILITY_CHANGED ) )
2131 actor->VisibilityChangedSignal().Connect( tracker, functor );
2133 else if( 0 == signalName.compare( SIGNAL_LAYOUT_DIRECTION_CHANGED ) )
2135 actor->LayoutDirectionChangedSignal().Connect( tracker, functor );
2137 else if( 0 == signalName.compare( SIGNAL_CHILD_ADDED ) )
2139 actor->ChildAddedSignal().Connect( tracker, functor );
2141 else if( 0 == signalName.compare( SIGNAL_CHILD_REMOVED ) )
2143 actor->ChildRemovedSignal().Connect( tracker, functor );
2147 // signalName does not match any signal
2154 Actor::Actor( DerivedType derivedType )
2159 mParentOrigin( NULL ),
2160 mAnchorPoint( NULL ),
2161 mRelayoutData( NULL ),
2162 mGestureData( NULL ),
2166 mWheelEventSignal(),
2169 mOnRelayoutSignal(),
2170 mVisibilityChangedSignal(),
2171 mLayoutDirectionChangedSignal(),
2172 mChildAddedSignal(),
2173 mChildRemovedSignal(),
2174 mChildOrderChangedSignal(),
2175 mTargetOrientation( Quaternion::IDENTITY ),
2176 mTargetColor( Color::WHITE ),
2177 mTargetSize( Vector3::ZERO ),
2178 mTargetPosition( Vector3::ZERO ),
2179 mTargetScale( Vector3::ONE ),
2181 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
2184 mIsRoot( ROOT_LAYER == derivedType ),
2185 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2186 mIsOnStage( false ),
2188 mLeaveRequired( false ),
2189 mKeyboardFocusable( false ),
2190 mDerivedRequiresTouch( false ),
2191 mDerivedRequiresHover( false ),
2192 mDerivedRequiresWheelEvent( false ),
2193 mOnStageSignalled( false ),
2194 mInsideOnSizeSet( false ),
2195 mInheritPosition( true ),
2196 mInheritOrientation( true ),
2197 mInheritScale( true ),
2198 mPositionUsesAnchorPoint( true ),
2200 mInheritLayoutDirection( true ),
2201 mLayoutDirection( LayoutDirection::LEFT_TO_RIGHT ),
2202 mDrawMode( DrawMode::NORMAL ),
2203 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2204 mColorMode( Node::DEFAULT_COLOR_MODE ),
2205 mClippingMode( ClippingMode::DISABLED )
2209 void Actor::Initialize()
2211 // Node creation, keep raw-pointer to Node for messaging
2212 mNode = CreateNode();
2213 OwnerPointer< SceneGraph::Node > transferOwnership( const_cast< SceneGraph::Node* >( mNode ) );
2214 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), transferOwnership );
2218 GetEventThreadServices().RegisterObject( this );
2223 // Remove mParent pointers from children even if we're destroying core,
2224 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2227 ActorConstIter endIter = mChildren->end();
2228 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2230 (*iter)->SetParent( NULL );
2236 // Guard to allow handle destruction after Core has been destroyed
2237 if( EventThreadServices::IsCoreRunning() )
2241 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2242 mNode = NULL; // Node is about to be destroyed
2245 GetEventThreadServices().UnregisterObject( this );
2248 // Cleanup optional gesture data
2249 delete mGestureData;
2251 // Cleanup optional parent origin and anchor
2252 delete mParentOrigin;
2253 delete mAnchorPoint;
2255 // Delete optional relayout data
2258 delete mRelayoutData;
2262 void Actor::ConnectToStage( unsigned int parentDepth )
2264 // This container is used instead of walking the Actor hierarchy.
2265 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
2266 ActorContainer connectionList;
2268 StagePtr stage = Stage::GetCurrent();
2271 stage->RequestRebuildDepthTree();
2274 // This stage is atomic i.e. not interrupted by user callbacks.
2275 RecursiveConnectToStage( connectionList, parentDepth + 1 );
2277 // Notify applications about the newly connected actors.
2278 const ActorIter endIter = connectionList.end();
2279 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2281 (*iter)->NotifyStageConnection();
2287 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth )
2289 DALI_ASSERT_ALWAYS( !OnStage() );
2294 ConnectToSceneGraph();
2296 // Notification for internal derived classes
2297 OnStageConnectionInternal();
2299 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2300 connectionList.push_back( ActorPtr( this ) );
2302 // Recursively connect children
2305 ActorConstIter endIter = mChildren->end();
2306 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2308 (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
2314 * This method is called when the Actor is connected to the Stage.
2315 * The parent must have added its Node to the scene-graph.
2316 * The child must connect its Node to the parent's Node.
2317 * This is recursive; the child calls ConnectToStage() for its children.
2319 void Actor::ConnectToSceneGraph()
2321 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2325 // Reparent Node in next Update
2326 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode );
2329 // Request relayout on all actors that are added to the scenegraph
2332 // Notification for Object::Observers
2336 void Actor::NotifyStageConnection()
2338 // Actors can be removed (in a callback), before the on-stage stage is reported.
2339 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2340 if( OnStage() && !mOnStageSignalled )
2342 // Notification for external (CustomActor) derived classes
2343 OnStageConnectionExternal( mDepth );
2345 if( !mOnStageSignal.Empty() )
2347 Dali::Actor handle( this );
2348 mOnStageSignal.Emit( handle );
2351 // Guard against Remove during callbacks
2354 mOnStageSignalled = true; // signal required next time Actor is removed
2359 void Actor::DisconnectFromStage()
2361 // This container is used instead of walking the Actor hierachy.
2362 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2363 ActorContainer disconnectionList;
2365 StagePtr stage = Stage::GetCurrent();
2368 stage->RequestRebuildDepthTree();
2371 // This stage is atomic i.e. not interrupted by user callbacks
2372 RecursiveDisconnectFromStage( disconnectionList );
2374 // Notify applications about the newly disconnected actors.
2375 const ActorIter endIter = disconnectionList.end();
2376 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2378 (*iter)->NotifyStageDisconnection();
2382 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2384 DALI_ASSERT_ALWAYS( OnStage() );
2386 // Recursively disconnect children
2389 ActorConstIter endIter = mChildren->end();
2390 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2392 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2396 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2397 disconnectionList.push_back( ActorPtr( this ) );
2399 // Notification for internal derived classes
2400 OnStageDisconnectionInternal();
2402 DisconnectFromSceneGraph();
2408 * This method is called by an actor or its parent, before a node removal message is sent.
2409 * This is recursive; the child calls DisconnectFromStage() for its children.
2411 void Actor::DisconnectFromSceneGraph()
2413 // Notification for Object::Observers
2414 OnSceneObjectRemove();
2417 void Actor::NotifyStageDisconnection()
2419 // Actors can be added (in a callback), before the off-stage state is reported.
2420 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2421 // only do this step if there is a stage, i.e. Core is not being shut down
2422 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2424 // Notification for external (CustomeActor) derived classes
2425 OnStageDisconnectionExternal();
2427 if( !mOffStageSignal.Empty() )
2429 Dali::Actor handle( this );
2430 mOffStageSignal.Emit( handle );
2433 // Guard against Add during callbacks
2436 mOnStageSignalled = false; // signal required next time Actor is added
2441 bool Actor::IsNodeConnected() const
2443 bool connected( false );
2445 if( OnStage() && ( NULL != mNode ) )
2447 if( IsRoot() || mNode->GetParent() )
2456 // This method initiates traversal of the actor tree using depth-first
2457 // traversal to set a depth index based on traversal order. It sends a
2458 // single message to update manager to update all the actor's nodes in
2459 // this tree with the depth index. The sceneGraphNodeDepths vector's
2460 // elements are ordered by depth, and could be used to reduce sorting
2461 // in the update thread.
2462 void Actor::RebuildDepthTree()
2464 DALI_LOG_TIMER_START(depthTimer);
2466 // Vector of scene-graph nodes and their depths to send to UpdateManager
2467 // in a single message
2468 OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths( new SceneGraph::NodeDepths() );
2471 DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
2473 SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths );
2474 DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
2477 void Actor::DepthTraverseActorTree( OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths, int& depthIndex )
2479 mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
2480 sceneGraphNodeDepths->Add( const_cast<SceneGraph::Node*>( mNode ), mSortedDepth );
2482 // Create/add to children of this node
2485 for( ActorContainer::iterator it = mChildren->begin(); it != mChildren->end(); ++it )
2487 Actor* childActor = (*it).Get();
2489 childActor->DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
2494 unsigned int Actor::GetDefaultPropertyCount() const
2496 return DEFAULT_PROPERTY_COUNT;
2499 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2501 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2503 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2505 indices.PushBack( i );
2509 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2511 if( index < DEFAULT_PROPERTY_COUNT )
2513 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2519 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2521 Property::Index index = Property::INVALID_INDEX;
2523 // Look for name in default properties
2524 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2526 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2527 if( 0 == name.compare( property->name ) )
2537 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2539 if( index < DEFAULT_PROPERTY_COUNT )
2541 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2547 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2549 if( index < DEFAULT_PROPERTY_COUNT )
2551 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2557 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2559 if( index < DEFAULT_PROPERTY_COUNT )
2561 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2567 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2569 if( index < DEFAULT_PROPERTY_COUNT )
2571 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2574 // index out of range...return Property::NONE
2575 return Property::NONE;
2578 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2582 case Dali::Actor::Property::PARENT_ORIGIN:
2584 Property::Type type = property.GetType();
2585 if( type == Property::VECTOR3 )
2587 SetParentOrigin( property.Get< Vector3 >() );
2589 else if ( type == Property::STRING )
2591 std::string parentOriginString;
2592 property.Get( parentOriginString );
2593 Vector3 parentOrigin;
2594 if( GetParentOriginConstant( parentOriginString, parentOrigin ) )
2596 SetParentOrigin( parentOrigin );
2602 case Dali::Actor::Property::PARENT_ORIGIN_X:
2604 SetParentOriginX( property.Get< float >() );
2608 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2610 SetParentOriginY( property.Get< float >() );
2614 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2616 SetParentOriginZ( property.Get< float >() );
2620 case Dali::Actor::Property::ANCHOR_POINT:
2622 Property::Type type = property.GetType();
2623 if( type == Property::VECTOR3 )
2625 SetAnchorPoint( property.Get< Vector3 >() );
2627 else if ( type == Property::STRING )
2629 std::string anchorPointString;
2630 property.Get( anchorPointString );
2632 if( GetAnchorPointConstant( anchorPointString, anchor ) )
2634 SetAnchorPoint( anchor );
2640 case Dali::Actor::Property::ANCHOR_POINT_X:
2642 SetAnchorPointX( property.Get< float >() );
2646 case Dali::Actor::Property::ANCHOR_POINT_Y:
2648 SetAnchorPointY( property.Get< float >() );
2652 case Dali::Actor::Property::ANCHOR_POINT_Z:
2654 SetAnchorPointZ( property.Get< float >() );
2658 case Dali::Actor::Property::SIZE:
2660 SetSize( property.Get< Vector3 >() );
2664 case Dali::Actor::Property::SIZE_WIDTH:
2666 SetWidth( property.Get< float >() );
2670 case Dali::Actor::Property::SIZE_HEIGHT:
2672 SetHeight( property.Get< float >() );
2676 case Dali::Actor::Property::SIZE_DEPTH:
2678 SetDepth( property.Get< float >() );
2682 case Dali::Actor::Property::POSITION:
2684 SetPosition( property.Get< Vector3 >() );
2688 case Dali::Actor::Property::POSITION_X:
2690 SetX( property.Get< float >() );
2694 case Dali::Actor::Property::POSITION_Y:
2696 SetY( property.Get< float >() );
2700 case Dali::Actor::Property::POSITION_Z:
2702 SetZ( property.Get< float >() );
2706 case Dali::Actor::Property::ORIENTATION:
2708 SetOrientation( property.Get< Quaternion >() );
2712 case Dali::Actor::Property::SCALE:
2714 SetScale( property.Get< Vector3 >() );
2718 case Dali::Actor::Property::SCALE_X:
2720 SetScaleX( property.Get< float >() );
2724 case Dali::Actor::Property::SCALE_Y:
2726 SetScaleY( property.Get< float >() );
2730 case Dali::Actor::Property::SCALE_Z:
2732 SetScaleZ( property.Get< float >() );
2736 case Dali::Actor::Property::VISIBLE:
2738 SetVisible( property.Get< bool >() );
2742 case Dali::Actor::Property::COLOR:
2744 SetColor( property.Get< Vector4 >() );
2748 case Dali::Actor::Property::COLOR_RED:
2750 SetColorRed( property.Get< float >() );
2754 case Dali::Actor::Property::COLOR_GREEN:
2756 SetColorGreen( property.Get< float >() );
2760 case Dali::Actor::Property::COLOR_BLUE:
2762 SetColorBlue( property.Get< float >() );
2766 case Dali::Actor::Property::COLOR_ALPHA:
2767 case Dali::DevelActor::Property::OPACITY:
2770 if( property.Get( value ) )
2772 SetOpacity( value );
2777 case Dali::Actor::Property::NAME:
2779 SetName( property.Get< std::string >() );
2783 case Dali::Actor::Property::SENSITIVE:
2785 SetSensitive( property.Get< bool >() );
2789 case Dali::Actor::Property::LEAVE_REQUIRED:
2791 SetLeaveRequired( property.Get< bool >() );
2795 case Dali::Actor::Property::INHERIT_POSITION:
2797 SetInheritPosition( property.Get< bool >() );
2801 case Dali::Actor::Property::INHERIT_ORIENTATION:
2803 SetInheritOrientation( property.Get< bool >() );
2807 case Dali::Actor::Property::INHERIT_SCALE:
2809 SetInheritScale( property.Get< bool >() );
2813 case Dali::Actor::Property::COLOR_MODE:
2815 ColorMode mode = mColorMode;
2816 if ( Scripting::GetEnumerationProperty< ColorMode >( property, COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT, mode ) )
2818 SetColorMode( mode );
2823 case Dali::Actor::Property::POSITION_INHERITANCE:
2825 PositionInheritanceMode mode = mPositionInheritanceMode;
2826 if( Scripting::GetEnumerationProperty< PositionInheritanceMode >( property, POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT, mode ) )
2828 SetPositionInheritanceMode( mode );
2833 case Dali::Actor::Property::DRAW_MODE:
2835 DrawMode::Type mode = mDrawMode;
2836 if( Scripting::GetEnumerationProperty< DrawMode::Type >( property, DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT, mode ) )
2838 SetDrawMode( mode );
2843 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2845 SetSizeModeFactor( property.Get< Vector3 >() );
2849 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2851 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
2852 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2854 SetResizePolicy( type, Dimension::WIDTH );
2859 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2861 ResizePolicy::Type type = static_cast< ResizePolicy::Type >( -1 ); // Set to invalid number so it definitely gets set.
2862 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2864 SetResizePolicy( type, Dimension::HEIGHT );
2869 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2871 SizeScalePolicy::Type type;
2872 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT, type ) )
2874 SetSizeScalePolicy( type );
2879 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2881 if( property.Get< bool >() )
2883 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2888 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2890 if( property.Get< bool >() )
2892 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2897 case Dali::Actor::Property::PADDING:
2899 Vector4 padding = property.Get< Vector4 >();
2900 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2901 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2905 case Dali::Actor::Property::MINIMUM_SIZE:
2907 Vector2 size = property.Get< Vector2 >();
2908 SetMinimumSize( size.x, Dimension::WIDTH );
2909 SetMinimumSize( size.y, Dimension::HEIGHT );
2913 case Dali::Actor::Property::MAXIMUM_SIZE:
2915 Vector2 size = property.Get< Vector2 >();
2916 SetMaximumSize( size.x, Dimension::WIDTH );
2917 SetMaximumSize( size.y, Dimension::HEIGHT );
2921 case Dali::DevelActor::Property::SIBLING_ORDER:
2925 if( property.Get( value ) )
2927 SetSiblingOrder( value );
2932 case Dali::Actor::Property::CLIPPING_MODE:
2934 ClippingMode::Type convertedValue = mClippingMode;
2935 if( Scripting::GetEnumerationProperty< ClippingMode::Type >( property, CLIPPING_MODE_TABLE, CLIPPING_MODE_TABLE_COUNT, convertedValue ) )
2937 mClippingMode = convertedValue;
2940 SetClippingModeMessage( GetEventThreadServices(), *mNode, mClippingMode );
2946 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
2949 if( property.Get( value ) && value != mPositionUsesAnchorPoint )
2951 mPositionUsesAnchorPoint = value;
2954 SetPositionUsesAnchorPointMessage( GetEventThreadServices(), *mNode, mPositionUsesAnchorPoint );
2960 case Dali::Actor::Property::LAYOUT_DIRECTION:
2962 Dali::LayoutDirection::Type direction = mLayoutDirection;
2963 mInheritLayoutDirection = false;
2965 if( Scripting::GetEnumerationProperty< LayoutDirection::Type >( property, LAYOUT_DIRECTION_TABLE, LAYOUT_DIRECTION_TABLE_COUNT, direction ) )
2967 InheritLayoutDirectionRecursively( this, direction, true );
2972 case Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION:
2975 if( property.Get( value ) )
2977 SetInheritLayoutDirection( value );
2984 // this can happen in the case of a non-animatable default property so just do nothing
2990 // TODO: This method needs to be removed
2991 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2993 switch( entry.GetType() )
2995 case Property::BOOLEAN:
2997 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2998 DALI_ASSERT_DEBUG( NULL != property );
3000 // property is being used in a separate thread; queue a message to set the property
3001 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
3006 case Property::INTEGER:
3008 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
3009 DALI_ASSERT_DEBUG( NULL != property );
3011 // property is being used in a separate thread; queue a message to set the property
3012 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
3017 case Property::FLOAT:
3019 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
3020 DALI_ASSERT_DEBUG( NULL != property );
3022 // property is being used in a separate thread; queue a message to set the property
3023 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
3028 case Property::VECTOR2:
3030 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
3031 DALI_ASSERT_DEBUG( NULL != property );
3033 // property is being used in a separate thread; queue a message to set the property
3034 if(entry.componentIndex == 0)
3036 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
3038 else if(entry.componentIndex == 1)
3040 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
3044 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
3050 case Property::VECTOR3:
3052 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
3053 DALI_ASSERT_DEBUG( NULL != property );
3055 // property is being used in a separate thread; queue a message to set the property
3056 if(entry.componentIndex == 0)
3058 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
3060 else if(entry.componentIndex == 1)
3062 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
3064 else if(entry.componentIndex == 2)
3066 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
3070 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
3076 case Property::VECTOR4:
3078 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
3079 DALI_ASSERT_DEBUG( NULL != property );
3081 // property is being used in a separate thread; queue a message to set the property
3082 if(entry.componentIndex == 0)
3084 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
3086 else if(entry.componentIndex == 1)
3088 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
3090 else if(entry.componentIndex == 2)
3092 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
3094 else if(entry.componentIndex == 3)
3096 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
3100 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3106 case Property::ROTATION:
3108 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3109 DALI_ASSERT_DEBUG( NULL != property );
3111 // property is being used in a separate thread; queue a message to set the property
3112 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3117 case Property::MATRIX:
3119 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3120 DALI_ASSERT_DEBUG( NULL != property );
3122 // property is being used in a separate thread; queue a message to set the property
3123 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3128 case Property::MATRIX3:
3130 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3131 DALI_ASSERT_DEBUG( NULL != property );
3133 // property is being used in a separate thread; queue a message to set the property
3134 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3141 // nothing to do for other types
3146 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3148 Property::Value value;
3150 if( ! GetCachedPropertyValue( index, value ) )
3152 // If property value is not stored in the event-side, then it must be a scene-graph only property
3153 GetCurrentPropertyValue( index, value );
3159 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
3161 Property::Value value;
3163 if( ! GetCurrentPropertyValue( index, value ) )
3165 // If unable to retrieve scene-graph property value, then it must be an event-side only property
3166 GetCachedPropertyValue( index, value );
3172 void Actor::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
3174 switch( animationType )
3177 case Animation::BETWEEN:
3181 case Dali::Actor::Property::SIZE:
3183 if( value.Get( mTargetSize ) )
3185 // Notify deriving classes
3186 OnSizeAnimation( animation, mTargetSize );
3191 case Dali::Actor::Property::SIZE_WIDTH:
3193 if( value.Get( mTargetSize.width ) )
3195 // Notify deriving classes
3196 OnSizeAnimation( animation, mTargetSize );
3201 case Dali::Actor::Property::SIZE_HEIGHT:
3203 if( value.Get( mTargetSize.height ) )
3205 // Notify deriving classes
3206 OnSizeAnimation( animation, mTargetSize );
3211 case Dali::Actor::Property::SIZE_DEPTH:
3213 if( value.Get( mTargetSize.depth ) )
3215 // Notify deriving classes
3216 OnSizeAnimation( animation, mTargetSize );
3221 case Dali::Actor::Property::POSITION:
3223 value.Get( mTargetPosition );
3227 case Dali::Actor::Property::POSITION_X:
3229 value.Get( mTargetPosition.x );
3233 case Dali::Actor::Property::POSITION_Y:
3235 value.Get( mTargetPosition.y );
3239 case Dali::Actor::Property::POSITION_Z:
3241 value.Get( mTargetPosition.z );
3245 case Dali::Actor::Property::ORIENTATION:
3247 value.Get( mTargetOrientation );
3251 case Dali::Actor::Property::SCALE:
3253 value.Get( mTargetScale );
3257 case Dali::Actor::Property::SCALE_X:
3259 value.Get( mTargetScale.x );
3263 case Dali::Actor::Property::SCALE_Y:
3265 value.Get( mTargetScale.y );
3269 case Dali::Actor::Property::SCALE_Z:
3271 value.Get( mTargetScale.z );
3275 case Dali::Actor::Property::VISIBLE:
3277 SetVisibleInternal( value.Get< bool >(), SendMessage::FALSE );
3281 case Dali::Actor::Property::COLOR:
3283 value.Get( mTargetColor );
3287 case Dali::Actor::Property::COLOR_RED:
3289 value.Get( mTargetColor.r );
3293 case Dali::Actor::Property::COLOR_GREEN:
3295 value.Get( mTargetColor.g );
3299 case Dali::Actor::Property::COLOR_BLUE:
3301 value.Get( mTargetColor.b );
3305 case Dali::Actor::Property::COLOR_ALPHA:
3306 case Dali::DevelActor::Property::OPACITY:
3308 value.Get( mTargetColor.a );
3314 // Not an animatable property. Do nothing.
3325 case Dali::Actor::Property::SIZE:
3327 if( AdjustValue< Vector3 >( mTargetSize, value ) )
3329 // Notify deriving classes
3330 OnSizeAnimation( animation, mTargetSize );
3335 case Dali::Actor::Property::SIZE_WIDTH:
3337 if( AdjustValue< float >( mTargetSize.width, value ) )
3339 // Notify deriving classes
3340 OnSizeAnimation( animation, mTargetSize );
3345 case Dali::Actor::Property::SIZE_HEIGHT:
3347 if( AdjustValue< float >( mTargetSize.height, value ) )
3349 // Notify deriving classes
3350 OnSizeAnimation( animation, mTargetSize );
3355 case Dali::Actor::Property::SIZE_DEPTH:
3357 if( AdjustValue< float >( mTargetSize.depth, value ) )
3359 // Notify deriving classes
3360 OnSizeAnimation( animation, mTargetSize );
3365 case Dali::Actor::Property::POSITION:
3367 AdjustValue< Vector3 >( mTargetPosition, value );
3371 case Dali::Actor::Property::POSITION_X:
3373 AdjustValue< float >( mTargetPosition.x, value );
3377 case Dali::Actor::Property::POSITION_Y:
3379 AdjustValue< float >( mTargetPosition.y, value );
3383 case Dali::Actor::Property::POSITION_Z:
3385 AdjustValue< float >( mTargetPosition.z, value );
3389 case Dali::Actor::Property::ORIENTATION:
3391 Quaternion relativeValue;
3392 if( value.Get( relativeValue ) )
3394 mTargetOrientation *= relativeValue;
3399 case Dali::Actor::Property::SCALE:
3401 AdjustValue< Vector3 >( mTargetScale, value );
3405 case Dali::Actor::Property::SCALE_X:
3407 AdjustValue< float >( mTargetScale.x, value );
3411 case Dali::Actor::Property::SCALE_Y:
3413 AdjustValue< float >( mTargetScale.y, value );
3417 case Dali::Actor::Property::SCALE_Z:
3419 AdjustValue< float >( mTargetScale.z, value );
3423 case Dali::Actor::Property::VISIBLE:
3425 bool relativeValue = false;
3426 if( value.Get( relativeValue ) )
3428 bool visible = mVisible || relativeValue;
3429 SetVisibleInternal( visible, SendMessage::FALSE );
3434 case Dali::Actor::Property::COLOR:
3436 AdjustValue< Vector4 >( mTargetColor, value );
3440 case Dali::Actor::Property::COLOR_RED:
3442 AdjustValue< float >( mTargetColor.r, value );
3446 case Dali::Actor::Property::COLOR_GREEN:
3448 AdjustValue< float >( mTargetColor.g, value );
3452 case Dali::Actor::Property::COLOR_BLUE:
3454 AdjustValue< float >( mTargetColor.b, value );
3458 case Dali::Actor::Property::COLOR_ALPHA:
3459 case Dali::DevelActor::Property::OPACITY:
3461 AdjustValue< float >( mTargetColor.a, value );
3467 // Not an animatable property. Do nothing.
3476 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3481 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3483 // This method should only return an object connected to the scene-graph
3484 return OnStage() ? mNode : NULL;
3487 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3489 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3491 const PropertyBase* property( NULL );
3493 // This method should only return a property of an object connected to the scene-graph
3499 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3501 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3502 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3504 property = animatable->GetSceneGraphProperty();
3506 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3507 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3509 CustomPropertyMetadata* custom = FindCustomProperty( index );
3510 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3512 property = custom->GetSceneGraphProperty();
3514 else if( NULL != mNode )
3518 case Dali::Actor::Property::SIZE:
3519 property = &mNode->mSize;
3522 case Dali::Actor::Property::SIZE_WIDTH:
3523 property = &mNode->mSize;
3526 case Dali::Actor::Property::SIZE_HEIGHT:
3527 property = &mNode->mSize;
3530 case Dali::Actor::Property::SIZE_DEPTH:
3531 property = &mNode->mSize;
3534 case Dali::Actor::Property::POSITION:
3535 property = &mNode->mPosition;
3538 case Dali::Actor::Property::POSITION_X:
3539 property = &mNode->mPosition;
3542 case Dali::Actor::Property::POSITION_Y:
3543 property = &mNode->mPosition;
3546 case Dali::Actor::Property::POSITION_Z:
3547 property = &mNode->mPosition;
3550 case Dali::Actor::Property::ORIENTATION:
3551 property = &mNode->mOrientation;
3554 case Dali::Actor::Property::SCALE:
3555 property = &mNode->mScale;
3558 case Dali::Actor::Property::SCALE_X:
3559 property = &mNode->mScale;
3562 case Dali::Actor::Property::SCALE_Y:
3563 property = &mNode->mScale;
3566 case Dali::Actor::Property::SCALE_Z:
3567 property = &mNode->mScale;
3570 case Dali::Actor::Property::VISIBLE:
3571 property = &mNode->mVisible;
3574 case Dali::Actor::Property::COLOR:
3575 property = &mNode->mColor;
3578 case Dali::Actor::Property::COLOR_RED:
3579 property = &mNode->mColor;
3582 case Dali::Actor::Property::COLOR_GREEN:
3583 property = &mNode->mColor;
3586 case Dali::Actor::Property::COLOR_BLUE:
3587 property = &mNode->mColor;
3590 case Dali::Actor::Property::COLOR_ALPHA:
3591 case Dali::DevelActor::Property::OPACITY:
3592 property = &mNode->mColor;
3603 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3605 const PropertyInputImpl* property( NULL );
3607 // This method should only return a property of an object connected to the scene-graph
3613 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3615 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3616 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3618 property = animatable->GetSceneGraphProperty();
3620 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3621 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3623 CustomPropertyMetadata* custom = FindCustomProperty( index );
3624 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3625 property = custom->GetSceneGraphProperty();
3627 else if( NULL != mNode )
3631 case Dali::Actor::Property::PARENT_ORIGIN:
3632 property = &mNode->mParentOrigin;
3635 case Dali::Actor::Property::PARENT_ORIGIN_X:
3636 property = &mNode->mParentOrigin;
3639 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3640 property = &mNode->mParentOrigin;
3643 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3644 property = &mNode->mParentOrigin;
3647 case Dali::Actor::Property::ANCHOR_POINT:
3648 property = &mNode->mAnchorPoint;
3651 case Dali::Actor::Property::ANCHOR_POINT_X:
3652 property = &mNode->mAnchorPoint;
3655 case Dali::Actor::Property::ANCHOR_POINT_Y:
3656 property = &mNode->mAnchorPoint;
3659 case Dali::Actor::Property::ANCHOR_POINT_Z:
3660 property = &mNode->mAnchorPoint;
3663 case Dali::Actor::Property::SIZE:
3664 property = &mNode->mSize;
3667 case Dali::Actor::Property::SIZE_WIDTH:
3668 property = &mNode->mSize;
3671 case Dali::Actor::Property::SIZE_HEIGHT:
3672 property = &mNode->mSize;
3675 case Dali::Actor::Property::SIZE_DEPTH:
3676 property = &mNode->mSize;
3679 case Dali::Actor::Property::POSITION:
3680 property = &mNode->mPosition;
3683 case Dali::Actor::Property::POSITION_X:
3684 property = &mNode->mPosition;
3687 case Dali::Actor::Property::POSITION_Y:
3688 property = &mNode->mPosition;
3691 case Dali::Actor::Property::POSITION_Z:
3692 property = &mNode->mPosition;
3695 case Dali::Actor::Property::WORLD_POSITION:
3696 property = &mNode->mWorldPosition;
3699 case Dali::Actor::Property::WORLD_POSITION_X:
3700 property = &mNode->mWorldPosition;
3703 case Dali::Actor::Property::WORLD_POSITION_Y:
3704 property = &mNode->mWorldPosition;
3707 case Dali::Actor::Property::WORLD_POSITION_Z:
3708 property = &mNode->mWorldPosition;
3711 case Dali::Actor::Property::ORIENTATION:
3712 property = &mNode->mOrientation;
3715 case Dali::Actor::Property::WORLD_ORIENTATION:
3716 property = &mNode->mWorldOrientation;
3719 case Dali::Actor::Property::SCALE:
3720 property = &mNode->mScale;
3723 case Dali::Actor::Property::SCALE_X:
3724 property = &mNode->mScale;
3727 case Dali::Actor::Property::SCALE_Y:
3728 property = &mNode->mScale;
3731 case Dali::Actor::Property::SCALE_Z:
3732 property = &mNode->mScale;
3735 case Dali::Actor::Property::WORLD_SCALE:
3736 property = &mNode->mWorldScale;
3739 case Dali::Actor::Property::VISIBLE:
3740 property = &mNode->mVisible;
3743 case Dali::Actor::Property::COLOR:
3744 property = &mNode->mColor;
3747 case Dali::Actor::Property::COLOR_RED:
3748 property = &mNode->mColor;
3751 case Dali::Actor::Property::COLOR_GREEN:
3752 property = &mNode->mColor;
3755 case Dali::Actor::Property::COLOR_BLUE:
3756 property = &mNode->mColor;
3759 case Dali::Actor::Property::COLOR_ALPHA:
3760 case Dali::DevelActor::Property::OPACITY:
3762 property = &mNode->mColor;
3766 case Dali::Actor::Property::WORLD_COLOR:
3767 property = &mNode->mWorldColor;
3770 case Dali::Actor::Property::WORLD_MATRIX:
3771 property = &mNode->mWorldMatrix;
3782 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3784 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3786 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3788 // check whether the animatable property is registered already, if not then register one.
3789 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3790 if( animatableProperty )
3792 componentIndex = animatableProperty->componentIndex;
3799 case Dali::Actor::Property::PARENT_ORIGIN_X:
3800 case Dali::Actor::Property::ANCHOR_POINT_X:
3801 case Dali::Actor::Property::SIZE_WIDTH:
3802 case Dali::Actor::Property::POSITION_X:
3803 case Dali::Actor::Property::WORLD_POSITION_X:
3804 case Dali::Actor::Property::SCALE_X:
3805 case Dali::Actor::Property::COLOR_RED:
3811 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3812 case Dali::Actor::Property::ANCHOR_POINT_Y:
3813 case Dali::Actor::Property::SIZE_HEIGHT:
3814 case Dali::Actor::Property::POSITION_Y:
3815 case Dali::Actor::Property::WORLD_POSITION_Y:
3816 case Dali::Actor::Property::SCALE_Y:
3817 case Dali::Actor::Property::COLOR_GREEN:
3823 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3824 case Dali::Actor::Property::ANCHOR_POINT_Z:
3825 case Dali::Actor::Property::SIZE_DEPTH:
3826 case Dali::Actor::Property::POSITION_Z:
3827 case Dali::Actor::Property::WORLD_POSITION_Z:
3828 case Dali::Actor::Property::SCALE_Z:
3829 case Dali::Actor::Property::COLOR_BLUE:
3835 case Dali::Actor::Property::COLOR_ALPHA:
3836 case Dali::DevelActor::Property::OPACITY:
3850 return componentIndex;
3853 void Actor::SetParent( Actor* parent )
3857 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3861 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3864 // Instruct each actor to create a corresponding node in the scene graph
3865 ConnectToStage( parent->GetHierarchyDepth() );
3868 // Resolve the name and index for the child properties if any
3869 ResolveChildProperties();
3871 else // parent being set to NULL
3873 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3877 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3880 DALI_ASSERT_ALWAYS( mNode != NULL );
3884 // Disconnect the Node & its children from the scene-graph.
3885 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3888 // Instruct each actor to discard pointers to the scene-graph
3889 DisconnectFromStage();
3894 SceneGraph::Node* Actor::CreateNode() const
3896 return Node::New( mId );
3899 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3902 Actor* actor = dynamic_cast< Actor* >( object );
3906 if( 0 == actionName.compare( ACTION_SHOW ) )
3908 actor->SetVisible( true );
3911 else if( 0 == actionName.compare( ACTION_HIDE ) )
3913 actor->SetVisible( false );
3921 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
3923 bool valueSet = true;
3927 case Dali::Actor::Property::PARENT_ORIGIN:
3929 value = GetCurrentParentOrigin();
3933 case Dali::Actor::Property::PARENT_ORIGIN_X:
3935 value = GetCurrentParentOrigin().x;
3939 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3941 value = GetCurrentParentOrigin().y;
3945 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3947 value = GetCurrentParentOrigin().z;
3951 case Dali::Actor::Property::ANCHOR_POINT:
3953 value = GetCurrentAnchorPoint();
3957 case Dali::Actor::Property::ANCHOR_POINT_X:
3959 value = GetCurrentAnchorPoint().x;
3963 case Dali::Actor::Property::ANCHOR_POINT_Y:
3965 value = GetCurrentAnchorPoint().y;
3969 case Dali::Actor::Property::ANCHOR_POINT_Z:
3971 value = GetCurrentAnchorPoint().z;
3975 case Dali::Actor::Property::SIZE:
3977 value = GetTargetSize();
3981 case Dali::Actor::Property::SIZE_WIDTH:
3983 value = GetTargetSize().width;
3987 case Dali::Actor::Property::SIZE_HEIGHT:
3989 value = GetTargetSize().height;
3993 case Dali::Actor::Property::SIZE_DEPTH:
3995 value = GetTargetSize().depth;
3999 case Dali::Actor::Property::POSITION:
4001 value = GetTargetPosition();
4005 case Dali::Actor::Property::POSITION_X:
4007 value = GetTargetPosition().x;
4011 case Dali::Actor::Property::POSITION_Y:
4013 value = GetTargetPosition().y;
4017 case Dali::Actor::Property::POSITION_Z:
4019 value = GetTargetPosition().z;
4023 case Dali::Actor::Property::ORIENTATION:
4025 value = mTargetOrientation;
4029 case Dali::Actor::Property::SCALE:
4031 value = mTargetScale;
4035 case Dali::Actor::Property::SCALE_X:
4037 value = mTargetScale.x;
4041 case Dali::Actor::Property::SCALE_Y:
4043 value = mTargetScale.y;
4047 case Dali::Actor::Property::SCALE_Z:
4049 value = mTargetScale.z;
4053 case Dali::Actor::Property::VISIBLE:
4059 case Dali::Actor::Property::COLOR:
4061 value = mTargetColor;
4065 case Dali::Actor::Property::COLOR_RED:
4067 value = mTargetColor.r;
4071 case Dali::Actor::Property::COLOR_GREEN:
4073 value = mTargetColor.g;
4077 case Dali::Actor::Property::COLOR_BLUE:
4079 value = mTargetColor.b;
4083 case Dali::Actor::Property::COLOR_ALPHA:
4084 case Dali::DevelActor::Property::OPACITY:
4086 value = mTargetColor.a;
4090 case Dali::Actor::Property::NAME:
4096 case Dali::Actor::Property::SENSITIVE:
4098 value = IsSensitive();
4102 case Dali::Actor::Property::LEAVE_REQUIRED:
4104 value = GetLeaveRequired();
4108 case Dali::Actor::Property::INHERIT_POSITION:
4110 value = IsPositionInherited();
4114 case Dali::Actor::Property::INHERIT_ORIENTATION:
4116 value = IsOrientationInherited();
4120 case Dali::Actor::Property::INHERIT_SCALE:
4122 value = IsScaleInherited();
4126 case Dali::Actor::Property::COLOR_MODE:
4128 value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
4132 case Dali::Actor::Property::POSITION_INHERITANCE:
4134 value = Scripting::GetLinearEnumerationName< PositionInheritanceMode >( GetPositionInheritanceMode(), POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT );
4138 case Dali::Actor::Property::DRAW_MODE:
4140 value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
4144 case Dali::Actor::Property::SIZE_MODE_FACTOR:
4146 value = GetSizeModeFactor();
4150 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
4152 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
4156 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
4158 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
4162 case Dali::Actor::Property::SIZE_SCALE_POLICY:
4164 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT );
4168 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
4170 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
4174 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
4176 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
4180 case Dali::Actor::Property::PADDING:
4182 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
4183 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
4184 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
4188 case Dali::Actor::Property::MINIMUM_SIZE:
4190 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
4194 case Dali::Actor::Property::MAXIMUM_SIZE:
4196 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
4200 case Dali::Actor::Property::CLIPPING_MODE:
4202 value = mClippingMode;
4206 case Dali::DevelActor::Property::SIBLING_ORDER:
4208 value = static_cast<int>( GetSiblingOrder() );
4212 case Dali::DevelActor::Property::SCREEN_POSITION:
4214 value = GetCurrentScreenPosition();
4218 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
4220 value = mPositionUsesAnchorPoint;
4224 case Dali::Actor::Property::LAYOUT_DIRECTION:
4226 value = mLayoutDirection;
4230 case Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION:
4232 value = IsLayoutDirectionInherited();
4238 // Must be a scene-graph only property
4247 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
4249 bool valueSet = true;
4253 case Dali::Actor::Property::SIZE:
4255 value = GetCurrentSize();
4259 case Dali::Actor::Property::SIZE_WIDTH:
4261 value = GetCurrentSize().width;
4265 case Dali::Actor::Property::SIZE_HEIGHT:
4267 value = GetCurrentSize().height;
4271 case Dali::Actor::Property::SIZE_DEPTH:
4273 value = GetCurrentSize().depth;
4277 case Dali::Actor::Property::POSITION:
4279 value = GetCurrentPosition();
4283 case Dali::Actor::Property::POSITION_X:
4285 value = GetCurrentPosition().x;
4289 case Dali::Actor::Property::POSITION_Y:
4291 value = GetCurrentPosition().y;
4295 case Dali::Actor::Property::POSITION_Z:
4297 value = GetCurrentPosition().z;
4301 case Dali::Actor::Property::WORLD_POSITION:
4303 value = GetCurrentWorldPosition();
4307 case Dali::Actor::Property::WORLD_POSITION_X:
4309 value = GetCurrentWorldPosition().x;
4313 case Dali::Actor::Property::WORLD_POSITION_Y:
4315 value = GetCurrentWorldPosition().y;
4319 case Dali::Actor::Property::WORLD_POSITION_Z:
4321 value = GetCurrentWorldPosition().z;
4325 case Dali::Actor::Property::ORIENTATION:
4327 value = GetCurrentOrientation();
4331 case Dali::Actor::Property::WORLD_ORIENTATION:
4333 value = GetCurrentWorldOrientation();
4337 case Dali::Actor::Property::SCALE:
4339 value = GetCurrentScale();
4343 case Dali::Actor::Property::SCALE_X:
4345 value = GetCurrentScale().x;
4349 case Dali::Actor::Property::SCALE_Y:
4351 value = GetCurrentScale().y;
4355 case Dali::Actor::Property::SCALE_Z:
4357 value = GetCurrentScale().z;
4361 case Dali::Actor::Property::WORLD_SCALE:
4363 value = GetCurrentWorldScale();
4367 case Dali::Actor::Property::COLOR:
4369 value = GetCurrentColor();
4373 case Dali::Actor::Property::COLOR_RED:
4375 value = GetCurrentColor().r;
4379 case Dali::Actor::Property::COLOR_GREEN:
4381 value = GetCurrentColor().g;
4385 case Dali::Actor::Property::COLOR_BLUE:
4387 value = GetCurrentColor().b;
4391 case Dali::Actor::Property::COLOR_ALPHA:
4392 case Dali::DevelActor::Property::OPACITY:
4394 value = GetCurrentColor().a;
4398 case Dali::Actor::Property::WORLD_COLOR:
4400 value = GetCurrentWorldColor();
4404 case Dali::Actor::Property::WORLD_MATRIX:
4406 value = GetCurrentWorldMatrix();
4410 case Dali::Actor::Property::VISIBLE:
4412 value = IsVisible();
4418 // Must be an event-side only property
4427 void Actor::EnsureRelayoutData()
4429 // Assign relayout data.
4430 if( !mRelayoutData )
4432 mRelayoutData = new RelayoutData();
4436 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
4438 // Check if actor is dependent on parent
4439 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4441 if( ( dimension & ( 1 << i ) ) )
4443 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4444 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
4454 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
4456 // Check if actor is dependent on children
4457 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4459 if( ( dimension & ( 1 << i ) ) )
4461 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4462 switch( resizePolicy )
4464 case ResizePolicy::FIT_TO_CHILDREN:
4465 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
4481 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
4483 return Actor::RelayoutDependentOnChildren( dimension );
4486 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
4488 // Check each possible dimension and see if it is dependent on the input one
4489 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4491 if( dimension & ( 1 << i ) )
4493 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
4500 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
4502 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4504 if( dimension & ( 1 << i ) )
4506 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
4511 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
4513 // If more than one dimension is requested, just return the first one found
4514 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4516 if( ( dimension & ( 1 << i ) ) )
4518 return mRelayoutData->negotiatedDimensions[ i ];
4522 return 0.0f; // Default
4525 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
4527 EnsureRelayoutData();
4529 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4531 if( dimension & ( 1 << i ) )
4533 mRelayoutData->dimensionPadding[ i ] = padding;
4538 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4540 if ( mRelayoutData )
4542 // If more than one dimension is requested, just return the first one found
4543 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4545 if( ( dimension & ( 1 << i ) ) )
4547 return mRelayoutData->dimensionPadding[ i ];
4552 return GetDefaultDimensionPadding();
4555 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4557 EnsureRelayoutData();
4559 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4561 if( dimension & ( 1 << i ) )
4563 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4568 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4570 if ( mRelayoutData )
4572 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4574 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4584 float Actor::GetHeightForWidthBase( float width )
4586 float height = 0.0f;
4588 const Vector3 naturalSize = GetNaturalSize();
4589 if( naturalSize.width > 0.0f )
4591 height = naturalSize.height * width / naturalSize.width;
4593 else // we treat 0 as 1:1 aspect ratio
4601 float Actor::GetWidthForHeightBase( float height )
4605 const Vector3 naturalSize = GetNaturalSize();
4606 if( naturalSize.height > 0.0f )
4608 width = naturalSize.width * height / naturalSize.height;
4610 else // we treat 0 as 1:1 aspect ratio
4618 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4620 // Fill to parent, taking size mode factor into account
4621 switch( child.GetResizePolicy( dimension ) )
4623 case ResizePolicy::FILL_TO_PARENT:
4625 return GetLatestSize( dimension );
4628 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4630 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4633 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4635 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4640 return GetLatestSize( dimension );
4645 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4647 // Can be overridden in derived class
4648 return CalculateChildSizeBase( child, dimension );
4651 float Actor::GetHeightForWidth( float width )
4653 // Can be overridden in derived class
4654 return GetHeightForWidthBase( width );
4657 float Actor::GetWidthForHeight( float height )
4659 // Can be overridden in derived class
4660 return GetWidthForHeightBase( height );
4663 float Actor::GetLatestSize( Dimension::Type dimension ) const
4665 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4668 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4670 Vector2 padding = GetPadding( dimension );
4672 return GetLatestSize( dimension ) + padding.x + padding.y;
4675 float Actor::NegotiateFromParent( Dimension::Type dimension )
4677 Actor* parent = GetParent();
4680 Vector2 padding( GetPadding( dimension ) );
4681 Vector2 parentPadding( parent->GetPadding( dimension ) );
4682 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4688 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4690 float maxDimensionPoint = 0.0f;
4692 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4694 ActorPtr child = GetChildAt( i );
4696 if( !child->RelayoutDependentOnParent( dimension ) )
4698 // Calculate the min and max points that the children range across
4699 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
4700 float dimensionSize = child->GetRelayoutSize( dimension );
4701 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4705 return maxDimensionPoint;
4708 float Actor::GetSize( Dimension::Type dimension ) const
4710 return GetDimensionValue( mTargetSize, dimension );
4713 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4715 return GetDimensionValue( GetNaturalSize(), dimension );
4718 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4720 switch( GetResizePolicy( dimension ) )
4722 case ResizePolicy::USE_NATURAL_SIZE:
4724 return GetNaturalSize( dimension );
4727 case ResizePolicy::FIXED:
4729 return GetDimensionValue( GetPreferredSize(), dimension );
4732 case ResizePolicy::USE_ASSIGNED_SIZE:
4734 return GetDimensionValue( maximumSize, dimension );
4737 case ResizePolicy::FILL_TO_PARENT:
4738 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4739 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4741 return NegotiateFromParent( dimension );
4744 case ResizePolicy::FIT_TO_CHILDREN:
4746 return NegotiateFromChildren( dimension );
4749 case ResizePolicy::DIMENSION_DEPENDENCY:
4751 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4754 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4756 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4759 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4761 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4773 return 0.0f; // Default
4776 float Actor::ClampDimension( float size, Dimension::Type dimension )
4778 const float minSize = GetMinimumSize( dimension );
4779 const float maxSize = GetMaximumSize( dimension );
4781 return std::max( minSize, std::min( size, maxSize ) );
4784 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4786 // Check if it needs to be negotiated
4787 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4789 // Check that we havn't gotten into an infinite loop
4790 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4791 bool recursionFound = false;
4792 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4794 if( *it == searchActor )
4796 recursionFound = true;
4801 if( !recursionFound )
4803 // Record the path that we have taken
4804 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4806 // Dimension dependency check
4807 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4809 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4811 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4813 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4817 // Parent dependency check
4818 Actor* parent = GetParent();
4819 if( parent && RelayoutDependentOnParent( dimension ) )
4821 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4824 // Children dependency check
4825 if( RelayoutDependentOnChildren( dimension ) )
4827 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
4829 ActorPtr child = GetChildAt( i );
4831 // Only relayout child first if it is not dependent on this actor
4832 if( !child->RelayoutDependentOnParent( dimension ) )
4834 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
4839 // For deriving classes
4840 OnCalculateRelayoutSize( dimension );
4842 // All dependencies checked, calculate the size and set negotiated flag
4843 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4845 SetNegotiatedDimension( newSize, dimension );
4846 SetLayoutNegotiated( true, dimension );
4848 // For deriving classes
4849 OnLayoutNegotiated( newSize, dimension );
4851 // This actor has been successfully processed, pop it off the recursion stack
4852 recursionStack.pop_back();
4856 // TODO: Break infinite loop
4857 SetLayoutNegotiated( true, dimension );
4862 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4864 // Negotiate all dimensions that require it
4865 ActorDimensionStack recursionStack;
4867 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4869 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4872 NegotiateDimension( dimension, allocatedSize, recursionStack );
4876 Vector2 Actor::ApplySizeSetPolicy( const Vector2& size )
4878 switch( mRelayoutData->sizeSetPolicy )
4880 case SizeScalePolicy::USE_SIZE_SET:
4885 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4887 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4888 const Vector3 naturalSize = GetNaturalSize();
4889 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4891 const float sizeRatio = size.width / size.height;
4892 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4894 if( naturalSizeRatio < sizeRatio )
4896 return Vector2( naturalSizeRatio * size.height, size.height );
4898 else if( naturalSizeRatio > sizeRatio )
4900 return Vector2( size.width, size.width / naturalSizeRatio );
4911 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4913 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4914 const Vector3 naturalSize = GetNaturalSize();
4915 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4917 const float sizeRatio = size.width / size.height;
4918 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4920 if( naturalSizeRatio < sizeRatio )
4922 return Vector2( size.width, size.width / naturalSizeRatio );
4924 else if( naturalSizeRatio > sizeRatio )
4926 return Vector2( naturalSizeRatio * size.height, size.height );
4945 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4947 // Do the set actor size
4948 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4950 // Adjust for size set policy
4951 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4953 // Lock the flag to stop recursive relayouts on set size
4954 mRelayoutData->insideRelayout = true;
4955 SetSize( negotiatedSize );
4956 mRelayoutData->insideRelayout = false;
4958 // Clear flags for all dimensions
4959 SetLayoutDirty( false );
4961 // Give deriving classes a chance to respond
4962 OnRelayout( negotiatedSize, container );
4964 if( !mOnRelayoutSignal.Empty() )
4966 Dali::Actor handle( this );
4967 mOnRelayoutSignal.Emit( handle );
4971 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4973 // Force a size negotiation for actors that has assigned size during relayout
4974 // This is required as otherwise the flags that force a relayout will not
4975 // necessarilly be set. This will occur if the actor has already been laid out.
4976 // The dirty flags are then cleared. Then if the actor is added back into the
4977 // relayout container afterwards, the dirty flags would still be clear...
4978 // causing a relayout to be skipped. Here we force any actors added to the
4979 // container to be relayed out.
4980 DALI_LOG_TIMER_START( NegSizeTimer1 );
4982 if( GetUseAssignedSize(Dimension::WIDTH ) )
4984 SetLayoutNegotiated( false, Dimension::WIDTH );
4986 if( GetUseAssignedSize( Dimension::HEIGHT ) )
4988 SetLayoutNegotiated( false, Dimension::HEIGHT );
4991 // Do the negotiation
4992 NegotiateDimensions( allocatedSize );
4994 // Set the actor size
4995 SetNegotiatedSize( container );
4997 // Negotiate down to children
4998 for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
5000 ActorPtr child = GetChildAt( i );
5002 // Forces children that have already been laid out to be relayed out
5003 // if they have assigned size during relayout.
5004 if( child->GetUseAssignedSize(Dimension::WIDTH) )
5006 child->SetLayoutNegotiated(false, Dimension::WIDTH);
5007 child->SetLayoutDirty(true, Dimension::WIDTH);
5010 if( child->GetUseAssignedSize(Dimension::HEIGHT) )
5012 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
5013 child->SetLayoutDirty(true, Dimension::HEIGHT);
5016 // Only relayout if required
5017 if( child->RelayoutRequired() )
5019 container.Add( Dali::Actor( child.Get() ), mTargetSize.GetVectorXY() );
5022 DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
5025 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
5029 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5031 if( dimension & ( 1 << i ) )
5033 mRelayoutData->useAssignedSize[ i ] = use;
5039 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
5041 if ( mRelayoutData )
5043 // If more than one dimension is requested, just return the first one found
5044 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5046 if( dimension & ( 1 << i ) )
5048 return mRelayoutData->useAssignedSize[ i ];
5056 void Actor::RelayoutRequest( Dimension::Type dimension )
5058 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
5059 if( relayoutController )
5061 Dali::Actor self( this );
5062 relayoutController->RequestRelayout( self, dimension );
5066 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
5070 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
5074 void Actor::SetPreferredSize( const Vector2& size )
5076 EnsureRelayoutData();
5078 if( size.width > 0.0f )
5080 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
5083 if( size.height > 0.0f )
5085 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
5088 mRelayoutData->preferredSize = size;
5093 Vector2 Actor::GetPreferredSize() const
5095 if ( mRelayoutData )
5097 return Vector2( mRelayoutData->preferredSize );
5100 return GetDefaultPreferredSize();
5103 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
5105 EnsureRelayoutData();
5107 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5109 if( dimension & ( 1 << i ) )
5111 mRelayoutData->minimumSize[ i ] = size;
5118 float Actor::GetMinimumSize( Dimension::Type dimension ) const
5120 if ( mRelayoutData )
5122 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5124 if( dimension & ( 1 << i ) )
5126 return mRelayoutData->minimumSize[ i ];
5131 return 0.0f; // Default
5134 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
5136 EnsureRelayoutData();
5138 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5140 if( dimension & ( 1 << i ) )
5142 mRelayoutData->maximumSize[ i ] = size;
5149 float Actor::GetMaximumSize( Dimension::Type dimension ) const
5151 if ( mRelayoutData )
5153 for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5155 if( dimension & ( 1 << i ) )
5157 return mRelayoutData->maximumSize[ i ];
5162 return FLT_MAX; // Default
5165 Object* Actor::GetParentObject() const
5170 void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
5172 if( mVisible != visible )
5174 if( sendMessage == SendMessage::TRUE && NULL != mNode )
5176 // mNode is being used in a separate thread; queue a message to set the value & base value
5177 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
5182 // Emit the signal on this actor and all its children
5183 EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
5187 void Actor::SetSiblingOrder( unsigned int order )
5191 ActorContainer& siblings = *(mParent->mChildren);
5192 unsigned int currentOrder = GetSiblingOrder();
5194 if( order != currentOrder )
5200 else if( order < siblings.size() -1 )
5202 if( order > currentOrder )
5204 RaiseAbove( *siblings[order] );
5208 LowerBelow( *siblings[order] );
5219 unsigned int Actor::GetSiblingOrder() const
5221 unsigned int order = 0;
5225 ActorContainer& siblings = *(mParent->mChildren);
5226 for( size_t i=0; i<siblings.size(); ++i )
5228 if( siblings[i] == this )
5239 void Actor::RequestRebuildDepthTree()
5243 StagePtr stage = Stage::GetCurrent();
5246 stage->RequestRebuildDepthTree();
5255 ActorContainer& siblings = *(mParent->mChildren);
5256 if( siblings.back() != this ) // If not already at end
5258 for( size_t i=0; i<siblings.size(); ++i )
5260 if( siblings[i] == this )
5263 ActorPtr next = siblings[i+1];
5264 siblings[i+1] = this;
5271 Dali::Actor handle( this );
5272 mParent->mChildOrderChangedSignal.Emit( handle );
5274 RequestRebuildDepthTree();
5278 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5286 ActorContainer& siblings = *(mParent->mChildren);
5287 if( siblings.front() != this ) // If not already at beginning
5289 for( size_t i=1; i<siblings.size(); ++i )
5291 if( siblings[i] == this )
5293 // Swap with previous
5294 ActorPtr previous = siblings[i-1];
5295 siblings[i-1] = this;
5296 siblings[i] = previous;
5302 Dali::Actor handle( this );
5303 mParent->mChildOrderChangedSignal.Emit( handle );
5305 RequestRebuildDepthTree();
5309 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5313 void Actor::RaiseToTop()
5317 ActorContainer& siblings = *(mParent->mChildren);
5318 if( siblings.back() != this ) // If not already at end
5320 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
5321 if( iter != siblings.end() )
5323 siblings.erase(iter);
5324 siblings.push_back(ActorPtr(this));
5328 Dali::Actor handle( this );
5329 mParent->mChildOrderChangedSignal.Emit( handle );
5331 RequestRebuildDepthTree();
5335 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5339 void Actor::LowerToBottom()
5343 ActorContainer& siblings = *(mParent->mChildren);
5344 if( siblings.front() != this ) // If not already at bottom,
5346 ActorPtr thisPtr(this); // ensure this actor remains referenced.
5348 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
5349 if( iter != siblings.end() )
5351 siblings.erase(iter);
5352 siblings.insert(siblings.begin(), thisPtr);
5356 Dali::Actor handle( this );
5357 mParent->mChildOrderChangedSignal.Emit( handle );
5359 RequestRebuildDepthTree();
5363 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5367 void Actor::RaiseAbove( Internal::Actor& target )
5371 ActorContainer& siblings = *(mParent->mChildren);
5372 if( siblings.back() != this && target.mParent == mParent ) // If not already at top
5374 ActorPtr thisPtr(this); // ensure this actor remains referenced.
5376 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
5377 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
5378 if( thisIter < targetIter )
5380 siblings.erase(thisIter);
5381 // Erasing early invalidates the targetIter. (Conversely, inserting first may also
5382 // invalidate thisIter)
5383 targetIter = std::find( siblings.begin(), siblings.end(), &target );
5385 siblings.insert(targetIter, thisPtr);
5388 Dali::Actor handle( this );
5389 mParent->mChildOrderChangedSignal.Emit( handle );
5391 RequestRebuildDepthTree();
5396 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5400 void Actor::LowerBelow( Internal::Actor& target )
5404 ActorContainer& siblings = *(mParent->mChildren);
5405 if( siblings.front() != this && target.mParent == mParent ) // If not already at bottom
5407 ActorPtr thisPtr(this); // ensure this actor remains referenced.
5409 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
5410 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
5412 if( thisIter > targetIter )
5414 siblings.erase(thisIter); // this only invalidates iterators at or after this point.
5415 siblings.insert(targetIter, thisPtr);
5418 Dali::Actor handle( this );
5419 mParent->mChildOrderChangedSignal.Emit( handle );
5421 RequestRebuildDepthTree();
5426 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5430 void Actor::SetInheritLayoutDirection( bool inherit )
5432 if( mInheritLayoutDirection != inherit )
5434 mInheritLayoutDirection = inherit;
5436 if( inherit && mParent )
5438 InheritLayoutDirectionRecursively( this, mParent->mLayoutDirection );
5443 bool Actor::IsLayoutDirectionInherited() const
5445 return mInheritLayoutDirection;
5448 void Actor::InheritLayoutDirectionRecursively( ActorPtr actor, Dali::LayoutDirection::Type direction, bool set )
5450 if( actor && ( actor->mInheritLayoutDirection || set ) )
5452 if( actor->mLayoutDirection != direction)
5454 actor->mLayoutDirection = direction;
5455 actor->EmitLayoutDirectionChangedSignal( direction );
5456 actor->RelayoutRequest();
5459 if( actor->GetChildCount() > 0 )
5461 ActorContainer& children = actor->GetChildrenInternal();
5462 for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter )
5464 InheritLayoutDirectionRecursively( *iter, direction );
5470 } // namespace Internal