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_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperties )
150 const char* const SIGNAL_HOVERED = "hovered";
151 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
152 const char* const SIGNAL_ON_SCENE = "onScene";
153 const char* const SIGNAL_OFF_SCENE = "offScene";
154 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
155 const char* const SIGNAL_TOUCHED = "touched";
156 const char* const SIGNAL_VISIBILITY_CHANGED = "visibilityChanged";
157 const char* const SIGNAL_LAYOUT_DIRECTION_CHANGED = "layoutDirectionChanged";
158 const char* const SIGNAL_CHILD_ADDED = "childAdded";
159 const char* const SIGNAL_CHILD_REMOVED = "childRemoved";
163 const char* const ACTION_SHOW = "show";
164 const char* const ACTION_HIDE = "hide";
166 BaseHandle CreateActor()
168 return Dali::Actor::New();
171 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor, ActorDefaultProperties );
173 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
174 SignalConnectorType signalConnector3( mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal );
175 SignalConnectorType signalConnector4( mType, SIGNAL_ON_SCENE, &Actor::DoConnectSignal );
176 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_SCENE, &Actor::DoConnectSignal );
177 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
178 SignalConnectorType signalConnector7( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
179 SignalConnectorType signalConnector8( mType, SIGNAL_VISIBILITY_CHANGED, &Actor::DoConnectSignal );
180 SignalConnectorType signalConnector9( mType, SIGNAL_LAYOUT_DIRECTION_CHANGED, &Actor::DoConnectSignal );
181 SignalConnectorType signalConnector10( mType, SIGNAL_CHILD_ADDED, &Actor::DoConnectSignal );
182 SignalConnectorType signalConnector11( mType, SIGNAL_CHILD_REMOVED, &Actor::DoConnectSignal );
184 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
185 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
188 * @brief Extract a given dimension from a Vector2
190 * @param[in] values The values to extract from
191 * @param[in] dimension The dimension to extract
192 * @return Return the value for the dimension
194 constexpr float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
198 case Dimension::WIDTH:
202 case Dimension::HEIGHT:
204 return values.height;
215 * @brief Extract a given dimension from a Vector3
217 * @param[in] values The values to extract from
218 * @param[in] dimension The dimension to extract
219 * @return Return the value for the dimension
221 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
223 return GetDimensionValue( values.GetVectorXY(), dimension );
227 * @brief Recursively emits the visibility-changed-signal on the actor tree.
228 * @param[in] actor The actor to emit the signal on
229 * @param[in] visible The new visibility of the actor
230 * @param[in] type Whether the actor's visible property has changed or a parent's
232 void EmitVisibilityChangedSignalRecursively( ActorPtr actor, bool visible, DevelActor::VisibilityChange::Type type )
236 actor->EmitVisibilityChangedSignal( visible, type );
238 if( actor->GetChildCount() > 0 )
240 for( ActorPtr& child : actor->GetChildrenInternal() )
242 EmitVisibilityChangedSignalRecursively( child, visible, DevelActor::VisibilityChange::PARENT );
248 /// Helper for emitting a signal
249 template<typename Signal, typename Event>
250 bool EmitConsumingSignal( Actor& actor, Signal& signal, const Event& event )
252 bool consumed = false;
254 if( !signal.Empty() )
256 Dali::Actor handle( &actor );
257 consumed = signal.Emit( handle, event );
263 /// Helper for emitting signals with multiple parameters
264 template<typename Signal, typename... Param>
265 void EmitSignal( Actor& actor, Signal& signal, Param... params)
267 if( !signal.Empty() )
269 Dali::Actor handle( &actor );
270 signal.Emit( handle, params... );
274 bool ScreenToLocalInternal(
275 const Matrix& viewMatrix,
276 const Matrix& projectionMatrix,
277 const Matrix& worldMatrix,
278 const Viewport& viewport,
279 const Vector3& currentSize,
285 // Get the ModelView matrix
287 Matrix::Multiply( modelView, worldMatrix, viewMatrix );
289 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
290 Matrix invertedMvp( false/*don't init*/);
291 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
292 bool success = invertedMvp.Invert();
294 // Convert to GL coordinates
295 Vector4 screenPos( screenX - static_cast<float>( viewport.x ), static_cast<float>( viewport.height ) - screenY - static_cast<float>( viewport.y ), 0.f, 1.f );
300 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), nearPos );
307 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), farPos );
313 if( XyPlaneIntersect( nearPos, farPos, local ) )
315 Vector3 size = currentSize;
316 localX = local.x + size.x * 0.5f;
317 localY = local.y + size.y * 0.5f;
328 } // unnamed namespace
330 ActorPtr Actor::New()
332 // pass a reference to actor, actor does not own its node
333 ActorPtr actor( new Actor( BASIC, *CreateNode() ) );
335 // Second-phase construction
341 const SceneGraph::Node* Actor::CreateNode()
343 // create node. Nodes are owned by the update manager
344 SceneGraph::Node* node = SceneGraph::Node::New();
345 OwnerPointer< SceneGraph::Node > transferOwnership( node );
346 Internal::ThreadLocalStorage* tls = Internal::ThreadLocalStorage::GetInternal();
348 DALI_ASSERT_ALWAYS( tls && "ThreadLocalStorage is null" );
350 AddNodeMessage( tls->GetUpdateManager(), transferOwnership );
355 void Actor::SetName( const std::string& name )
359 // ATTENTION: string for debug purposes is not thread safe.
360 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( &GetNode() ), name );
363 uint32_t Actor::GetId() const
365 return GetNode().GetId();
368 Dali::Layer Actor::GetLayer()
372 // Short-circuit for Layer derived actors
375 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
378 // Find the immediate Layer parent
379 for( Actor* parent = mParent; !layer && parent != nullptr; parent = parent->GetParent() )
381 if( parent->IsLayer() )
383 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
390 void Actor::Add( Actor& child )
392 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
393 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
397 mChildren = new ActorContainer;
400 Actor* const oldParent( child.mParent );
402 // child might already be ours
403 if( this != oldParent )
405 // if we already have parent, unparent us first
408 oldParent->Remove( child ); // This causes OnChildRemove callback & ChildRemoved signal
410 // Old parent may need to readjust to missing child
411 if( oldParent->RelayoutDependentOnChildren() )
413 oldParent->RelayoutRequest();
417 // Guard against Add() during previous OnChildRemove callback
420 // Do this first, since user callbacks from within SetParent() may need to remove child
421 mChildren->push_back( ActorPtr( &child ) );
423 // SetParent asserts that child can be added
424 child.SetParent( this );
426 // Notification for derived classes
428 EmitChildAddedSignal( child );
430 InheritLayoutDirectionRecursively( ActorPtr( &child ), mLayoutDirection );
432 // Only put in a relayout request if there is a suitable dependency
433 if( RelayoutDependentOnChildren() )
441 void Actor::Remove( Actor& child )
443 if( (this == &child) || (!mChildren) )
445 // no children or removing itself
451 // Find the child in mChildren, and unparent it
452 ActorIter end = mChildren->end();
453 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
455 ActorPtr actor = (*iter);
457 if( actor.Get() == &child )
459 // Keep handle for OnChildRemove notification
462 // Do this first, since user callbacks from within SetParent() may need to add the child
463 mChildren->erase( iter );
465 DALI_ASSERT_DEBUG( actor->GetParent() == this );
466 actor->SetParent( nullptr );
474 // Only put in a relayout request if there is a suitable dependency
475 if( RelayoutDependentOnChildren() )
481 // Notification for derived classes
482 OnChildRemove( child );
483 EmitChildRemovedSignal( child );
486 void Actor::Unparent()
490 // Remove this actor from the parent. The remove will put a relayout request in for
491 // the parent if required
492 mParent->Remove( *this );
493 // mParent is now NULL!
497 uint32_t Actor::GetChildCount() const
499 return ( nullptr != mChildren ) ? static_cast<uint32_t>( mChildren->size() ) : 0; // only 4,294,967,295 children per actor
502 ActorPtr Actor::GetChildAt( uint32_t index ) const
504 DALI_ASSERT_ALWAYS( index < GetChildCount() );
506 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
509 ActorPtr Actor::FindChildByName( const std::string& actorName )
511 ActorPtr child = nullptr;
512 if( actorName == mName )
518 ActorIter end = mChildren->end();
519 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
521 child = (*iter)->FindChildByName( actorName );
532 ActorPtr Actor::FindChildById( const uint32_t id )
534 ActorPtr child = nullptr;
541 ActorIter end = mChildren->end();
542 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
544 child = (*iter)->FindChildById( id );
555 void Actor::SetParentOrigin( const Vector3& origin )
557 // node is being used in a separate thread; queue a message to set the value & base value
558 SetParentOriginMessage( GetEventThreadServices(), GetNode(), origin );
560 // Cache for event-thread access
563 // not allocated, check if different from default
564 if( ParentOrigin::DEFAULT != origin )
566 mParentOrigin = new Vector3( origin );
571 // check if different from current costs more than just set
572 *mParentOrigin = origin;
576 const Vector3& Actor::GetCurrentParentOrigin() const
578 // Cached for event-thread access
579 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
582 void Actor::SetAnchorPoint( const Vector3& anchor )
584 // node is being used in a separate thread; queue a message to set the value & base value
585 SetAnchorPointMessage( GetEventThreadServices(), GetNode(), anchor );
587 // Cache for event-thread access
590 // not allocated, check if different from default
591 if( AnchorPoint::DEFAULT != anchor )
593 mAnchorPoint = new Vector3( anchor );
598 // check if different from current costs more than just set
599 *mAnchorPoint = anchor;
603 const Vector3& Actor::GetCurrentAnchorPoint() const
605 // Cached for event-thread access
606 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
609 void Actor::SetPosition( float x, float y )
611 SetPosition( Vector3( x, y, 0.0f ) );
614 void Actor::SetPosition( float x, float y, float z )
616 SetPosition( Vector3( x, y, z ) );
619 void Actor::SetPosition( const Vector3& position )
621 mTargetPosition = position;
623 // node is being used in a separate thread; queue a message to set the value & base value
624 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
627 void Actor::SetX( float x )
629 mTargetPosition.x = x;
631 // node is being used in a separate thread; queue a message to set the value & base value
632 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
635 void Actor::SetY( float y )
637 mTargetPosition.y = y;
639 // node is being used in a separate thread; queue a message to set the value & base value
640 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
643 void Actor::SetZ( float z )
645 mTargetPosition.z = z;
647 // node is being used in a separate thread; queue a message to set the value & base value
648 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
651 void Actor::TranslateBy( const Vector3& distance )
653 mTargetPosition += distance;
655 // node is being used in a separate thread; queue a message to set the value & base value
656 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
659 const Vector3& Actor::GetCurrentPosition() const
661 // node is being used in a separate thread; copy the value from the previous update
662 return GetNode().GetPosition(GetEventThreadServices().GetEventBufferIndex());
665 const Vector3& Actor::GetCurrentWorldPosition() const
667 // node is being used in a separate thread; copy the value from the previous update
668 return GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
671 const Vector2 Actor::GetCurrentScreenPosition() const
673 if( mScene && OnScene() )
675 Vector3 worldPosition = GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
676 Vector3 cameraPosition = mScene->GetDefaultCameraActor().GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
677 worldPosition -= cameraPosition;
679 Vector3 actorSize = GetCurrentSize() * GetCurrentWorldScale();
680 Vector2 halfSceneSize( mScene->GetSize() * 0.5f ); // World position origin is center of scene
681 Vector3 halfActorSize( actorSize * 0.5f );
682 Vector3 anchorPointOffSet = halfActorSize - actorSize * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
684 return Vector2( halfSceneSize.width + worldPosition.x - anchorPointOffSet.x,
685 halfSceneSize.height + worldPosition.y - anchorPointOffSet.y );
688 return Vector2::ZERO;
691 void Actor::SetInheritPosition( bool inherit )
693 if( mInheritPosition != inherit )
695 // non animatable so keep local copy
696 mInheritPosition = inherit;
697 SetInheritPositionMessage( GetEventThreadServices(), GetNode(), inherit );
701 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
703 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
704 normalizedAxis.Normalize();
706 Quaternion orientation( angle, normalizedAxis );
708 SetOrientation( orientation );
711 void Actor::SetOrientation( const Quaternion& orientation )
713 mTargetOrientation = orientation;
715 // node is being used in a separate thread; queue a message to set the value & base value
716 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation );
719 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
721 RotateBy( Quaternion(angle, axis) );
724 void Actor::RotateBy( const Quaternion& relativeRotation )
726 mTargetOrientation *= Quaternion( relativeRotation );
728 // node is being used in a separate thread; queue a message to set the value & base value
729 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
732 const Quaternion& Actor::GetCurrentOrientation() const
734 // node is being used in a separate thread; copy the value from the previous update
735 return GetNode().GetOrientation(GetEventThreadServices().GetEventBufferIndex());
738 const Quaternion& Actor::GetCurrentWorldOrientation() const
740 // node is being used in a separate thread; copy the value from the previous update
741 return GetNode().GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
744 void Actor::SetScale( float scale )
746 SetScale( Vector3( scale, scale, scale ) );
749 void Actor::SetScale( float x, float y, float z )
751 SetScale( Vector3( x, y, z ) );
754 void Actor::SetScale( const Vector3& scale )
756 mTargetScale = scale;
758 // node is being used in a separate thread; queue a message to set the value & base value
759 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
762 void Actor::SetScaleX( float x )
766 // node is being used in a separate thread; queue a message to set the value & base value
767 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
770 void Actor::SetScaleY( float y )
774 // node is being used in a separate thread; queue a message to set the value & base value
775 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
778 void Actor::SetScaleZ( float z )
782 // node is being used in a separate thread; queue a message to set the value & base value
783 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
786 void Actor::ScaleBy(const Vector3& relativeScale)
788 mTargetScale *= relativeScale;
790 // node is being used in a separate thread; queue a message to set the value & base value
791 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
794 const Vector3& Actor::GetCurrentScale() const
796 // node is being used in a separate thread; copy the value from the previous update
797 return GetNode().GetScale(GetEventThreadServices().GetEventBufferIndex());
800 const Vector3& Actor::GetCurrentWorldScale() const
802 // node is being used in a separate thread; copy the value from the previous update
803 return GetNode().GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
806 void Actor::SetInheritScale( bool inherit )
808 if( mInheritScale != inherit )
810 // non animatable so keep local copy
811 mInheritScale = inherit;
812 // node is being used in a separate thread; queue a message to set the value
813 SetInheritScaleMessage( GetEventThreadServices(), GetNode(), inherit );
817 Matrix Actor::GetCurrentWorldMatrix() const
819 return GetNode().GetWorldMatrix(0);
822 void Actor::SetVisible( bool visible )
824 SetVisibleInternal( visible, SendMessage::TRUE );
827 bool Actor::IsVisible() const
829 // node is being used in a separate thread; copy the value from the previous update
830 return GetNode().IsVisible( GetEventThreadServices().GetEventBufferIndex() );
833 void Actor::SetOpacity( float opacity )
835 mTargetColor.a = opacity;
837 // node is being used in a separate thread; queue a message to set the value & base value
838 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
840 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
843 float Actor::GetCurrentOpacity() const
845 // node is being used in a separate thread; copy the value from the previous update
846 return GetNode().GetOpacity(GetEventThreadServices().GetEventBufferIndex());
849 const Vector4& Actor::GetCurrentWorldColor() const
851 return GetNode().GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
854 void Actor::SetColor( const Vector4& color )
856 mTargetColor = color;
858 // node is being used in a separate thread; queue a message to set the value & base value
859 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::Bake, color );
861 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
864 void Actor::SetColorRed( float red )
866 mTargetColor.r = red;
868 // node is being used in a separate thread; queue a message to set the value & base value
869 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeX, red );
871 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
874 void Actor::SetColorGreen( float green )
876 mTargetColor.g = green;
878 // node is being used in a separate thread; queue a message to set the value & base value
879 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeY, green );
881 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
884 void Actor::SetColorBlue( float blue )
886 mTargetColor.b = blue;
888 // node is being used in a separate thread; queue a message to set the value & base value
889 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
891 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
894 const Vector4& Actor::GetCurrentColor() const
896 // node is being used in a separate thread; copy the value from the previous update
897 return GetNode().GetColor(GetEventThreadServices().GetEventBufferIndex());
900 void Actor::SetInheritOrientation( bool inherit )
902 if( mInheritOrientation != inherit )
904 // non animatable so keep local copy
905 mInheritOrientation = inherit;
906 // node is being used in a separate thread; queue a message to set the value
907 SetInheritOrientationMessage( GetEventThreadServices(), GetNode(), inherit );
911 void Actor::SetSizeModeFactor( const Vector3& factor )
915 mRelayoutData->sizeModeFactor = factor;
918 const Vector3& Actor::GetSizeModeFactor() const
922 return mRelayoutData->sizeModeFactor;
925 return Relayouter::DEFAULT_SIZE_MODE_FACTOR;
928 void Actor::SetColorMode( ColorMode colorMode )
930 // non animatable so keep local copy
931 mColorMode = colorMode;
932 // node is being used in a separate thread; queue a message to set the value
933 SetColorModeMessage( GetEventThreadServices(), GetNode(), colorMode );
936 void Actor::SetSize( float width, float height )
938 SetSize( Vector2( width, height ) );
941 void Actor::SetSize( float width, float height, float depth )
943 SetSize( Vector3( width, height, depth ) );
946 void Actor::SetSize( const Vector2& size )
948 SetSize( Vector3( size.width, size.height, 0.f ) );
951 void Actor::SetSizeInternal( const Vector2& size )
953 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
956 void Actor::SetSize( const Vector3& size )
958 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
960 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
961 SetPreferredSize( size.GetVectorXY() );
965 SetSizeInternal( size );
969 void Actor::SetSizeInternal( const Vector3& size )
971 // dont allow recursive loop
972 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
973 // 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
974 if( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
975 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
976 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) )
980 // node is being used in a separate thread; queue a message to set the value & base value
981 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
983 // Notification for derived classes
984 mInsideOnSizeSet = true;
985 OnSizeSet( mTargetSize );
986 mInsideOnSizeSet = false;
988 // Raise a relayout request if the flag is not locked
989 if( mRelayoutData && !mRelayoutData->insideRelayout )
996 void Actor::SetWidth( float width )
998 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1000 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
1001 mRelayoutData->preferredSize.width = width;
1005 mTargetSize.width = width;
1007 // node is being used in a separate thread; queue a message to set the value & base value
1008 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1011 mUseAnimatedSize &= ~AnimatedSizeFlag::WIDTH;
1016 void Actor::SetHeight( float height )
1018 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1020 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
1021 mRelayoutData->preferredSize.height = height;
1025 mTargetSize.height = height;
1027 // node is being used in a separate thread; queue a message to set the value & base value
1028 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1031 mUseAnimatedSize &= ~AnimatedSizeFlag::HEIGHT;
1036 void Actor::SetDepth( float depth )
1038 mTargetSize.depth = depth;
1040 mUseAnimatedSize &= ~AnimatedSizeFlag::DEPTH;
1042 // node is being used in a separate thread; queue a message to set the value & base value
1043 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1046 Vector3 Actor::GetTargetSize() const
1048 Vector3 size = mTargetSize;
1050 if( mUseAnimatedSize & AnimatedSizeFlag::WIDTH )
1052 // Should return animated size if size is animated
1053 size.width = mAnimatedSize.width;
1057 // Should return preferred size if size is fixed as set by SetSize
1058 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
1060 size.width = GetPreferredSize().width;
1064 if( mUseAnimatedSize & AnimatedSizeFlag::HEIGHT )
1066 size.height = mAnimatedSize.height;
1070 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
1072 size.height = GetPreferredSize().height;
1076 if( mUseAnimatedSize & AnimatedSizeFlag::DEPTH )
1078 size.depth = mAnimatedSize.depth;
1084 const Vector3& Actor::GetCurrentSize() const
1086 // node is being used in a separate thread; copy the value from the previous update
1087 return GetNode().GetSize( GetEventThreadServices().GetEventBufferIndex() );
1090 Vector3 Actor::GetNaturalSize() const
1092 // It is up to deriving classes to return the appropriate natural size
1093 return Vector3( 0.0f, 0.0f, 0.0f );
1096 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1098 EnsureRelayouter().SetResizePolicy(policy, dimension, mTargetSize);
1100 OnSetResizePolicy( policy, dimension );
1102 // Trigger relayout on this control
1106 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1108 if ( mRelayoutData )
1110 return mRelayoutData->GetResizePolicy(dimension);
1113 return ResizePolicy::DEFAULT;
1116 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1120 mRelayoutData->sizeSetPolicy = policy;
1122 // Trigger relayout on this control
1126 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1128 if ( mRelayoutData )
1130 return mRelayoutData->sizeSetPolicy;
1133 return Relayouter::DEFAULT_SIZE_SCALE_POLICY;
1136 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1138 EnsureRelayouter().SetDimensionDependency(dimension, dependency);
1141 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1143 if ( mRelayoutData )
1145 return mRelayoutData->GetDimensionDependency(dimension);
1148 return Dimension::ALL_DIMENSIONS; // Default
1151 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1153 // If relayout data has not been allocated yet and the client is requesting
1154 // to disable it, do nothing
1155 if( mRelayoutData || relayoutEnabled )
1159 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1161 mRelayoutData->relayoutEnabled = relayoutEnabled;
1165 bool Actor::IsRelayoutEnabled() const
1167 // Assume that if relayout data has not been allocated yet then
1168 // relayout is disabled
1169 return mRelayoutData && mRelayoutData->relayoutEnabled;
1172 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1174 EnsureRelayouter().SetLayoutDirty(dirty, dimension);
1177 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1179 return mRelayoutData && mRelayoutData->IsLayoutDirty(dimension);
1182 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1184 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1187 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1189 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1192 uint32_t Actor::AddRenderer( Renderer& renderer )
1196 mRenderers = new RendererContainer;
1199 uint32_t index = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1200 RendererPtr rendererPtr = RendererPtr( &renderer );
1201 mRenderers->push_back( rendererPtr );
1202 AttachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1206 uint32_t Actor::GetRendererCount() const
1208 uint32_t rendererCount(0);
1211 rendererCount = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1214 return rendererCount;
1217 RendererPtr Actor::GetRendererAt( uint32_t index )
1219 RendererPtr renderer;
1220 if( index < GetRendererCount() )
1222 renderer = ( *mRenderers )[ index ];
1228 void Actor::RemoveRenderer( Renderer& renderer )
1232 RendererIter end = mRenderers->end();
1233 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1235 if( (*iter).Get() == &renderer )
1237 mRenderers->erase( iter );
1238 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1245 void Actor::RemoveRenderer( uint32_t index )
1247 if( index < GetRendererCount() )
1249 RendererPtr renderer = ( *mRenderers )[ index ];
1250 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.Get()->GetRendererSceneObject() );
1251 mRenderers->erase( mRenderers->begin()+index );
1255 void Actor::SetDrawMode( DrawMode::Type drawMode )
1257 // this flag is not animatable so keep the value
1258 mDrawMode = drawMode;
1260 // node is being used in a separate thread; queue a message to set the value
1261 SetDrawModeMessage( GetEventThreadServices(), GetNode(), drawMode );
1264 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1266 // only valid when on-stage
1267 if( mScene && OnScene() )
1269 const RenderTaskList& taskList = mScene->GetRenderTaskList();
1271 Vector2 converted( screenX, screenY );
1273 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1274 uint32_t taskCount = taskList.GetTaskCount();
1275 for( uint32_t i = taskCount; i > 0; --i )
1277 RenderTaskPtr task = taskList.GetTask( i - 1 );
1278 if( ScreenToLocal( *task, localX, localY, screenX, screenY ) )
1280 // found a task where this conversion was ok so return
1288 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1290 bool retval = false;
1291 // only valid when on-stage
1294 CameraActor* camera = renderTask.GetCameraActor();
1298 renderTask.GetViewport( viewport );
1300 // need to translate coordinates to render tasks coordinate space
1301 Vector2 converted( screenX, screenY );
1302 if( renderTask.TranslateCoordinates( converted ) )
1304 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1311 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1313 return OnScene() && ScreenToLocalInternal(viewMatrix, projectionMatrix, GetNode().GetWorldMatrix(0), viewport, GetCurrentSize(), localX, localY, screenX, screenY);
1316 ActorGestureData& Actor::GetGestureData()
1318 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1319 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1320 if( nullptr == mGestureData )
1322 mGestureData = new ActorGestureData;
1324 return *mGestureData;
1327 bool Actor::IsGestureRequired( GestureType::Value type ) const
1329 return mGestureData && mGestureData->IsGestureRequired( type );
1332 bool Actor::EmitInterceptTouchEventSignal( const Dali::TouchEvent& touch )
1334 return EmitConsumingSignal( *this, mInterceptTouchedSignal, touch );
1337 bool Actor::EmitTouchEventSignal( const Dali::TouchEvent& touch )
1339 return EmitConsumingSignal( *this, mTouchedSignal, touch );
1342 bool Actor::EmitHoverEventSignal( const Dali::HoverEvent& event )
1344 return EmitConsumingSignal( *this, mHoveredSignal, event );
1347 bool Actor::EmitWheelEventSignal( const Dali::WheelEvent& event )
1349 return EmitConsumingSignal( *this, mWheelEventSignal, event );
1352 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
1354 EmitSignal( *this, mVisibilityChangedSignal, visible, type );
1357 void Actor::EmitLayoutDirectionChangedSignal( LayoutDirection::Type type )
1359 EmitSignal( *this, mLayoutDirectionChangedSignal, type );
1362 void Actor::EmitChildAddedSignal( Actor& child )
1364 EmitSignal( child, mChildAddedSignal );
1367 void Actor::EmitChildRemovedSignal( Actor& child )
1369 EmitSignal( child, mChildRemovedSignal );
1372 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1374 bool connected( true );
1375 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
1377 if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1379 actor->HoveredSignal().Connect( tracker, functor );
1381 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1383 actor->WheelEventSignal().Connect( tracker, functor );
1385 else if( 0 == signalName.compare( SIGNAL_ON_SCENE ) )
1387 actor->OnSceneSignal().Connect( tracker, functor );
1389 else if( 0 == signalName.compare( SIGNAL_OFF_SCENE ) )
1391 actor->OffSceneSignal().Connect( tracker, functor );
1393 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
1395 actor->OnRelayoutSignal().Connect( tracker, functor );
1397 else if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1399 actor->TouchedSignal().Connect( tracker, functor );
1401 else if( 0 == signalName.compare( SIGNAL_VISIBILITY_CHANGED ) )
1403 actor->VisibilityChangedSignal().Connect( tracker, functor );
1405 else if( 0 == signalName.compare( SIGNAL_LAYOUT_DIRECTION_CHANGED ) )
1407 actor->LayoutDirectionChangedSignal().Connect( tracker, functor );
1409 else if( 0 == signalName.compare( SIGNAL_CHILD_ADDED ) )
1411 actor->ChildAddedSignal().Connect( tracker, functor );
1413 else if( 0 == signalName.compare( SIGNAL_CHILD_REMOVED ) )
1415 actor->ChildRemovedSignal().Connect( tracker, functor );
1419 // signalName does not match any signal
1426 Actor::Actor( DerivedType derivedType, const SceneGraph::Node& node )
1430 mChildren( nullptr ),
1431 mRenderers( nullptr ),
1432 mParentOrigin( nullptr ),
1433 mAnchorPoint( nullptr ),
1434 mRelayoutData( nullptr ),
1435 mGestureData( nullptr ),
1436 mInterceptTouchedSignal(),
1439 mWheelEventSignal(),
1442 mOnRelayoutSignal(),
1443 mVisibilityChangedSignal(),
1444 mLayoutDirectionChangedSignal(),
1445 mChildAddedSignal(),
1446 mChildRemovedSignal(),
1447 mChildOrderChangedSignal(),
1448 mTargetOrientation( Quaternion::IDENTITY ),
1449 mTargetColor( Color::WHITE ),
1450 mTargetSize( Vector3::ZERO ),
1451 mTargetPosition( Vector3::ZERO ),
1452 mTargetScale( Vector3::ONE ),
1453 mAnimatedSize( Vector3::ZERO ),
1457 mUseAnimatedSize( AnimatedSizeFlag::CLEAR ),
1458 mIsRoot( ROOT_LAYER == derivedType ),
1459 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
1460 mIsOnScene( false ),
1462 mLeaveRequired( false ),
1463 mKeyboardFocusable( false ),
1464 mOnSceneSignalled( false ),
1465 mInsideOnSizeSet( false ),
1466 mInheritPosition( true ),
1467 mInheritOrientation( true ),
1468 mInheritScale( true ),
1469 mPositionUsesAnchorPoint( true ),
1471 mInheritLayoutDirection( true ),
1472 mCaptureAllTouchAfterStart( false ),
1473 mLayoutDirection( LayoutDirection::LEFT_TO_RIGHT ),
1474 mDrawMode( DrawMode::NORMAL ),
1475 mColorMode( Node::DEFAULT_COLOR_MODE ),
1476 mClippingMode( ClippingMode::DISABLED )
1480 void Actor::Initialize()
1484 GetEventThreadServices().RegisterObject( this );
1489 // Remove mParent pointers from children even if we're destroying core,
1490 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1493 ActorConstIter endIter = mChildren->end();
1494 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1496 (*iter)->SetParent( nullptr );
1502 // Guard to allow handle destruction after Core has been destroyed
1503 if( EventThreadServices::IsCoreRunning() )
1505 // Root layer will destroy its node in its own destructor
1508 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
1510 GetEventThreadServices().UnregisterObject( this );
1514 // Cleanup optional gesture data
1515 delete mGestureData;
1517 // Cleanup optional parent origin and anchor
1518 delete mParentOrigin;
1519 delete mAnchorPoint;
1521 // Delete optional relayout data
1522 delete mRelayoutData;
1525 void Actor::ConnectToScene( uint32_t parentDepth )
1527 // This container is used instead of walking the Actor hierarchy.
1528 // It protects us when the Actor hierarchy is modified during OnSceneConnectionExternal callbacks.
1529 ActorContainer connectionList;
1533 mScene->RequestRebuildDepthTree();
1536 // This stage is atomic i.e. not interrupted by user callbacks.
1537 RecursiveConnectToScene( connectionList, parentDepth + 1 );
1539 // Notify applications about the newly connected actors.
1540 const ActorIter endIter = connectionList.end();
1541 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
1543 (*iter)->NotifyStageConnection();
1549 void Actor::RecursiveConnectToScene( ActorContainer& connectionList, uint32_t depth )
1551 DALI_ASSERT_ALWAYS( !OnScene() );
1554 mDepth = static_cast< uint16_t >( depth ); // overflow ignored, not expected in practice
1556 ConnectToSceneGraph();
1558 // Notification for internal derived classes
1559 OnSceneConnectionInternal();
1561 // This stage is atomic; avoid emitting callbacks until all Actors are connected
1562 connectionList.push_back( ActorPtr( this ) );
1564 // Recursively connect children
1567 ActorConstIter endIter = mChildren->end();
1568 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1570 (*iter)->SetScene( *mScene );
1571 (*iter)->RecursiveConnectToScene( connectionList, depth + 1 );
1577 * This method is called when the Actor is connected to the Stage.
1578 * The parent must have added its Node to the scene-graph.
1579 * The child must connect its Node to the parent's Node.
1580 * This is recursive; the child calls ConnectToScene() for its children.
1582 void Actor::ConnectToSceneGraph()
1584 DALI_ASSERT_DEBUG( mParent != NULL);
1586 // Reparent Node in next Update
1587 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), mParent->GetNode(), GetNode() );
1589 // Request relayout on all actors that are added to the scenegraph
1592 // Notification for Object::Observers
1596 void Actor::NotifyStageConnection()
1598 // Actors can be removed (in a callback), before the on-stage stage is reported.
1599 // The actor may also have been reparented, in which case mOnSceneSignalled will be true.
1600 if( OnScene() && !mOnSceneSignalled )
1602 // Notification for external (CustomActor) derived classes
1603 OnSceneConnectionExternal( mDepth );
1605 if( !mOnSceneSignal.Empty() )
1607 Dali::Actor handle( this );
1608 mOnSceneSignal.Emit( handle );
1611 // Guard against Remove during callbacks
1614 mOnSceneSignalled = true; // signal required next time Actor is removed
1619 void Actor::DisconnectFromStage()
1621 // This container is used instead of walking the Actor hierachy.
1622 // It protects us when the Actor hierachy is modified during OnSceneDisconnectionExternal callbacks.
1623 ActorContainer disconnectionList;
1627 mScene->RequestRebuildDepthTree();
1630 // This stage is atomic i.e. not interrupted by user callbacks
1631 RecursiveDisconnectFromStage( disconnectionList );
1633 // Notify applications about the newly disconnected actors.
1634 const ActorIter endIter = disconnectionList.end();
1635 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
1637 (*iter)->NotifyStageDisconnection();
1641 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
1643 // need to change state first so that internals relying on IsOnScene() inside OnSceneDisconnectionInternal() get the correct value
1646 // Recursively disconnect children
1649 ActorConstIter endIter = mChildren->end();
1650 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1652 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
1656 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
1657 disconnectionList.push_back( ActorPtr( this ) );
1659 // Notification for internal derived classes
1660 OnSceneDisconnectionInternal();
1662 DisconnectFromSceneGraph();
1666 * This method is called by an actor or its parent, before a node removal message is sent.
1667 * This is recursive; the child calls DisconnectFromStage() for its children.
1669 void Actor::DisconnectFromSceneGraph()
1671 // Notification for Object::Observers
1672 OnSceneObjectRemove();
1675 void Actor::NotifyStageDisconnection()
1677 // Actors can be added (in a callback), before the off-stage state is reported.
1678 // Also if the actor was added & removed before mOnSceneSignalled was set, then we don't notify here.
1679 // only do this step if there is a stage, i.e. Core is not being shut down
1680 if ( EventThreadServices::IsCoreRunning() && !OnScene() && mOnSceneSignalled )
1682 // Notification for external (CustomeActor) derived classes
1683 OnSceneDisconnectionExternal();
1685 if( !mOffSceneSignal.Empty() )
1687 Dali::Actor handle( this );
1688 mOffSceneSignal.Emit( handle );
1691 // Guard against Add during callbacks
1694 mOnSceneSignalled = false; // signal required next time Actor is added
1699 bool Actor::IsNodeConnected() const
1701 bool connected( false );
1705 if( IsRoot() || GetNode().GetParent() )
1714 // This method initiates traversal of the actor tree using depth-first
1715 // traversal to set a depth index based on traversal order. It sends a
1716 // single message to update manager to update all the actor's nodes in
1717 // this tree with the depth index. The sceneGraphNodeDepths vector's
1718 // elements are ordered by depth, and could be used to reduce sorting
1719 // in the update thread.
1720 void Actor::RebuildDepthTree()
1722 DALI_LOG_TIMER_START(depthTimer);
1724 // Vector of scene-graph nodes and their depths to send to UpdateManager
1725 // in a single message
1726 OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths( new SceneGraph::NodeDepths() );
1728 int32_t depthIndex = 1;
1729 DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
1731 SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths );
1732 DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
1735 void Actor::DepthTraverseActorTree( OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths, int32_t& depthIndex )
1737 mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
1738 sceneGraphNodeDepths->Add( const_cast<SceneGraph::Node*>( &GetNode() ), mSortedDepth );
1740 // Create/add to children of this node
1743 for( ActorContainer::iterator it = mChildren->begin(); it != mChildren->end(); ++it )
1745 Actor* childActor = (*it).Get();
1747 childActor->DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
1752 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
1754 PropertyHandler::SetDefaultProperty(*this, index, property);
1757 // TODO: This method needs to be removed
1758 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
1760 PropertyHandler::SetSceneGraphProperty(index, entry, value, GetEventThreadServices(), GetNode());
1763 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
1765 Property::Value value;
1767 if( ! GetCachedPropertyValue( index, value ) )
1769 // If property value is not stored in the event-side, then it must be a scene-graph only property
1770 GetCurrentPropertyValue( index, value );
1776 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
1778 Property::Value value;
1780 if( ! GetCurrentPropertyValue( index, value ) )
1782 // If unable to retrieve scene-graph property value, then it must be an event-side only property
1783 GetCachedPropertyValue( index, value );
1789 void Actor::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
1791 PropertyHandler::OnNotifyDefaultPropertyAnimation(*this, animation, index, value, animationType);
1794 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
1796 const PropertyBase* property = PropertyHandler::GetSceneObjectAnimatableProperty(index, GetNode());
1799 // not our property, ask base
1800 property = Object::GetSceneObjectAnimatableProperty( index );
1806 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
1808 const PropertyInputImpl* property = PropertyHandler::GetSceneObjectInputProperty(index, GetNode());
1811 // reuse animatable property getter as animatable properties are inputs as well
1812 // animatable property chains back to Object::GetSceneObjectInputProperty() so all properties get covered
1813 property = GetSceneObjectAnimatableProperty( index );
1819 int32_t Actor::GetPropertyComponentIndex( Property::Index index ) const
1821 int32_t componentIndex = PropertyHandler::GetPropertyComponentIndex(index);
1822 if( Property::INVALID_COMPONENT_INDEX == componentIndex )
1825 componentIndex = Object::GetPropertyComponentIndex( index );
1828 return componentIndex;
1831 void Actor::SetParent( Actor* parent )
1835 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
1839 mScene = parent->mScene;
1841 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1844 // Instruct each actor to create a corresponding node in the scene graph
1845 ConnectToScene( parent->GetHierarchyDepth() );
1848 // Resolve the name and index for the child properties if any
1849 ResolveChildProperties();
1851 else // parent being set to NULL
1853 DALI_ASSERT_ALWAYS( mParent != nullptr && "Actor should have a parent" );
1857 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1860 // Disconnect the Node & its children from the scene-graph.
1861 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
1863 // Instruct each actor to discard pointers to the scene-graph
1864 DisconnectFromStage();
1871 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
1874 Actor* actor = dynamic_cast< Actor* >( object );
1878 if( 0 == actionName.compare( ACTION_SHOW ) )
1880 actor->SetVisible( true );
1883 else if( 0 == actionName.compare( ACTION_HIDE ) )
1885 actor->SetVisible( false );
1893 Rect<> Actor::CalculateScreenExtents( ) const
1895 auto screenPosition = GetCurrentScreenPosition();
1896 Vector3 size = GetCurrentSize() * GetCurrentWorldScale();
1897 Vector3 anchorPointOffSet = size * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
1898 Vector2 position = Vector2( screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y );
1899 return { position.x, position.y, size.x, size.y };
1902 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
1904 return PropertyHandler::GetCachedPropertyValue(*this, index, value);
1907 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
1909 return PropertyHandler::GetCurrentPropertyValue(*this, index, value);
1912 Actor::Relayouter& Actor::EnsureRelayouter()
1914 // Assign relayouter
1915 if( !mRelayoutData )
1917 mRelayoutData = new Relayouter();
1920 return *mRelayoutData;
1923 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
1925 // Check if actor is dependent on parent
1926 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1928 if( ( dimension & ( 1 << i ) ) )
1930 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
1931 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
1941 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
1943 // Check if actor is dependent on children
1944 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1946 if( ( dimension & ( 1 << i ) ) )
1948 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
1949 switch( resizePolicy )
1951 case ResizePolicy::FIT_TO_CHILDREN:
1952 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
1968 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
1970 return Actor::RelayoutDependentOnChildren( dimension );
1973 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
1975 // Check each possible dimension and see if it is dependent on the input one
1976 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1978 if( dimension & ( 1 << i ) )
1980 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
1987 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
1989 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1991 if( dimension & ( 1 << i ) )
1993 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
1998 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
2000 // If more than one dimension is requested, just return the first one found
2001 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2003 if( ( dimension & ( 1 << i ) ) )
2005 return mRelayoutData->negotiatedDimensions[ i ];
2009 return 0.0f; // Default
2012 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
2014 EnsureRelayouter().SetPadding( padding, dimension );
2017 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
2019 if ( mRelayoutData )
2021 // If more than one dimension is requested, just return the first one found
2022 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2024 if( ( dimension & ( 1 << i ) ) )
2026 return mRelayoutData->dimensionPadding[ i ];
2031 return Relayouter::DEFAULT_DIMENSION_PADDING;
2034 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
2036 EnsureRelayouter().SetLayoutNegotiated(negotiated, dimension);
2039 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
2041 return mRelayoutData && mRelayoutData->IsLayoutNegotiated(dimension);
2044 float Actor::GetHeightForWidthBase( float width )
2046 float height = 0.0f;
2048 const Vector3 naturalSize = GetNaturalSize();
2049 if( naturalSize.width > 0.0f )
2051 height = naturalSize.height * width / naturalSize.width;
2053 else // we treat 0 as 1:1 aspect ratio
2061 float Actor::GetWidthForHeightBase( float height )
2065 const Vector3 naturalSize = GetNaturalSize();
2066 if( naturalSize.height > 0.0f )
2068 width = naturalSize.width * height / naturalSize.height;
2070 else // we treat 0 as 1:1 aspect ratio
2078 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
2080 // Fill to parent, taking size mode factor into account
2081 switch( child.GetResizePolicy( dimension ) )
2083 case ResizePolicy::FILL_TO_PARENT:
2085 return GetLatestSize( dimension );
2088 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2090 return GetLatestSize( dimension ) * GetDimensionValue( child.GetProperty< Vector3 >( Dali::Actor::Property::SIZE_MODE_FACTOR ), dimension );
2093 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2095 return GetLatestSize( dimension ) + GetDimensionValue( child.GetProperty< Vector3 >( Dali::Actor::Property::SIZE_MODE_FACTOR ), dimension );
2100 return GetLatestSize( dimension );
2105 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
2107 // Can be overridden in derived class
2108 return CalculateChildSizeBase( child, dimension );
2111 float Actor::GetHeightForWidth( float width )
2113 // Can be overridden in derived class
2114 return GetHeightForWidthBase( width );
2117 float Actor::GetWidthForHeight( float height )
2119 // Can be overridden in derived class
2120 return GetWidthForHeightBase( height );
2123 float Actor::GetLatestSize( Dimension::Type dimension ) const
2125 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
2128 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
2130 Vector2 padding = GetPadding( dimension );
2132 return GetLatestSize( dimension ) + padding.x + padding.y;
2135 float Actor::NegotiateFromParent( Dimension::Type dimension )
2137 Actor* parent = GetParent();
2140 Vector2 padding( GetPadding( dimension ) );
2141 Vector2 parentPadding( parent->GetPadding( dimension ) );
2142 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
2148 float Actor::NegotiateFromChildren( Dimension::Type dimension )
2150 float maxDimensionPoint = 0.0f;
2152 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2154 ActorPtr child = GetChildAt( i );
2156 if( !child->RelayoutDependentOnParent( dimension ) )
2158 // Calculate the min and max points that the children range across
2159 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
2160 float dimensionSize = child->GetRelayoutSize( dimension );
2161 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
2165 return maxDimensionPoint;
2168 float Actor::GetSize( Dimension::Type dimension ) const
2170 return GetDimensionValue( mTargetSize, dimension );
2173 float Actor::GetNaturalSize( Dimension::Type dimension ) const
2175 return GetDimensionValue( GetNaturalSize(), dimension );
2178 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
2180 switch( GetResizePolicy( dimension ) )
2182 case ResizePolicy::USE_NATURAL_SIZE:
2184 return GetNaturalSize( dimension );
2187 case ResizePolicy::FIXED:
2189 return GetDimensionValue( GetPreferredSize(), dimension );
2192 case ResizePolicy::USE_ASSIGNED_SIZE:
2194 return GetDimensionValue( maximumSize, dimension );
2197 case ResizePolicy::FILL_TO_PARENT:
2198 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2199 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2201 return NegotiateFromParent( dimension );
2204 case ResizePolicy::FIT_TO_CHILDREN:
2206 return NegotiateFromChildren( dimension );
2209 case ResizePolicy::DIMENSION_DEPENDENCY:
2211 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
2214 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
2216 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
2219 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
2221 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
2233 return 0.0f; // Default
2236 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
2238 // Check if it needs to be negotiated
2239 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
2241 // Check that we havn't gotten into an infinite loop
2242 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
2243 bool recursionFound = false;
2244 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
2246 if( *it == searchActor )
2248 recursionFound = true;
2253 if( !recursionFound )
2255 // Record the path that we have taken
2256 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
2258 // Dimension dependency check
2259 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2261 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
2263 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
2265 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
2269 // Parent dependency check
2270 Actor* parent = GetParent();
2271 if( parent && RelayoutDependentOnParent( dimension ) )
2273 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
2276 // Children dependency check
2277 if( RelayoutDependentOnChildren( dimension ) )
2279 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2281 ActorPtr child = GetChildAt( i );
2283 // Only relayout child first if it is not dependent on this actor
2284 if( !child->RelayoutDependentOnParent( dimension ) )
2286 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
2291 // For deriving classes
2292 OnCalculateRelayoutSize( dimension );
2294 // All dependencies checked, calculate the size and set negotiated flag
2295 const float newSize = Relayouter::ClampDimension( *this, CalculateSize( dimension, allocatedSize ), dimension );
2297 SetNegotiatedDimension( newSize, dimension );
2298 SetLayoutNegotiated( true, dimension );
2300 // For deriving classes
2301 OnLayoutNegotiated( newSize, dimension );
2303 // This actor has been successfully processed, pop it off the recursion stack
2304 recursionStack.pop_back();
2308 // TODO: Break infinite loop
2309 SetLayoutNegotiated( true, dimension );
2314 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
2316 // Negotiate all dimensions that require it
2317 ActorDimensionStack recursionStack;
2319 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2321 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
2324 NegotiateDimension( dimension, allocatedSize, recursionStack );
2328 Vector2 Actor::ApplySizeSetPolicy( const Vector2& size )
2330 return mRelayoutData->ApplySizeSetPolicy(*this, size);
2333 void Actor::SetNegotiatedSize( RelayoutContainer& container )
2335 // Do the set actor size
2336 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
2338 // Adjust for size set policy
2339 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
2341 // Lock the flag to stop recursive relayouts on set size
2342 mRelayoutData->insideRelayout = true;
2343 SetSize( negotiatedSize );
2344 mRelayoutData->insideRelayout = false;
2346 // Clear flags for all dimensions
2347 SetLayoutDirty( false );
2349 // Give deriving classes a chance to respond
2350 OnRelayout( negotiatedSize, container );
2352 if( !mOnRelayoutSignal.Empty() )
2354 Dali::Actor handle( this );
2355 mOnRelayoutSignal.Emit( handle );
2359 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
2361 // Force a size negotiation for actors that has assigned size during relayout
2362 // This is required as otherwise the flags that force a relayout will not
2363 // necessarilly be set. This will occur if the actor has already been laid out.
2364 // The dirty flags are then cleared. Then if the actor is added back into the
2365 // relayout container afterwards, the dirty flags would still be clear...
2366 // causing a relayout to be skipped. Here we force any actors added to the
2367 // container to be relayed out.
2368 DALI_LOG_TIMER_START( NegSizeTimer1 );
2370 if( GetUseAssignedSize(Dimension::WIDTH ) )
2372 SetLayoutNegotiated( false, Dimension::WIDTH );
2374 if( GetUseAssignedSize( Dimension::HEIGHT ) )
2376 SetLayoutNegotiated( false, Dimension::HEIGHT );
2379 // Do the negotiation
2380 NegotiateDimensions( allocatedSize );
2382 // Set the actor size
2383 SetNegotiatedSize( container );
2385 // Negotiate down to children
2386 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2388 ActorPtr child = GetChildAt( i );
2390 // Forces children that have already been laid out to be relayed out
2391 // if they have assigned size during relayout.
2392 if( child->GetUseAssignedSize(Dimension::WIDTH) )
2394 child->SetLayoutNegotiated(false, Dimension::WIDTH);
2395 child->SetLayoutDirty(true, Dimension::WIDTH);
2398 if( child->GetUseAssignedSize(Dimension::HEIGHT) )
2400 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
2401 child->SetLayoutDirty(true, Dimension::HEIGHT);
2404 // Only relayout if required
2405 if( child->RelayoutRequired() )
2407 container.Add( Dali::Actor( child.Get() ), mTargetSize.GetVectorXY() );
2410 DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
2413 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
2417 mRelayoutData->SetUseAssignedSize(use, dimension);
2421 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
2423 return mRelayoutData && mRelayoutData->GetUseAssignedSize(dimension);
2426 void Actor::RelayoutRequest( Dimension::Type dimension )
2428 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
2429 if( relayoutController )
2431 Dali::Actor self( this );
2432 relayoutController->RequestRelayout( self, dimension );
2436 void Actor::SetPreferredSize( const Vector2& size )
2440 // If valid width or height, then set the resize policy to FIXED
2441 // 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,
2442 // then change to FIXED as well
2444 if( size.width > 0.0f || GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DEFAULT )
2446 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
2449 if( size.height > 0.0f || GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DEFAULT )
2451 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
2454 mRelayoutData->preferredSize = size;
2456 mUseAnimatedSize = AnimatedSizeFlag::CLEAR;
2461 Vector2 Actor::GetPreferredSize() const
2463 if ( mRelayoutData )
2465 return Vector2( mRelayoutData->preferredSize );
2468 return Relayouter::DEFAULT_PREFERRED_SIZE;
2471 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
2473 EnsureRelayouter().SetMinimumSize(size, dimension);
2477 float Actor::GetMinimumSize( Dimension::Type dimension ) const
2479 if ( mRelayoutData )
2481 return mRelayoutData->GetMinimumSize(dimension);
2484 return 0.0f; // Default
2487 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
2489 EnsureRelayouter().SetMaximumSize(size, dimension);
2493 float Actor::GetMaximumSize( Dimension::Type dimension ) const
2495 if ( mRelayoutData )
2497 return mRelayoutData->GetMaximumSize(dimension);
2500 return FLT_MAX; // Default
2503 void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
2505 if( mVisible != visible )
2507 if( sendMessage == SendMessage::TRUE )
2509 // node is being used in a separate thread; queue a message to set the value & base value
2510 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible );
2512 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
2517 // Emit the signal on this actor and all its children
2518 EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
2522 void Actor::SetSiblingOrder( uint32_t order )
2526 ActorContainer& siblings = *(mParent->mChildren);
2527 uint32_t currentOrder = GetSiblingOrder();
2529 if( order != currentOrder )
2535 else if( order < siblings.size() -1 )
2537 if( order > currentOrder )
2539 RaiseAbove( *siblings[order] );
2543 LowerBelow( *siblings[order] );
2554 uint32_t Actor::GetSiblingOrder() const
2560 ActorContainer& siblings = *(mParent->mChildren);
2561 for( std::size_t i = 0; i < siblings.size(); ++i )
2563 if( siblings[i] == this )
2565 order = static_cast<uint32_t>( i );
2574 void Actor::RequestRebuildDepthTree()
2580 mScene->RequestRebuildDepthTree();
2589 ActorContainer& siblings = *(mParent->mChildren);
2590 if( siblings.back() != this ) // If not already at end
2592 for( std::size_t i=0; i<siblings.size(); ++i )
2594 if( siblings[i] == this )
2597 ActorPtr next = siblings[i+1];
2598 siblings[i+1] = this;
2605 Dali::Actor handle( this );
2606 mParent->mChildOrderChangedSignal.Emit( handle );
2608 RequestRebuildDepthTree();
2612 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2620 ActorContainer& siblings = *(mParent->mChildren);
2621 if( siblings.front() != this ) // If not already at beginning
2623 for( std::size_t i=1; i<siblings.size(); ++i )
2625 if( siblings[i] == this )
2627 // Swap with previous
2628 ActorPtr previous = siblings[i-1];
2629 siblings[i-1] = this;
2630 siblings[i] = previous;
2636 Dali::Actor handle( this );
2637 mParent->mChildOrderChangedSignal.Emit( handle );
2639 RequestRebuildDepthTree();
2643 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2647 void Actor::RaiseToTop()
2651 ActorContainer& siblings = *(mParent->mChildren);
2652 if( siblings.back() != this ) // If not already at end
2654 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
2655 if( iter != siblings.end() )
2657 siblings.erase(iter);
2658 siblings.push_back(ActorPtr(this));
2662 Dali::Actor handle( this );
2663 mParent->mChildOrderChangedSignal.Emit( handle );
2665 RequestRebuildDepthTree();
2669 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2673 void Actor::LowerToBottom()
2677 ActorContainer& siblings = *(mParent->mChildren);
2678 if( siblings.front() != this ) // If not already at bottom,
2680 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2682 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
2683 if( iter != siblings.end() )
2685 siblings.erase(iter);
2686 siblings.insert(siblings.begin(), thisPtr);
2690 Dali::Actor handle( this );
2691 mParent->mChildOrderChangedSignal.Emit( handle );
2693 RequestRebuildDepthTree();
2697 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2701 void Actor::RaiseAbove( Internal::Actor& target )
2705 ActorContainer& siblings = *(mParent->mChildren);
2706 if( siblings.back() != this && target.mParent == mParent ) // If not already at top
2708 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2710 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
2711 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
2712 if( thisIter < targetIter )
2714 siblings.erase(thisIter);
2715 // Erasing early invalidates the targetIter. (Conversely, inserting first may also
2716 // invalidate thisIter)
2717 targetIter = std::find( siblings.begin(), siblings.end(), &target );
2719 siblings.insert(targetIter, thisPtr);
2722 Dali::Actor handle( this );
2723 mParent->mChildOrderChangedSignal.Emit( handle );
2725 RequestRebuildDepthTree();
2730 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2734 void Actor::LowerBelow( Internal::Actor& target )
2738 ActorContainer& siblings = *(mParent->mChildren);
2739 if( siblings.front() != this && target.mParent == mParent ) // If not already at bottom
2741 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2743 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
2744 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
2746 if( thisIter > targetIter )
2748 siblings.erase(thisIter); // this only invalidates iterators at or after this point.
2749 siblings.insert(targetIter, thisPtr);
2752 Dali::Actor handle( this );
2753 mParent->mChildOrderChangedSignal.Emit( handle );
2755 RequestRebuildDepthTree();
2760 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2764 void Actor::SetInheritLayoutDirection( bool inherit )
2766 if( mInheritLayoutDirection != inherit )
2768 mInheritLayoutDirection = inherit;
2770 if( inherit && mParent )
2772 InheritLayoutDirectionRecursively( this, mParent->mLayoutDirection );
2777 void Actor::InheritLayoutDirectionRecursively( ActorPtr actor, Dali::LayoutDirection::Type direction, bool set )
2779 if( actor && ( actor->mInheritLayoutDirection || set ) )
2781 if( actor->mLayoutDirection != direction )
2783 actor->mLayoutDirection = direction;
2784 actor->EmitLayoutDirectionChangedSignal( direction );
2785 actor->RelayoutRequest();
2788 if( actor->GetChildCount() > 0 )
2790 for( ActorPtr& child : actor->GetChildrenInternal() )
2792 InheritLayoutDirectionRecursively( child, direction );
2798 void Actor::SetUpdateSizeHint( const Vector2& updateSizeHint )
2800 // node is being used in a separate thread; queue a message to set the value & base value
2801 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mUpdateSizeHint, &AnimatableProperty<Vector3>::Bake, Vector3(updateSizeHint.width, updateSizeHint.height, 0.f ) );
2804 } // namespace Internal