2 * Copyright (c) 2020 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/math/vector2.h>
31 #include <dali/public-api/math/vector3.h>
32 #include <dali/public-api/math/radian.h>
33 #include <dali/public-api/object/type-registry.h>
34 #include <dali/devel-api/actors/actor-devel.h>
35 #include <dali/internal/event/actors/actor-property-handler.h>
36 #include <dali/internal/event/actors/actor-relayouter.h>
37 #include <dali/internal/event/common/event-thread-services.h>
38 #include <dali/internal/event/render-tasks/render-task-impl.h>
39 #include <dali/internal/event/actors/camera-actor-impl.h>
40 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
41 #include <dali/internal/event/common/property-helper.h>
42 #include <dali/internal/event/common/stage-impl.h>
43 #include <dali/internal/event/common/type-info-impl.h>
44 #include <dali/internal/event/common/scene-impl.h>
45 #include <dali/internal/event/common/thread-local-storage.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/nodes/node-messages.h>
49 #include <dali/internal/event/events/actor-gesture-data.h>
50 #include <dali/integration-api/debug.h>
52 using Dali::Internal::SceneGraph::Node;
53 using Dali::Internal::SceneGraph::AnimatableProperty;
54 using Dali::Internal::SceneGraph::PropertyBase;
56 #if defined(DEBUG_ENABLED)
57 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_DEPTH_TIMER" );
58 Debug::Filter* gLogRelayoutFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_TIMER" );
67 namespace // unnamed namespace
73 * We want to discourage the use of property strings (minimize string comparisons),
74 * particularly for the default properties.
75 * Name Type writable animatable constraint-input enum for index-checking
77 DALI_PROPERTY_TABLE_BEGIN
78 DALI_PROPERTY( "parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
79 DALI_PROPERTY( "parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
80 DALI_PROPERTY( "parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
81 DALI_PROPERTY( "parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
82 DALI_PROPERTY( "anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
83 DALI_PROPERTY( "anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
84 DALI_PROPERTY( "anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
85 DALI_PROPERTY( "anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
86 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
87 DALI_PROPERTY( "sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
88 DALI_PROPERTY( "sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
89 DALI_PROPERTY( "sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
90 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
91 DALI_PROPERTY( "positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
92 DALI_PROPERTY( "positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
93 DALI_PROPERTY( "positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
94 DALI_PROPERTY( "worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
95 DALI_PROPERTY( "worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
96 DALI_PROPERTY( "worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
97 DALI_PROPERTY( "worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
98 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
99 DALI_PROPERTY( "worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
100 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
101 DALI_PROPERTY( "scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
102 DALI_PROPERTY( "scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
103 DALI_PROPERTY( "scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
104 DALI_PROPERTY( "worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
105 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
106 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
107 DALI_PROPERTY( "colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
108 DALI_PROPERTY( "colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
109 DALI_PROPERTY( "colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
110 DALI_PROPERTY( "colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
111 DALI_PROPERTY( "worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
112 DALI_PROPERTY( "worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
113 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
114 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
115 DALI_PROPERTY( "leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
116 DALI_PROPERTY( "inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
117 DALI_PROPERTY( "inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
118 DALI_PROPERTY( "colorMode", INTEGER, true, false, false, Dali::Actor::Property::COLOR_MODE )
119 DALI_PROPERTY( "drawMode", INTEGER, true, false, false, Dali::Actor::Property::DRAW_MODE )
120 DALI_PROPERTY( "sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
121 DALI_PROPERTY( "widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
122 DALI_PROPERTY( "heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
123 DALI_PROPERTY( "sizeScalePolicy", INTEGER, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
124 DALI_PROPERTY( "widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
125 DALI_PROPERTY( "heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
126 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
127 DALI_PROPERTY( "minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
128 DALI_PROPERTY( "maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
129 DALI_PROPERTY( "inheritPosition", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_POSITION )
130 DALI_PROPERTY( "clippingMode", STRING, true, false, false, Dali::Actor::Property::CLIPPING_MODE )
131 DALI_PROPERTY( "layoutDirection", STRING, true, false, false, Dali::Actor::Property::LAYOUT_DIRECTION )
132 DALI_PROPERTY( "inheritLayoutDirection", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION )
133 DALI_PROPERTY( "opacity", FLOAT, true, true, true, Dali::Actor::Property::OPACITY )
134 DALI_PROPERTY( "screenPosition", VECTOR2, false, false, false, Dali::Actor::Property::SCREEN_POSITION )
135 DALI_PROPERTY( "positionUsesAnchorPoint", BOOLEAN, true, false, false, Dali::Actor::Property::POSITION_USES_ANCHOR_POINT )
136 DALI_PROPERTY( "culled", BOOLEAN, false, false, true, Dali::Actor::Property::CULLED )
137 DALI_PROPERTY( "id", INTEGER, false, false, false, Dali::Actor::Property::ID )
138 DALI_PROPERTY( "hierarchyDepth", INTEGER, false, false, false, Dali::Actor::Property::HIERARCHY_DEPTH )
139 DALI_PROPERTY( "isRoot", BOOLEAN, false, false, false, Dali::Actor::Property::IS_ROOT )
140 DALI_PROPERTY( "isLayer", BOOLEAN, false, false, false, Dali::Actor::Property::IS_LAYER )
141 DALI_PROPERTY( "connectedToScene", BOOLEAN, false, false, false, Dali::Actor::Property::CONNECTED_TO_SCENE )
142 DALI_PROPERTY( "keyboardFocusable", BOOLEAN, true, false, false, Dali::Actor::Property::KEYBOARD_FOCUSABLE )
143 DALI_PROPERTY( "siblingOrder", INTEGER, true, false, false, Dali::DevelActor::Property::SIBLING_ORDER )
144 DALI_PROPERTY( "updateSizeHint", VECTOR2, true, false, false, Dali::DevelActor::Property::UPDATE_SIZE_HINT )
145 DALI_PROPERTY( "captureAllTouchAfterStart", BOOLEAN, true, false, false, Dali::DevelActor::Property::CAPTURE_ALL_TOUCH_AFTER_START )
146 DALI_PROPERTY( "touchDelegateArea", VECTOR2, true, false, false, Dali::DevelActor::Property::TOUCH_DELEGATE_AREA )
147 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperties )
151 const char* const SIGNAL_HOVERED = "hovered";
152 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
153 const char* const SIGNAL_ON_SCENE = "onScene";
154 const char* const SIGNAL_OFF_SCENE = "offScene";
155 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
156 const char* const SIGNAL_TOUCHED = "touched";
157 const char* const SIGNAL_VISIBILITY_CHANGED = "visibilityChanged";
158 const char* const SIGNAL_LAYOUT_DIRECTION_CHANGED = "layoutDirectionChanged";
159 const char* const SIGNAL_CHILD_ADDED = "childAdded";
160 const char* const SIGNAL_CHILD_REMOVED = "childRemoved";
164 const char* const ACTION_SHOW = "show";
165 const char* const ACTION_HIDE = "hide";
167 BaseHandle CreateActor()
169 return Dali::Actor::New();
172 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor, ActorDefaultProperties );
174 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
175 SignalConnectorType signalConnector3( mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal );
176 SignalConnectorType signalConnector4( mType, SIGNAL_ON_SCENE, &Actor::DoConnectSignal );
177 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_SCENE, &Actor::DoConnectSignal );
178 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
179 SignalConnectorType signalConnector7( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
180 SignalConnectorType signalConnector8( mType, SIGNAL_VISIBILITY_CHANGED, &Actor::DoConnectSignal );
181 SignalConnectorType signalConnector9( mType, SIGNAL_LAYOUT_DIRECTION_CHANGED, &Actor::DoConnectSignal );
182 SignalConnectorType signalConnector10( mType, SIGNAL_CHILD_ADDED, &Actor::DoConnectSignal );
183 SignalConnectorType signalConnector11( mType, SIGNAL_CHILD_REMOVED, &Actor::DoConnectSignal );
185 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
186 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
189 * @brief Extract a given dimension from a Vector2
191 * @param[in] values The values to extract from
192 * @param[in] dimension The dimension to extract
193 * @return Return the value for the dimension
195 constexpr float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
199 case Dimension::WIDTH:
203 case Dimension::HEIGHT:
205 return values.height;
216 * @brief Extract a given dimension from a Vector3
218 * @param[in] values The values to extract from
219 * @param[in] dimension The dimension to extract
220 * @return Return the value for the dimension
222 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
224 return GetDimensionValue( values.GetVectorXY(), dimension );
228 * @brief Recursively emits the visibility-changed-signal on the actor tree.
229 * @param[in] actor The actor to emit the signal on
230 * @param[in] visible The new visibility of the actor
231 * @param[in] type Whether the actor's visible property has changed or a parent's
233 void EmitVisibilityChangedSignalRecursively( ActorPtr actor, bool visible, DevelActor::VisibilityChange::Type type )
237 actor->EmitVisibilityChangedSignal( visible, type );
239 if( actor->GetChildCount() > 0 )
241 for( ActorPtr& child : actor->GetChildrenInternal() )
243 EmitVisibilityChangedSignalRecursively( child, visible, DevelActor::VisibilityChange::PARENT );
249 /// Helper for emitting a signal
250 template<typename Signal, typename Event>
251 bool EmitConsumingSignal( Actor& actor, Signal& signal, const Event& event )
253 bool consumed = false;
255 if( !signal.Empty() )
257 Dali::Actor handle( &actor );
258 consumed = signal.Emit( handle, event );
264 /// Helper for emitting signals with multiple parameters
265 template<typename Signal, typename... Param>
266 void EmitSignal( Actor& actor, Signal& signal, Param... params)
268 if( !signal.Empty() )
270 Dali::Actor handle( &actor );
271 signal.Emit( handle, params... );
275 bool ScreenToLocalInternal(
276 const Matrix& viewMatrix,
277 const Matrix& projectionMatrix,
278 const Matrix& worldMatrix,
279 const Viewport& viewport,
280 const Vector3& currentSize,
286 // Get the ModelView matrix
288 Matrix::Multiply( modelView, worldMatrix, viewMatrix );
290 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
291 Matrix invertedMvp( false/*don't init*/);
292 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
293 bool success = invertedMvp.Invert();
295 // Convert to GL coordinates
296 Vector4 screenPos( screenX - static_cast<float>( viewport.x ), static_cast<float>( viewport.height ) - screenY - static_cast<float>( viewport.y ), 0.f, 1.f );
301 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), nearPos );
308 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), farPos );
314 if( XyPlaneIntersect( nearPos, farPos, local ) )
316 Vector3 size = currentSize;
317 localX = local.x + size.x * 0.5f;
318 localY = local.y + size.y * 0.5f;
329 } // unnamed namespace
331 ActorPtr Actor::New()
333 // pass a reference to actor, actor does not own its node
334 ActorPtr actor( new Actor( BASIC, *CreateNode() ) );
336 // Second-phase construction
342 const SceneGraph::Node* Actor::CreateNode()
344 // create node. Nodes are owned by the update manager
345 SceneGraph::Node* node = SceneGraph::Node::New();
346 OwnerPointer< SceneGraph::Node > transferOwnership( node );
347 Internal::ThreadLocalStorage* tls = Internal::ThreadLocalStorage::GetInternal();
349 DALI_ASSERT_ALWAYS( tls && "ThreadLocalStorage is null" );
351 AddNodeMessage( tls->GetUpdateManager(), transferOwnership );
356 void Actor::SetName( const std::string& name )
360 // ATTENTION: string for debug purposes is not thread safe.
361 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( &GetNode() ), name );
364 uint32_t Actor::GetId() const
366 return GetNode().GetId();
369 Dali::Layer Actor::GetLayer()
373 // Short-circuit for Layer derived actors
376 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
379 // Find the immediate Layer parent
380 for( Actor* parent = mParent; !layer && parent != nullptr; parent = parent->GetParent() )
382 if( parent->IsLayer() )
384 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
391 void Actor::Add( Actor& child )
393 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
394 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
398 mChildren = new ActorContainer;
401 Actor* const oldParent( child.mParent );
403 // child might already be ours
404 if( this != oldParent )
406 // if we already have parent, unparent us first
409 oldParent->Remove( child ); // This causes OnChildRemove callback & ChildRemoved signal
411 // Old parent may need to readjust to missing child
412 if( oldParent->RelayoutDependentOnChildren() )
414 oldParent->RelayoutRequest();
418 // Guard against Add() during previous OnChildRemove callback
421 // Do this first, since user callbacks from within SetParent() may need to remove child
422 mChildren->push_back( ActorPtr( &child ) );
424 // SetParent asserts that child can be added
425 child.SetParent( this );
427 // Notification for derived classes
429 EmitChildAddedSignal( child );
431 InheritLayoutDirectionRecursively( ActorPtr( &child ), mLayoutDirection );
433 // Only put in a relayout request if there is a suitable dependency
434 if( RelayoutDependentOnChildren() )
442 void Actor::Remove( Actor& child )
444 if( (this == &child) || (!mChildren) )
446 // no children or removing itself
452 // Find the child in mChildren, and unparent it
453 ActorIter end = mChildren->end();
454 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
456 ActorPtr actor = (*iter);
458 if( actor.Get() == &child )
460 // Keep handle for OnChildRemove notification
463 // Do this first, since user callbacks from within SetParent() may need to add the child
464 mChildren->erase( iter );
466 DALI_ASSERT_DEBUG( actor->GetParent() == this );
467 actor->SetParent( nullptr );
475 // Only put in a relayout request if there is a suitable dependency
476 if( RelayoutDependentOnChildren() )
482 // Notification for derived classes
483 OnChildRemove( child );
484 EmitChildRemovedSignal( child );
487 void Actor::Unparent()
491 // Remove this actor from the parent. The remove will put a relayout request in for
492 // the parent if required
493 mParent->Remove( *this );
494 // mParent is now NULL!
498 uint32_t Actor::GetChildCount() const
500 return ( nullptr != mChildren ) ? static_cast<uint32_t>( mChildren->size() ) : 0; // only 4,294,967,295 children per actor
503 ActorPtr Actor::GetChildAt( uint32_t index ) const
505 DALI_ASSERT_ALWAYS( index < GetChildCount() );
507 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
510 ActorPtr Actor::FindChildByName( const std::string& actorName )
512 ActorPtr child = nullptr;
513 if( actorName == mName )
519 ActorIter end = mChildren->end();
520 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
522 child = (*iter)->FindChildByName( actorName );
533 ActorPtr Actor::FindChildById( const uint32_t id )
535 ActorPtr child = nullptr;
542 ActorIter end = mChildren->end();
543 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
545 child = (*iter)->FindChildById( id );
556 void Actor::SetParentOrigin( const Vector3& origin )
558 // node is being used in a separate thread; queue a message to set the value & base value
559 SetParentOriginMessage( GetEventThreadServices(), GetNode(), origin );
561 // Cache for event-thread access
564 // not allocated, check if different from default
565 if( ParentOrigin::DEFAULT != origin )
567 mParentOrigin = new Vector3( origin );
572 // check if different from current costs more than just set
573 *mParentOrigin = origin;
577 const Vector3& Actor::GetCurrentParentOrigin() const
579 // Cached for event-thread access
580 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
583 void Actor::SetAnchorPoint( const Vector3& anchor )
585 // node is being used in a separate thread; queue a message to set the value & base value
586 SetAnchorPointMessage( GetEventThreadServices(), GetNode(), anchor );
588 // Cache for event-thread access
591 // not allocated, check if different from default
592 if( AnchorPoint::DEFAULT != anchor )
594 mAnchorPoint = new Vector3( anchor );
599 // check if different from current costs more than just set
600 *mAnchorPoint = anchor;
604 const Vector3& Actor::GetCurrentAnchorPoint() const
606 // Cached for event-thread access
607 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
610 void Actor::SetPosition( float x, float y )
612 SetPosition( Vector3( x, y, 0.0f ) );
615 void Actor::SetPosition( float x, float y, float z )
617 SetPosition( Vector3( x, y, z ) );
620 void Actor::SetPosition( const Vector3& position )
622 mTargetPosition = position;
624 // node is being used in a separate thread; queue a message to set the value & base value
625 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
628 void Actor::SetX( float x )
630 mTargetPosition.x = x;
632 // node is being used in a separate thread; queue a message to set the value & base value
633 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
636 void Actor::SetY( float y )
638 mTargetPosition.y = y;
640 // node is being used in a separate thread; queue a message to set the value & base value
641 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
644 void Actor::SetZ( float z )
646 mTargetPosition.z = z;
648 // node is being used in a separate thread; queue a message to set the value & base value
649 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
652 void Actor::TranslateBy( const Vector3& distance )
654 mTargetPosition += distance;
656 // node is being used in a separate thread; queue a message to set the value & base value
657 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
660 const Vector3& Actor::GetCurrentPosition() const
662 // node is being used in a separate thread; copy the value from the previous update
663 return GetNode().GetPosition(GetEventThreadServices().GetEventBufferIndex());
666 const Vector3& Actor::GetCurrentWorldPosition() const
668 // node is being used in a separate thread; copy the value from the previous update
669 return GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
672 const Vector2 Actor::GetCurrentScreenPosition() const
674 if( mScene && OnScene() )
676 Vector3 worldPosition = GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
677 Vector3 cameraPosition = mScene->GetDefaultCameraActor().GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
678 worldPosition -= cameraPosition;
680 Vector3 actorSize = GetCurrentSize() * GetCurrentWorldScale();
681 Vector2 halfSceneSize( mScene->GetSize() * 0.5f ); // World position origin is center of scene
682 Vector3 halfActorSize( actorSize * 0.5f );
683 Vector3 anchorPointOffSet = halfActorSize - actorSize * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
685 return Vector2( halfSceneSize.width + worldPosition.x - anchorPointOffSet.x,
686 halfSceneSize.height + worldPosition.y - anchorPointOffSet.y );
689 return Vector2::ZERO;
692 void Actor::SetInheritPosition( bool inherit )
694 if( mInheritPosition != inherit )
696 // non animatable so keep local copy
697 mInheritPosition = inherit;
698 SetInheritPositionMessage( GetEventThreadServices(), GetNode(), inherit );
702 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
704 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
705 normalizedAxis.Normalize();
707 Quaternion orientation( angle, normalizedAxis );
709 SetOrientation( orientation );
712 void Actor::SetOrientation( const Quaternion& orientation )
714 mTargetOrientation = orientation;
716 // node is being used in a separate thread; queue a message to set the value & base value
717 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation );
720 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
722 RotateBy( Quaternion(angle, axis) );
725 void Actor::RotateBy( const Quaternion& relativeRotation )
727 mTargetOrientation *= Quaternion( relativeRotation );
729 // node is being used in a separate thread; queue a message to set the value & base value
730 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
733 const Quaternion& Actor::GetCurrentOrientation() const
735 // node is being used in a separate thread; copy the value from the previous update
736 return GetNode().GetOrientation(GetEventThreadServices().GetEventBufferIndex());
739 const Quaternion& Actor::GetCurrentWorldOrientation() const
741 // node is being used in a separate thread; copy the value from the previous update
742 return GetNode().GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
745 void Actor::SetScale( float scale )
747 SetScale( Vector3( scale, scale, scale ) );
750 void Actor::SetScale( float x, float y, float z )
752 SetScale( Vector3( x, y, z ) );
755 void Actor::SetScale( const Vector3& scale )
757 mTargetScale = scale;
759 // node is being used in a separate thread; queue a message to set the value & base value
760 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
763 void Actor::SetScaleX( float x )
767 // node is being used in a separate thread; queue a message to set the value & base value
768 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
771 void Actor::SetScaleY( float y )
775 // node is being used in a separate thread; queue a message to set the value & base value
776 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
779 void Actor::SetScaleZ( float z )
783 // node is being used in a separate thread; queue a message to set the value & base value
784 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
787 void Actor::ScaleBy(const Vector3& relativeScale)
789 mTargetScale *= relativeScale;
791 // node is being used in a separate thread; queue a message to set the value & base value
792 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
795 const Vector3& Actor::GetCurrentScale() const
797 // node is being used in a separate thread; copy the value from the previous update
798 return GetNode().GetScale(GetEventThreadServices().GetEventBufferIndex());
801 const Vector3& Actor::GetCurrentWorldScale() const
803 // node is being used in a separate thread; copy the value from the previous update
804 return GetNode().GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
807 void Actor::SetInheritScale( bool inherit )
809 if( mInheritScale != inherit )
811 // non animatable so keep local copy
812 mInheritScale = inherit;
813 // node is being used in a separate thread; queue a message to set the value
814 SetInheritScaleMessage( GetEventThreadServices(), GetNode(), inherit );
818 Matrix Actor::GetCurrentWorldMatrix() const
820 return GetNode().GetWorldMatrix(0);
823 void Actor::SetVisible( bool visible )
825 SetVisibleInternal( visible, SendMessage::TRUE );
828 bool Actor::IsVisible() const
830 // node is being used in a separate thread; copy the value from the previous update
831 return GetNode().IsVisible( GetEventThreadServices().GetEventBufferIndex() );
834 void Actor::SetOpacity( float opacity )
836 mTargetColor.a = opacity;
838 // node is being used in a separate thread; queue a message to set the value & base value
839 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
841 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
844 float Actor::GetCurrentOpacity() const
846 // node is being used in a separate thread; copy the value from the previous update
847 return GetNode().GetOpacity(GetEventThreadServices().GetEventBufferIndex());
850 const Vector4& Actor::GetCurrentWorldColor() const
852 return GetNode().GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
855 void Actor::SetColor( const Vector4& color )
857 mTargetColor = color;
859 // node is being used in a separate thread; queue a message to set the value & base value
860 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::Bake, color );
862 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
865 void Actor::SetColorRed( float red )
867 mTargetColor.r = red;
869 // node is being used in a separate thread; queue a message to set the value & base value
870 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeX, red );
872 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
875 void Actor::SetColorGreen( float green )
877 mTargetColor.g = green;
879 // node is being used in a separate thread; queue a message to set the value & base value
880 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeY, green );
882 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
885 void Actor::SetColorBlue( float blue )
887 mTargetColor.b = blue;
889 // node is being used in a separate thread; queue a message to set the value & base value
890 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
892 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
895 const Vector4& Actor::GetCurrentColor() const
897 // node is being used in a separate thread; copy the value from the previous update
898 return GetNode().GetColor(GetEventThreadServices().GetEventBufferIndex());
901 void Actor::SetInheritOrientation( bool inherit )
903 if( mInheritOrientation != inherit )
905 // non animatable so keep local copy
906 mInheritOrientation = inherit;
907 // node is being used in a separate thread; queue a message to set the value
908 SetInheritOrientationMessage( GetEventThreadServices(), GetNode(), inherit );
912 void Actor::SetSizeModeFactor( const Vector3& factor )
916 mRelayoutData->sizeModeFactor = factor;
919 const Vector3& Actor::GetSizeModeFactor() const
923 return mRelayoutData->sizeModeFactor;
926 return Relayouter::DEFAULT_SIZE_MODE_FACTOR;
929 void Actor::SetColorMode( ColorMode colorMode )
931 // non animatable so keep local copy
932 mColorMode = colorMode;
933 // node is being used in a separate thread; queue a message to set the value
934 SetColorModeMessage( GetEventThreadServices(), GetNode(), colorMode );
937 void Actor::SetSize( float width, float height )
939 SetSize( Vector2( width, height ) );
942 void Actor::SetSize( float width, float height, float depth )
944 SetSize( Vector3( width, height, depth ) );
947 void Actor::SetSize( const Vector2& size )
949 SetSize( Vector3( size.width, size.height, 0.f ) );
952 void Actor::SetSizeInternal( const Vector2& size )
954 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
957 void Actor::SetSize( const Vector3& size )
959 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
961 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
962 SetPreferredSize( size.GetVectorXY() );
966 SetSizeInternal( size );
970 void Actor::SetSizeInternal( const Vector3& size )
972 // dont allow recursive loop
973 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
974 // 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
975 if( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
976 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
977 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) )
981 // node is being used in a separate thread; queue a message to set the value & base value
982 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
984 // Notification for derived classes
985 mInsideOnSizeSet = true;
986 OnSizeSet( mTargetSize );
987 mInsideOnSizeSet = false;
989 // Raise a relayout request if the flag is not locked
990 if( mRelayoutData && !mRelayoutData->insideRelayout )
997 void Actor::SetWidth( float width )
999 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1001 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
1002 mRelayoutData->preferredSize.width = width;
1006 mTargetSize.width = width;
1008 // node is being used in a separate thread; queue a message to set the value & base value
1009 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1012 mUseAnimatedSize &= ~AnimatedSizeFlag::WIDTH;
1017 void Actor::SetHeight( float height )
1019 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1021 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
1022 mRelayoutData->preferredSize.height = height;
1026 mTargetSize.height = height;
1028 // node is being used in a separate thread; queue a message to set the value & base value
1029 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1032 mUseAnimatedSize &= ~AnimatedSizeFlag::HEIGHT;
1037 void Actor::SetDepth( float depth )
1039 mTargetSize.depth = depth;
1041 mUseAnimatedSize &= ~AnimatedSizeFlag::DEPTH;
1043 // node is being used in a separate thread; queue a message to set the value & base value
1044 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1047 Vector3 Actor::GetTargetSize() const
1049 Vector3 size = mTargetSize;
1051 if( mUseAnimatedSize & AnimatedSizeFlag::WIDTH )
1053 // Should return animated size if size is animated
1054 size.width = mAnimatedSize.width;
1058 // Should return preferred size if size is fixed as set by SetSize
1059 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
1061 size.width = GetPreferredSize().width;
1065 if( mUseAnimatedSize & AnimatedSizeFlag::HEIGHT )
1067 size.height = mAnimatedSize.height;
1071 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
1073 size.height = GetPreferredSize().height;
1077 if( mUseAnimatedSize & AnimatedSizeFlag::DEPTH )
1079 size.depth = mAnimatedSize.depth;
1085 const Vector3& Actor::GetCurrentSize() const
1087 // node is being used in a separate thread; copy the value from the previous update
1088 return GetNode().GetSize( GetEventThreadServices().GetEventBufferIndex() );
1091 Vector3 Actor::GetNaturalSize() const
1093 // It is up to deriving classes to return the appropriate natural size
1094 return Vector3( 0.0f, 0.0f, 0.0f );
1097 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1099 EnsureRelayouter().SetResizePolicy(policy, dimension, mTargetSize);
1101 OnSetResizePolicy( policy, dimension );
1103 // Trigger relayout on this control
1107 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1109 if ( mRelayoutData )
1111 return mRelayoutData->GetResizePolicy(dimension);
1114 return ResizePolicy::DEFAULT;
1117 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1121 mRelayoutData->sizeSetPolicy = policy;
1123 // Trigger relayout on this control
1127 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1129 if ( mRelayoutData )
1131 return mRelayoutData->sizeSetPolicy;
1134 return Relayouter::DEFAULT_SIZE_SCALE_POLICY;
1137 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1139 EnsureRelayouter().SetDimensionDependency(dimension, dependency);
1142 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1144 if ( mRelayoutData )
1146 return mRelayoutData->GetDimensionDependency(dimension);
1149 return Dimension::ALL_DIMENSIONS; // Default
1152 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1154 // If relayout data has not been allocated yet and the client is requesting
1155 // to disable it, do nothing
1156 if( mRelayoutData || relayoutEnabled )
1160 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1162 mRelayoutData->relayoutEnabled = relayoutEnabled;
1166 bool Actor::IsRelayoutEnabled() const
1168 // Assume that if relayout data has not been allocated yet then
1169 // relayout is disabled
1170 return mRelayoutData && mRelayoutData->relayoutEnabled;
1173 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1175 EnsureRelayouter().SetLayoutDirty(dirty, dimension);
1178 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1180 return mRelayoutData && mRelayoutData->IsLayoutDirty(dimension);
1183 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1185 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1188 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1190 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1193 uint32_t Actor::AddRenderer( Renderer& renderer )
1197 mRenderers = new RendererContainer;
1200 uint32_t index = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1201 RendererPtr rendererPtr = RendererPtr( &renderer );
1202 mRenderers->push_back( rendererPtr );
1203 AttachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1207 uint32_t Actor::GetRendererCount() const
1209 uint32_t rendererCount(0);
1212 rendererCount = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1215 return rendererCount;
1218 RendererPtr Actor::GetRendererAt( uint32_t index )
1220 RendererPtr renderer;
1221 if( index < GetRendererCount() )
1223 renderer = ( *mRenderers )[ index ];
1229 void Actor::RemoveRenderer( Renderer& renderer )
1233 RendererIter end = mRenderers->end();
1234 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1236 if( (*iter).Get() == &renderer )
1238 mRenderers->erase( iter );
1239 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1246 void Actor::RemoveRenderer( uint32_t index )
1248 if( index < GetRendererCount() )
1250 RendererPtr renderer = ( *mRenderers )[ index ];
1251 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.Get()->GetRendererSceneObject() );
1252 mRenderers->erase( mRenderers->begin()+index );
1256 void Actor::SetDrawMode( DrawMode::Type drawMode )
1258 // this flag is not animatable so keep the value
1259 mDrawMode = drawMode;
1261 // node is being used in a separate thread; queue a message to set the value
1262 SetDrawModeMessage( GetEventThreadServices(), GetNode(), drawMode );
1265 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1267 // only valid when on-stage
1268 if( mScene && OnScene() )
1270 const RenderTaskList& taskList = mScene->GetRenderTaskList();
1272 Vector2 converted( screenX, screenY );
1274 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1275 uint32_t taskCount = taskList.GetTaskCount();
1276 for( uint32_t i = taskCount; i > 0; --i )
1278 RenderTaskPtr task = taskList.GetTask( i - 1 );
1279 if( ScreenToLocal( *task, localX, localY, screenX, screenY ) )
1281 // found a task where this conversion was ok so return
1289 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1291 bool retval = false;
1292 // only valid when on-stage
1295 CameraActor* camera = renderTask.GetCameraActor();
1299 renderTask.GetViewport( viewport );
1301 // need to translate coordinates to render tasks coordinate space
1302 Vector2 converted( screenX, screenY );
1303 if( renderTask.TranslateCoordinates( converted ) )
1305 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1312 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1314 return OnScene() && ScreenToLocalInternal(viewMatrix, projectionMatrix, GetNode().GetWorldMatrix(0), viewport, GetCurrentSize(), localX, localY, screenX, screenY);
1317 ActorGestureData& Actor::GetGestureData()
1319 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1320 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1321 if( nullptr == mGestureData )
1323 mGestureData = new ActorGestureData;
1325 return *mGestureData;
1328 bool Actor::IsGestureRequired( GestureType::Value type ) const
1330 return mGestureData && mGestureData->IsGestureRequired( type );
1333 bool Actor::EmitInterceptTouchEventSignal( const Dali::TouchEvent& touch )
1335 return EmitConsumingSignal( *this, mInterceptTouchedSignal, touch );
1338 bool Actor::EmitTouchEventSignal( const Dali::TouchEvent& touch )
1340 return EmitConsumingSignal( *this, mTouchedSignal, touch );
1343 bool Actor::EmitHoverEventSignal( const Dali::HoverEvent& event )
1345 return EmitConsumingSignal( *this, mHoveredSignal, event );
1348 bool Actor::EmitWheelEventSignal( const Dali::WheelEvent& event )
1350 return EmitConsumingSignal( *this, mWheelEventSignal, event );
1353 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
1355 EmitSignal( *this, mVisibilityChangedSignal, visible, type );
1358 void Actor::EmitLayoutDirectionChangedSignal( LayoutDirection::Type type )
1360 EmitSignal( *this, mLayoutDirectionChangedSignal, type );
1363 void Actor::EmitChildAddedSignal( Actor& child )
1365 EmitSignal( child, mChildAddedSignal );
1368 void Actor::EmitChildRemovedSignal( Actor& child )
1370 EmitSignal( child, mChildRemovedSignal );
1373 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1375 bool connected( true );
1376 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
1378 if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1380 actor->HoveredSignal().Connect( tracker, functor );
1382 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1384 actor->WheelEventSignal().Connect( tracker, functor );
1386 else if( 0 == signalName.compare( SIGNAL_ON_SCENE ) )
1388 actor->OnSceneSignal().Connect( tracker, functor );
1390 else if( 0 == signalName.compare( SIGNAL_OFF_SCENE ) )
1392 actor->OffSceneSignal().Connect( tracker, functor );
1394 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
1396 actor->OnRelayoutSignal().Connect( tracker, functor );
1398 else if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1400 actor->TouchedSignal().Connect( tracker, functor );
1402 else if( 0 == signalName.compare( SIGNAL_VISIBILITY_CHANGED ) )
1404 actor->VisibilityChangedSignal().Connect( tracker, functor );
1406 else if( 0 == signalName.compare( SIGNAL_LAYOUT_DIRECTION_CHANGED ) )
1408 actor->LayoutDirectionChangedSignal().Connect( tracker, functor );
1410 else if( 0 == signalName.compare( SIGNAL_CHILD_ADDED ) )
1412 actor->ChildAddedSignal().Connect( tracker, functor );
1414 else if( 0 == signalName.compare( SIGNAL_CHILD_REMOVED ) )
1416 actor->ChildRemovedSignal().Connect( tracker, functor );
1420 // signalName does not match any signal
1427 Actor::Actor( DerivedType derivedType, const SceneGraph::Node& node )
1431 mChildren( nullptr ),
1432 mRenderers( nullptr ),
1433 mParentOrigin( nullptr ),
1434 mAnchorPoint( nullptr ),
1435 mRelayoutData( nullptr ),
1436 mGestureData( nullptr ),
1437 mInterceptTouchedSignal(),
1440 mWheelEventSignal(),
1443 mOnRelayoutSignal(),
1444 mVisibilityChangedSignal(),
1445 mLayoutDirectionChangedSignal(),
1446 mChildAddedSignal(),
1447 mChildRemovedSignal(),
1448 mChildOrderChangedSignal(),
1449 mTargetOrientation( Quaternion::IDENTITY ),
1450 mTargetColor( Color::WHITE ),
1451 mTargetSize( Vector3::ZERO ),
1452 mTargetPosition( Vector3::ZERO ),
1453 mTargetScale( Vector3::ONE ),
1454 mAnimatedSize( Vector3::ZERO ),
1455 mTouchDelegateArea( Vector2::ZERO ),
1459 mUseAnimatedSize( AnimatedSizeFlag::CLEAR ),
1460 mIsRoot( ROOT_LAYER == derivedType ),
1461 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
1462 mIsOnScene( false ),
1464 mLeaveRequired( false ),
1465 mKeyboardFocusable( false ),
1466 mOnSceneSignalled( false ),
1467 mInsideOnSizeSet( false ),
1468 mInheritPosition( true ),
1469 mInheritOrientation( true ),
1470 mInheritScale( true ),
1471 mPositionUsesAnchorPoint( true ),
1473 mInheritLayoutDirection( true ),
1474 mCaptureAllTouchAfterStart( false ),
1475 mLayoutDirection( LayoutDirection::LEFT_TO_RIGHT ),
1476 mDrawMode( DrawMode::NORMAL ),
1477 mColorMode( Node::DEFAULT_COLOR_MODE ),
1478 mClippingMode( ClippingMode::DISABLED )
1482 void Actor::Initialize()
1486 GetEventThreadServices().RegisterObject( this );
1491 // Remove mParent pointers from children even if we're destroying core,
1492 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1495 ActorConstIter endIter = mChildren->end();
1496 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1498 (*iter)->SetParent( nullptr );
1504 // Guard to allow handle destruction after Core has been destroyed
1505 if( EventThreadServices::IsCoreRunning() )
1507 // Root layer will destroy its node in its own destructor
1510 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
1512 GetEventThreadServices().UnregisterObject( this );
1516 // Cleanup optional gesture data
1517 delete mGestureData;
1519 // Cleanup optional parent origin and anchor
1520 delete mParentOrigin;
1521 delete mAnchorPoint;
1523 // Delete optional relayout data
1524 delete mRelayoutData;
1527 void Actor::ConnectToScene( uint32_t parentDepth )
1529 // This container is used instead of walking the Actor hierarchy.
1530 // It protects us when the Actor hierarchy is modified during OnSceneConnectionExternal callbacks.
1531 ActorContainer connectionList;
1535 mScene->RequestRebuildDepthTree();
1538 // This stage is atomic i.e. not interrupted by user callbacks.
1539 RecursiveConnectToScene( connectionList, parentDepth + 1 );
1541 // Notify applications about the newly connected actors.
1542 const ActorIter endIter = connectionList.end();
1543 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
1545 (*iter)->NotifyStageConnection();
1551 void Actor::RecursiveConnectToScene( ActorContainer& connectionList, uint32_t depth )
1553 DALI_ASSERT_ALWAYS( !OnScene() );
1556 mDepth = static_cast< uint16_t >( depth ); // overflow ignored, not expected in practice
1558 ConnectToSceneGraph();
1560 // Notification for internal derived classes
1561 OnSceneConnectionInternal();
1563 // This stage is atomic; avoid emitting callbacks until all Actors are connected
1564 connectionList.push_back( ActorPtr( this ) );
1566 // Recursively connect children
1569 ActorConstIter endIter = mChildren->end();
1570 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1572 (*iter)->SetScene( *mScene );
1573 (*iter)->RecursiveConnectToScene( connectionList, depth + 1 );
1579 * This method is called when the Actor is connected to the Stage.
1580 * The parent must have added its Node to the scene-graph.
1581 * The child must connect its Node to the parent's Node.
1582 * This is recursive; the child calls ConnectToScene() for its children.
1584 void Actor::ConnectToSceneGraph()
1586 DALI_ASSERT_DEBUG( mParent != NULL);
1588 // Reparent Node in next Update
1589 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), mParent->GetNode(), GetNode() );
1591 // Request relayout on all actors that are added to the scenegraph
1594 // Notification for Object::Observers
1598 void Actor::NotifyStageConnection()
1600 // Actors can be removed (in a callback), before the on-stage stage is reported.
1601 // The actor may also have been reparented, in which case mOnSceneSignalled will be true.
1602 if( OnScene() && !mOnSceneSignalled )
1604 // Notification for external (CustomActor) derived classes
1605 OnSceneConnectionExternal( mDepth );
1607 if( !mOnSceneSignal.Empty() )
1609 Dali::Actor handle( this );
1610 mOnSceneSignal.Emit( handle );
1613 // Guard against Remove during callbacks
1616 mOnSceneSignalled = true; // signal required next time Actor is removed
1621 void Actor::DisconnectFromStage()
1623 // This container is used instead of walking the Actor hierachy.
1624 // It protects us when the Actor hierachy is modified during OnSceneDisconnectionExternal callbacks.
1625 ActorContainer disconnectionList;
1629 mScene->RequestRebuildDepthTree();
1632 // This stage is atomic i.e. not interrupted by user callbacks
1633 RecursiveDisconnectFromStage( disconnectionList );
1635 // Notify applications about the newly disconnected actors.
1636 const ActorIter endIter = disconnectionList.end();
1637 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
1639 (*iter)->NotifyStageDisconnection();
1643 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
1645 // need to change state first so that internals relying on IsOnScene() inside OnSceneDisconnectionInternal() get the correct value
1648 // Recursively disconnect children
1651 ActorConstIter endIter = mChildren->end();
1652 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1654 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
1658 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
1659 disconnectionList.push_back( ActorPtr( this ) );
1661 // Notification for internal derived classes
1662 OnSceneDisconnectionInternal();
1664 DisconnectFromSceneGraph();
1668 * This method is called by an actor or its parent, before a node removal message is sent.
1669 * This is recursive; the child calls DisconnectFromStage() for its children.
1671 void Actor::DisconnectFromSceneGraph()
1673 // Notification for Object::Observers
1674 OnSceneObjectRemove();
1677 void Actor::NotifyStageDisconnection()
1679 // Actors can be added (in a callback), before the off-stage state is reported.
1680 // Also if the actor was added & removed before mOnSceneSignalled was set, then we don't notify here.
1681 // only do this step if there is a stage, i.e. Core is not being shut down
1682 if ( EventThreadServices::IsCoreRunning() && !OnScene() && mOnSceneSignalled )
1684 // Notification for external (CustomeActor) derived classes
1685 OnSceneDisconnectionExternal();
1687 if( !mOffSceneSignal.Empty() )
1689 Dali::Actor handle( this );
1690 mOffSceneSignal.Emit( handle );
1693 // Guard against Add during callbacks
1696 mOnSceneSignalled = false; // signal required next time Actor is added
1701 bool Actor::IsNodeConnected() const
1703 bool connected( false );
1707 if( IsRoot() || GetNode().GetParent() )
1716 // This method initiates traversal of the actor tree using depth-first
1717 // traversal to set a depth index based on traversal order. It sends a
1718 // single message to update manager to update all the actor's nodes in
1719 // this tree with the depth index. The sceneGraphNodeDepths vector's
1720 // elements are ordered by depth, and could be used to reduce sorting
1721 // in the update thread.
1722 void Actor::RebuildDepthTree()
1724 DALI_LOG_TIMER_START(depthTimer);
1726 // Vector of scene-graph nodes and their depths to send to UpdateManager
1727 // in a single message
1728 OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths( new SceneGraph::NodeDepths() );
1730 int32_t depthIndex = 1;
1731 DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
1733 SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths );
1734 DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
1737 void Actor::DepthTraverseActorTree( OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths, int32_t& depthIndex )
1739 mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
1740 sceneGraphNodeDepths->Add( const_cast<SceneGraph::Node*>( &GetNode() ), mSortedDepth );
1742 // Create/add to children of this node
1745 for( ActorContainer::iterator it = mChildren->begin(); it != mChildren->end(); ++it )
1747 Actor* childActor = (*it).Get();
1749 childActor->DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
1754 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
1756 PropertyHandler::SetDefaultProperty(*this, index, property);
1759 // TODO: This method needs to be removed
1760 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
1762 PropertyHandler::SetSceneGraphProperty(index, entry, value, GetEventThreadServices(), GetNode());
1765 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
1767 Property::Value value;
1769 if( ! GetCachedPropertyValue( index, value ) )
1771 // If property value is not stored in the event-side, then it must be a scene-graph only property
1772 GetCurrentPropertyValue( index, value );
1778 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
1780 Property::Value value;
1782 if( ! GetCurrentPropertyValue( index, value ) )
1784 // If unable to retrieve scene-graph property value, then it must be an event-side only property
1785 GetCachedPropertyValue( index, value );
1791 void Actor::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
1793 PropertyHandler::OnNotifyDefaultPropertyAnimation(*this, animation, index, value, animationType);
1796 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
1798 const PropertyBase* property = PropertyHandler::GetSceneObjectAnimatableProperty(index, GetNode());
1801 // not our property, ask base
1802 property = Object::GetSceneObjectAnimatableProperty( index );
1808 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
1810 const PropertyInputImpl* property = PropertyHandler::GetSceneObjectInputProperty(index, GetNode());
1813 // reuse animatable property getter as animatable properties are inputs as well
1814 // animatable property chains back to Object::GetSceneObjectInputProperty() so all properties get covered
1815 property = GetSceneObjectAnimatableProperty( index );
1821 int32_t Actor::GetPropertyComponentIndex( Property::Index index ) const
1823 int32_t componentIndex = PropertyHandler::GetPropertyComponentIndex(index);
1824 if( Property::INVALID_COMPONENT_INDEX == componentIndex )
1827 componentIndex = Object::GetPropertyComponentIndex( index );
1830 return componentIndex;
1833 void Actor::SetParent( Actor* parent )
1837 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
1841 mScene = parent->mScene;
1843 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1846 // Instruct each actor to create a corresponding node in the scene graph
1847 ConnectToScene( parent->GetHierarchyDepth() );
1850 // Resolve the name and index for the child properties if any
1851 ResolveChildProperties();
1853 else // parent being set to NULL
1855 DALI_ASSERT_ALWAYS( mParent != nullptr && "Actor should have a parent" );
1859 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1862 // Disconnect the Node & its children from the scene-graph.
1863 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
1865 // Instruct each actor to discard pointers to the scene-graph
1866 DisconnectFromStage();
1873 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
1876 Actor* actor = dynamic_cast< Actor* >( object );
1880 if( 0 == actionName.compare( ACTION_SHOW ) )
1882 actor->SetVisible( true );
1885 else if( 0 == actionName.compare( ACTION_HIDE ) )
1887 actor->SetVisible( false );
1895 Rect<> Actor::CalculateScreenExtents( ) const
1897 auto screenPosition = GetCurrentScreenPosition();
1898 Vector3 size = GetCurrentSize() * GetCurrentWorldScale();
1899 Vector3 anchorPointOffSet = size * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
1900 Vector2 position = Vector2( screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y );
1901 return { position.x, position.y, size.x, size.y };
1904 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
1906 return PropertyHandler::GetCachedPropertyValue(*this, index, value);
1909 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
1911 return PropertyHandler::GetCurrentPropertyValue(*this, index, value);
1914 Actor::Relayouter& Actor::EnsureRelayouter()
1916 // Assign relayouter
1917 if( !mRelayoutData )
1919 mRelayoutData = new Relayouter();
1922 return *mRelayoutData;
1925 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
1927 // Check if actor is dependent on parent
1928 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1930 if( ( dimension & ( 1 << i ) ) )
1932 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
1933 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
1943 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
1945 // Check if actor is dependent on children
1946 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1948 if( ( dimension & ( 1 << i ) ) )
1950 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
1951 switch( resizePolicy )
1953 case ResizePolicy::FIT_TO_CHILDREN:
1954 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
1970 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
1972 return Actor::RelayoutDependentOnChildren( dimension );
1975 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
1977 // Check each possible dimension and see if it is dependent on the input one
1978 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1980 if( dimension & ( 1 << i ) )
1982 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
1989 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
1991 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1993 if( dimension & ( 1 << i ) )
1995 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
2000 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
2002 // If more than one dimension is requested, just return the first one found
2003 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2005 if( ( dimension & ( 1 << i ) ) )
2007 return mRelayoutData->negotiatedDimensions[ i ];
2011 return 0.0f; // Default
2014 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
2016 EnsureRelayouter().SetPadding( padding, dimension );
2019 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
2021 if ( mRelayoutData )
2023 // If more than one dimension is requested, just return the first one found
2024 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2026 if( ( dimension & ( 1 << i ) ) )
2028 return mRelayoutData->dimensionPadding[ i ];
2033 return Relayouter::DEFAULT_DIMENSION_PADDING;
2036 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
2038 EnsureRelayouter().SetLayoutNegotiated(negotiated, dimension);
2041 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
2043 return mRelayoutData && mRelayoutData->IsLayoutNegotiated(dimension);
2046 float Actor::GetHeightForWidthBase( float width )
2048 float height = 0.0f;
2050 const Vector3 naturalSize = GetNaturalSize();
2051 if( naturalSize.width > 0.0f )
2053 height = naturalSize.height * width / naturalSize.width;
2055 else // we treat 0 as 1:1 aspect ratio
2063 float Actor::GetWidthForHeightBase( float height )
2067 const Vector3 naturalSize = GetNaturalSize();
2068 if( naturalSize.height > 0.0f )
2070 width = naturalSize.width * height / naturalSize.height;
2072 else // we treat 0 as 1:1 aspect ratio
2080 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
2082 // Fill to parent, taking size mode factor into account
2083 switch( child.GetResizePolicy( dimension ) )
2085 case ResizePolicy::FILL_TO_PARENT:
2087 return GetLatestSize( dimension );
2090 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2092 return GetLatestSize( dimension ) * GetDimensionValue( child.GetProperty< Vector3 >( Dali::Actor::Property::SIZE_MODE_FACTOR ), dimension );
2095 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2097 return GetLatestSize( dimension ) + GetDimensionValue( child.GetProperty< Vector3 >( Dali::Actor::Property::SIZE_MODE_FACTOR ), dimension );
2102 return GetLatestSize( dimension );
2107 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
2109 // Can be overridden in derived class
2110 return CalculateChildSizeBase( child, dimension );
2113 float Actor::GetHeightForWidth( float width )
2115 // Can be overridden in derived class
2116 return GetHeightForWidthBase( width );
2119 float Actor::GetWidthForHeight( float height )
2121 // Can be overridden in derived class
2122 return GetWidthForHeightBase( height );
2125 float Actor::GetLatestSize( Dimension::Type dimension ) const
2127 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
2130 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
2132 Vector2 padding = GetPadding( dimension );
2134 return GetLatestSize( dimension ) + padding.x + padding.y;
2137 float Actor::NegotiateFromParent( Dimension::Type dimension )
2139 Actor* parent = GetParent();
2142 Vector2 padding( GetPadding( dimension ) );
2143 Vector2 parentPadding( parent->GetPadding( dimension ) );
2144 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
2150 float Actor::NegotiateFromChildren( Dimension::Type dimension )
2152 float maxDimensionPoint = 0.0f;
2154 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2156 ActorPtr child = GetChildAt( i );
2158 if( !child->RelayoutDependentOnParent( dimension ) )
2160 // Calculate the min and max points that the children range across
2161 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
2162 float dimensionSize = child->GetRelayoutSize( dimension );
2163 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
2167 return maxDimensionPoint;
2170 float Actor::GetSize( Dimension::Type dimension ) const
2172 return GetDimensionValue( mTargetSize, dimension );
2175 float Actor::GetNaturalSize( Dimension::Type dimension ) const
2177 return GetDimensionValue( GetNaturalSize(), dimension );
2180 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
2182 switch( GetResizePolicy( dimension ) )
2184 case ResizePolicy::USE_NATURAL_SIZE:
2186 return GetNaturalSize( dimension );
2189 case ResizePolicy::FIXED:
2191 return GetDimensionValue( GetPreferredSize(), dimension );
2194 case ResizePolicy::USE_ASSIGNED_SIZE:
2196 return GetDimensionValue( maximumSize, dimension );
2199 case ResizePolicy::FILL_TO_PARENT:
2200 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2201 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2203 return NegotiateFromParent( dimension );
2206 case ResizePolicy::FIT_TO_CHILDREN:
2208 return NegotiateFromChildren( dimension );
2211 case ResizePolicy::DIMENSION_DEPENDENCY:
2213 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
2216 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
2218 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
2221 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
2223 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
2235 return 0.0f; // Default
2238 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
2240 // Check if it needs to be negotiated
2241 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
2243 // Check that we havn't gotten into an infinite loop
2244 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
2245 bool recursionFound = false;
2246 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
2248 if( *it == searchActor )
2250 recursionFound = true;
2255 if( !recursionFound )
2257 // Record the path that we have taken
2258 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
2260 // Dimension dependency check
2261 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2263 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
2265 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
2267 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
2271 // Parent dependency check
2272 Actor* parent = GetParent();
2273 if( parent && RelayoutDependentOnParent( dimension ) )
2275 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
2278 // Children dependency check
2279 if( RelayoutDependentOnChildren( dimension ) )
2281 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2283 ActorPtr child = GetChildAt( i );
2285 // Only relayout child first if it is not dependent on this actor
2286 if( !child->RelayoutDependentOnParent( dimension ) )
2288 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
2293 // For deriving classes
2294 OnCalculateRelayoutSize( dimension );
2296 // All dependencies checked, calculate the size and set negotiated flag
2297 const float newSize = Relayouter::ClampDimension( *this, CalculateSize( dimension, allocatedSize ), dimension );
2299 SetNegotiatedDimension( newSize, dimension );
2300 SetLayoutNegotiated( true, dimension );
2302 // For deriving classes
2303 OnLayoutNegotiated( newSize, dimension );
2305 // This actor has been successfully processed, pop it off the recursion stack
2306 recursionStack.pop_back();
2310 // TODO: Break infinite loop
2311 SetLayoutNegotiated( true, dimension );
2316 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
2318 // Negotiate all dimensions that require it
2319 ActorDimensionStack recursionStack;
2321 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2323 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
2326 NegotiateDimension( dimension, allocatedSize, recursionStack );
2330 Vector2 Actor::ApplySizeSetPolicy( const Vector2& size )
2332 return mRelayoutData->ApplySizeSetPolicy(*this, size);
2335 void Actor::SetNegotiatedSize( RelayoutContainer& container )
2337 // Do the set actor size
2338 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
2340 // Adjust for size set policy
2341 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
2343 // Lock the flag to stop recursive relayouts on set size
2344 mRelayoutData->insideRelayout = true;
2345 SetSize( negotiatedSize );
2346 mRelayoutData->insideRelayout = false;
2348 // Clear flags for all dimensions
2349 SetLayoutDirty( false );
2351 // Give deriving classes a chance to respond
2352 OnRelayout( negotiatedSize, container );
2354 if( !mOnRelayoutSignal.Empty() )
2356 Dali::Actor handle( this );
2357 mOnRelayoutSignal.Emit( handle );
2361 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
2363 // Force a size negotiation for actors that has assigned size during relayout
2364 // This is required as otherwise the flags that force a relayout will not
2365 // necessarilly be set. This will occur if the actor has already been laid out.
2366 // The dirty flags are then cleared. Then if the actor is added back into the
2367 // relayout container afterwards, the dirty flags would still be clear...
2368 // causing a relayout to be skipped. Here we force any actors added to the
2369 // container to be relayed out.
2370 DALI_LOG_TIMER_START( NegSizeTimer1 );
2372 if( GetUseAssignedSize(Dimension::WIDTH ) )
2374 SetLayoutNegotiated( false, Dimension::WIDTH );
2376 if( GetUseAssignedSize( Dimension::HEIGHT ) )
2378 SetLayoutNegotiated( false, Dimension::HEIGHT );
2381 // Do the negotiation
2382 NegotiateDimensions( allocatedSize );
2384 // Set the actor size
2385 SetNegotiatedSize( container );
2387 // Negotiate down to children
2388 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2390 ActorPtr child = GetChildAt( i );
2392 // Forces children that have already been laid out to be relayed out
2393 // if they have assigned size during relayout.
2394 if( child->GetUseAssignedSize(Dimension::WIDTH) )
2396 child->SetLayoutNegotiated(false, Dimension::WIDTH);
2397 child->SetLayoutDirty(true, Dimension::WIDTH);
2400 if( child->GetUseAssignedSize(Dimension::HEIGHT) )
2402 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
2403 child->SetLayoutDirty(true, Dimension::HEIGHT);
2406 // Only relayout if required
2407 if( child->RelayoutRequired() )
2409 container.Add( Dali::Actor( child.Get() ), mTargetSize.GetVectorXY() );
2412 DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
2415 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
2419 mRelayoutData->SetUseAssignedSize(use, dimension);
2423 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
2425 return mRelayoutData && mRelayoutData->GetUseAssignedSize(dimension);
2428 void Actor::RelayoutRequest( Dimension::Type dimension )
2430 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
2431 if( relayoutController )
2433 Dali::Actor self( this );
2434 relayoutController->RequestRelayout( self, dimension );
2438 void Actor::SetPreferredSize( const Vector2& size )
2442 // If valid width or height, then set the resize policy to FIXED
2443 // A 0 width or height may also be required so if the resize policy has not been changed, i.e. is still set to DEFAULT,
2444 // then change to FIXED as well
2446 if( size.width > 0.0f || GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DEFAULT )
2448 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
2451 if( size.height > 0.0f || GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DEFAULT )
2453 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
2456 mRelayoutData->preferredSize = size;
2458 mUseAnimatedSize = AnimatedSizeFlag::CLEAR;
2463 Vector2 Actor::GetPreferredSize() const
2465 if ( mRelayoutData )
2467 return Vector2( mRelayoutData->preferredSize );
2470 return Relayouter::DEFAULT_PREFERRED_SIZE;
2473 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
2475 EnsureRelayouter().SetMinimumSize(size, dimension);
2479 float Actor::GetMinimumSize( Dimension::Type dimension ) const
2481 if ( mRelayoutData )
2483 return mRelayoutData->GetMinimumSize(dimension);
2486 return 0.0f; // Default
2489 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
2491 EnsureRelayouter().SetMaximumSize(size, dimension);
2495 float Actor::GetMaximumSize( Dimension::Type dimension ) const
2497 if ( mRelayoutData )
2499 return mRelayoutData->GetMaximumSize(dimension);
2502 return FLT_MAX; // Default
2505 void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
2507 if( mVisible != visible )
2509 if( sendMessage == SendMessage::TRUE )
2511 // node is being used in a separate thread; queue a message to set the value & base value
2512 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible );
2514 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
2519 // Emit the signal on this actor and all its children
2520 EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
2524 void Actor::SetSiblingOrder( uint32_t order )
2528 ActorContainer& siblings = *(mParent->mChildren);
2529 uint32_t currentOrder = GetSiblingOrder();
2531 if( order != currentOrder )
2537 else if( order < siblings.size() -1 )
2539 if( order > currentOrder )
2541 RaiseAbove( *siblings[order] );
2545 LowerBelow( *siblings[order] );
2556 uint32_t Actor::GetSiblingOrder() const
2562 ActorContainer& siblings = *(mParent->mChildren);
2563 for( std::size_t i = 0; i < siblings.size(); ++i )
2565 if( siblings[i] == this )
2567 order = static_cast<uint32_t>( i );
2576 void Actor::RequestRebuildDepthTree()
2582 mScene->RequestRebuildDepthTree();
2591 ActorContainer& siblings = *(mParent->mChildren);
2592 if( siblings.back() != this ) // If not already at end
2594 for( std::size_t i=0; i<siblings.size(); ++i )
2596 if( siblings[i] == this )
2599 ActorPtr next = siblings[i+1];
2600 siblings[i+1] = this;
2607 Dali::Actor handle( this );
2608 mParent->mChildOrderChangedSignal.Emit( handle );
2610 RequestRebuildDepthTree();
2614 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2622 ActorContainer& siblings = *(mParent->mChildren);
2623 if( siblings.front() != this ) // If not already at beginning
2625 for( std::size_t i=1; i<siblings.size(); ++i )
2627 if( siblings[i] == this )
2629 // Swap with previous
2630 ActorPtr previous = siblings[i-1];
2631 siblings[i-1] = this;
2632 siblings[i] = previous;
2638 Dali::Actor handle( this );
2639 mParent->mChildOrderChangedSignal.Emit( handle );
2641 RequestRebuildDepthTree();
2645 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2649 void Actor::RaiseToTop()
2653 ActorContainer& siblings = *(mParent->mChildren);
2654 if( siblings.back() != this ) // If not already at end
2656 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
2657 if( iter != siblings.end() )
2659 siblings.erase(iter);
2660 siblings.push_back(ActorPtr(this));
2664 Dali::Actor handle( this );
2665 mParent->mChildOrderChangedSignal.Emit( handle );
2667 RequestRebuildDepthTree();
2671 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2675 void Actor::LowerToBottom()
2679 ActorContainer& siblings = *(mParent->mChildren);
2680 if( siblings.front() != this ) // If not already at bottom,
2682 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2684 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
2685 if( iter != siblings.end() )
2687 siblings.erase(iter);
2688 siblings.insert(siblings.begin(), thisPtr);
2692 Dali::Actor handle( this );
2693 mParent->mChildOrderChangedSignal.Emit( handle );
2695 RequestRebuildDepthTree();
2699 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2703 void Actor::RaiseAbove( Internal::Actor& target )
2707 ActorContainer& siblings = *(mParent->mChildren);
2708 if( siblings.back() != this && target.mParent == mParent ) // If not already at top
2710 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2712 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
2713 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
2714 if( thisIter < targetIter )
2716 siblings.erase(thisIter);
2717 // Erasing early invalidates the targetIter. (Conversely, inserting first may also
2718 // invalidate thisIter)
2719 targetIter = std::find( siblings.begin(), siblings.end(), &target );
2721 siblings.insert(targetIter, thisPtr);
2724 Dali::Actor handle( this );
2725 mParent->mChildOrderChangedSignal.Emit( handle );
2727 RequestRebuildDepthTree();
2732 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2736 void Actor::LowerBelow( Internal::Actor& target )
2740 ActorContainer& siblings = *(mParent->mChildren);
2741 if( siblings.front() != this && target.mParent == mParent ) // If not already at bottom
2743 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2745 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
2746 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
2748 if( thisIter > targetIter )
2750 siblings.erase(thisIter); // this only invalidates iterators at or after this point.
2751 siblings.insert(targetIter, thisPtr);
2754 Dali::Actor handle( this );
2755 mParent->mChildOrderChangedSignal.Emit( handle );
2757 RequestRebuildDepthTree();
2762 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2766 void Actor::SetInheritLayoutDirection( bool inherit )
2768 if( mInheritLayoutDirection != inherit )
2770 mInheritLayoutDirection = inherit;
2772 if( inherit && mParent )
2774 InheritLayoutDirectionRecursively( this, mParent->mLayoutDirection );
2779 void Actor::InheritLayoutDirectionRecursively( ActorPtr actor, Dali::LayoutDirection::Type direction, bool set )
2781 if( actor && ( actor->mInheritLayoutDirection || set ) )
2783 if( actor->mLayoutDirection != direction )
2785 actor->mLayoutDirection = direction;
2786 actor->EmitLayoutDirectionChangedSignal( direction );
2787 actor->RelayoutRequest();
2790 if( actor->GetChildCount() > 0 )
2792 for( ActorPtr& child : actor->GetChildrenInternal() )
2794 InheritLayoutDirectionRecursively( child, direction );
2800 void Actor::SetUpdateSizeHint( const Vector2& updateSizeHint )
2802 // node is being used in a separate thread; queue a message to set the value & base value
2803 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mUpdateSizeHint, &AnimatableProperty<Vector3>::Bake, Vector3(updateSizeHint.width, updateSizeHint.height, 0.f ) );
2806 } // namespace Internal