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 uint32_t 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( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
108 resizePolicies[ i ] = ResizePolicy::DEFAULT;
109 useAssignedSize[ i ] = false;
110 negotiatedDimensions[ i ] = 0.0f;
111 dimensionNegotiated[ i ] = false;
112 dimensionDirty[ i ] = false;
113 dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
114 dimensionPadding[ i ] = GetDefaultDimensionPadding();
115 minimumSize[ i ] = 0.0f;
116 maximumSize[ i ] = FLT_MAX;
120 ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies
121 bool useAssignedSize[ Dimension::DIMENSION_COUNT ]; ///< The flag to specify whether the size should be assigned to the actor
123 Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies
125 Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
127 float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor
129 float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be
130 float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be
132 bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated
133 bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not
135 Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes
137 Vector2 preferredSize; ///< The preferred size of the actor
139 SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum
141 bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
142 bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set
145 namespace // unnamed namespace
151 * We want to discourage the use of property strings (minimize string comparisons),
152 * particularly for the default properties.
153 * Name Type writable animatable constraint-input enum for index-checking
155 DALI_PROPERTY_TABLE_BEGIN
156 DALI_PROPERTY( "parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
157 DALI_PROPERTY( "parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
158 DALI_PROPERTY( "parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
159 DALI_PROPERTY( "parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
160 DALI_PROPERTY( "anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
161 DALI_PROPERTY( "anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
162 DALI_PROPERTY( "anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
163 DALI_PROPERTY( "anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
164 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
165 DALI_PROPERTY( "sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
166 DALI_PROPERTY( "sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
167 DALI_PROPERTY( "sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
168 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
169 DALI_PROPERTY( "positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
170 DALI_PROPERTY( "positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
171 DALI_PROPERTY( "positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
172 DALI_PROPERTY( "worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
173 DALI_PROPERTY( "worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
174 DALI_PROPERTY( "worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
175 DALI_PROPERTY( "worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
176 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
177 DALI_PROPERTY( "worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
178 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
179 DALI_PROPERTY( "scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
180 DALI_PROPERTY( "scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
181 DALI_PROPERTY( "scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
182 DALI_PROPERTY( "worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
183 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
184 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
185 DALI_PROPERTY( "colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
186 DALI_PROPERTY( "colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
187 DALI_PROPERTY( "colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
188 DALI_PROPERTY( "colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
189 DALI_PROPERTY( "worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
190 DALI_PROPERTY( "worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
191 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
192 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
193 DALI_PROPERTY( "leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
194 DALI_PROPERTY( "inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
195 DALI_PROPERTY( "inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
196 DALI_PROPERTY( "colorMode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE )
197 DALI_PROPERTY( "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( "culled", BOOLEAN, false, false, true, Dali::DevelActor::Property::CULLED )
217 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
221 const char* const SIGNAL_TOUCHED = "touched";
222 const char* const SIGNAL_HOVERED = "hovered";
223 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
224 const char* const SIGNAL_ON_STAGE = "onStage";
225 const char* const SIGNAL_OFF_STAGE = "offStage";
226 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
227 const char* const SIGNAL_TOUCH = "touch";
228 const char* const SIGNAL_VISIBILITY_CHANGED = "visibilityChanged";
229 const char* const SIGNAL_LAYOUT_DIRECTION_CHANGED = "layoutDirectionChanged";
230 const char* const SIGNAL_CHILD_ADDED = "childAdded";
231 const char* const SIGNAL_CHILD_REMOVED = "childRemoved";
235 const char* const ACTION_SHOW = "show";
236 const char* const ACTION_HIDE = "hide";
238 BaseHandle CreateActor()
240 return Dali::Actor::New();
243 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
245 SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
246 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
247 SignalConnectorType signalConnector3( mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal );
248 SignalConnectorType signalConnector4( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
249 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
250 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
251 SignalConnectorType signalConnector7( mType, SIGNAL_TOUCH, &Actor::DoConnectSignal );
252 SignalConnectorType signalConnector8( mType, SIGNAL_VISIBILITY_CHANGED, &Actor::DoConnectSignal );
253 SignalConnectorType signalConnector9( mType, SIGNAL_LAYOUT_DIRECTION_CHANGED, &Actor::DoConnectSignal );
254 SignalConnectorType signalConnector10( mType, SIGNAL_CHILD_ADDED, &Actor::DoConnectSignal );
255 SignalConnectorType signalConnector11( mType, SIGNAL_CHILD_REMOVED, &Actor::DoConnectSignal );
257 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
258 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
263 const Vector3& value;
266 DALI_ENUM_TO_STRING_TABLE_BEGIN_WITH_TYPE( AnchorValue, ANCHOR_CONSTANT )
267 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_LEFT )
268 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_CENTER )
269 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, TOP_RIGHT )
270 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_LEFT )
271 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER )
272 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, CENTER_RIGHT )
273 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_LEFT )
274 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_CENTER )
275 DALI_ENUM_TO_STRING_WITH_SCOPE( AnchorPoint, BOTTOM_RIGHT )
276 DALI_ENUM_TO_STRING_TABLE_END( ANCHOR_CONSTANT )
278 DALI_ENUM_TO_STRING_TABLE_BEGIN( COLOR_MODE )
279 DALI_ENUM_TO_STRING( USE_OWN_COLOR )
280 DALI_ENUM_TO_STRING( USE_PARENT_COLOR )
281 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_COLOR )
282 DALI_ENUM_TO_STRING( USE_OWN_MULTIPLY_PARENT_ALPHA )
283 DALI_ENUM_TO_STRING_TABLE_END( COLOR_MODE )
285 DALI_ENUM_TO_STRING_TABLE_BEGIN( POSITION_INHERITANCE_MODE )
286 DALI_ENUM_TO_STRING( INHERIT_PARENT_POSITION )
287 DALI_ENUM_TO_STRING( USE_PARENT_POSITION )
288 DALI_ENUM_TO_STRING( USE_PARENT_POSITION_PLUS_LOCAL_POSITION )
289 DALI_ENUM_TO_STRING( DONT_INHERIT_POSITION )
290 DALI_ENUM_TO_STRING_TABLE_END( POSITION_INHERITANCE_MODE )
292 DALI_ENUM_TO_STRING_TABLE_BEGIN( DRAW_MODE )
293 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, NORMAL )
294 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, OVERLAY_2D )
295 DALI_ENUM_TO_STRING_WITH_SCOPE( DrawMode, STENCIL )
296 DALI_ENUM_TO_STRING_TABLE_END( DRAW_MODE )
298 DALI_ENUM_TO_STRING_TABLE_BEGIN( RESIZE_POLICY )
299 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIXED )
300 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_NATURAL_SIZE )
301 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FILL_TO_PARENT )
302 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_RELATIVE_TO_PARENT )
303 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, SIZE_FIXED_OFFSET_FROM_PARENT )
304 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, FIT_TO_CHILDREN )
305 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, DIMENSION_DEPENDENCY )
306 DALI_ENUM_TO_STRING_WITH_SCOPE( ResizePolicy, USE_ASSIGNED_SIZE )
307 DALI_ENUM_TO_STRING_TABLE_END( RESIZE_POLICY )
309 DALI_ENUM_TO_STRING_TABLE_BEGIN( SIZE_SCALE_POLICY )
310 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, USE_SIZE_SET )
311 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FIT_WITH_ASPECT_RATIO )
312 DALI_ENUM_TO_STRING_WITH_SCOPE( SizeScalePolicy, FILL_WITH_ASPECT_RATIO )
313 DALI_ENUM_TO_STRING_TABLE_END( SIZE_SCALE_POLICY )
315 DALI_ENUM_TO_STRING_TABLE_BEGIN( CLIPPING_MODE )
316 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, DISABLED )
317 DALI_ENUM_TO_STRING_WITH_SCOPE( ClippingMode, CLIP_CHILDREN )
318 DALI_ENUM_TO_STRING_TABLE_END( CLIPPING_MODE )
320 DALI_ENUM_TO_STRING_TABLE_BEGIN( LAYOUT_DIRECTION )
321 DALI_ENUM_TO_STRING_WITH_SCOPE( LayoutDirection, LEFT_TO_RIGHT )
322 DALI_ENUM_TO_STRING_WITH_SCOPE( LayoutDirection, RIGHT_TO_LEFT )
323 DALI_ENUM_TO_STRING_TABLE_END( LAYOUT_DIRECTION )
325 bool GetAnchorPointConstant( const std::string& value, Vector3& anchor )
327 for( uint32_t i = 0; i < ANCHOR_CONSTANT_TABLE_COUNT; ++i )
329 uint32_t sizeIgnored = 0;
330 if( CompareTokens( value.c_str(), ANCHOR_CONSTANT_TABLE[ i ].name, sizeIgnored ) )
332 anchor = ANCHOR_CONSTANT_TABLE[ i ].value;
339 inline bool GetParentOriginConstant( const std::string& value, Vector3& parentOrigin )
341 // Values are the same so just use the same table as anchor-point
342 return GetAnchorPointConstant( value, parentOrigin );
346 * @brief Extract a given dimension from a Vector2
348 * @param[in] values The values to extract from
349 * @param[in] dimension The dimension to extract
350 * @return Return the value for the dimension
352 float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
356 case Dimension::WIDTH:
360 case Dimension::HEIGHT:
362 return values.height;
373 * @brief Extract a given dimension from a Vector3
375 * @param[in] values The values to extract from
376 * @param[in] dimension The dimension to extract
377 * @return Return the value for the dimension
379 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
381 return GetDimensionValue( values.GetVectorXY(), dimension );
385 * @brief Recursively emits the visibility-changed-signal on the actor tree.
386 * @param[in] actor The actor to emit the signal on
387 * @param[in] visible The new visibility of the actor
388 * @param[in] type Whether the actor's visible property has changed or a parent's
390 void EmitVisibilityChangedSignalRecursively( ActorPtr actor, bool visible, DevelActor::VisibilityChange::Type type )
394 actor->EmitVisibilityChangedSignal( visible, type );
396 if( actor->GetChildCount() > 0 )
398 ActorContainer& children = actor->GetChildrenInternal();
399 for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter )
401 EmitVisibilityChangedSignalRecursively( *iter, visible, DevelActor::VisibilityChange::PARENT );
407 } // unnamed namespace
409 ActorPtr Actor::New()
411 ActorPtr actor( new Actor( BASIC ) );
413 // Second-phase construction
419 const std::string& Actor::GetName() const
424 void Actor::SetName( const std::string& name )
430 // ATTENTION: string for debug purposes is not thread safe.
431 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
435 uint32_t Actor::GetId() const
440 bool Actor::OnStage() const
445 Dali::Layer Actor::GetLayer()
449 // Short-circuit for Layer derived actors
452 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
455 // Find the immediate Layer parent
456 for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
458 if( parent->IsLayer() )
460 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
467 void Actor::Add( Actor& child )
469 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
470 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
474 mChildren = new ActorContainer;
477 Actor* const oldParent( child.mParent );
479 // child might already be ours
480 if( this != oldParent )
482 // if we already have parent, unparent us first
485 oldParent->Remove( child ); // This causes OnChildRemove callback & ChildRemoved signal
487 // Old parent may need to readjust to missing child
488 if( oldParent->RelayoutDependentOnChildren() )
490 oldParent->RelayoutRequest();
494 // Guard against Add() during previous OnChildRemove callback
497 // Do this first, since user callbacks from within SetParent() may need to remove child
498 mChildren->push_back( ActorPtr( &child ) );
500 // SetParent asserts that child can be added
501 child.SetParent( this );
503 // Notification for derived classes
505 EmitChildAddedSignal( child );
507 InheritLayoutDirectionRecursively( ActorPtr( &child ), mLayoutDirection );
509 // Only put in a relayout request if there is a suitable dependency
510 if( RelayoutDependentOnChildren() )
518 void Actor::Remove( Actor& child )
520 if( (this == &child) || (!mChildren) )
522 // no children or removing itself
528 // Find the child in mChildren, and unparent it
529 ActorIter end = mChildren->end();
530 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
532 ActorPtr actor = (*iter);
534 if( actor.Get() == &child )
536 // Keep handle for OnChildRemove notification
539 // Do this first, since user callbacks from within SetParent() may need to add the child
540 mChildren->erase( iter );
542 DALI_ASSERT_DEBUG( actor->GetParent() == this );
543 actor->SetParent( NULL );
551 // Only put in a relayout request if there is a suitable dependency
552 if( RelayoutDependentOnChildren() )
558 // Notification for derived classes
559 OnChildRemove( child );
560 EmitChildRemovedSignal( child );
563 void Actor::Unparent()
567 // Remove this actor from the parent. The remove will put a relayout request in for
568 // the parent if required
569 mParent->Remove( *this );
570 // mParent is now NULL!
574 uint32_t Actor::GetChildCount() const
576 return ( NULL != mChildren ) ? static_cast<uint32_t>( mChildren->size() ) : 0; // only 4,294,967,295 children per actor
579 ActorPtr Actor::GetChildAt( uint32_t index ) const
581 DALI_ASSERT_ALWAYS( index < GetChildCount() );
583 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
586 ActorPtr Actor::FindChildByName( const std::string& actorName )
589 if( actorName == mName )
595 ActorIter end = mChildren->end();
596 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
598 child = (*iter)->FindChildByName( actorName );
609 ActorPtr Actor::FindChildById( const uint32_t id )
618 ActorIter end = mChildren->end();
619 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
621 child = (*iter)->FindChildById( id );
632 void Actor::SetParentOrigin( const Vector3& origin )
636 // mNode is being used in a separate thread; queue a message to set the value & base value
637 SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
640 // Cache for event-thread access
643 // not allocated, check if different from default
644 if( ParentOrigin::DEFAULT != origin )
646 mParentOrigin = new Vector3( origin );
651 // check if different from current costs more than just set
652 *mParentOrigin = origin;
656 void Actor::SetParentOriginX( float x )
658 const Vector3& current = GetCurrentParentOrigin();
660 SetParentOrigin( Vector3( x, current.y, current.z ) );
663 void Actor::SetParentOriginY( float y )
665 const Vector3& current = GetCurrentParentOrigin();
667 SetParentOrigin( Vector3( current.x, y, current.z ) );
670 void Actor::SetParentOriginZ( float z )
672 const Vector3& current = GetCurrentParentOrigin();
674 SetParentOrigin( Vector3( current.x, current.y, z ) );
677 const Vector3& Actor::GetCurrentParentOrigin() const
679 // Cached for event-thread access
680 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
683 void Actor::SetAnchorPoint( const Vector3& anchor )
687 // mNode is being used in a separate thread; queue a message to set the value & base value
688 SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
691 // Cache for event-thread access
694 // not allocated, check if different from default
695 if( AnchorPoint::DEFAULT != anchor )
697 mAnchorPoint = new Vector3( anchor );
702 // check if different from current costs more than just set
703 *mAnchorPoint = anchor;
707 void Actor::SetAnchorPointX( float x )
709 const Vector3& current = GetCurrentAnchorPoint();
711 SetAnchorPoint( Vector3( x, current.y, current.z ) );
714 void Actor::SetAnchorPointY( float y )
716 const Vector3& current = GetCurrentAnchorPoint();
718 SetAnchorPoint( Vector3( current.x, y, current.z ) );
721 void Actor::SetAnchorPointZ( float z )
723 const Vector3& current = GetCurrentAnchorPoint();
725 SetAnchorPoint( Vector3( current.x, current.y, z ) );
728 const Vector3& Actor::GetCurrentAnchorPoint() const
730 // Cached for event-thread access
731 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
734 void Actor::SetPosition( float x, float y )
736 SetPosition( Vector3( x, y, 0.0f ) );
739 void Actor::SetPosition( float x, float y, float z )
741 SetPosition( Vector3( x, y, z ) );
744 void Actor::SetPosition( const Vector3& position )
746 mTargetPosition = position;
750 // mNode is being used in a separate thread; queue a message to set the value & base value
751 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
755 void Actor::SetX( float x )
757 mTargetPosition.x = x;
761 // mNode is being used in a separate thread; queue a message to set the value & base value
762 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
766 void Actor::SetY( float y )
768 mTargetPosition.y = y;
772 // mNode is being used in a separate thread; queue a message to set the value & base value
773 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
777 void Actor::SetZ( float z )
779 mTargetPosition.z = z;
783 // mNode is being used in a separate thread; queue a message to set the value & base value
784 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
788 void Actor::TranslateBy( const Vector3& distance )
790 mTargetPosition += distance;
794 // mNode is being used in a separate thread; queue a message to set the value & base value
795 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
799 const Vector3& Actor::GetCurrentPosition() const
803 // mNode is being used in a separate thread; copy the value from the previous update
804 return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
807 return Vector3::ZERO;
810 const Vector3& Actor::GetTargetPosition() const
812 return mTargetPosition;
815 const Vector3& Actor::GetCurrentWorldPosition() const
819 // mNode is being used in a separate thread; copy the value from the previous update
820 return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
823 return Vector3::ZERO;
826 const Vector2 Actor::GetCurrentScreenPosition() const
828 StagePtr stage = Stage::GetCurrent();
829 if( stage && OnStage() && NULL != mNode )
831 Vector3 worldPosition = mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
832 Vector3 cameraPosition = stage->GetDefaultCameraActor().mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
833 worldPosition -= cameraPosition;
835 Vector3 actorSize = GetCurrentSize() * GetCurrentWorldScale();
836 Vector2 halfStageSize( stage->GetSize() * 0.5f ); // World position origin is center of stage
837 Vector3 halfActorSize( actorSize * 0.5f );
838 Vector3 anchorPointOffSet = halfActorSize - actorSize * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
840 return Vector2( halfStageSize.width + worldPosition.x - anchorPointOffSet.x,
841 halfStageSize.height + worldPosition.y - anchorPointOffSet.y );
844 return Vector2::ZERO;
847 void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
849 // this flag is not animatable so keep the value
850 mPositionInheritanceMode = mode;
853 // mNode is being used in a separate thread; queue a message to set the value
854 SetInheritPositionMessage( GetEventThreadServices(), *mNode, mode == INHERIT_PARENT_POSITION );
858 PositionInheritanceMode Actor::GetPositionInheritanceMode() const
860 // Cached for event-thread access
861 return mPositionInheritanceMode;
864 void Actor::SetInheritPosition( bool inherit )
866 if( mInheritPosition != inherit && NULL != mNode )
868 // non animateable so keep local copy
869 mInheritPosition = inherit;
870 SetInheritPositionMessage( GetEventThreadServices(), *mNode, inherit );
874 bool Actor::IsPositionInherited() const
876 return mInheritPosition;
879 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
881 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
882 normalizedAxis.Normalize();
884 Quaternion orientation( angle, normalizedAxis );
886 SetOrientation( orientation );
889 void Actor::SetOrientation( const Quaternion& orientation )
891 mTargetOrientation = orientation;
895 // mNode is being used in a separate thread; queue a message to set the value & base value
896 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation );
900 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
902 RotateBy( Quaternion(angle, axis) );
905 void Actor::RotateBy( const Quaternion& relativeRotation )
907 mTargetOrientation *= Quaternion( relativeRotation );
911 // mNode is being used in a separate thread; queue a message to set the value & base value
912 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
916 const Quaternion& Actor::GetCurrentOrientation() const
920 // mNode is being used in a separate thread; copy the value from the previous update
921 return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
924 return Quaternion::IDENTITY;
927 const Quaternion& Actor::GetCurrentWorldOrientation() const
931 // mNode is being used in a separate thread; copy the value from the previous update
932 return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
935 return Quaternion::IDENTITY;
938 void Actor::SetScale( float scale )
940 SetScale( Vector3( scale, scale, scale ) );
943 void Actor::SetScale( float x, float y, float z )
945 SetScale( Vector3( x, y, z ) );
948 void Actor::SetScale( const Vector3& scale )
950 mTargetScale = scale;
954 // mNode is being used in a separate thread; queue a message to set the value & base value
955 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
959 void Actor::SetScaleX( float x )
965 // mNode is being used in a separate thread; queue a message to set the value & base value
966 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
970 void Actor::SetScaleY( float y )
976 // mNode is being used in a separate thread; queue a message to set the value & base value
977 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
981 void Actor::SetScaleZ( float z )
987 // mNode is being used in a separate thread; queue a message to set the value & base value
988 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
992 void Actor::ScaleBy(const Vector3& relativeScale)
994 mTargetScale *= relativeScale;
998 // mNode is being used in a separate thread; queue a message to set the value & base value
999 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
1003 const Vector3& Actor::GetCurrentScale() const
1007 // mNode is being used in a separate thread; copy the value from the previous update
1008 return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
1011 return Vector3::ONE;
1014 const Vector3& Actor::GetCurrentWorldScale() const
1018 // mNode is being used in a separate thread; copy the value from the previous update
1019 return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
1022 return Vector3::ONE;
1025 void Actor::SetInheritScale( bool inherit )
1028 if( mInheritScale != inherit && NULL != mNode )
1030 // non animateable so keep local copy
1031 mInheritScale = inherit;
1032 // mNode is being used in a separate thread; queue a message to set the value
1033 SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
1037 bool Actor::IsScaleInherited() const
1039 return mInheritScale;
1042 Matrix Actor::GetCurrentWorldMatrix() const
1046 return mNode->GetWorldMatrix(0);
1049 return Matrix::IDENTITY;
1052 void Actor::SetVisible( bool visible )
1054 SetVisibleInternal( visible, SendMessage::TRUE );
1057 bool Actor::IsVisible() const
1061 // mNode is being used in a separate thread; copy the value from the previous update
1062 return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
1068 void Actor::SetOpacity( float opacity )
1070 mTargetColor.a = opacity;
1074 // mNode is being used in a separate thread; queue a message to set the value & base value
1075 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
1079 float Actor::GetCurrentOpacity() const
1083 // mNode is being used in a separate thread; copy the value from the previous update
1084 return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
1090 ClippingMode::Type Actor::GetClippingMode() const
1092 return mClippingMode;
1095 uint32_t Actor::GetSortingDepth()
1097 return mSortedDepth;
1100 const Vector4& Actor::GetCurrentWorldColor() const
1104 return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
1107 return Color::WHITE;
1110 void Actor::SetColor( const Vector4& color )
1112 mTargetColor = color;
1116 // mNode is being used in a separate thread; queue a message to set the value & base value
1117 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
1121 void Actor::SetColorRed( float red )
1123 mTargetColor.r = red;
1127 // mNode is being used in a separate thread; queue a message to set the value & base value
1128 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
1132 void Actor::SetColorGreen( float green )
1134 mTargetColor.g = green;
1138 // mNode is being used in a separate thread; queue a message to set the value & base value
1139 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
1143 void Actor::SetColorBlue( float blue )
1145 mTargetColor.b = blue;
1149 // mNode is being used in a separate thread; queue a message to set the value & base value
1150 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
1154 const Vector4& Actor::GetCurrentColor() const
1158 // mNode is being used in a separate thread; copy the value from the previous update
1159 return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
1162 return Color::WHITE;
1165 void Actor::SetInheritOrientation( bool inherit )
1167 if( mInheritOrientation != inherit && NULL != mNode)
1169 // non animateable so keep local copy
1170 mInheritOrientation = inherit;
1171 // mNode is being used in a separate thread; queue a message to set the value
1172 SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
1176 bool Actor::IsOrientationInherited() const
1178 return mInheritOrientation;
1181 void Actor::SetSizeModeFactor( const Vector3& factor )
1183 EnsureRelayoutData();
1185 mRelayoutData->sizeModeFactor = factor;
1188 const Vector3& Actor::GetSizeModeFactor() const
1190 if ( mRelayoutData )
1192 return mRelayoutData->sizeModeFactor;
1195 return GetDefaultSizeModeFactor();
1198 void Actor::SetColorMode( ColorMode colorMode )
1200 // non animateable so keep local copy
1201 mColorMode = colorMode;
1204 // mNode is being used in a separate thread; queue a message to set the value
1205 SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
1209 ColorMode Actor::GetColorMode() const
1211 // we have cached copy
1215 void Actor::SetSize( float width, float height )
1217 SetSize( Vector2( width, height ) );
1220 void Actor::SetSize( float width, float height, float depth )
1222 SetSize( Vector3( width, height, depth ) );
1225 void Actor::SetSize( const Vector2& size )
1227 SetSize( Vector3( size.width, size.height, 0.f ) );
1230 void Actor::SetSizeInternal( const Vector2& size )
1232 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
1235 void Actor::SetSize( const Vector3& size )
1237 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1239 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
1240 SetPreferredSize( size.GetVectorXY() );
1244 SetSizeInternal( size );
1248 void Actor::SetSizeInternal( const Vector3& size )
1250 // dont allow recursive loop
1251 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
1252 // 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
1253 if( ( NULL != mNode )&&
1254 ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
1255 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
1256 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) )
1260 // mNode is being used in a separate thread; queue a message to set the value & base value
1261 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
1263 // Notification for derived classes
1264 mInsideOnSizeSet = true;
1265 OnSizeSet( mTargetSize );
1266 mInsideOnSizeSet = false;
1268 // Raise a relayout request if the flag is not locked
1269 if( mRelayoutData && !mRelayoutData->insideRelayout )
1276 void Actor::SetWidth( float width )
1278 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1280 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
1281 mRelayoutData->preferredSize.width = width;
1285 mTargetSize.width = width;
1289 // mNode is being used in a separate thread; queue a message to set the value & base value
1290 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1297 void Actor::SetHeight( float height )
1299 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1301 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
1302 mRelayoutData->preferredSize.height = height;
1306 mTargetSize.height = height;
1310 // mNode is being used in a separate thread; queue a message to set the value & base value
1311 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1318 void Actor::SetDepth( float depth )
1320 mTargetSize.depth = depth;
1324 // mNode is being used in a separate thread; queue a message to set the value & base value
1325 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1329 Vector3 Actor::GetTargetSize() const
1331 Vector3 size = mTargetSize;
1333 // Should return preferred size if size is fixed as set by SetSize
1334 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
1336 size.width = GetPreferredSize().width;
1338 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
1340 size.height = GetPreferredSize().height;
1346 const Vector3& Actor::GetCurrentSize() const
1350 // mNode is being used in a separate thread; copy the value from the previous update
1351 return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
1354 return Vector3::ZERO;
1357 Vector3 Actor::GetNaturalSize() const
1359 // It is up to deriving classes to return the appropriate natural size
1360 return Vector3( 0.0f, 0.0f, 0.0f );
1363 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1365 EnsureRelayoutData();
1367 ResizePolicy::Type originalWidthPolicy = GetResizePolicy(Dimension::WIDTH);
1368 ResizePolicy::Type originalHeightPolicy = GetResizePolicy(Dimension::HEIGHT);
1370 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1372 if( dimension & ( 1 << i ) )
1374 if ( policy == ResizePolicy::USE_ASSIGNED_SIZE )
1376 mRelayoutData->useAssignedSize[ i ] = true;
1380 mRelayoutData->resizePolicies[ i ] = policy;
1381 mRelayoutData->useAssignedSize[ i ] = false;
1386 if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
1388 if( dimension & Dimension::WIDTH )
1390 SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
1393 if( dimension & Dimension::HEIGHT )
1395 SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
1399 // If calling SetResizePolicy, assume we want relayout enabled
1400 SetRelayoutEnabled( true );
1402 // If the resize policy is set to be FIXED, the preferred size
1403 // should be overrided by the target size. Otherwise the target
1404 // size should be overrided by the preferred size.
1406 if( dimension & Dimension::WIDTH )
1408 if( originalWidthPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1410 mRelayoutData->preferredSize.width = mTargetSize.width;
1412 else if( originalWidthPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1414 mTargetSize.width = mRelayoutData->preferredSize.width;
1418 if( dimension & Dimension::HEIGHT )
1420 if( originalHeightPolicy != ResizePolicy::FIXED && policy == ResizePolicy::FIXED )
1422 mRelayoutData->preferredSize.height = mTargetSize.height;
1424 else if( originalHeightPolicy == ResizePolicy::FIXED && policy != ResizePolicy::FIXED )
1426 mTargetSize.height = mRelayoutData->preferredSize.height;
1430 OnSetResizePolicy( policy, dimension );
1432 // Trigger relayout on this control
1436 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1438 if ( mRelayoutData )
1440 // If more than one dimension is requested, just return the first one found
1441 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1443 if( ( dimension & ( 1 << i ) ) )
1445 if( mRelayoutData->useAssignedSize[ i ] )
1447 return ResizePolicy::USE_ASSIGNED_SIZE;
1451 return mRelayoutData->resizePolicies[ i ];
1457 return ResizePolicy::DEFAULT;
1460 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1462 EnsureRelayoutData();
1464 mRelayoutData->sizeSetPolicy = policy;
1467 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1469 if ( mRelayoutData )
1471 return mRelayoutData->sizeSetPolicy;
1474 return DEFAULT_SIZE_SCALE_POLICY;
1477 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1479 EnsureRelayoutData();
1481 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1483 if( dimension & ( 1 << i ) )
1485 mRelayoutData->dimensionDependencies[ i ] = dependency;
1490 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1492 if ( mRelayoutData )
1494 // If more than one dimension is requested, just return the first one found
1495 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1497 if( ( dimension & ( 1 << i ) ) )
1499 return mRelayoutData->dimensionDependencies[ i ];
1504 return Dimension::ALL_DIMENSIONS; // Default
1507 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1509 // If relayout data has not been allocated yet and the client is requesting
1510 // to disable it, do nothing
1511 if( mRelayoutData || relayoutEnabled )
1513 EnsureRelayoutData();
1515 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1517 mRelayoutData->relayoutEnabled = relayoutEnabled;
1521 bool Actor::IsRelayoutEnabled() const
1523 // Assume that if relayout data has not been allocated yet then
1524 // relayout is disabled
1525 return mRelayoutData && mRelayoutData->relayoutEnabled;
1528 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1530 EnsureRelayoutData();
1532 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1534 if( dimension & ( 1 << i ) )
1536 mRelayoutData->dimensionDirty[ i ] = dirty;
1541 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1543 if ( mRelayoutData )
1545 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1547 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
1557 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1559 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1562 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1564 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1567 uint32_t Actor::AddRenderer( Renderer& renderer )
1571 mRenderers = new RendererContainer;
1574 uint32_t index = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1575 RendererPtr rendererPtr = RendererPtr( &renderer );
1576 mRenderers->push_back( rendererPtr );
1577 AddRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1581 uint32_t Actor::GetRendererCount() const
1583 uint32_t rendererCount(0);
1586 rendererCount = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1589 return rendererCount;
1592 RendererPtr Actor::GetRendererAt( uint32_t index )
1594 RendererPtr renderer;
1595 if( index < GetRendererCount() )
1597 renderer = ( *mRenderers )[ index ];
1603 void Actor::RemoveRenderer( Renderer& renderer )
1607 RendererIter end = mRenderers->end();
1608 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1610 if( (*iter).Get() == &renderer )
1612 mRenderers->erase( iter );
1613 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.GetRendererSceneObject() );
1620 void Actor::RemoveRenderer( uint32_t index )
1622 if( index < GetRendererCount() )
1624 RendererPtr renderer = ( *mRenderers )[ index ];
1625 RemoveRendererMessage( GetEventThreadServices(), *mNode, renderer.Get()->GetRendererSceneObject() );
1626 mRenderers->erase( mRenderers->begin()+index );
1630 bool Actor::IsOverlay() const
1632 return ( DrawMode::OVERLAY_2D == mDrawMode );
1635 void Actor::SetDrawMode( DrawMode::Type drawMode )
1637 // this flag is not animatable so keep the value
1638 mDrawMode = drawMode;
1639 if( ( NULL != mNode ) && ( drawMode != DrawMode::STENCIL ) )
1641 // mNode is being used in a separate thread; queue a message to set the value
1642 SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
1646 DrawMode::Type Actor::GetDrawMode() const
1651 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1653 // only valid when on-stage
1654 StagePtr stage = Stage::GetCurrent();
1655 if( stage && OnStage() )
1657 const RenderTaskList& taskList = stage->GetRenderTaskList();
1659 Vector2 converted( screenX, screenY );
1661 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1662 uint32_t taskCount = taskList.GetTaskCount();
1663 for( uint32_t i = taskCount; i > 0; --i )
1665 Dali::RenderTask task = taskList.GetTask( i - 1 );
1666 if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
1668 // found a task where this conversion was ok so return
1676 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1678 bool retval = false;
1679 // only valid when on-stage
1682 CameraActor* camera = renderTask.GetCameraActor();
1686 renderTask.GetViewport( viewport );
1688 // need to translate coordinates to render tasks coordinate space
1689 Vector2 converted( screenX, screenY );
1690 if( renderTask.TranslateCoordinates( converted ) )
1692 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1699 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1701 // Early-out if mNode is NULL
1707 // Get the ModelView matrix
1709 Matrix::Multiply( modelView, mNode->GetWorldMatrix(0), viewMatrix );
1711 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
1712 Matrix invertedMvp( false/*don't init*/);
1713 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
1714 bool success = invertedMvp.Invert();
1716 // Convert to GL coordinates
1717 Vector4 screenPos( screenX - static_cast<float>( viewport.x ), static_cast<float>( viewport.height ) - screenY - static_cast<float>( viewport.y ), 0.f, 1.f );
1722 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), nearPos );
1729 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), farPos );
1735 if( XyPlaneIntersect( nearPos, farPos, local ) )
1737 Vector3 size = GetCurrentSize();
1738 localX = local.x + size.x * 0.5f;
1739 localY = local.y + size.y * 0.5f;
1750 bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
1753 http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
1755 Mathematical Formulation
1757 Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
1759 ( p - c ) dot ( p - c ) = r^2
1761 Given a ray with a point of origin 'o', and a direction vector 'd':
1763 ray(t) = o + td, t >= 0
1765 we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
1767 (o + td - c ) dot ( o + td - c ) = r^2
1769 To solve for t we first expand the above into a more recognisable quadratic equation form
1771 ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
1780 B = 2( o - c ) dot d
1781 C = ( o - c ) dot ( o - c ) - r^2
1783 which can be solved using a standard quadratic formula.
1785 Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
1787 Practical Simplification
1789 In a renderer, we often differentiate between world space and object space. In the object space
1790 of a sphere it is centred at origin, meaning that if we first transform the ray from world space
1791 into object space, the mathematical solution presented above can be simplified significantly.
1793 If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
1797 and we can find the t at which the (transformed) ray intersects the sphere by
1799 ( o + td ) dot ( o + td ) = r^2
1801 According to the reasoning above, we expand the above quadratic equation into the general form
1805 which now has coefficients:
1812 // Early out if mNode is NULL
1818 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1820 // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
1821 const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
1822 Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
1824 // Compute the radius is not needed, square radius it's enough.
1825 const Vector3& size( mNode->GetSize( bufferIndex ) );
1827 // Scale the sphere.
1828 const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
1830 const float width = size.width * scale.width;
1831 const float height = size.height * scale.height;
1833 float squareSphereRadius = 0.5f * ( width * width + height * height );
1835 float a = rayDir.Dot( rayDir ); // a
1836 float b2 = rayDir.Dot( rayOriginLocal ); // b/2
1837 float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c
1839 return ( b2 * b2 - a * c ) >= 0.f;
1842 bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector2& hitPointLocal, float& distance ) const
1846 if( OnStage() && NULL != mNode )
1848 // Transforms the ray to the local reference system.
1849 // Calculate the inverse of Model matrix
1850 Matrix invModelMatrix( false/*don't init*/);
1852 BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
1853 invModelMatrix = mNode->GetWorldMatrix(0);
1854 invModelMatrix.Invert();
1856 Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
1857 Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
1859 // Test with the actor's XY plane (Normal = 0 0 1 1).
1861 float a = -rayOriginLocal.z;
1862 float b = rayDirLocal.z;
1864 if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
1866 // Ray travels distance * rayDirLocal to intersect with plane.
1869 const Vector3& size = mNode->GetSize( bufferIndex );
1871 hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
1872 hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
1874 // Test with the actor's geometry.
1875 hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
1882 void Actor::SetLeaveRequired( bool required )
1884 mLeaveRequired = required;
1887 bool Actor::GetLeaveRequired() const
1889 return mLeaveRequired;
1892 void Actor::SetKeyboardFocusable( bool focusable )
1894 mKeyboardFocusable = focusable;
1897 bool Actor::IsKeyboardFocusable() const
1899 return mKeyboardFocusable;
1902 bool Actor::GetTouchRequired() const
1904 return !mTouchedSignal.Empty() || !mTouchSignal.Empty() || mDerivedRequiresTouch;
1907 bool Actor::GetHoverRequired() const
1909 return !mHoveredSignal.Empty() || mDerivedRequiresHover;
1912 bool Actor::GetWheelEventRequired() const
1914 return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
1917 bool Actor::IsHittable() const
1919 return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
1922 ActorGestureData& Actor::GetGestureData()
1924 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1925 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1926 if( NULL == mGestureData )
1928 mGestureData = new ActorGestureData;
1930 return *mGestureData;
1933 bool Actor::IsGestureRequred( Gesture::Type type ) const
1935 return mGestureData && mGestureData->IsGestureRequred( type );
1938 bool Actor::EmitTouchEventSignal( const TouchEvent& event, const Dali::TouchData& touch )
1940 bool consumed = false;
1942 if( !mTouchSignal.Empty() )
1944 Dali::Actor handle( this );
1945 consumed = mTouchSignal.Emit( handle, touch );
1948 if( !mTouchedSignal.Empty() )
1950 Dali::Actor handle( this );
1951 consumed |= mTouchedSignal.Emit( handle, event );
1956 // Notification for derived classes
1957 consumed = OnTouchEvent( event ); // TODO
1963 bool Actor::EmitHoverEventSignal( const HoverEvent& event )
1965 bool consumed = false;
1967 if( !mHoveredSignal.Empty() )
1969 Dali::Actor handle( this );
1970 consumed = mHoveredSignal.Emit( handle, event );
1975 // Notification for derived classes
1976 consumed = OnHoverEvent( event );
1982 bool Actor::EmitWheelEventSignal( const WheelEvent& event )
1984 bool consumed = false;
1986 if( !mWheelEventSignal.Empty() )
1988 Dali::Actor handle( this );
1989 consumed = mWheelEventSignal.Emit( handle, event );
1994 // Notification for derived classes
1995 consumed = OnWheelEvent( event );
2001 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
2003 if( ! mVisibilityChangedSignal.Empty() )
2005 Dali::Actor handle( this );
2006 mVisibilityChangedSignal.Emit( handle, visible, type );
2010 void Actor::EmitLayoutDirectionChangedSignal( LayoutDirection::Type type )
2012 if( ! mLayoutDirectionChangedSignal.Empty() )
2014 Dali::Actor handle( this );
2015 mLayoutDirectionChangedSignal.Emit( handle, type );
2019 void Actor::EmitChildAddedSignal( Actor& child )
2021 if( ! mChildAddedSignal.Empty() )
2023 Dali::Actor handle( &child );
2024 mChildAddedSignal.Emit( handle );
2028 void Actor::EmitChildRemovedSignal( Actor& child )
2030 if( ! mChildRemovedSignal.Empty() )
2032 Dali::Actor handle( &child );
2033 mChildRemovedSignal.Emit( handle );
2037 Dali::Actor::TouchSignalType& Actor::TouchedSignal()
2039 return mTouchedSignal;
2042 Dali::Actor::TouchDataSignalType& Actor::TouchSignal()
2044 return mTouchSignal;
2047 Dali::Actor::HoverSignalType& Actor::HoveredSignal()
2049 return mHoveredSignal;
2052 Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
2054 return mWheelEventSignal;
2057 Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
2059 return mOnStageSignal;
2062 Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
2064 return mOffStageSignal;
2067 Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
2069 return mOnRelayoutSignal;
2072 DevelActor::VisibilityChangedSignalType& Actor::VisibilityChangedSignal()
2074 return mVisibilityChangedSignal;
2077 Dali::Actor::LayoutDirectionChangedSignalType& Actor::LayoutDirectionChangedSignal()
2079 return mLayoutDirectionChangedSignal;
2082 DevelActor::ChildChangedSignalType& Actor::ChildAddedSignal()
2084 return mChildAddedSignal;
2087 DevelActor::ChildChangedSignalType& Actor::ChildRemovedSignal()
2089 return mChildRemovedSignal;
2092 DevelActor::ChildOrderChangedSignalType& Actor::ChildOrderChangedSignal()
2094 return mChildOrderChangedSignal;
2097 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
2099 bool connected( true );
2100 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
2102 if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
2104 actor->TouchedSignal().Connect( tracker, functor );
2106 else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
2108 actor->HoveredSignal().Connect( tracker, functor );
2110 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
2112 actor->WheelEventSignal().Connect( tracker, functor );
2114 else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
2116 actor->OnStageSignal().Connect( tracker, functor );
2118 else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
2120 actor->OffStageSignal().Connect( tracker, functor );
2122 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
2124 actor->OnRelayoutSignal().Connect( tracker, functor );
2126 else if( 0 == signalName.compare( SIGNAL_TOUCH ) )
2128 actor->TouchSignal().Connect( tracker, functor );
2130 else if( 0 == signalName.compare( SIGNAL_VISIBILITY_CHANGED ) )
2132 actor->VisibilityChangedSignal().Connect( tracker, functor );
2134 else if( 0 == signalName.compare( SIGNAL_LAYOUT_DIRECTION_CHANGED ) )
2136 actor->LayoutDirectionChangedSignal().Connect( tracker, functor );
2138 else if( 0 == signalName.compare( SIGNAL_CHILD_ADDED ) )
2140 actor->ChildAddedSignal().Connect( tracker, functor );
2142 else if( 0 == signalName.compare( SIGNAL_CHILD_REMOVED ) )
2144 actor->ChildRemovedSignal().Connect( tracker, functor );
2148 // signalName does not match any signal
2155 Actor::Actor( DerivedType derivedType )
2160 mParentOrigin( NULL ),
2161 mAnchorPoint( NULL ),
2162 mRelayoutData( NULL ),
2163 mGestureData( NULL ),
2167 mWheelEventSignal(),
2170 mOnRelayoutSignal(),
2171 mVisibilityChangedSignal(),
2172 mLayoutDirectionChangedSignal(),
2173 mChildAddedSignal(),
2174 mChildRemovedSignal(),
2175 mChildOrderChangedSignal(),
2176 mTargetOrientation( Quaternion::IDENTITY ),
2177 mTargetColor( Color::WHITE ),
2178 mTargetSize( Vector3::ZERO ),
2179 mTargetPosition( Vector3::ZERO ),
2180 mTargetScale( Vector3::ONE ),
2182 mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
2185 mIsRoot( ROOT_LAYER == derivedType ),
2186 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
2187 mIsOnStage( false ),
2189 mLeaveRequired( false ),
2190 mKeyboardFocusable( false ),
2191 mDerivedRequiresTouch( false ),
2192 mDerivedRequiresHover( false ),
2193 mDerivedRequiresWheelEvent( false ),
2194 mOnStageSignalled( false ),
2195 mInsideOnSizeSet( false ),
2196 mInheritPosition( true ),
2197 mInheritOrientation( true ),
2198 mInheritScale( true ),
2199 mPositionUsesAnchorPoint( true ),
2201 mInheritLayoutDirection( true ),
2202 mLayoutDirection( LayoutDirection::LEFT_TO_RIGHT ),
2203 mDrawMode( DrawMode::NORMAL ),
2204 mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
2205 mColorMode( Node::DEFAULT_COLOR_MODE ),
2206 mClippingMode( ClippingMode::DISABLED )
2210 void Actor::Initialize()
2212 // Node creation, keep raw-pointer to Node for messaging
2213 mNode = CreateNode();
2214 OwnerPointer< SceneGraph::Node > transferOwnership( const_cast< SceneGraph::Node* >( mNode ) );
2215 AddNodeMessage( GetEventThreadServices().GetUpdateManager(), transferOwnership );
2219 GetEventThreadServices().RegisterObject( this );
2224 // Remove mParent pointers from children even if we're destroying core,
2225 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
2228 ActorConstIter endIter = mChildren->end();
2229 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2231 (*iter)->SetParent( NULL );
2237 // Guard to allow handle destruction after Core has been destroyed
2238 if( EventThreadServices::IsCoreRunning() )
2242 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
2243 mNode = NULL; // Node is about to be destroyed
2246 GetEventThreadServices().UnregisterObject( this );
2249 // Cleanup optional gesture data
2250 delete mGestureData;
2252 // Cleanup optional parent origin and anchor
2253 delete mParentOrigin;
2254 delete mAnchorPoint;
2256 // Delete optional relayout data
2259 delete mRelayoutData;
2263 void Actor::ConnectToStage( uint32_t parentDepth )
2265 // This container is used instead of walking the Actor hierarchy.
2266 // It protects us when the Actor hierarchy is modified during OnStageConnectionExternal callbacks.
2267 ActorContainer connectionList;
2269 StagePtr stage = Stage::GetCurrent();
2272 stage->RequestRebuildDepthTree();
2275 // This stage is atomic i.e. not interrupted by user callbacks.
2276 RecursiveConnectToStage( connectionList, parentDepth + 1 );
2278 // Notify applications about the newly connected actors.
2279 const ActorIter endIter = connectionList.end();
2280 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
2282 (*iter)->NotifyStageConnection();
2288 void Actor::RecursiveConnectToStage( ActorContainer& connectionList, uint32_t depth )
2290 DALI_ASSERT_ALWAYS( !OnStage() );
2293 mDepth = static_cast< uint16_t >( depth ); // overflow ignored, not expected in practice
2295 ConnectToSceneGraph();
2297 // Notification for internal derived classes
2298 OnStageConnectionInternal();
2300 // This stage is atomic; avoid emitting callbacks until all Actors are connected
2301 connectionList.push_back( ActorPtr( this ) );
2303 // Recursively connect children
2306 ActorConstIter endIter = mChildren->end();
2307 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2309 (*iter)->RecursiveConnectToStage( connectionList, depth + 1 );
2315 * This method is called when the Actor is connected to the Stage.
2316 * The parent must have added its Node to the scene-graph.
2317 * The child must connect its Node to the parent's Node.
2318 * This is recursive; the child calls ConnectToStage() for its children.
2320 void Actor::ConnectToSceneGraph()
2322 DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
2326 // Reparent Node in next Update
2327 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode );
2330 // Request relayout on all actors that are added to the scenegraph
2333 // Notification for Object::Observers
2337 void Actor::NotifyStageConnection()
2339 // Actors can be removed (in a callback), before the on-stage stage is reported.
2340 // The actor may also have been reparented, in which case mOnStageSignalled will be true.
2341 if( OnStage() && !mOnStageSignalled )
2343 // Notification for external (CustomActor) derived classes
2344 OnStageConnectionExternal( mDepth );
2346 if( !mOnStageSignal.Empty() )
2348 Dali::Actor handle( this );
2349 mOnStageSignal.Emit( handle );
2352 // Guard against Remove during callbacks
2355 mOnStageSignalled = true; // signal required next time Actor is removed
2360 void Actor::DisconnectFromStage()
2362 // This container is used instead of walking the Actor hierachy.
2363 // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
2364 ActorContainer disconnectionList;
2366 StagePtr stage = Stage::GetCurrent();
2369 stage->RequestRebuildDepthTree();
2372 // This stage is atomic i.e. not interrupted by user callbacks
2373 RecursiveDisconnectFromStage( disconnectionList );
2375 // Notify applications about the newly disconnected actors.
2376 const ActorIter endIter = disconnectionList.end();
2377 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
2379 (*iter)->NotifyStageDisconnection();
2383 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
2385 DALI_ASSERT_ALWAYS( OnStage() );
2387 // Recursively disconnect children
2390 ActorConstIter endIter = mChildren->end();
2391 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
2393 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
2397 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
2398 disconnectionList.push_back( ActorPtr( this ) );
2400 // Notification for internal derived classes
2401 OnStageDisconnectionInternal();
2403 DisconnectFromSceneGraph();
2409 * This method is called by an actor or its parent, before a node removal message is sent.
2410 * This is recursive; the child calls DisconnectFromStage() for its children.
2412 void Actor::DisconnectFromSceneGraph()
2414 // Notification for Object::Observers
2415 OnSceneObjectRemove();
2418 void Actor::NotifyStageDisconnection()
2420 // Actors can be added (in a callback), before the off-stage state is reported.
2421 // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
2422 // only do this step if there is a stage, i.e. Core is not being shut down
2423 if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
2425 // Notification for external (CustomeActor) derived classes
2426 OnStageDisconnectionExternal();
2428 if( !mOffStageSignal.Empty() )
2430 Dali::Actor handle( this );
2431 mOffStageSignal.Emit( handle );
2434 // Guard against Add during callbacks
2437 mOnStageSignalled = false; // signal required next time Actor is added
2442 bool Actor::IsNodeConnected() const
2444 bool connected( false );
2446 if( OnStage() && ( NULL != mNode ) )
2448 if( IsRoot() || mNode->GetParent() )
2457 // This method initiates traversal of the actor tree using depth-first
2458 // traversal to set a depth index based on traversal order. It sends a
2459 // single message to update manager to update all the actor's nodes in
2460 // this tree with the depth index. The sceneGraphNodeDepths vector's
2461 // elements are ordered by depth, and could be used to reduce sorting
2462 // in the update thread.
2463 void Actor::RebuildDepthTree()
2465 DALI_LOG_TIMER_START(depthTimer);
2467 // Vector of scene-graph nodes and their depths to send to UpdateManager
2468 // in a single message
2469 OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths( new SceneGraph::NodeDepths() );
2471 int32_t depthIndex = 1;
2472 DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
2474 SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths );
2475 DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
2478 void Actor::DepthTraverseActorTree( OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths, int32_t& depthIndex )
2480 mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
2481 sceneGraphNodeDepths->Add( const_cast<SceneGraph::Node*>( mNode ), mSortedDepth );
2483 // Create/add to children of this node
2486 for( ActorContainer::iterator it = mChildren->begin(); it != mChildren->end(); ++it )
2488 Actor* childActor = (*it).Get();
2490 childActor->DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
2495 uint32_t Actor::GetDefaultPropertyCount() const
2497 return DEFAULT_PROPERTY_COUNT;
2500 void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
2502 indices.Reserve( DEFAULT_PROPERTY_COUNT );
2504 for( int32_t i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2506 indices.PushBack( i );
2510 const char* Actor::GetDefaultPropertyName( Property::Index index ) const
2512 if( index < DEFAULT_PROPERTY_COUNT )
2514 return DEFAULT_PROPERTY_DETAILS[ index ].name;
2520 Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
2522 Property::Index index = Property::INVALID_INDEX;
2524 // Look for name in default properties
2525 for( int32_t i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
2527 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
2528 if( 0 == name.compare( property->name ) )
2538 bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
2540 if( index < DEFAULT_PROPERTY_COUNT )
2542 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
2548 bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
2550 if( index < DEFAULT_PROPERTY_COUNT )
2552 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
2558 bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
2560 if( index < DEFAULT_PROPERTY_COUNT )
2562 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
2568 Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
2570 if( index < DEFAULT_PROPERTY_COUNT )
2572 return DEFAULT_PROPERTY_DETAILS[ index ].type;
2575 // index out of range...return Property::NONE
2576 return Property::NONE;
2579 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
2583 case Dali::Actor::Property::PARENT_ORIGIN:
2585 Property::Type type = property.GetType();
2586 if( type == Property::VECTOR3 )
2588 SetParentOrigin( property.Get< Vector3 >() );
2590 else if ( type == Property::STRING )
2592 std::string parentOriginString;
2593 property.Get( parentOriginString );
2594 Vector3 parentOrigin;
2595 if( GetParentOriginConstant( parentOriginString, parentOrigin ) )
2597 SetParentOrigin( parentOrigin );
2603 case Dali::Actor::Property::PARENT_ORIGIN_X:
2605 SetParentOriginX( property.Get< float >() );
2609 case Dali::Actor::Property::PARENT_ORIGIN_Y:
2611 SetParentOriginY( property.Get< float >() );
2615 case Dali::Actor::Property::PARENT_ORIGIN_Z:
2617 SetParentOriginZ( property.Get< float >() );
2621 case Dali::Actor::Property::ANCHOR_POINT:
2623 Property::Type type = property.GetType();
2624 if( type == Property::VECTOR3 )
2626 SetAnchorPoint( property.Get< Vector3 >() );
2628 else if ( type == Property::STRING )
2630 std::string anchorPointString;
2631 property.Get( anchorPointString );
2633 if( GetAnchorPointConstant( anchorPointString, anchor ) )
2635 SetAnchorPoint( anchor );
2641 case Dali::Actor::Property::ANCHOR_POINT_X:
2643 SetAnchorPointX( property.Get< float >() );
2647 case Dali::Actor::Property::ANCHOR_POINT_Y:
2649 SetAnchorPointY( property.Get< float >() );
2653 case Dali::Actor::Property::ANCHOR_POINT_Z:
2655 SetAnchorPointZ( property.Get< float >() );
2659 case Dali::Actor::Property::SIZE:
2661 SetSize( property.Get< Vector3 >() );
2665 case Dali::Actor::Property::SIZE_WIDTH:
2667 SetWidth( property.Get< float >() );
2671 case Dali::Actor::Property::SIZE_HEIGHT:
2673 SetHeight( property.Get< float >() );
2677 case Dali::Actor::Property::SIZE_DEPTH:
2679 SetDepth( property.Get< float >() );
2683 case Dali::Actor::Property::POSITION:
2685 SetPosition( property.Get< Vector3 >() );
2689 case Dali::Actor::Property::POSITION_X:
2691 SetX( property.Get< float >() );
2695 case Dali::Actor::Property::POSITION_Y:
2697 SetY( property.Get< float >() );
2701 case Dali::Actor::Property::POSITION_Z:
2703 SetZ( property.Get< float >() );
2707 case Dali::Actor::Property::ORIENTATION:
2709 SetOrientation( property.Get< Quaternion >() );
2713 case Dali::Actor::Property::SCALE:
2715 SetScale( property.Get< Vector3 >() );
2719 case Dali::Actor::Property::SCALE_X:
2721 SetScaleX( property.Get< float >() );
2725 case Dali::Actor::Property::SCALE_Y:
2727 SetScaleY( property.Get< float >() );
2731 case Dali::Actor::Property::SCALE_Z:
2733 SetScaleZ( property.Get< float >() );
2737 case Dali::Actor::Property::VISIBLE:
2739 SetVisible( property.Get< bool >() );
2743 case Dali::Actor::Property::COLOR:
2745 SetColor( property.Get< Vector4 >() );
2749 case Dali::Actor::Property::COLOR_RED:
2751 SetColorRed( property.Get< float >() );
2755 case Dali::Actor::Property::COLOR_GREEN:
2757 SetColorGreen( property.Get< float >() );
2761 case Dali::Actor::Property::COLOR_BLUE:
2763 SetColorBlue( property.Get< float >() );
2767 case Dali::Actor::Property::COLOR_ALPHA:
2768 case Dali::DevelActor::Property::OPACITY:
2771 if( property.Get( value ) )
2773 SetOpacity( value );
2778 case Dali::Actor::Property::NAME:
2780 SetName( property.Get< std::string >() );
2784 case Dali::Actor::Property::SENSITIVE:
2786 SetSensitive( property.Get< bool >() );
2790 case Dali::Actor::Property::LEAVE_REQUIRED:
2792 SetLeaveRequired( property.Get< bool >() );
2796 case Dali::Actor::Property::INHERIT_POSITION:
2798 SetInheritPosition( property.Get< bool >() );
2802 case Dali::Actor::Property::INHERIT_ORIENTATION:
2804 SetInheritOrientation( property.Get< bool >() );
2808 case Dali::Actor::Property::INHERIT_SCALE:
2810 SetInheritScale( property.Get< bool >() );
2814 case Dali::Actor::Property::COLOR_MODE:
2816 ColorMode mode = mColorMode;
2817 if ( Scripting::GetEnumerationProperty< ColorMode >( property, COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT, mode ) )
2819 SetColorMode( mode );
2824 case Dali::Actor::Property::POSITION_INHERITANCE:
2826 PositionInheritanceMode mode = mPositionInheritanceMode;
2827 if( Scripting::GetEnumerationProperty< PositionInheritanceMode >( property, POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT, mode ) )
2829 SetPositionInheritanceMode( mode );
2834 case Dali::Actor::Property::DRAW_MODE:
2836 DrawMode::Type mode = mDrawMode;
2837 if( Scripting::GetEnumerationProperty< DrawMode::Type >( property, DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT, mode ) )
2839 SetDrawMode( mode );
2844 case Dali::Actor::Property::SIZE_MODE_FACTOR:
2846 SetSizeModeFactor( property.Get< Vector3 >() );
2850 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
2852 ResizePolicy::Type type;
2853 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2855 SetResizePolicy( type, Dimension::WIDTH );
2860 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
2862 ResizePolicy::Type type;
2863 if( Scripting::GetEnumerationProperty< ResizePolicy::Type >( property, RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT, type ) )
2865 SetResizePolicy( type, Dimension::HEIGHT );
2870 case Dali::Actor::Property::SIZE_SCALE_POLICY:
2872 SizeScalePolicy::Type type;
2873 if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT, type ) )
2875 SetSizeScalePolicy( type );
2880 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
2882 if( property.Get< bool >() )
2884 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
2889 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
2891 if( property.Get< bool >() )
2893 SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
2898 case Dali::Actor::Property::PADDING:
2900 Vector4 padding = property.Get< Vector4 >();
2901 SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
2902 SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
2906 case Dali::Actor::Property::MINIMUM_SIZE:
2908 Vector2 size = property.Get< Vector2 >();
2909 SetMinimumSize( size.x, Dimension::WIDTH );
2910 SetMinimumSize( size.y, Dimension::HEIGHT );
2914 case Dali::Actor::Property::MAXIMUM_SIZE:
2916 Vector2 size = property.Get< Vector2 >();
2917 SetMaximumSize( size.x, Dimension::WIDTH );
2918 SetMaximumSize( size.y, Dimension::HEIGHT );
2922 case Dali::DevelActor::Property::SIBLING_ORDER:
2926 if( property.Get( value ) )
2928 SetSiblingOrder( value );
2933 case Dali::Actor::Property::CLIPPING_MODE:
2935 ClippingMode::Type convertedValue = mClippingMode;
2936 if( Scripting::GetEnumerationProperty< ClippingMode::Type >( property, CLIPPING_MODE_TABLE, CLIPPING_MODE_TABLE_COUNT, convertedValue ) )
2938 mClippingMode = convertedValue;
2941 SetClippingModeMessage( GetEventThreadServices(), *mNode, mClippingMode );
2947 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
2950 if( property.Get( value ) && value != mPositionUsesAnchorPoint )
2952 mPositionUsesAnchorPoint = value;
2955 SetPositionUsesAnchorPointMessage( GetEventThreadServices(), *mNode, mPositionUsesAnchorPoint );
2961 case Dali::Actor::Property::LAYOUT_DIRECTION:
2963 Dali::LayoutDirection::Type direction = mLayoutDirection;
2964 mInheritLayoutDirection = false;
2966 if( Scripting::GetEnumerationProperty< LayoutDirection::Type >( property, LAYOUT_DIRECTION_TABLE, LAYOUT_DIRECTION_TABLE_COUNT, direction ) )
2968 InheritLayoutDirectionRecursively( this, direction, true );
2973 case Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION:
2976 if( property.Get( value ) )
2978 SetInheritLayoutDirection( value );
2985 // this can happen in the case of a non-animatable default property so just do nothing
2991 // TODO: This method needs to be removed
2992 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
2994 switch( entry.GetType() )
2996 case Property::BOOLEAN:
2998 const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
2999 DALI_ASSERT_DEBUG( NULL != property );
3001 // property is being used in a separate thread; queue a message to set the property
3002 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
3007 case Property::INTEGER:
3009 const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
3010 DALI_ASSERT_DEBUG( NULL != property );
3012 // property is being used in a separate thread; queue a message to set the property
3013 SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
3018 case Property::FLOAT:
3020 const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
3021 DALI_ASSERT_DEBUG( NULL != property );
3023 // property is being used in a separate thread; queue a message to set the property
3024 SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
3029 case Property::VECTOR2:
3031 const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
3032 DALI_ASSERT_DEBUG( NULL != property );
3034 // property is being used in a separate thread; queue a message to set the property
3035 if(entry.componentIndex == 0)
3037 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
3039 else if(entry.componentIndex == 1)
3041 SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
3045 SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
3051 case Property::VECTOR3:
3053 const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
3054 DALI_ASSERT_DEBUG( NULL != property );
3056 // property is being used in a separate thread; queue a message to set the property
3057 if(entry.componentIndex == 0)
3059 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
3061 else if(entry.componentIndex == 1)
3063 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
3065 else if(entry.componentIndex == 2)
3067 SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
3071 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
3077 case Property::VECTOR4:
3079 const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
3080 DALI_ASSERT_DEBUG( NULL != property );
3082 // property is being used in a separate thread; queue a message to set the property
3083 if(entry.componentIndex == 0)
3085 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
3087 else if(entry.componentIndex == 1)
3089 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
3091 else if(entry.componentIndex == 2)
3093 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
3095 else if(entry.componentIndex == 3)
3097 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
3101 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
3107 case Property::ROTATION:
3109 const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
3110 DALI_ASSERT_DEBUG( NULL != property );
3112 // property is being used in a separate thread; queue a message to set the property
3113 SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake, value.Get<Quaternion>() );
3118 case Property::MATRIX:
3120 const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
3121 DALI_ASSERT_DEBUG( NULL != property );
3123 // property is being used in a separate thread; queue a message to set the property
3124 SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake, value.Get<Matrix>() );
3129 case Property::MATRIX3:
3131 const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
3132 DALI_ASSERT_DEBUG( NULL != property );
3134 // property is being used in a separate thread; queue a message to set the property
3135 SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake, value.Get<Matrix3>() );
3142 // nothing to do for other types
3147 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
3149 Property::Value value;
3151 if( ! GetCachedPropertyValue( index, value ) )
3153 // If property value is not stored in the event-side, then it must be a scene-graph only property
3154 GetCurrentPropertyValue( index, value );
3160 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
3162 Property::Value value;
3164 if( ! GetCurrentPropertyValue( index, value ) )
3166 // If unable to retrieve scene-graph property value, then it must be an event-side only property
3167 GetCachedPropertyValue( index, value );
3173 void Actor::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
3175 switch( animationType )
3178 case Animation::BETWEEN:
3182 case Dali::Actor::Property::SIZE:
3184 if( value.Get( mTargetSize ) )
3186 // Notify deriving classes
3187 OnSizeAnimation( animation, mTargetSize );
3192 case Dali::Actor::Property::SIZE_WIDTH:
3194 if( value.Get( mTargetSize.width ) )
3196 // Notify deriving classes
3197 OnSizeAnimation( animation, mTargetSize );
3202 case Dali::Actor::Property::SIZE_HEIGHT:
3204 if( value.Get( mTargetSize.height ) )
3206 // Notify deriving classes
3207 OnSizeAnimation( animation, mTargetSize );
3212 case Dali::Actor::Property::SIZE_DEPTH:
3214 if( value.Get( mTargetSize.depth ) )
3216 // Notify deriving classes
3217 OnSizeAnimation( animation, mTargetSize );
3222 case Dali::Actor::Property::POSITION:
3224 value.Get( mTargetPosition );
3228 case Dali::Actor::Property::POSITION_X:
3230 value.Get( mTargetPosition.x );
3234 case Dali::Actor::Property::POSITION_Y:
3236 value.Get( mTargetPosition.y );
3240 case Dali::Actor::Property::POSITION_Z:
3242 value.Get( mTargetPosition.z );
3246 case Dali::Actor::Property::ORIENTATION:
3248 value.Get( mTargetOrientation );
3252 case Dali::Actor::Property::SCALE:
3254 value.Get( mTargetScale );
3258 case Dali::Actor::Property::SCALE_X:
3260 value.Get( mTargetScale.x );
3264 case Dali::Actor::Property::SCALE_Y:
3266 value.Get( mTargetScale.y );
3270 case Dali::Actor::Property::SCALE_Z:
3272 value.Get( mTargetScale.z );
3276 case Dali::Actor::Property::VISIBLE:
3278 SetVisibleInternal( value.Get< bool >(), SendMessage::FALSE );
3282 case Dali::Actor::Property::COLOR:
3284 value.Get( mTargetColor );
3288 case Dali::Actor::Property::COLOR_RED:
3290 value.Get( mTargetColor.r );
3294 case Dali::Actor::Property::COLOR_GREEN:
3296 value.Get( mTargetColor.g );
3300 case Dali::Actor::Property::COLOR_BLUE:
3302 value.Get( mTargetColor.b );
3306 case Dali::Actor::Property::COLOR_ALPHA:
3307 case Dali::DevelActor::Property::OPACITY:
3309 value.Get( mTargetColor.a );
3315 // Not an animatable property. Do nothing.
3326 case Dali::Actor::Property::SIZE:
3328 if( AdjustValue< Vector3 >( mTargetSize, value ) )
3330 // Notify deriving classes
3331 OnSizeAnimation( animation, mTargetSize );
3336 case Dali::Actor::Property::SIZE_WIDTH:
3338 if( AdjustValue< float >( mTargetSize.width, value ) )
3340 // Notify deriving classes
3341 OnSizeAnimation( animation, mTargetSize );
3346 case Dali::Actor::Property::SIZE_HEIGHT:
3348 if( AdjustValue< float >( mTargetSize.height, value ) )
3350 // Notify deriving classes
3351 OnSizeAnimation( animation, mTargetSize );
3356 case Dali::Actor::Property::SIZE_DEPTH:
3358 if( AdjustValue< float >( mTargetSize.depth, value ) )
3360 // Notify deriving classes
3361 OnSizeAnimation( animation, mTargetSize );
3366 case Dali::Actor::Property::POSITION:
3368 AdjustValue< Vector3 >( mTargetPosition, value );
3372 case Dali::Actor::Property::POSITION_X:
3374 AdjustValue< float >( mTargetPosition.x, value );
3378 case Dali::Actor::Property::POSITION_Y:
3380 AdjustValue< float >( mTargetPosition.y, value );
3384 case Dali::Actor::Property::POSITION_Z:
3386 AdjustValue< float >( mTargetPosition.z, value );
3390 case Dali::Actor::Property::ORIENTATION:
3392 Quaternion relativeValue;
3393 if( value.Get( relativeValue ) )
3395 mTargetOrientation *= relativeValue;
3400 case Dali::Actor::Property::SCALE:
3402 AdjustValue< Vector3 >( mTargetScale, value );
3406 case Dali::Actor::Property::SCALE_X:
3408 AdjustValue< float >( mTargetScale.x, value );
3412 case Dali::Actor::Property::SCALE_Y:
3414 AdjustValue< float >( mTargetScale.y, value );
3418 case Dali::Actor::Property::SCALE_Z:
3420 AdjustValue< float >( mTargetScale.z, value );
3424 case Dali::Actor::Property::VISIBLE:
3426 bool relativeValue = false;
3427 if( value.Get( relativeValue ) )
3429 bool visible = mVisible || relativeValue;
3430 SetVisibleInternal( visible, SendMessage::FALSE );
3435 case Dali::Actor::Property::COLOR:
3437 AdjustValue< Vector4 >( mTargetColor, value );
3441 case Dali::Actor::Property::COLOR_RED:
3443 AdjustValue< float >( mTargetColor.r, value );
3447 case Dali::Actor::Property::COLOR_GREEN:
3449 AdjustValue< float >( mTargetColor.g, value );
3453 case Dali::Actor::Property::COLOR_BLUE:
3455 AdjustValue< float >( mTargetColor.b, value );
3459 case Dali::Actor::Property::COLOR_ALPHA:
3460 case Dali::DevelActor::Property::OPACITY:
3462 AdjustValue< float >( mTargetColor.a, value );
3468 // Not an animatable property. Do nothing.
3477 const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
3482 const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
3484 // This method should only return an object connected to the scene-graph
3485 return OnStage() ? mNode : NULL;
3488 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
3490 DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
3492 const PropertyBase* property( NULL );
3494 // This method should only return a property of an object connected to the scene-graph
3500 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3502 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3503 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3505 property = animatable->GetSceneGraphProperty();
3507 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3508 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3510 CustomPropertyMetadata* custom = FindCustomProperty( index );
3511 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3513 property = custom->GetSceneGraphProperty();
3515 else if( NULL != mNode )
3519 case Dali::Actor::Property::SIZE:
3520 property = &mNode->mSize;
3523 case Dali::Actor::Property::SIZE_WIDTH:
3524 property = &mNode->mSize;
3527 case Dali::Actor::Property::SIZE_HEIGHT:
3528 property = &mNode->mSize;
3531 case Dali::Actor::Property::SIZE_DEPTH:
3532 property = &mNode->mSize;
3535 case Dali::Actor::Property::POSITION:
3536 property = &mNode->mPosition;
3539 case Dali::Actor::Property::POSITION_X:
3540 property = &mNode->mPosition;
3543 case Dali::Actor::Property::POSITION_Y:
3544 property = &mNode->mPosition;
3547 case Dali::Actor::Property::POSITION_Z:
3548 property = &mNode->mPosition;
3551 case Dali::Actor::Property::ORIENTATION:
3552 property = &mNode->mOrientation;
3555 case Dali::Actor::Property::SCALE:
3556 property = &mNode->mScale;
3559 case Dali::Actor::Property::SCALE_X:
3560 property = &mNode->mScale;
3563 case Dali::Actor::Property::SCALE_Y:
3564 property = &mNode->mScale;
3567 case Dali::Actor::Property::SCALE_Z:
3568 property = &mNode->mScale;
3571 case Dali::Actor::Property::VISIBLE:
3572 property = &mNode->mVisible;
3575 case Dali::Actor::Property::COLOR:
3576 property = &mNode->mColor;
3579 case Dali::Actor::Property::COLOR_RED:
3580 property = &mNode->mColor;
3583 case Dali::Actor::Property::COLOR_GREEN:
3584 property = &mNode->mColor;
3587 case Dali::Actor::Property::COLOR_BLUE:
3588 property = &mNode->mColor;
3591 case Dali::Actor::Property::COLOR_ALPHA:
3592 case Dali::DevelActor::Property::OPACITY:
3593 property = &mNode->mColor;
3604 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
3606 const PropertyInputImpl* property( NULL );
3608 // This method should only return a property of an object connected to the scene-graph
3614 if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
3616 AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
3617 DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
3619 property = animatable->GetSceneGraphProperty();
3621 else if ( ( index >= CHILD_PROPERTY_REGISTRATION_START_INDEX ) && // Child properties are also stored as custom properties
3622 ( index <= PROPERTY_CUSTOM_MAX_INDEX ) )
3624 CustomPropertyMetadata* custom = FindCustomProperty( index );
3625 DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
3626 property = custom->GetSceneGraphProperty();
3628 else if( NULL != mNode )
3632 case Dali::Actor::Property::PARENT_ORIGIN:
3633 property = &mNode->mParentOrigin;
3636 case Dali::Actor::Property::PARENT_ORIGIN_X:
3637 property = &mNode->mParentOrigin;
3640 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3641 property = &mNode->mParentOrigin;
3644 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3645 property = &mNode->mParentOrigin;
3648 case Dali::Actor::Property::ANCHOR_POINT:
3649 property = &mNode->mAnchorPoint;
3652 case Dali::Actor::Property::ANCHOR_POINT_X:
3653 property = &mNode->mAnchorPoint;
3656 case Dali::Actor::Property::ANCHOR_POINT_Y:
3657 property = &mNode->mAnchorPoint;
3660 case Dali::Actor::Property::ANCHOR_POINT_Z:
3661 property = &mNode->mAnchorPoint;
3664 case Dali::Actor::Property::SIZE:
3665 property = &mNode->mSize;
3668 case Dali::Actor::Property::SIZE_WIDTH:
3669 property = &mNode->mSize;
3672 case Dali::Actor::Property::SIZE_HEIGHT:
3673 property = &mNode->mSize;
3676 case Dali::Actor::Property::SIZE_DEPTH:
3677 property = &mNode->mSize;
3680 case Dali::Actor::Property::POSITION:
3681 property = &mNode->mPosition;
3684 case Dali::Actor::Property::POSITION_X:
3685 property = &mNode->mPosition;
3688 case Dali::Actor::Property::POSITION_Y:
3689 property = &mNode->mPosition;
3692 case Dali::Actor::Property::POSITION_Z:
3693 property = &mNode->mPosition;
3696 case Dali::Actor::Property::WORLD_POSITION:
3697 property = &mNode->mWorldPosition;
3700 case Dali::Actor::Property::WORLD_POSITION_X:
3701 property = &mNode->mWorldPosition;
3704 case Dali::Actor::Property::WORLD_POSITION_Y:
3705 property = &mNode->mWorldPosition;
3708 case Dali::Actor::Property::WORLD_POSITION_Z:
3709 property = &mNode->mWorldPosition;
3712 case Dali::Actor::Property::ORIENTATION:
3713 property = &mNode->mOrientation;
3716 case Dali::Actor::Property::WORLD_ORIENTATION:
3717 property = &mNode->mWorldOrientation;
3720 case Dali::Actor::Property::SCALE:
3721 property = &mNode->mScale;
3724 case Dali::Actor::Property::SCALE_X:
3725 property = &mNode->mScale;
3728 case Dali::Actor::Property::SCALE_Y:
3729 property = &mNode->mScale;
3732 case Dali::Actor::Property::SCALE_Z:
3733 property = &mNode->mScale;
3736 case Dali::Actor::Property::WORLD_SCALE:
3737 property = &mNode->mWorldScale;
3740 case Dali::Actor::Property::VISIBLE:
3741 property = &mNode->mVisible;
3744 case Dali::Actor::Property::COLOR:
3745 property = &mNode->mColor;
3748 case Dali::Actor::Property::COLOR_RED:
3749 property = &mNode->mColor;
3752 case Dali::Actor::Property::COLOR_GREEN:
3753 property = &mNode->mColor;
3756 case Dali::Actor::Property::COLOR_BLUE:
3757 property = &mNode->mColor;
3760 case Dali::Actor::Property::COLOR_ALPHA:
3761 case Dali::DevelActor::Property::OPACITY:
3763 property = &mNode->mColor;
3767 case Dali::Actor::Property::WORLD_COLOR:
3768 property = &mNode->mWorldColor;
3771 case Dali::Actor::Property::WORLD_MATRIX:
3772 property = &mNode->mWorldMatrix;
3775 case Dali::DevelActor::Property::CULLED:
3776 property = &mNode->mCulled;
3787 int Actor::GetPropertyComponentIndex( Property::Index index ) const
3789 int componentIndex( Property::INVALID_COMPONENT_INDEX );
3791 if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
3793 // check whether the animatable property is registered already, if not then register one.
3794 AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
3795 if( animatableProperty )
3797 componentIndex = animatableProperty->componentIndex;
3804 case Dali::Actor::Property::PARENT_ORIGIN_X:
3805 case Dali::Actor::Property::ANCHOR_POINT_X:
3806 case Dali::Actor::Property::SIZE_WIDTH:
3807 case Dali::Actor::Property::POSITION_X:
3808 case Dali::Actor::Property::WORLD_POSITION_X:
3809 case Dali::Actor::Property::SCALE_X:
3810 case Dali::Actor::Property::COLOR_RED:
3816 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3817 case Dali::Actor::Property::ANCHOR_POINT_Y:
3818 case Dali::Actor::Property::SIZE_HEIGHT:
3819 case Dali::Actor::Property::POSITION_Y:
3820 case Dali::Actor::Property::WORLD_POSITION_Y:
3821 case Dali::Actor::Property::SCALE_Y:
3822 case Dali::Actor::Property::COLOR_GREEN:
3828 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3829 case Dali::Actor::Property::ANCHOR_POINT_Z:
3830 case Dali::Actor::Property::SIZE_DEPTH:
3831 case Dali::Actor::Property::POSITION_Z:
3832 case Dali::Actor::Property::WORLD_POSITION_Z:
3833 case Dali::Actor::Property::SCALE_Z:
3834 case Dali::Actor::Property::COLOR_BLUE:
3840 case Dali::Actor::Property::COLOR_ALPHA:
3841 case Dali::DevelActor::Property::OPACITY:
3855 return componentIndex;
3858 void Actor::SetParent( Actor* parent )
3862 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
3866 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3869 // Instruct each actor to create a corresponding node in the scene graph
3870 ConnectToStage( parent->GetHierarchyDepth() );
3873 // Resolve the name and index for the child properties if any
3874 ResolveChildProperties();
3876 else // parent being set to NULL
3878 DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
3882 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
3885 DALI_ASSERT_ALWAYS( mNode != NULL );
3889 // Disconnect the Node & its children from the scene-graph.
3890 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
3893 // Instruct each actor to discard pointers to the scene-graph
3894 DisconnectFromStage();
3899 SceneGraph::Node* Actor::CreateNode() const
3901 return Node::New( mId );
3904 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
3907 Actor* actor = dynamic_cast< Actor* >( object );
3911 if( 0 == actionName.compare( ACTION_SHOW ) )
3913 actor->SetVisible( true );
3916 else if( 0 == actionName.compare( ACTION_HIDE ) )
3918 actor->SetVisible( false );
3926 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
3928 bool valueSet = true;
3932 case Dali::Actor::Property::PARENT_ORIGIN:
3934 value = GetCurrentParentOrigin();
3938 case Dali::Actor::Property::PARENT_ORIGIN_X:
3940 value = GetCurrentParentOrigin().x;
3944 case Dali::Actor::Property::PARENT_ORIGIN_Y:
3946 value = GetCurrentParentOrigin().y;
3950 case Dali::Actor::Property::PARENT_ORIGIN_Z:
3952 value = GetCurrentParentOrigin().z;
3956 case Dali::Actor::Property::ANCHOR_POINT:
3958 value = GetCurrentAnchorPoint();
3962 case Dali::Actor::Property::ANCHOR_POINT_X:
3964 value = GetCurrentAnchorPoint().x;
3968 case Dali::Actor::Property::ANCHOR_POINT_Y:
3970 value = GetCurrentAnchorPoint().y;
3974 case Dali::Actor::Property::ANCHOR_POINT_Z:
3976 value = GetCurrentAnchorPoint().z;
3980 case Dali::Actor::Property::SIZE:
3982 value = GetTargetSize();
3986 case Dali::Actor::Property::SIZE_WIDTH:
3988 value = GetTargetSize().width;
3992 case Dali::Actor::Property::SIZE_HEIGHT:
3994 value = GetTargetSize().height;
3998 case Dali::Actor::Property::SIZE_DEPTH:
4000 value = GetTargetSize().depth;
4004 case Dali::Actor::Property::POSITION:
4006 value = GetTargetPosition();
4010 case Dali::Actor::Property::POSITION_X:
4012 value = GetTargetPosition().x;
4016 case Dali::Actor::Property::POSITION_Y:
4018 value = GetTargetPosition().y;
4022 case Dali::Actor::Property::POSITION_Z:
4024 value = GetTargetPosition().z;
4028 case Dali::Actor::Property::ORIENTATION:
4030 value = mTargetOrientation;
4034 case Dali::Actor::Property::SCALE:
4036 value = mTargetScale;
4040 case Dali::Actor::Property::SCALE_X:
4042 value = mTargetScale.x;
4046 case Dali::Actor::Property::SCALE_Y:
4048 value = mTargetScale.y;
4052 case Dali::Actor::Property::SCALE_Z:
4054 value = mTargetScale.z;
4058 case Dali::Actor::Property::VISIBLE:
4064 case Dali::Actor::Property::COLOR:
4066 value = mTargetColor;
4070 case Dali::Actor::Property::COLOR_RED:
4072 value = mTargetColor.r;
4076 case Dali::Actor::Property::COLOR_GREEN:
4078 value = mTargetColor.g;
4082 case Dali::Actor::Property::COLOR_BLUE:
4084 value = mTargetColor.b;
4088 case Dali::Actor::Property::COLOR_ALPHA:
4089 case Dali::DevelActor::Property::OPACITY:
4091 value = mTargetColor.a;
4095 case Dali::Actor::Property::NAME:
4101 case Dali::Actor::Property::SENSITIVE:
4103 value = IsSensitive();
4107 case Dali::Actor::Property::LEAVE_REQUIRED:
4109 value = GetLeaveRequired();
4113 case Dali::Actor::Property::INHERIT_POSITION:
4115 value = IsPositionInherited();
4119 case Dali::Actor::Property::INHERIT_ORIENTATION:
4121 value = IsOrientationInherited();
4125 case Dali::Actor::Property::INHERIT_SCALE:
4127 value = IsScaleInherited();
4131 case Dali::Actor::Property::COLOR_MODE:
4133 value = Scripting::GetLinearEnumerationName< ColorMode >( GetColorMode(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
4137 case Dali::Actor::Property::POSITION_INHERITANCE:
4139 value = Scripting::GetLinearEnumerationName< PositionInheritanceMode >( GetPositionInheritanceMode(), POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT );
4143 case Dali::Actor::Property::DRAW_MODE:
4145 value = Scripting::GetEnumerationName< DrawMode::Type >( GetDrawMode(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
4149 case Dali::Actor::Property::SIZE_MODE_FACTOR:
4151 value = GetSizeModeFactor();
4155 case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
4157 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
4161 case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
4163 value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), RESIZE_POLICY_TABLE, RESIZE_POLICY_TABLE_COUNT );
4167 case Dali::Actor::Property::SIZE_SCALE_POLICY:
4169 value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SIZE_SCALE_POLICY_TABLE, SIZE_SCALE_POLICY_TABLE_COUNT );
4173 case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
4175 value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
4179 case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
4181 value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
4185 case Dali::Actor::Property::PADDING:
4187 Vector2 widthPadding = GetPadding( Dimension::WIDTH );
4188 Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
4189 value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
4193 case Dali::Actor::Property::MINIMUM_SIZE:
4195 value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
4199 case Dali::Actor::Property::MAXIMUM_SIZE:
4201 value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
4205 case Dali::Actor::Property::CLIPPING_MODE:
4207 value = mClippingMode;
4211 case Dali::DevelActor::Property::SIBLING_ORDER:
4213 value = static_cast<int>( GetSiblingOrder() );
4217 case Dali::DevelActor::Property::SCREEN_POSITION:
4219 value = GetCurrentScreenPosition();
4223 case Dali::DevelActor::Property::POSITION_USES_ANCHOR_POINT:
4225 value = mPositionUsesAnchorPoint;
4229 case Dali::Actor::Property::LAYOUT_DIRECTION:
4231 value = mLayoutDirection;
4235 case Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION:
4237 value = IsLayoutDirectionInherited();
4243 // Must be a scene-graph only property
4252 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
4254 bool valueSet = true;
4258 case Dali::Actor::Property::SIZE:
4260 value = GetCurrentSize();
4264 case Dali::Actor::Property::SIZE_WIDTH:
4266 value = GetCurrentSize().width;
4270 case Dali::Actor::Property::SIZE_HEIGHT:
4272 value = GetCurrentSize().height;
4276 case Dali::Actor::Property::SIZE_DEPTH:
4278 value = GetCurrentSize().depth;
4282 case Dali::Actor::Property::POSITION:
4284 value = GetCurrentPosition();
4288 case Dali::Actor::Property::POSITION_X:
4290 value = GetCurrentPosition().x;
4294 case Dali::Actor::Property::POSITION_Y:
4296 value = GetCurrentPosition().y;
4300 case Dali::Actor::Property::POSITION_Z:
4302 value = GetCurrentPosition().z;
4306 case Dali::Actor::Property::WORLD_POSITION:
4308 value = GetCurrentWorldPosition();
4312 case Dali::Actor::Property::WORLD_POSITION_X:
4314 value = GetCurrentWorldPosition().x;
4318 case Dali::Actor::Property::WORLD_POSITION_Y:
4320 value = GetCurrentWorldPosition().y;
4324 case Dali::Actor::Property::WORLD_POSITION_Z:
4326 value = GetCurrentWorldPosition().z;
4330 case Dali::Actor::Property::ORIENTATION:
4332 value = GetCurrentOrientation();
4336 case Dali::Actor::Property::WORLD_ORIENTATION:
4338 value = GetCurrentWorldOrientation();
4342 case Dali::Actor::Property::SCALE:
4344 value = GetCurrentScale();
4348 case Dali::Actor::Property::SCALE_X:
4350 value = GetCurrentScale().x;
4354 case Dali::Actor::Property::SCALE_Y:
4356 value = GetCurrentScale().y;
4360 case Dali::Actor::Property::SCALE_Z:
4362 value = GetCurrentScale().z;
4366 case Dali::Actor::Property::WORLD_SCALE:
4368 value = GetCurrentWorldScale();
4372 case Dali::Actor::Property::COLOR:
4374 value = GetCurrentColor();
4378 case Dali::Actor::Property::COLOR_RED:
4380 value = GetCurrentColor().r;
4384 case Dali::Actor::Property::COLOR_GREEN:
4386 value = GetCurrentColor().g;
4390 case Dali::Actor::Property::COLOR_BLUE:
4392 value = GetCurrentColor().b;
4396 case Dali::Actor::Property::COLOR_ALPHA:
4397 case Dali::DevelActor::Property::OPACITY:
4399 value = GetCurrentColor().a;
4403 case Dali::Actor::Property::WORLD_COLOR:
4405 value = GetCurrentWorldColor();
4409 case Dali::Actor::Property::WORLD_MATRIX:
4411 value = GetCurrentWorldMatrix();
4415 case Dali::Actor::Property::VISIBLE:
4417 value = IsVisible();
4421 case DevelActor::Property::CULLED:
4423 value = mNode->IsCulled( GetEventThreadServices().GetEventBufferIndex() );
4429 // Must be an event-side only property
4438 void Actor::EnsureRelayoutData()
4440 // Assign relayout data.
4441 if( !mRelayoutData )
4443 mRelayoutData = new RelayoutData();
4447 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
4449 // Check if actor is dependent on parent
4450 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4452 if( ( dimension & ( 1 << i ) ) )
4454 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4455 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
4465 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
4467 // Check if actor is dependent on children
4468 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4470 if( ( dimension & ( 1 << i ) ) )
4472 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
4473 switch( resizePolicy )
4475 case ResizePolicy::FIT_TO_CHILDREN:
4476 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
4492 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
4494 return Actor::RelayoutDependentOnChildren( dimension );
4497 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
4499 // Check each possible dimension and see if it is dependent on the input one
4500 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4502 if( dimension & ( 1 << i ) )
4504 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
4511 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
4513 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4515 if( dimension & ( 1 << i ) )
4517 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
4522 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
4524 // If more than one dimension is requested, just return the first one found
4525 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4527 if( ( dimension & ( 1 << i ) ) )
4529 return mRelayoutData->negotiatedDimensions[ i ];
4533 return 0.0f; // Default
4536 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
4538 EnsureRelayoutData();
4540 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4542 if( dimension & ( 1 << i ) )
4544 mRelayoutData->dimensionPadding[ i ] = padding;
4549 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
4551 if ( mRelayoutData )
4553 // If more than one dimension is requested, just return the first one found
4554 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4556 if( ( dimension & ( 1 << i ) ) )
4558 return mRelayoutData->dimensionPadding[ i ];
4563 return GetDefaultDimensionPadding();
4566 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
4568 EnsureRelayoutData();
4570 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4572 if( dimension & ( 1 << i ) )
4574 mRelayoutData->dimensionNegotiated[ i ] = negotiated;
4579 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
4581 if ( mRelayoutData )
4583 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4585 if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
4595 float Actor::GetHeightForWidthBase( float width )
4597 float height = 0.0f;
4599 const Vector3 naturalSize = GetNaturalSize();
4600 if( naturalSize.width > 0.0f )
4602 height = naturalSize.height * width / naturalSize.width;
4604 else // we treat 0 as 1:1 aspect ratio
4612 float Actor::GetWidthForHeightBase( float height )
4616 const Vector3 naturalSize = GetNaturalSize();
4617 if( naturalSize.height > 0.0f )
4619 width = naturalSize.width * height / naturalSize.height;
4621 else // we treat 0 as 1:1 aspect ratio
4629 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
4631 // Fill to parent, taking size mode factor into account
4632 switch( child.GetResizePolicy( dimension ) )
4634 case ResizePolicy::FILL_TO_PARENT:
4636 return GetLatestSize( dimension );
4639 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4641 return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
4644 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4646 return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
4651 return GetLatestSize( dimension );
4656 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
4658 // Can be overridden in derived class
4659 return CalculateChildSizeBase( child, dimension );
4662 float Actor::GetHeightForWidth( float width )
4664 // Can be overridden in derived class
4665 return GetHeightForWidthBase( width );
4668 float Actor::GetWidthForHeight( float height )
4670 // Can be overridden in derived class
4671 return GetWidthForHeightBase( height );
4674 float Actor::GetLatestSize( Dimension::Type dimension ) const
4676 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
4679 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
4681 Vector2 padding = GetPadding( dimension );
4683 return GetLatestSize( dimension ) + padding.x + padding.y;
4686 float Actor::NegotiateFromParent( Dimension::Type dimension )
4688 Actor* parent = GetParent();
4691 Vector2 padding( GetPadding( dimension ) );
4692 Vector2 parentPadding( parent->GetPadding( dimension ) );
4693 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
4699 float Actor::NegotiateFromChildren( Dimension::Type dimension )
4701 float maxDimensionPoint = 0.0f;
4703 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4705 ActorPtr child = GetChildAt( i );
4707 if( !child->RelayoutDependentOnParent( dimension ) )
4709 // Calculate the min and max points that the children range across
4710 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
4711 float dimensionSize = child->GetRelayoutSize( dimension );
4712 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
4716 return maxDimensionPoint;
4719 float Actor::GetSize( Dimension::Type dimension ) const
4721 return GetDimensionValue( mTargetSize, dimension );
4724 float Actor::GetNaturalSize( Dimension::Type dimension ) const
4726 return GetDimensionValue( GetNaturalSize(), dimension );
4729 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
4731 switch( GetResizePolicy( dimension ) )
4733 case ResizePolicy::USE_NATURAL_SIZE:
4735 return GetNaturalSize( dimension );
4738 case ResizePolicy::FIXED:
4740 return GetDimensionValue( GetPreferredSize(), dimension );
4743 case ResizePolicy::USE_ASSIGNED_SIZE:
4745 return GetDimensionValue( maximumSize, dimension );
4748 case ResizePolicy::FILL_TO_PARENT:
4749 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
4750 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
4752 return NegotiateFromParent( dimension );
4755 case ResizePolicy::FIT_TO_CHILDREN:
4757 return NegotiateFromChildren( dimension );
4760 case ResizePolicy::DIMENSION_DEPENDENCY:
4762 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
4765 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
4767 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
4770 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
4772 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
4784 return 0.0f; // Default
4787 float Actor::ClampDimension( float size, Dimension::Type dimension )
4789 const float minSize = GetMinimumSize( dimension );
4790 const float maxSize = GetMaximumSize( dimension );
4792 return std::max( minSize, std::min( size, maxSize ) );
4795 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
4797 // Check if it needs to be negotiated
4798 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
4800 // Check that we havn't gotten into an infinite loop
4801 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
4802 bool recursionFound = false;
4803 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
4805 if( *it == searchActor )
4807 recursionFound = true;
4812 if( !recursionFound )
4814 // Record the path that we have taken
4815 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
4817 // Dimension dependency check
4818 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4820 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
4822 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
4824 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
4828 // Parent dependency check
4829 Actor* parent = GetParent();
4830 if( parent && RelayoutDependentOnParent( dimension ) )
4832 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
4835 // Children dependency check
4836 if( RelayoutDependentOnChildren( dimension ) )
4838 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
4840 ActorPtr child = GetChildAt( i );
4842 // Only relayout child first if it is not dependent on this actor
4843 if( !child->RelayoutDependentOnParent( dimension ) )
4845 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
4850 // For deriving classes
4851 OnCalculateRelayoutSize( dimension );
4853 // All dependencies checked, calculate the size and set negotiated flag
4854 const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
4856 SetNegotiatedDimension( newSize, dimension );
4857 SetLayoutNegotiated( true, dimension );
4859 // For deriving classes
4860 OnLayoutNegotiated( newSize, dimension );
4862 // This actor has been successfully processed, pop it off the recursion stack
4863 recursionStack.pop_back();
4867 // TODO: Break infinite loop
4868 SetLayoutNegotiated( true, dimension );
4873 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
4875 // Negotiate all dimensions that require it
4876 ActorDimensionStack recursionStack;
4878 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
4880 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
4883 NegotiateDimension( dimension, allocatedSize, recursionStack );
4887 Vector2 Actor::ApplySizeSetPolicy( const Vector2& size )
4889 switch( mRelayoutData->sizeSetPolicy )
4891 case SizeScalePolicy::USE_SIZE_SET:
4896 case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
4898 // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
4899 const Vector3 naturalSize = GetNaturalSize();
4900 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4902 const float sizeRatio = size.width / size.height;
4903 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4905 if( naturalSizeRatio < sizeRatio )
4907 return Vector2( naturalSizeRatio * size.height, size.height );
4909 else if( naturalSizeRatio > sizeRatio )
4911 return Vector2( size.width, size.width / naturalSizeRatio );
4922 case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
4924 // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
4925 const Vector3 naturalSize = GetNaturalSize();
4926 if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
4928 const float sizeRatio = size.width / size.height;
4929 const float naturalSizeRatio = naturalSize.width / naturalSize.height;
4931 if( naturalSizeRatio < sizeRatio )
4933 return Vector2( size.width, size.width / naturalSizeRatio );
4935 else if( naturalSizeRatio > sizeRatio )
4937 return Vector2( naturalSizeRatio * size.height, size.height );
4956 void Actor::SetNegotiatedSize( RelayoutContainer& container )
4958 // Do the set actor size
4959 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
4961 // Adjust for size set policy
4962 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
4964 // Lock the flag to stop recursive relayouts on set size
4965 mRelayoutData->insideRelayout = true;
4966 SetSize( negotiatedSize );
4967 mRelayoutData->insideRelayout = false;
4969 // Clear flags for all dimensions
4970 SetLayoutDirty( false );
4972 // Give deriving classes a chance to respond
4973 OnRelayout( negotiatedSize, container );
4975 if( !mOnRelayoutSignal.Empty() )
4977 Dali::Actor handle( this );
4978 mOnRelayoutSignal.Emit( handle );
4982 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
4984 // Force a size negotiation for actors that has assigned size during relayout
4985 // This is required as otherwise the flags that force a relayout will not
4986 // necessarilly be set. This will occur if the actor has already been laid out.
4987 // The dirty flags are then cleared. Then if the actor is added back into the
4988 // relayout container afterwards, the dirty flags would still be clear...
4989 // causing a relayout to be skipped. Here we force any actors added to the
4990 // container to be relayed out.
4991 DALI_LOG_TIMER_START( NegSizeTimer1 );
4993 if( GetUseAssignedSize(Dimension::WIDTH ) )
4995 SetLayoutNegotiated( false, Dimension::WIDTH );
4997 if( GetUseAssignedSize( Dimension::HEIGHT ) )
4999 SetLayoutNegotiated( false, Dimension::HEIGHT );
5002 // Do the negotiation
5003 NegotiateDimensions( allocatedSize );
5005 // Set the actor size
5006 SetNegotiatedSize( container );
5008 // Negotiate down to children
5009 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
5011 ActorPtr child = GetChildAt( i );
5013 // Forces children that have already been laid out to be relayed out
5014 // if they have assigned size during relayout.
5015 if( child->GetUseAssignedSize(Dimension::WIDTH) )
5017 child->SetLayoutNegotiated(false, Dimension::WIDTH);
5018 child->SetLayoutDirty(true, Dimension::WIDTH);
5021 if( child->GetUseAssignedSize(Dimension::HEIGHT) )
5023 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
5024 child->SetLayoutDirty(true, Dimension::HEIGHT);
5027 // Only relayout if required
5028 if( child->RelayoutRequired() )
5030 container.Add( Dali::Actor( child.Get() ), mTargetSize.GetVectorXY() );
5033 DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
5036 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
5040 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5042 if( dimension & ( 1 << i ) )
5044 mRelayoutData->useAssignedSize[ i ] = use;
5050 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
5052 if ( mRelayoutData )
5054 // If more than one dimension is requested, just return the first one found
5055 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5057 if( dimension & ( 1 << i ) )
5059 return mRelayoutData->useAssignedSize[ i ];
5067 void Actor::RelayoutRequest( Dimension::Type dimension )
5069 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
5070 if( relayoutController )
5072 Dali::Actor self( this );
5073 relayoutController->RequestRelayout( self, dimension );
5077 void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
5081 void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
5085 void Actor::SetPreferredSize( const Vector2& size )
5087 EnsureRelayoutData();
5089 if( size.width > 0.0f )
5091 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
5094 if( size.height > 0.0f )
5096 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
5099 mRelayoutData->preferredSize = size;
5104 Vector2 Actor::GetPreferredSize() const
5106 if ( mRelayoutData )
5108 return Vector2( mRelayoutData->preferredSize );
5111 return GetDefaultPreferredSize();
5114 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
5116 EnsureRelayoutData();
5118 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5120 if( dimension & ( 1 << i ) )
5122 mRelayoutData->minimumSize[ i ] = size;
5129 float Actor::GetMinimumSize( Dimension::Type dimension ) const
5131 if ( mRelayoutData )
5133 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5135 if( dimension & ( 1 << i ) )
5137 return mRelayoutData->minimumSize[ i ];
5142 return 0.0f; // Default
5145 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
5147 EnsureRelayoutData();
5149 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5151 if( dimension & ( 1 << i ) )
5153 mRelayoutData->maximumSize[ i ] = size;
5160 float Actor::GetMaximumSize( Dimension::Type dimension ) const
5162 if ( mRelayoutData )
5164 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
5166 if( dimension & ( 1 << i ) )
5168 return mRelayoutData->maximumSize[ i ];
5173 return FLT_MAX; // Default
5176 Object* Actor::GetParentObject() const
5181 void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
5183 if( mVisible != visible )
5185 if( sendMessage == SendMessage::TRUE && NULL != mNode )
5187 // mNode is being used in a separate thread; queue a message to set the value & base value
5188 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
5193 // Emit the signal on this actor and all its children
5194 EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
5198 void Actor::SetSiblingOrder( uint32_t order )
5202 ActorContainer& siblings = *(mParent->mChildren);
5203 uint32_t currentOrder = GetSiblingOrder();
5205 if( order != currentOrder )
5211 else if( order < siblings.size() -1 )
5213 if( order > currentOrder )
5215 RaiseAbove( *siblings[order] );
5219 LowerBelow( *siblings[order] );
5230 uint32_t Actor::GetSiblingOrder() const
5236 ActorContainer& siblings = *(mParent->mChildren);
5237 for( std::size_t i = 0; i < siblings.size(); ++i )
5239 if( siblings[i] == this )
5241 order = static_cast<uint32_t>( i );
5250 void Actor::RequestRebuildDepthTree()
5254 StagePtr stage = Stage::GetCurrent();
5257 stage->RequestRebuildDepthTree();
5266 ActorContainer& siblings = *(mParent->mChildren);
5267 if( siblings.back() != this ) // If not already at end
5269 for( std::size_t i=0; i<siblings.size(); ++i )
5271 if( siblings[i] == this )
5274 ActorPtr next = siblings[i+1];
5275 siblings[i+1] = this;
5282 Dali::Actor handle( this );
5283 mParent->mChildOrderChangedSignal.Emit( handle );
5285 RequestRebuildDepthTree();
5289 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5297 ActorContainer& siblings = *(mParent->mChildren);
5298 if( siblings.front() != this ) // If not already at beginning
5300 for( std::size_t i=1; i<siblings.size(); ++i )
5302 if( siblings[i] == this )
5304 // Swap with previous
5305 ActorPtr previous = siblings[i-1];
5306 siblings[i-1] = this;
5307 siblings[i] = previous;
5313 Dali::Actor handle( this );
5314 mParent->mChildOrderChangedSignal.Emit( handle );
5316 RequestRebuildDepthTree();
5320 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5324 void Actor::RaiseToTop()
5328 ActorContainer& siblings = *(mParent->mChildren);
5329 if( siblings.back() != this ) // If not already at end
5331 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
5332 if( iter != siblings.end() )
5334 siblings.erase(iter);
5335 siblings.push_back(ActorPtr(this));
5339 Dali::Actor handle( this );
5340 mParent->mChildOrderChangedSignal.Emit( handle );
5342 RequestRebuildDepthTree();
5346 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5350 void Actor::LowerToBottom()
5354 ActorContainer& siblings = *(mParent->mChildren);
5355 if( siblings.front() != this ) // If not already at bottom,
5357 ActorPtr thisPtr(this); // ensure this actor remains referenced.
5359 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
5360 if( iter != siblings.end() )
5362 siblings.erase(iter);
5363 siblings.insert(siblings.begin(), thisPtr);
5367 Dali::Actor handle( this );
5368 mParent->mChildOrderChangedSignal.Emit( handle );
5370 RequestRebuildDepthTree();
5374 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5378 void Actor::RaiseAbove( Internal::Actor& target )
5382 ActorContainer& siblings = *(mParent->mChildren);
5383 if( siblings.back() != this && target.mParent == mParent ) // If not already at top
5385 ActorPtr thisPtr(this); // ensure this actor remains referenced.
5387 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
5388 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
5389 if( thisIter < targetIter )
5391 siblings.erase(thisIter);
5392 // Erasing early invalidates the targetIter. (Conversely, inserting first may also
5393 // invalidate thisIter)
5394 targetIter = std::find( siblings.begin(), siblings.end(), &target );
5396 siblings.insert(targetIter, thisPtr);
5399 Dali::Actor handle( this );
5400 mParent->mChildOrderChangedSignal.Emit( handle );
5402 RequestRebuildDepthTree();
5407 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5411 void Actor::LowerBelow( Internal::Actor& target )
5415 ActorContainer& siblings = *(mParent->mChildren);
5416 if( siblings.front() != this && target.mParent == mParent ) // If not already at bottom
5418 ActorPtr thisPtr(this); // ensure this actor remains referenced.
5420 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
5421 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
5423 if( thisIter > targetIter )
5425 siblings.erase(thisIter); // this only invalidates iterators at or after this point.
5426 siblings.insert(targetIter, thisPtr);
5429 Dali::Actor handle( this );
5430 mParent->mChildOrderChangedSignal.Emit( handle );
5432 RequestRebuildDepthTree();
5437 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
5441 void Actor::SetInheritLayoutDirection( bool inherit )
5443 if( mInheritLayoutDirection != inherit )
5445 mInheritLayoutDirection = inherit;
5447 if( inherit && mParent )
5449 InheritLayoutDirectionRecursively( this, mParent->mLayoutDirection );
5454 bool Actor::IsLayoutDirectionInherited() const
5456 return mInheritLayoutDirection;
5459 void Actor::InheritLayoutDirectionRecursively( ActorPtr actor, Dali::LayoutDirection::Type direction, bool set )
5461 if( actor && ( actor->mInheritLayoutDirection || set ) )
5463 if( actor->mLayoutDirection != direction )
5465 actor->mLayoutDirection = direction;
5466 actor->EmitLayoutDirectionChangedSignal( direction );
5467 actor->RelayoutRequest();
5470 if( actor->GetChildCount() > 0 )
5472 ActorContainer& children = actor->GetChildrenInternal();
5473 for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter )
5475 InheritLayoutDirectionRecursively( *iter, direction );
5481 } // namespace Internal