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::EmitTouchEventSignal( const Dali::TouchEvent& touch )
1334 return EmitConsumingSignal( *this, mTouchedSignal, touch );
1337 bool Actor::EmitHoverEventSignal( const Dali::HoverEvent& event )
1339 return EmitConsumingSignal( *this, mHoveredSignal, event );
1342 bool Actor::EmitWheelEventSignal( const Dali::WheelEvent& event )
1344 return EmitConsumingSignal( *this, mWheelEventSignal, event );
1347 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
1349 EmitSignal( *this, mVisibilityChangedSignal, visible, type );
1352 void Actor::EmitLayoutDirectionChangedSignal( LayoutDirection::Type type )
1354 EmitSignal( *this, mLayoutDirectionChangedSignal, type );
1357 void Actor::EmitChildAddedSignal( Actor& child )
1359 EmitSignal( child, mChildAddedSignal );
1362 void Actor::EmitChildRemovedSignal( Actor& child )
1364 EmitSignal( child, mChildRemovedSignal );
1367 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1369 bool connected( true );
1370 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
1372 if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1374 actor->HoveredSignal().Connect( tracker, functor );
1376 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1378 actor->WheelEventSignal().Connect( tracker, functor );
1380 else if( 0 == signalName.compare( SIGNAL_ON_SCENE ) )
1382 actor->OnSceneSignal().Connect( tracker, functor );
1384 else if( 0 == signalName.compare( SIGNAL_OFF_SCENE ) )
1386 actor->OffSceneSignal().Connect( tracker, functor );
1388 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
1390 actor->OnRelayoutSignal().Connect( tracker, functor );
1392 else if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1394 actor->TouchedSignal().Connect( tracker, functor );
1396 else if( 0 == signalName.compare( SIGNAL_VISIBILITY_CHANGED ) )
1398 actor->VisibilityChangedSignal().Connect( tracker, functor );
1400 else if( 0 == signalName.compare( SIGNAL_LAYOUT_DIRECTION_CHANGED ) )
1402 actor->LayoutDirectionChangedSignal().Connect( tracker, functor );
1404 else if( 0 == signalName.compare( SIGNAL_CHILD_ADDED ) )
1406 actor->ChildAddedSignal().Connect( tracker, functor );
1408 else if( 0 == signalName.compare( SIGNAL_CHILD_REMOVED ) )
1410 actor->ChildRemovedSignal().Connect( tracker, functor );
1414 // signalName does not match any signal
1421 Actor::Actor( DerivedType derivedType, const SceneGraph::Node& node )
1425 mChildren( nullptr ),
1426 mRenderers( nullptr ),
1427 mParentOrigin( nullptr ),
1428 mAnchorPoint( nullptr ),
1429 mRelayoutData( nullptr ),
1430 mGestureData( nullptr ),
1433 mWheelEventSignal(),
1436 mOnRelayoutSignal(),
1437 mVisibilityChangedSignal(),
1438 mLayoutDirectionChangedSignal(),
1439 mChildAddedSignal(),
1440 mChildRemovedSignal(),
1441 mChildOrderChangedSignal(),
1442 mTargetOrientation( Quaternion::IDENTITY ),
1443 mTargetColor( Color::WHITE ),
1444 mTargetSize( Vector3::ZERO ),
1445 mTargetPosition( Vector3::ZERO ),
1446 mTargetScale( Vector3::ONE ),
1447 mAnimatedSize( Vector3::ZERO ),
1451 mUseAnimatedSize( AnimatedSizeFlag::CLEAR ),
1452 mIsRoot( ROOT_LAYER == derivedType ),
1453 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
1454 mIsOnScene( false ),
1456 mLeaveRequired( false ),
1457 mKeyboardFocusable( false ),
1458 mOnSceneSignalled( false ),
1459 mInsideOnSizeSet( false ),
1460 mInheritPosition( true ),
1461 mInheritOrientation( true ),
1462 mInheritScale( true ),
1463 mPositionUsesAnchorPoint( true ),
1465 mInheritLayoutDirection( true ),
1466 mCaptureAllTouchAfterStart( false ),
1467 mLayoutDirection( LayoutDirection::LEFT_TO_RIGHT ),
1468 mDrawMode( DrawMode::NORMAL ),
1469 mColorMode( Node::DEFAULT_COLOR_MODE ),
1470 mClippingMode( ClippingMode::DISABLED )
1474 void Actor::Initialize()
1478 GetEventThreadServices().RegisterObject( this );
1483 // Remove mParent pointers from children even if we're destroying core,
1484 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1487 ActorConstIter endIter = mChildren->end();
1488 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1490 (*iter)->SetParent( nullptr );
1496 // Guard to allow handle destruction after Core has been destroyed
1497 if( EventThreadServices::IsCoreRunning() )
1499 // Root layer will destroy its node in its own destructor
1502 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
1504 GetEventThreadServices().UnregisterObject( this );
1508 // Cleanup optional gesture data
1509 delete mGestureData;
1511 // Cleanup optional parent origin and anchor
1512 delete mParentOrigin;
1513 delete mAnchorPoint;
1515 // Delete optional relayout data
1516 delete mRelayoutData;
1519 void Actor::ConnectToScene( uint32_t parentDepth )
1521 // This container is used instead of walking the Actor hierarchy.
1522 // It protects us when the Actor hierarchy is modified during OnSceneConnectionExternal callbacks.
1523 ActorContainer connectionList;
1527 mScene->RequestRebuildDepthTree();
1530 // This stage is atomic i.e. not interrupted by user callbacks.
1531 RecursiveConnectToScene( connectionList, parentDepth + 1 );
1533 // Notify applications about the newly connected actors.
1534 const ActorIter endIter = connectionList.end();
1535 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
1537 (*iter)->NotifyStageConnection();
1543 void Actor::RecursiveConnectToScene( ActorContainer& connectionList, uint32_t depth )
1545 DALI_ASSERT_ALWAYS( !OnScene() );
1548 mDepth = static_cast< uint16_t >( depth ); // overflow ignored, not expected in practice
1550 ConnectToSceneGraph();
1552 // Notification for internal derived classes
1553 OnSceneConnectionInternal();
1555 // This stage is atomic; avoid emitting callbacks until all Actors are connected
1556 connectionList.push_back( ActorPtr( this ) );
1558 // Recursively connect children
1561 ActorConstIter endIter = mChildren->end();
1562 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1564 (*iter)->SetScene( *mScene );
1565 (*iter)->RecursiveConnectToScene( connectionList, depth + 1 );
1571 * This method is called when the Actor is connected to the Stage.
1572 * The parent must have added its Node to the scene-graph.
1573 * The child must connect its Node to the parent's Node.
1574 * This is recursive; the child calls ConnectToScene() for its children.
1576 void Actor::ConnectToSceneGraph()
1578 DALI_ASSERT_DEBUG( mParent != NULL);
1580 // Reparent Node in next Update
1581 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), mParent->GetNode(), GetNode() );
1583 // Request relayout on all actors that are added to the scenegraph
1586 // Notification for Object::Observers
1590 void Actor::NotifyStageConnection()
1592 // Actors can be removed (in a callback), before the on-stage stage is reported.
1593 // The actor may also have been reparented, in which case mOnSceneSignalled will be true.
1594 if( OnScene() && !mOnSceneSignalled )
1596 // Notification for external (CustomActor) derived classes
1597 OnSceneConnectionExternal( mDepth );
1599 if( !mOnSceneSignal.Empty() )
1601 Dali::Actor handle( this );
1602 mOnSceneSignal.Emit( handle );
1605 // Guard against Remove during callbacks
1608 mOnSceneSignalled = true; // signal required next time Actor is removed
1613 void Actor::DisconnectFromStage()
1615 // This container is used instead of walking the Actor hierachy.
1616 // It protects us when the Actor hierachy is modified during OnSceneDisconnectionExternal callbacks.
1617 ActorContainer disconnectionList;
1621 mScene->RequestRebuildDepthTree();
1624 // This stage is atomic i.e. not interrupted by user callbacks
1625 RecursiveDisconnectFromStage( disconnectionList );
1627 // Notify applications about the newly disconnected actors.
1628 const ActorIter endIter = disconnectionList.end();
1629 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
1631 (*iter)->NotifyStageDisconnection();
1635 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
1637 // need to change state first so that internals relying on IsOnScene() inside OnSceneDisconnectionInternal() get the correct value
1640 // Recursively disconnect children
1643 ActorConstIter endIter = mChildren->end();
1644 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1646 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
1650 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
1651 disconnectionList.push_back( ActorPtr( this ) );
1653 // Notification for internal derived classes
1654 OnSceneDisconnectionInternal();
1656 DisconnectFromSceneGraph();
1660 * This method is called by an actor or its parent, before a node removal message is sent.
1661 * This is recursive; the child calls DisconnectFromStage() for its children.
1663 void Actor::DisconnectFromSceneGraph()
1665 // Notification for Object::Observers
1666 OnSceneObjectRemove();
1669 void Actor::NotifyStageDisconnection()
1671 // Actors can be added (in a callback), before the off-stage state is reported.
1672 // Also if the actor was added & removed before mOnSceneSignalled was set, then we don't notify here.
1673 // only do this step if there is a stage, i.e. Core is not being shut down
1674 if ( EventThreadServices::IsCoreRunning() && !OnScene() && mOnSceneSignalled )
1676 // Notification for external (CustomeActor) derived classes
1677 OnSceneDisconnectionExternal();
1679 if( !mOffSceneSignal.Empty() )
1681 Dali::Actor handle( this );
1682 mOffSceneSignal.Emit( handle );
1685 // Guard against Add during callbacks
1688 mOnSceneSignalled = false; // signal required next time Actor is added
1693 bool Actor::IsNodeConnected() const
1695 bool connected( false );
1699 if( IsRoot() || GetNode().GetParent() )
1708 // This method initiates traversal of the actor tree using depth-first
1709 // traversal to set a depth index based on traversal order. It sends a
1710 // single message to update manager to update all the actor's nodes in
1711 // this tree with the depth index. The sceneGraphNodeDepths vector's
1712 // elements are ordered by depth, and could be used to reduce sorting
1713 // in the update thread.
1714 void Actor::RebuildDepthTree()
1716 DALI_LOG_TIMER_START(depthTimer);
1718 // Vector of scene-graph nodes and their depths to send to UpdateManager
1719 // in a single message
1720 OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths( new SceneGraph::NodeDepths() );
1722 int32_t depthIndex = 1;
1723 DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
1725 SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths );
1726 DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
1729 void Actor::DepthTraverseActorTree( OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths, int32_t& depthIndex )
1731 mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
1732 sceneGraphNodeDepths->Add( const_cast<SceneGraph::Node*>( &GetNode() ), mSortedDepth );
1734 // Create/add to children of this node
1737 for( ActorContainer::iterator it = mChildren->begin(); it != mChildren->end(); ++it )
1739 Actor* childActor = (*it).Get();
1741 childActor->DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
1746 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
1748 PropertyHandler::SetDefaultProperty(*this, index, property);
1751 // TODO: This method needs to be removed
1752 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
1754 PropertyHandler::SetSceneGraphProperty(index, entry, value, GetEventThreadServices(), GetNode());
1757 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
1759 Property::Value value;
1761 if( ! GetCachedPropertyValue( index, value ) )
1763 // If property value is not stored in the event-side, then it must be a scene-graph only property
1764 GetCurrentPropertyValue( index, value );
1770 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
1772 Property::Value value;
1774 if( ! GetCurrentPropertyValue( index, value ) )
1776 // If unable to retrieve scene-graph property value, then it must be an event-side only property
1777 GetCachedPropertyValue( index, value );
1783 void Actor::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
1785 PropertyHandler::OnNotifyDefaultPropertyAnimation(*this, animation, index, value, animationType);
1788 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
1790 const PropertyBase* property = PropertyHandler::GetSceneObjectAnimatableProperty(index, GetNode());
1793 // not our property, ask base
1794 property = Object::GetSceneObjectAnimatableProperty( index );
1800 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
1802 const PropertyInputImpl* property = PropertyHandler::GetSceneObjectInputProperty(index, GetNode());
1805 // reuse animatable property getter as animatable properties are inputs as well
1806 // animatable property chains back to Object::GetSceneObjectInputProperty() so all properties get covered
1807 property = GetSceneObjectAnimatableProperty( index );
1813 int32_t Actor::GetPropertyComponentIndex( Property::Index index ) const
1815 int32_t componentIndex = PropertyHandler::GetPropertyComponentIndex(index);
1816 if( Property::INVALID_COMPONENT_INDEX == componentIndex )
1819 componentIndex = Object::GetPropertyComponentIndex( index );
1822 return componentIndex;
1825 void Actor::SetParent( Actor* parent )
1829 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
1833 mScene = parent->mScene;
1835 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1838 // Instruct each actor to create a corresponding node in the scene graph
1839 ConnectToScene( parent->GetHierarchyDepth() );
1842 // Resolve the name and index for the child properties if any
1843 ResolveChildProperties();
1845 else // parent being set to NULL
1847 DALI_ASSERT_ALWAYS( mParent != nullptr && "Actor should have a parent" );
1851 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1854 // Disconnect the Node & its children from the scene-graph.
1855 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
1857 // Instruct each actor to discard pointers to the scene-graph
1858 DisconnectFromStage();
1865 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
1868 Actor* actor = dynamic_cast< Actor* >( object );
1872 if( 0 == actionName.compare( ACTION_SHOW ) )
1874 actor->SetVisible( true );
1877 else if( 0 == actionName.compare( ACTION_HIDE ) )
1879 actor->SetVisible( false );
1887 Rect<> Actor::CalculateScreenExtents( ) const
1889 auto screenPosition = GetCurrentScreenPosition();
1890 Vector3 size = GetCurrentSize() * GetCurrentWorldScale();
1891 Vector3 anchorPointOffSet = size * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
1892 Vector2 position = Vector2( screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y );
1893 return { position.x, position.y, size.x, size.y };
1896 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
1898 return PropertyHandler::GetCachedPropertyValue(*this, index, value);
1901 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
1903 return PropertyHandler::GetCurrentPropertyValue(*this, index, value);
1906 Actor::Relayouter& Actor::EnsureRelayouter()
1908 // Assign relayouter
1909 if( !mRelayoutData )
1911 mRelayoutData = new Relayouter();
1914 return *mRelayoutData;
1917 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
1919 // Check if actor is dependent on parent
1920 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1922 if( ( dimension & ( 1 << i ) ) )
1924 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
1925 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
1935 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
1937 // Check if actor is dependent on children
1938 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1940 if( ( dimension & ( 1 << i ) ) )
1942 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
1943 switch( resizePolicy )
1945 case ResizePolicy::FIT_TO_CHILDREN:
1946 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
1962 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
1964 return Actor::RelayoutDependentOnChildren( dimension );
1967 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
1969 // Check each possible dimension and see if it is dependent on the input one
1970 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1972 if( dimension & ( 1 << i ) )
1974 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
1981 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
1983 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1985 if( dimension & ( 1 << i ) )
1987 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
1992 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
1994 // If more than one dimension is requested, just return the first one found
1995 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1997 if( ( dimension & ( 1 << i ) ) )
1999 return mRelayoutData->negotiatedDimensions[ i ];
2003 return 0.0f; // Default
2006 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
2008 EnsureRelayouter().SetPadding( padding, dimension );
2011 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
2013 if ( mRelayoutData )
2015 // If more than one dimension is requested, just return the first one found
2016 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2018 if( ( dimension & ( 1 << i ) ) )
2020 return mRelayoutData->dimensionPadding[ i ];
2025 return Relayouter::DEFAULT_DIMENSION_PADDING;
2028 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
2030 EnsureRelayouter().SetLayoutNegotiated(negotiated, dimension);
2033 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
2035 return mRelayoutData && mRelayoutData->IsLayoutNegotiated(dimension);
2038 float Actor::GetHeightForWidthBase( float width )
2040 float height = 0.0f;
2042 const Vector3 naturalSize = GetNaturalSize();
2043 if( naturalSize.width > 0.0f )
2045 height = naturalSize.height * width / naturalSize.width;
2047 else // we treat 0 as 1:1 aspect ratio
2055 float Actor::GetWidthForHeightBase( float height )
2059 const Vector3 naturalSize = GetNaturalSize();
2060 if( naturalSize.height > 0.0f )
2062 width = naturalSize.width * height / naturalSize.height;
2064 else // we treat 0 as 1:1 aspect ratio
2072 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
2074 // Fill to parent, taking size mode factor into account
2075 switch( child.GetResizePolicy( dimension ) )
2077 case ResizePolicy::FILL_TO_PARENT:
2079 return GetLatestSize( dimension );
2082 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2084 return GetLatestSize( dimension ) * GetDimensionValue( child.GetProperty< Vector3 >( Dali::Actor::Property::SIZE_MODE_FACTOR ), dimension );
2087 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2089 return GetLatestSize( dimension ) + GetDimensionValue( child.GetProperty< Vector3 >( Dali::Actor::Property::SIZE_MODE_FACTOR ), dimension );
2094 return GetLatestSize( dimension );
2099 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
2101 // Can be overridden in derived class
2102 return CalculateChildSizeBase( child, dimension );
2105 float Actor::GetHeightForWidth( float width )
2107 // Can be overridden in derived class
2108 return GetHeightForWidthBase( width );
2111 float Actor::GetWidthForHeight( float height )
2113 // Can be overridden in derived class
2114 return GetWidthForHeightBase( height );
2117 float Actor::GetLatestSize( Dimension::Type dimension ) const
2119 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
2122 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
2124 Vector2 padding = GetPadding( dimension );
2126 return GetLatestSize( dimension ) + padding.x + padding.y;
2129 float Actor::NegotiateFromParent( Dimension::Type dimension )
2131 Actor* parent = GetParent();
2134 Vector2 padding( GetPadding( dimension ) );
2135 Vector2 parentPadding( parent->GetPadding( dimension ) );
2136 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
2142 float Actor::NegotiateFromChildren( Dimension::Type dimension )
2144 float maxDimensionPoint = 0.0f;
2146 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2148 ActorPtr child = GetChildAt( i );
2150 if( !child->RelayoutDependentOnParent( dimension ) )
2152 // Calculate the min and max points that the children range across
2153 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
2154 float dimensionSize = child->GetRelayoutSize( dimension );
2155 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
2159 return maxDimensionPoint;
2162 float Actor::GetSize( Dimension::Type dimension ) const
2164 return GetDimensionValue( mTargetSize, dimension );
2167 float Actor::GetNaturalSize( Dimension::Type dimension ) const
2169 return GetDimensionValue( GetNaturalSize(), dimension );
2172 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
2174 switch( GetResizePolicy( dimension ) )
2176 case ResizePolicy::USE_NATURAL_SIZE:
2178 return GetNaturalSize( dimension );
2181 case ResizePolicy::FIXED:
2183 return GetDimensionValue( GetPreferredSize(), dimension );
2186 case ResizePolicy::USE_ASSIGNED_SIZE:
2188 return GetDimensionValue( maximumSize, dimension );
2191 case ResizePolicy::FILL_TO_PARENT:
2192 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2193 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2195 return NegotiateFromParent( dimension );
2198 case ResizePolicy::FIT_TO_CHILDREN:
2200 return NegotiateFromChildren( dimension );
2203 case ResizePolicy::DIMENSION_DEPENDENCY:
2205 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
2208 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
2210 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
2213 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
2215 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
2227 return 0.0f; // Default
2230 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
2232 // Check if it needs to be negotiated
2233 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
2235 // Check that we havn't gotten into an infinite loop
2236 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
2237 bool recursionFound = false;
2238 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
2240 if( *it == searchActor )
2242 recursionFound = true;
2247 if( !recursionFound )
2249 // Record the path that we have taken
2250 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
2252 // Dimension dependency check
2253 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2255 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
2257 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
2259 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
2263 // Parent dependency check
2264 Actor* parent = GetParent();
2265 if( parent && RelayoutDependentOnParent( dimension ) )
2267 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
2270 // Children dependency check
2271 if( RelayoutDependentOnChildren( dimension ) )
2273 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2275 ActorPtr child = GetChildAt( i );
2277 // Only relayout child first if it is not dependent on this actor
2278 if( !child->RelayoutDependentOnParent( dimension ) )
2280 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
2285 // For deriving classes
2286 OnCalculateRelayoutSize( dimension );
2288 // All dependencies checked, calculate the size and set negotiated flag
2289 const float newSize = Relayouter::ClampDimension( *this, CalculateSize( dimension, allocatedSize ), dimension );
2291 SetNegotiatedDimension( newSize, dimension );
2292 SetLayoutNegotiated( true, dimension );
2294 // For deriving classes
2295 OnLayoutNegotiated( newSize, dimension );
2297 // This actor has been successfully processed, pop it off the recursion stack
2298 recursionStack.pop_back();
2302 // TODO: Break infinite loop
2303 SetLayoutNegotiated( true, dimension );
2308 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
2310 // Negotiate all dimensions that require it
2311 ActorDimensionStack recursionStack;
2313 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2315 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
2318 NegotiateDimension( dimension, allocatedSize, recursionStack );
2322 Vector2 Actor::ApplySizeSetPolicy( const Vector2& size )
2324 return mRelayoutData->ApplySizeSetPolicy(*this, size);
2327 void Actor::SetNegotiatedSize( RelayoutContainer& container )
2329 // Do the set actor size
2330 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
2332 // Adjust for size set policy
2333 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
2335 // Lock the flag to stop recursive relayouts on set size
2336 mRelayoutData->insideRelayout = true;
2337 SetSize( negotiatedSize );
2338 mRelayoutData->insideRelayout = false;
2340 // Clear flags for all dimensions
2341 SetLayoutDirty( false );
2343 // Give deriving classes a chance to respond
2344 OnRelayout( negotiatedSize, container );
2346 if( !mOnRelayoutSignal.Empty() )
2348 Dali::Actor handle( this );
2349 mOnRelayoutSignal.Emit( handle );
2353 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
2355 // Force a size negotiation for actors that has assigned size during relayout
2356 // This is required as otherwise the flags that force a relayout will not
2357 // necessarilly be set. This will occur if the actor has already been laid out.
2358 // The dirty flags are then cleared. Then if the actor is added back into the
2359 // relayout container afterwards, the dirty flags would still be clear...
2360 // causing a relayout to be skipped. Here we force any actors added to the
2361 // container to be relayed out.
2362 DALI_LOG_TIMER_START( NegSizeTimer1 );
2364 if( GetUseAssignedSize(Dimension::WIDTH ) )
2366 SetLayoutNegotiated( false, Dimension::WIDTH );
2368 if( GetUseAssignedSize( Dimension::HEIGHT ) )
2370 SetLayoutNegotiated( false, Dimension::HEIGHT );
2373 // Do the negotiation
2374 NegotiateDimensions( allocatedSize );
2376 // Set the actor size
2377 SetNegotiatedSize( container );
2379 // Negotiate down to children
2380 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2382 ActorPtr child = GetChildAt( i );
2384 // Forces children that have already been laid out to be relayed out
2385 // if they have assigned size during relayout.
2386 if( child->GetUseAssignedSize(Dimension::WIDTH) )
2388 child->SetLayoutNegotiated(false, Dimension::WIDTH);
2389 child->SetLayoutDirty(true, Dimension::WIDTH);
2392 if( child->GetUseAssignedSize(Dimension::HEIGHT) )
2394 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
2395 child->SetLayoutDirty(true, Dimension::HEIGHT);
2398 // Only relayout if required
2399 if( child->RelayoutRequired() )
2401 container.Add( Dali::Actor( child.Get() ), mTargetSize.GetVectorXY() );
2404 DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
2407 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
2411 mRelayoutData->SetUseAssignedSize(use, dimension);
2415 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
2417 return mRelayoutData && mRelayoutData->GetUseAssignedSize(dimension);
2420 void Actor::RelayoutRequest( Dimension::Type dimension )
2422 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
2423 if( relayoutController )
2425 Dali::Actor self( this );
2426 relayoutController->RequestRelayout( self, dimension );
2430 void Actor::SetPreferredSize( const Vector2& size )
2434 // If valid width or height, then set the resize policy to FIXED
2435 // 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,
2436 // then change to FIXED as well
2438 if( size.width > 0.0f || GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DEFAULT )
2440 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
2443 if( size.height > 0.0f || GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DEFAULT )
2445 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
2448 mRelayoutData->preferredSize = size;
2450 mUseAnimatedSize = AnimatedSizeFlag::CLEAR;
2455 Vector2 Actor::GetPreferredSize() const
2457 if ( mRelayoutData )
2459 return Vector2( mRelayoutData->preferredSize );
2462 return Relayouter::DEFAULT_PREFERRED_SIZE;
2465 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
2467 EnsureRelayouter().SetMinimumSize(size, dimension);
2471 float Actor::GetMinimumSize( Dimension::Type dimension ) const
2473 if ( mRelayoutData )
2475 return mRelayoutData->GetMinimumSize(dimension);
2478 return 0.0f; // Default
2481 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
2483 EnsureRelayouter().SetMaximumSize(size, dimension);
2487 float Actor::GetMaximumSize( Dimension::Type dimension ) const
2489 if ( mRelayoutData )
2491 return mRelayoutData->GetMaximumSize(dimension);
2494 return FLT_MAX; // Default
2497 void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
2499 if( mVisible != visible )
2501 if( sendMessage == SendMessage::TRUE )
2503 // node is being used in a separate thread; queue a message to set the value & base value
2504 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible );
2506 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
2511 // Emit the signal on this actor and all its children
2512 EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
2516 void Actor::SetSiblingOrder( uint32_t order )
2520 ActorContainer& siblings = *(mParent->mChildren);
2521 uint32_t currentOrder = GetSiblingOrder();
2523 if( order != currentOrder )
2529 else if( order < siblings.size() -1 )
2531 if( order > currentOrder )
2533 RaiseAbove( *siblings[order] );
2537 LowerBelow( *siblings[order] );
2548 uint32_t Actor::GetSiblingOrder() const
2554 ActorContainer& siblings = *(mParent->mChildren);
2555 for( std::size_t i = 0; i < siblings.size(); ++i )
2557 if( siblings[i] == this )
2559 order = static_cast<uint32_t>( i );
2568 void Actor::RequestRebuildDepthTree()
2574 mScene->RequestRebuildDepthTree();
2583 ActorContainer& siblings = *(mParent->mChildren);
2584 if( siblings.back() != this ) // If not already at end
2586 for( std::size_t i=0; i<siblings.size(); ++i )
2588 if( siblings[i] == this )
2591 ActorPtr next = siblings[i+1];
2592 siblings[i+1] = this;
2599 Dali::Actor handle( this );
2600 mParent->mChildOrderChangedSignal.Emit( handle );
2602 RequestRebuildDepthTree();
2606 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2614 ActorContainer& siblings = *(mParent->mChildren);
2615 if( siblings.front() != this ) // If not already at beginning
2617 for( std::size_t i=1; i<siblings.size(); ++i )
2619 if( siblings[i] == this )
2621 // Swap with previous
2622 ActorPtr previous = siblings[i-1];
2623 siblings[i-1] = this;
2624 siblings[i] = previous;
2630 Dali::Actor handle( this );
2631 mParent->mChildOrderChangedSignal.Emit( handle );
2633 RequestRebuildDepthTree();
2637 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2641 void Actor::RaiseToTop()
2645 ActorContainer& siblings = *(mParent->mChildren);
2646 if( siblings.back() != this ) // If not already at end
2648 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
2649 if( iter != siblings.end() )
2651 siblings.erase(iter);
2652 siblings.push_back(ActorPtr(this));
2656 Dali::Actor handle( this );
2657 mParent->mChildOrderChangedSignal.Emit( handle );
2659 RequestRebuildDepthTree();
2663 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2667 void Actor::LowerToBottom()
2671 ActorContainer& siblings = *(mParent->mChildren);
2672 if( siblings.front() != this ) // If not already at bottom,
2674 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2676 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
2677 if( iter != siblings.end() )
2679 siblings.erase(iter);
2680 siblings.insert(siblings.begin(), thisPtr);
2684 Dali::Actor handle( this );
2685 mParent->mChildOrderChangedSignal.Emit( handle );
2687 RequestRebuildDepthTree();
2691 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2695 void Actor::RaiseAbove( Internal::Actor& target )
2699 ActorContainer& siblings = *(mParent->mChildren);
2700 if( siblings.back() != this && target.mParent == mParent ) // If not already at top
2702 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2704 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
2705 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
2706 if( thisIter < targetIter )
2708 siblings.erase(thisIter);
2709 // Erasing early invalidates the targetIter. (Conversely, inserting first may also
2710 // invalidate thisIter)
2711 targetIter = std::find( siblings.begin(), siblings.end(), &target );
2713 siblings.insert(targetIter, thisPtr);
2716 Dali::Actor handle( this );
2717 mParent->mChildOrderChangedSignal.Emit( handle );
2719 RequestRebuildDepthTree();
2724 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2728 void Actor::LowerBelow( Internal::Actor& target )
2732 ActorContainer& siblings = *(mParent->mChildren);
2733 if( siblings.front() != this && target.mParent == mParent ) // If not already at bottom
2735 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2737 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
2738 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
2740 if( thisIter > targetIter )
2742 siblings.erase(thisIter); // this only invalidates iterators at or after this point.
2743 siblings.insert(targetIter, thisPtr);
2746 Dali::Actor handle( this );
2747 mParent->mChildOrderChangedSignal.Emit( handle );
2749 RequestRebuildDepthTree();
2754 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2758 void Actor::SetInheritLayoutDirection( bool inherit )
2760 if( mInheritLayoutDirection != inherit )
2762 mInheritLayoutDirection = inherit;
2764 if( inherit && mParent )
2766 InheritLayoutDirectionRecursively( this, mParent->mLayoutDirection );
2771 void Actor::InheritLayoutDirectionRecursively( ActorPtr actor, Dali::LayoutDirection::Type direction, bool set )
2773 if( actor && ( actor->mInheritLayoutDirection || set ) )
2775 if( actor->mLayoutDirection != direction )
2777 actor->mLayoutDirection = direction;
2778 actor->EmitLayoutDirectionChangedSignal( direction );
2779 actor->RelayoutRequest();
2782 if( actor->GetChildCount() > 0 )
2784 for( ActorPtr& child : actor->GetChildrenInternal() )
2786 InheritLayoutDirectionRecursively( child, direction );
2792 void Actor::SetUpdateSizeHint( const Vector2& updateSizeHint )
2794 // node is being used in a separate thread; queue a message to set the value & base value
2795 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mUpdateSizeHint, &AnimatableProperty<Vector3>::Bake, Vector3(updateSizeHint.width, updateSizeHint.height, 0.f ) );
2798 } // namespace Internal