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 );
841 float Actor::GetCurrentOpacity() const
843 // node is being used in a separate thread; copy the value from the previous update
844 return GetNode().GetOpacity(GetEventThreadServices().GetEventBufferIndex());
847 const Vector4& Actor::GetCurrentWorldColor() const
849 return GetNode().GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
852 void Actor::SetColor( const Vector4& color )
854 mTargetColor = color;
856 // node is being used in a separate thread; queue a message to set the value & base value
857 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::Bake, color );
860 void Actor::SetColorRed( float red )
862 mTargetColor.r = red;
864 // node is being used in a separate thread; queue a message to set the value & base value
865 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeX, red );
868 void Actor::SetColorGreen( float green )
870 mTargetColor.g = green;
872 // node is being used in a separate thread; queue a message to set the value & base value
873 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeY, green );
876 void Actor::SetColorBlue( float blue )
878 mTargetColor.b = blue;
880 // node is being used in a separate thread; queue a message to set the value & base value
881 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
884 const Vector4& Actor::GetCurrentColor() const
886 // node is being used in a separate thread; copy the value from the previous update
887 return GetNode().GetColor(GetEventThreadServices().GetEventBufferIndex());
890 void Actor::SetInheritOrientation( bool inherit )
892 if( mInheritOrientation != inherit )
894 // non animatable so keep local copy
895 mInheritOrientation = inherit;
896 // node is being used in a separate thread; queue a message to set the value
897 SetInheritOrientationMessage( GetEventThreadServices(), GetNode(), inherit );
901 void Actor::SetSizeModeFactor( const Vector3& factor )
905 mRelayoutData->sizeModeFactor = factor;
908 const Vector3& Actor::GetSizeModeFactor() const
912 return mRelayoutData->sizeModeFactor;
915 return Relayouter::DEFAULT_SIZE_MODE_FACTOR;
918 void Actor::SetColorMode( ColorMode colorMode )
920 // non animatable so keep local copy
921 mColorMode = colorMode;
922 // node is being used in a separate thread; queue a message to set the value
923 SetColorModeMessage( GetEventThreadServices(), GetNode(), colorMode );
926 void Actor::SetSize( float width, float height )
928 SetSize( Vector2( width, height ) );
931 void Actor::SetSize( float width, float height, float depth )
933 SetSize( Vector3( width, height, depth ) );
936 void Actor::SetSize( const Vector2& size )
938 SetSize( Vector3( size.width, size.height, 0.f ) );
941 void Actor::SetSizeInternal( const Vector2& size )
943 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
946 void Actor::SetSize( const Vector3& size )
948 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
950 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
951 SetPreferredSize( size.GetVectorXY() );
955 SetSizeInternal( size );
959 void Actor::SetSizeInternal( const Vector3& size )
961 // dont allow recursive loop
962 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
963 // 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
964 if( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
965 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
966 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) )
970 // node is being used in a separate thread; queue a message to set the value & base value
971 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
973 // Notification for derived classes
974 mInsideOnSizeSet = true;
975 OnSizeSet( mTargetSize );
976 mInsideOnSizeSet = false;
978 // Raise a relayout request if the flag is not locked
979 if( mRelayoutData && !mRelayoutData->insideRelayout )
986 void Actor::SetWidth( float width )
988 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
990 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
991 mRelayoutData->preferredSize.width = width;
995 mTargetSize.width = width;
997 // node is being used in a separate thread; queue a message to set the value & base value
998 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1001 mUseAnimatedSize &= ~AnimatedSizeFlag::WIDTH;
1006 void Actor::SetHeight( float height )
1008 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1010 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
1011 mRelayoutData->preferredSize.height = height;
1015 mTargetSize.height = height;
1017 // node is being used in a separate thread; queue a message to set the value & base value
1018 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1021 mUseAnimatedSize &= ~AnimatedSizeFlag::HEIGHT;
1026 void Actor::SetDepth( float depth )
1028 mTargetSize.depth = depth;
1030 mUseAnimatedSize &= ~AnimatedSizeFlag::DEPTH;
1032 // node is being used in a separate thread; queue a message to set the value & base value
1033 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1036 Vector3 Actor::GetTargetSize() const
1038 Vector3 size = mTargetSize;
1040 if( mUseAnimatedSize & AnimatedSizeFlag::WIDTH )
1042 // Should return animated size if size is animated
1043 size.width = mAnimatedSize.width;
1047 // Should return preferred size if size is fixed as set by SetSize
1048 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
1050 size.width = GetPreferredSize().width;
1054 if( mUseAnimatedSize & AnimatedSizeFlag::HEIGHT )
1056 size.height = mAnimatedSize.height;
1060 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
1062 size.height = GetPreferredSize().height;
1066 if( mUseAnimatedSize & AnimatedSizeFlag::DEPTH )
1068 size.depth = mAnimatedSize.depth;
1074 const Vector3& Actor::GetCurrentSize() const
1076 // node is being used in a separate thread; copy the value from the previous update
1077 return GetNode().GetSize( GetEventThreadServices().GetEventBufferIndex() );
1080 Vector3 Actor::GetNaturalSize() const
1082 // It is up to deriving classes to return the appropriate natural size
1083 return Vector3( 0.0f, 0.0f, 0.0f );
1086 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1088 EnsureRelayouter().SetResizePolicy(policy, dimension, mTargetSize);
1090 OnSetResizePolicy( policy, dimension );
1092 // Trigger relayout on this control
1096 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1098 if ( mRelayoutData )
1100 return mRelayoutData->GetResizePolicy(dimension);
1103 return ResizePolicy::DEFAULT;
1106 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1110 mRelayoutData->sizeSetPolicy = policy;
1112 // Trigger relayout on this control
1116 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1118 if ( mRelayoutData )
1120 return mRelayoutData->sizeSetPolicy;
1123 return Relayouter::DEFAULT_SIZE_SCALE_POLICY;
1126 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1128 EnsureRelayouter().SetDimensionDependency(dimension, dependency);
1131 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1133 if ( mRelayoutData )
1135 return mRelayoutData->GetDimensionDependency(dimension);
1138 return Dimension::ALL_DIMENSIONS; // Default
1141 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1143 // If relayout data has not been allocated yet and the client is requesting
1144 // to disable it, do nothing
1145 if( mRelayoutData || relayoutEnabled )
1149 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1151 mRelayoutData->relayoutEnabled = relayoutEnabled;
1155 bool Actor::IsRelayoutEnabled() const
1157 // Assume that if relayout data has not been allocated yet then
1158 // relayout is disabled
1159 return mRelayoutData && mRelayoutData->relayoutEnabled;
1162 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1164 EnsureRelayouter().SetLayoutDirty(dirty, dimension);
1167 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1169 return mRelayoutData && mRelayoutData->IsLayoutDirty(dimension);
1172 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1174 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1177 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1179 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1182 uint32_t Actor::AddRenderer( Renderer& renderer )
1186 mRenderers = new RendererContainer;
1189 uint32_t index = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1190 RendererPtr rendererPtr = RendererPtr( &renderer );
1191 mRenderers->push_back( rendererPtr );
1192 AttachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1196 uint32_t Actor::GetRendererCount() const
1198 uint32_t rendererCount(0);
1201 rendererCount = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1204 return rendererCount;
1207 RendererPtr Actor::GetRendererAt( uint32_t index )
1209 RendererPtr renderer;
1210 if( index < GetRendererCount() )
1212 renderer = ( *mRenderers )[ index ];
1218 void Actor::RemoveRenderer( Renderer& renderer )
1222 RendererIter end = mRenderers->end();
1223 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1225 if( (*iter).Get() == &renderer )
1227 mRenderers->erase( iter );
1228 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1235 void Actor::RemoveRenderer( uint32_t index )
1237 if( index < GetRendererCount() )
1239 RendererPtr renderer = ( *mRenderers )[ index ];
1240 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.Get()->GetRendererSceneObject() );
1241 mRenderers->erase( mRenderers->begin()+index );
1245 void Actor::SetDrawMode( DrawMode::Type drawMode )
1247 // this flag is not animatable so keep the value
1248 mDrawMode = drawMode;
1250 // node is being used in a separate thread; queue a message to set the value
1251 SetDrawModeMessage( GetEventThreadServices(), GetNode(), drawMode );
1254 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1256 // only valid when on-stage
1257 if( mScene && OnScene() )
1259 const RenderTaskList& taskList = mScene->GetRenderTaskList();
1261 Vector2 converted( screenX, screenY );
1263 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1264 uint32_t taskCount = taskList.GetTaskCount();
1265 for( uint32_t i = taskCount; i > 0; --i )
1267 RenderTaskPtr task = taskList.GetTask( i - 1 );
1268 if( ScreenToLocal( *task, localX, localY, screenX, screenY ) )
1270 // found a task where this conversion was ok so return
1278 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1280 bool retval = false;
1281 // only valid when on-stage
1284 CameraActor* camera = renderTask.GetCameraActor();
1288 renderTask.GetViewport( viewport );
1290 // need to translate coordinates to render tasks coordinate space
1291 Vector2 converted( screenX, screenY );
1292 if( renderTask.TranslateCoordinates( converted ) )
1294 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1301 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1303 return OnScene() && ScreenToLocalInternal(viewMatrix, projectionMatrix, GetNode().GetWorldMatrix(0), viewport, GetCurrentSize(), localX, localY, screenX, screenY);
1306 ActorGestureData& Actor::GetGestureData()
1308 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1309 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1310 if( nullptr == mGestureData )
1312 mGestureData = new ActorGestureData;
1314 return *mGestureData;
1317 bool Actor::IsGestureRequired( GestureType::Value type ) const
1319 return mGestureData && mGestureData->IsGestureRequired( type );
1322 bool Actor::EmitInterceptTouchEventSignal( const Dali::TouchEvent& touch )
1324 return EmitConsumingSignal( *this, mInterceptTouchedSignal, touch );
1327 bool Actor::EmitTouchEventSignal( const Dali::TouchEvent& touch )
1329 return EmitConsumingSignal( *this, mTouchedSignal, touch );
1332 bool Actor::EmitHoverEventSignal( const Dali::HoverEvent& event )
1334 return EmitConsumingSignal( *this, mHoveredSignal, event );
1337 bool Actor::EmitWheelEventSignal( const Dali::WheelEvent& event )
1339 return EmitConsumingSignal( *this, mWheelEventSignal, event );
1342 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
1344 EmitSignal( *this, mVisibilityChangedSignal, visible, type );
1347 void Actor::EmitLayoutDirectionChangedSignal( LayoutDirection::Type type )
1349 EmitSignal( *this, mLayoutDirectionChangedSignal, type );
1352 void Actor::EmitChildAddedSignal( Actor& child )
1354 EmitSignal( child, mChildAddedSignal );
1357 void Actor::EmitChildRemovedSignal( Actor& child )
1359 EmitSignal( child, mChildRemovedSignal );
1362 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1364 bool connected( true );
1365 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
1367 if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1369 actor->HoveredSignal().Connect( tracker, functor );
1371 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1373 actor->WheelEventSignal().Connect( tracker, functor );
1375 else if( 0 == signalName.compare( SIGNAL_ON_SCENE ) )
1377 actor->OnSceneSignal().Connect( tracker, functor );
1379 else if( 0 == signalName.compare( SIGNAL_OFF_SCENE ) )
1381 actor->OffSceneSignal().Connect( tracker, functor );
1383 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
1385 actor->OnRelayoutSignal().Connect( tracker, functor );
1387 else if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1389 actor->TouchedSignal().Connect( tracker, functor );
1391 else if( 0 == signalName.compare( SIGNAL_VISIBILITY_CHANGED ) )
1393 actor->VisibilityChangedSignal().Connect( tracker, functor );
1395 else if( 0 == signalName.compare( SIGNAL_LAYOUT_DIRECTION_CHANGED ) )
1397 actor->LayoutDirectionChangedSignal().Connect( tracker, functor );
1399 else if( 0 == signalName.compare( SIGNAL_CHILD_ADDED ) )
1401 actor->ChildAddedSignal().Connect( tracker, functor );
1403 else if( 0 == signalName.compare( SIGNAL_CHILD_REMOVED ) )
1405 actor->ChildRemovedSignal().Connect( tracker, functor );
1409 // signalName does not match any signal
1416 Actor::Actor( DerivedType derivedType, const SceneGraph::Node& node )
1420 mChildren( nullptr ),
1421 mRenderers( nullptr ),
1422 mParentOrigin( nullptr ),
1423 mAnchorPoint( nullptr ),
1424 mRelayoutData( nullptr ),
1425 mGestureData( nullptr ),
1426 mInterceptTouchedSignal(),
1429 mWheelEventSignal(),
1432 mOnRelayoutSignal(),
1433 mVisibilityChangedSignal(),
1434 mLayoutDirectionChangedSignal(),
1435 mChildAddedSignal(),
1436 mChildRemovedSignal(),
1437 mChildOrderChangedSignal(),
1438 mTargetOrientation( Quaternion::IDENTITY ),
1439 mTargetColor( Color::WHITE ),
1440 mTargetSize( Vector3::ZERO ),
1441 mTargetPosition( Vector3::ZERO ),
1442 mTargetScale( Vector3::ONE ),
1443 mAnimatedSize( Vector3::ZERO ),
1447 mUseAnimatedSize( AnimatedSizeFlag::CLEAR ),
1448 mIsRoot( ROOT_LAYER == derivedType ),
1449 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
1450 mIsOnScene( false ),
1452 mLeaveRequired( false ),
1453 mKeyboardFocusable( false ),
1454 mOnSceneSignalled( false ),
1455 mInsideOnSizeSet( false ),
1456 mInheritPosition( true ),
1457 mInheritOrientation( true ),
1458 mInheritScale( true ),
1459 mPositionUsesAnchorPoint( true ),
1461 mInheritLayoutDirection( true ),
1462 mCaptureAllTouchAfterStart( false ),
1463 mLayoutDirection( LayoutDirection::LEFT_TO_RIGHT ),
1464 mDrawMode( DrawMode::NORMAL ),
1465 mColorMode( Node::DEFAULT_COLOR_MODE ),
1466 mClippingMode( ClippingMode::DISABLED )
1470 void Actor::Initialize()
1474 GetEventThreadServices().RegisterObject( this );
1479 // Remove mParent pointers from children even if we're destroying core,
1480 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1483 ActorConstIter endIter = mChildren->end();
1484 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1486 (*iter)->SetParent( nullptr );
1492 // Guard to allow handle destruction after Core has been destroyed
1493 if( EventThreadServices::IsCoreRunning() )
1495 // Root layer will destroy its node in its own destructor
1498 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
1500 GetEventThreadServices().UnregisterObject( this );
1504 // Cleanup optional gesture data
1505 delete mGestureData;
1507 // Cleanup optional parent origin and anchor
1508 delete mParentOrigin;
1509 delete mAnchorPoint;
1511 // Delete optional relayout data
1512 delete mRelayoutData;
1515 void Actor::ConnectToScene( uint32_t parentDepth )
1517 // This container is used instead of walking the Actor hierarchy.
1518 // It protects us when the Actor hierarchy is modified during OnSceneConnectionExternal callbacks.
1519 ActorContainer connectionList;
1523 mScene->RequestRebuildDepthTree();
1526 // This stage is atomic i.e. not interrupted by user callbacks.
1527 RecursiveConnectToScene( connectionList, parentDepth + 1 );
1529 // Notify applications about the newly connected actors.
1530 const ActorIter endIter = connectionList.end();
1531 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
1533 (*iter)->NotifyStageConnection();
1539 void Actor::RecursiveConnectToScene( ActorContainer& connectionList, uint32_t depth )
1541 DALI_ASSERT_ALWAYS( !OnScene() );
1544 mDepth = static_cast< uint16_t >( depth ); // overflow ignored, not expected in practice
1546 ConnectToSceneGraph();
1548 // Notification for internal derived classes
1549 OnSceneConnectionInternal();
1551 // This stage is atomic; avoid emitting callbacks until all Actors are connected
1552 connectionList.push_back( ActorPtr( this ) );
1554 // Recursively connect children
1557 ActorConstIter endIter = mChildren->end();
1558 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1560 (*iter)->SetScene( *mScene );
1561 (*iter)->RecursiveConnectToScene( connectionList, depth + 1 );
1567 * This method is called when the Actor is connected to the Stage.
1568 * The parent must have added its Node to the scene-graph.
1569 * The child must connect its Node to the parent's Node.
1570 * This is recursive; the child calls ConnectToScene() for its children.
1572 void Actor::ConnectToSceneGraph()
1574 DALI_ASSERT_DEBUG( mParent != NULL);
1576 // Reparent Node in next Update
1577 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), mParent->GetNode(), GetNode() );
1579 // Request relayout on all actors that are added to the scenegraph
1582 // Notification for Object::Observers
1586 void Actor::NotifyStageConnection()
1588 // Actors can be removed (in a callback), before the on-stage stage is reported.
1589 // The actor may also have been reparented, in which case mOnSceneSignalled will be true.
1590 if( OnScene() && !mOnSceneSignalled )
1592 // Notification for external (CustomActor) derived classes
1593 OnSceneConnectionExternal( mDepth );
1595 if( !mOnSceneSignal.Empty() )
1597 Dali::Actor handle( this );
1598 mOnSceneSignal.Emit( handle );
1601 // Guard against Remove during callbacks
1604 mOnSceneSignalled = true; // signal required next time Actor is removed
1609 void Actor::DisconnectFromStage()
1611 // This container is used instead of walking the Actor hierachy.
1612 // It protects us when the Actor hierachy is modified during OnSceneDisconnectionExternal callbacks.
1613 ActorContainer disconnectionList;
1617 mScene->RequestRebuildDepthTree();
1620 // This stage is atomic i.e. not interrupted by user callbacks
1621 RecursiveDisconnectFromStage( disconnectionList );
1623 // Notify applications about the newly disconnected actors.
1624 const ActorIter endIter = disconnectionList.end();
1625 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
1627 (*iter)->NotifyStageDisconnection();
1631 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
1633 // need to change state first so that internals relying on IsOnScene() inside OnSceneDisconnectionInternal() get the correct value
1636 // Recursively disconnect children
1639 ActorConstIter endIter = mChildren->end();
1640 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1642 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
1646 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
1647 disconnectionList.push_back( ActorPtr( this ) );
1649 // Notification for internal derived classes
1650 OnSceneDisconnectionInternal();
1652 DisconnectFromSceneGraph();
1656 * This method is called by an actor or its parent, before a node removal message is sent.
1657 * This is recursive; the child calls DisconnectFromStage() for its children.
1659 void Actor::DisconnectFromSceneGraph()
1661 // Notification for Object::Observers
1662 OnSceneObjectRemove();
1665 void Actor::NotifyStageDisconnection()
1667 // Actors can be added (in a callback), before the off-stage state is reported.
1668 // Also if the actor was added & removed before mOnSceneSignalled was set, then we don't notify here.
1669 // only do this step if there is a stage, i.e. Core is not being shut down
1670 if ( EventThreadServices::IsCoreRunning() && !OnScene() && mOnSceneSignalled )
1672 // Notification for external (CustomeActor) derived classes
1673 OnSceneDisconnectionExternal();
1675 if( !mOffSceneSignal.Empty() )
1677 Dali::Actor handle( this );
1678 mOffSceneSignal.Emit( handle );
1681 // Guard against Add during callbacks
1684 mOnSceneSignalled = false; // signal required next time Actor is added
1689 bool Actor::IsNodeConnected() const
1691 bool connected( false );
1695 if( IsRoot() || GetNode().GetParent() )
1704 // This method initiates traversal of the actor tree using depth-first
1705 // traversal to set a depth index based on traversal order. It sends a
1706 // single message to update manager to update all the actor's nodes in
1707 // this tree with the depth index. The sceneGraphNodeDepths vector's
1708 // elements are ordered by depth, and could be used to reduce sorting
1709 // in the update thread.
1710 void Actor::RebuildDepthTree()
1712 DALI_LOG_TIMER_START(depthTimer);
1714 // Vector of scene-graph nodes and their depths to send to UpdateManager
1715 // in a single message
1716 OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths( new SceneGraph::NodeDepths() );
1718 int32_t depthIndex = 1;
1719 DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
1721 SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths );
1722 DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
1725 void Actor::DepthTraverseActorTree( OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths, int32_t& depthIndex )
1727 mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
1728 sceneGraphNodeDepths->Add( const_cast<SceneGraph::Node*>( &GetNode() ), mSortedDepth );
1730 // Create/add to children of this node
1733 for( ActorContainer::iterator it = mChildren->begin(); it != mChildren->end(); ++it )
1735 Actor* childActor = (*it).Get();
1737 childActor->DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
1742 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
1744 PropertyHandler::SetDefaultProperty(*this, index, property);
1747 // TODO: This method needs to be removed
1748 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
1750 PropertyHandler::SetSceneGraphProperty(index, entry, value, GetEventThreadServices(), GetNode());
1753 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
1755 Property::Value value;
1757 if( ! GetCachedPropertyValue( index, value ) )
1759 // If property value is not stored in the event-side, then it must be a scene-graph only property
1760 GetCurrentPropertyValue( index, value );
1766 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
1768 Property::Value value;
1770 if( ! GetCurrentPropertyValue( index, value ) )
1772 // If unable to retrieve scene-graph property value, then it must be an event-side only property
1773 GetCachedPropertyValue( index, value );
1779 void Actor::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
1781 PropertyHandler::OnNotifyDefaultPropertyAnimation(*this, animation, index, value, animationType);
1784 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
1786 const PropertyBase* property = PropertyHandler::GetSceneObjectAnimatableProperty(index, GetNode());
1789 // not our property, ask base
1790 property = Object::GetSceneObjectAnimatableProperty( index );
1796 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
1798 const PropertyInputImpl* property = PropertyHandler::GetSceneObjectInputProperty(index, GetNode());
1801 // reuse animatable property getter as animatable properties are inputs as well
1802 // animatable property chains back to Object::GetSceneObjectInputProperty() so all properties get covered
1803 property = GetSceneObjectAnimatableProperty( index );
1809 int32_t Actor::GetPropertyComponentIndex( Property::Index index ) const
1811 int32_t componentIndex = PropertyHandler::GetPropertyComponentIndex(index);
1812 if( Property::INVALID_COMPONENT_INDEX == componentIndex )
1815 componentIndex = Object::GetPropertyComponentIndex( index );
1818 return componentIndex;
1821 void Actor::SetParent( Actor* parent )
1825 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
1829 mScene = parent->mScene;
1831 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1834 // Instruct each actor to create a corresponding node in the scene graph
1835 ConnectToScene( parent->GetHierarchyDepth() );
1838 // Resolve the name and index for the child properties if any
1839 ResolveChildProperties();
1841 else // parent being set to NULL
1843 DALI_ASSERT_ALWAYS( mParent != nullptr && "Actor should have a parent" );
1847 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1850 // Disconnect the Node & its children from the scene-graph.
1851 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
1853 // Instruct each actor to discard pointers to the scene-graph
1854 DisconnectFromStage();
1861 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
1864 Actor* actor = dynamic_cast< Actor* >( object );
1868 if( 0 == actionName.compare( ACTION_SHOW ) )
1870 actor->SetVisible( true );
1873 else if( 0 == actionName.compare( ACTION_HIDE ) )
1875 actor->SetVisible( false );
1883 Rect<> Actor::CalculateScreenExtents( ) const
1885 auto screenPosition = GetCurrentScreenPosition();
1886 Vector3 size = GetCurrentSize() * GetCurrentWorldScale();
1887 Vector3 anchorPointOffSet = size * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
1888 Vector2 position = Vector2( screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y );
1889 return { position.x, position.y, size.x, size.y };
1892 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
1894 return PropertyHandler::GetCachedPropertyValue(*this, index, value);
1897 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
1899 return PropertyHandler::GetCurrentPropertyValue(*this, index, value);
1902 Actor::Relayouter& Actor::EnsureRelayouter()
1904 // Assign relayouter
1905 if( !mRelayoutData )
1907 mRelayoutData = new Relayouter();
1910 return *mRelayoutData;
1913 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
1915 // Check if actor is dependent on parent
1916 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1918 if( ( dimension & ( 1 << i ) ) )
1920 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
1921 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
1931 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
1933 // Check if actor is dependent on children
1934 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1936 if( ( dimension & ( 1 << i ) ) )
1938 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
1939 switch( resizePolicy )
1941 case ResizePolicy::FIT_TO_CHILDREN:
1942 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
1958 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
1960 return Actor::RelayoutDependentOnChildren( dimension );
1963 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
1965 // Check each possible dimension and see if it is dependent on the input one
1966 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1968 if( dimension & ( 1 << i ) )
1970 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
1977 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
1979 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1981 if( dimension & ( 1 << i ) )
1983 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
1988 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
1990 // If more than one dimension is requested, just return the first one found
1991 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1993 if( ( dimension & ( 1 << i ) ) )
1995 return mRelayoutData->negotiatedDimensions[ i ];
1999 return 0.0f; // Default
2002 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
2004 EnsureRelayouter().SetPadding( padding, dimension );
2007 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
2009 if ( mRelayoutData )
2011 // If more than one dimension is requested, just return the first one found
2012 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2014 if( ( dimension & ( 1 << i ) ) )
2016 return mRelayoutData->dimensionPadding[ i ];
2021 return Relayouter::DEFAULT_DIMENSION_PADDING;
2024 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
2026 EnsureRelayouter().SetLayoutNegotiated(negotiated, dimension);
2029 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
2031 return mRelayoutData && mRelayoutData->IsLayoutNegotiated(dimension);
2034 float Actor::GetHeightForWidthBase( float width )
2036 float height = 0.0f;
2038 const Vector3 naturalSize = GetNaturalSize();
2039 if( naturalSize.width > 0.0f )
2041 height = naturalSize.height * width / naturalSize.width;
2043 else // we treat 0 as 1:1 aspect ratio
2051 float Actor::GetWidthForHeightBase( float height )
2055 const Vector3 naturalSize = GetNaturalSize();
2056 if( naturalSize.height > 0.0f )
2058 width = naturalSize.width * height / naturalSize.height;
2060 else // we treat 0 as 1:1 aspect ratio
2068 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
2070 // Fill to parent, taking size mode factor into account
2071 switch( child.GetResizePolicy( dimension ) )
2073 case ResizePolicy::FILL_TO_PARENT:
2075 return GetLatestSize( dimension );
2078 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2080 return GetLatestSize( dimension ) * GetDimensionValue( child.GetProperty< Vector3 >( Dali::Actor::Property::SIZE_MODE_FACTOR ), dimension );
2083 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2085 return GetLatestSize( dimension ) + GetDimensionValue( child.GetProperty< Vector3 >( Dali::Actor::Property::SIZE_MODE_FACTOR ), dimension );
2090 return GetLatestSize( dimension );
2095 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
2097 // Can be overridden in derived class
2098 return CalculateChildSizeBase( child, dimension );
2101 float Actor::GetHeightForWidth( float width )
2103 // Can be overridden in derived class
2104 return GetHeightForWidthBase( width );
2107 float Actor::GetWidthForHeight( float height )
2109 // Can be overridden in derived class
2110 return GetWidthForHeightBase( height );
2113 float Actor::GetLatestSize( Dimension::Type dimension ) const
2115 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
2118 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
2120 Vector2 padding = GetPadding( dimension );
2122 return GetLatestSize( dimension ) + padding.x + padding.y;
2125 float Actor::NegotiateFromParent( Dimension::Type dimension )
2127 Actor* parent = GetParent();
2130 Vector2 padding( GetPadding( dimension ) );
2131 Vector2 parentPadding( parent->GetPadding( dimension ) );
2132 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
2138 float Actor::NegotiateFromChildren( Dimension::Type dimension )
2140 float maxDimensionPoint = 0.0f;
2142 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2144 ActorPtr child = GetChildAt( i );
2146 if( !child->RelayoutDependentOnParent( dimension ) )
2148 // Calculate the min and max points that the children range across
2149 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
2150 float dimensionSize = child->GetRelayoutSize( dimension );
2151 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
2155 return maxDimensionPoint;
2158 float Actor::GetSize( Dimension::Type dimension ) const
2160 return GetDimensionValue( mTargetSize, dimension );
2163 float Actor::GetNaturalSize( Dimension::Type dimension ) const
2165 return GetDimensionValue( GetNaturalSize(), dimension );
2168 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
2170 switch( GetResizePolicy( dimension ) )
2172 case ResizePolicy::USE_NATURAL_SIZE:
2174 return GetNaturalSize( dimension );
2177 case ResizePolicy::FIXED:
2179 return GetDimensionValue( GetPreferredSize(), dimension );
2182 case ResizePolicy::USE_ASSIGNED_SIZE:
2184 return GetDimensionValue( maximumSize, dimension );
2187 case ResizePolicy::FILL_TO_PARENT:
2188 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2189 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2191 return NegotiateFromParent( dimension );
2194 case ResizePolicy::FIT_TO_CHILDREN:
2196 return NegotiateFromChildren( dimension );
2199 case ResizePolicy::DIMENSION_DEPENDENCY:
2201 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
2204 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
2206 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
2209 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
2211 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
2223 return 0.0f; // Default
2226 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
2228 // Check if it needs to be negotiated
2229 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
2231 // Check that we havn't gotten into an infinite loop
2232 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
2233 bool recursionFound = false;
2234 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
2236 if( *it == searchActor )
2238 recursionFound = true;
2243 if( !recursionFound )
2245 // Record the path that we have taken
2246 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
2248 // Dimension dependency check
2249 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2251 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
2253 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
2255 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
2259 // Parent dependency check
2260 Actor* parent = GetParent();
2261 if( parent && RelayoutDependentOnParent( dimension ) )
2263 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
2266 // Children dependency check
2267 if( RelayoutDependentOnChildren( dimension ) )
2269 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2271 ActorPtr child = GetChildAt( i );
2273 // Only relayout child first if it is not dependent on this actor
2274 if( !child->RelayoutDependentOnParent( dimension ) )
2276 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
2281 // For deriving classes
2282 OnCalculateRelayoutSize( dimension );
2284 // All dependencies checked, calculate the size and set negotiated flag
2285 const float newSize = Relayouter::ClampDimension( *this, CalculateSize( dimension, allocatedSize ), dimension );
2287 SetNegotiatedDimension( newSize, dimension );
2288 SetLayoutNegotiated( true, dimension );
2290 // For deriving classes
2291 OnLayoutNegotiated( newSize, dimension );
2293 // This actor has been successfully processed, pop it off the recursion stack
2294 recursionStack.pop_back();
2298 // TODO: Break infinite loop
2299 SetLayoutNegotiated( true, dimension );
2304 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
2306 // Negotiate all dimensions that require it
2307 ActorDimensionStack recursionStack;
2309 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2311 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
2314 NegotiateDimension( dimension, allocatedSize, recursionStack );
2318 Vector2 Actor::ApplySizeSetPolicy( const Vector2& size )
2320 return mRelayoutData->ApplySizeSetPolicy(*this, size);
2323 void Actor::SetNegotiatedSize( RelayoutContainer& container )
2325 // Do the set actor size
2326 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
2328 // Adjust for size set policy
2329 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
2331 // Lock the flag to stop recursive relayouts on set size
2332 mRelayoutData->insideRelayout = true;
2333 SetSize( negotiatedSize );
2334 mRelayoutData->insideRelayout = false;
2336 // Clear flags for all dimensions
2337 SetLayoutDirty( false );
2339 // Give deriving classes a chance to respond
2340 OnRelayout( negotiatedSize, container );
2342 if( !mOnRelayoutSignal.Empty() )
2344 Dali::Actor handle( this );
2345 mOnRelayoutSignal.Emit( handle );
2349 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
2351 // Force a size negotiation for actors that has assigned size during relayout
2352 // This is required as otherwise the flags that force a relayout will not
2353 // necessarilly be set. This will occur if the actor has already been laid out.
2354 // The dirty flags are then cleared. Then if the actor is added back into the
2355 // relayout container afterwards, the dirty flags would still be clear...
2356 // causing a relayout to be skipped. Here we force any actors added to the
2357 // container to be relayed out.
2358 DALI_LOG_TIMER_START( NegSizeTimer1 );
2360 if( GetUseAssignedSize(Dimension::WIDTH ) )
2362 SetLayoutNegotiated( false, Dimension::WIDTH );
2364 if( GetUseAssignedSize( Dimension::HEIGHT ) )
2366 SetLayoutNegotiated( false, Dimension::HEIGHT );
2369 // Do the negotiation
2370 NegotiateDimensions( allocatedSize );
2372 // Set the actor size
2373 SetNegotiatedSize( container );
2375 // Negotiate down to children
2376 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2378 ActorPtr child = GetChildAt( i );
2380 // Forces children that have already been laid out to be relayed out
2381 // if they have assigned size during relayout.
2382 if( child->GetUseAssignedSize(Dimension::WIDTH) )
2384 child->SetLayoutNegotiated(false, Dimension::WIDTH);
2385 child->SetLayoutDirty(true, Dimension::WIDTH);
2388 if( child->GetUseAssignedSize(Dimension::HEIGHT) )
2390 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
2391 child->SetLayoutDirty(true, Dimension::HEIGHT);
2394 // Only relayout if required
2395 if( child->RelayoutRequired() )
2397 container.Add( Dali::Actor( child.Get() ), mTargetSize.GetVectorXY() );
2400 DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
2403 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
2407 mRelayoutData->SetUseAssignedSize(use, dimension);
2411 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
2413 return mRelayoutData && mRelayoutData->GetUseAssignedSize(dimension);
2416 void Actor::RelayoutRequest( Dimension::Type dimension )
2418 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
2419 if( relayoutController )
2421 Dali::Actor self( this );
2422 relayoutController->RequestRelayout( self, dimension );
2426 void Actor::SetPreferredSize( const Vector2& size )
2430 // If valid width or height, then set the resize policy to FIXED
2431 // 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,
2432 // then change to FIXED as well
2434 if( size.width > 0.0f || GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DEFAULT )
2436 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
2439 if( size.height > 0.0f || GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DEFAULT )
2441 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
2444 mRelayoutData->preferredSize = size;
2446 mUseAnimatedSize = AnimatedSizeFlag::CLEAR;
2451 Vector2 Actor::GetPreferredSize() const
2453 if ( mRelayoutData )
2455 return Vector2( mRelayoutData->preferredSize );
2458 return Relayouter::DEFAULT_PREFERRED_SIZE;
2461 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
2463 EnsureRelayouter().SetMinimumSize(size, dimension);
2467 float Actor::GetMinimumSize( Dimension::Type dimension ) const
2469 if ( mRelayoutData )
2471 return mRelayoutData->GetMinimumSize(dimension);
2474 return 0.0f; // Default
2477 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
2479 EnsureRelayouter().SetMaximumSize(size, dimension);
2483 float Actor::GetMaximumSize( Dimension::Type dimension ) const
2485 if ( mRelayoutData )
2487 return mRelayoutData->GetMaximumSize(dimension);
2490 return FLT_MAX; // Default
2493 void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
2495 if( mVisible != visible )
2497 if( sendMessage == SendMessage::TRUE )
2499 // node is being used in a separate thread; queue a message to set the value & base value
2500 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible );
2505 // Emit the signal on this actor and all its children
2506 EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
2510 void Actor::SetSiblingOrder( uint32_t order )
2514 ActorContainer& siblings = *(mParent->mChildren);
2515 uint32_t currentOrder = GetSiblingOrder();
2517 if( order != currentOrder )
2523 else if( order < siblings.size() -1 )
2525 if( order > currentOrder )
2527 RaiseAbove( *siblings[order] );
2531 LowerBelow( *siblings[order] );
2542 uint32_t Actor::GetSiblingOrder() const
2548 ActorContainer& siblings = *(mParent->mChildren);
2549 for( std::size_t i = 0; i < siblings.size(); ++i )
2551 if( siblings[i] == this )
2553 order = static_cast<uint32_t>( i );
2562 void Actor::RequestRebuildDepthTree()
2568 mScene->RequestRebuildDepthTree();
2577 ActorContainer& siblings = *(mParent->mChildren);
2578 if( siblings.back() != this ) // If not already at end
2580 for( std::size_t i=0; i<siblings.size(); ++i )
2582 if( siblings[i] == this )
2585 ActorPtr next = siblings[i+1];
2586 siblings[i+1] = this;
2593 Dali::Actor handle( this );
2594 mParent->mChildOrderChangedSignal.Emit( handle );
2596 RequestRebuildDepthTree();
2600 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2608 ActorContainer& siblings = *(mParent->mChildren);
2609 if( siblings.front() != this ) // If not already at beginning
2611 for( std::size_t i=1; i<siblings.size(); ++i )
2613 if( siblings[i] == this )
2615 // Swap with previous
2616 ActorPtr previous = siblings[i-1];
2617 siblings[i-1] = this;
2618 siblings[i] = previous;
2624 Dali::Actor handle( this );
2625 mParent->mChildOrderChangedSignal.Emit( handle );
2627 RequestRebuildDepthTree();
2631 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2635 void Actor::RaiseToTop()
2639 ActorContainer& siblings = *(mParent->mChildren);
2640 if( siblings.back() != this ) // If not already at end
2642 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
2643 if( iter != siblings.end() )
2645 siblings.erase(iter);
2646 siblings.push_back(ActorPtr(this));
2650 Dali::Actor handle( this );
2651 mParent->mChildOrderChangedSignal.Emit( handle );
2653 RequestRebuildDepthTree();
2657 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2661 void Actor::LowerToBottom()
2665 ActorContainer& siblings = *(mParent->mChildren);
2666 if( siblings.front() != this ) // If not already at bottom,
2668 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2670 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
2671 if( iter != siblings.end() )
2673 siblings.erase(iter);
2674 siblings.insert(siblings.begin(), thisPtr);
2678 Dali::Actor handle( this );
2679 mParent->mChildOrderChangedSignal.Emit( handle );
2681 RequestRebuildDepthTree();
2685 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2689 void Actor::RaiseAbove( Internal::Actor& target )
2693 ActorContainer& siblings = *(mParent->mChildren);
2694 if( siblings.back() != this && target.mParent == mParent ) // If not already at top
2696 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2698 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
2699 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
2700 if( thisIter < targetIter )
2702 siblings.erase(thisIter);
2703 // Erasing early invalidates the targetIter. (Conversely, inserting first may also
2704 // invalidate thisIter)
2705 targetIter = std::find( siblings.begin(), siblings.end(), &target );
2707 siblings.insert(targetIter, thisPtr);
2710 Dali::Actor handle( this );
2711 mParent->mChildOrderChangedSignal.Emit( handle );
2713 RequestRebuildDepthTree();
2718 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2722 void Actor::LowerBelow( Internal::Actor& target )
2726 ActorContainer& siblings = *(mParent->mChildren);
2727 if( siblings.front() != this && target.mParent == mParent ) // If not already at bottom
2729 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2731 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
2732 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
2734 if( thisIter > targetIter )
2736 siblings.erase(thisIter); // this only invalidates iterators at or after this point.
2737 siblings.insert(targetIter, thisPtr);
2740 Dali::Actor handle( this );
2741 mParent->mChildOrderChangedSignal.Emit( handle );
2743 RequestRebuildDepthTree();
2748 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2752 void Actor::SetInheritLayoutDirection( bool inherit )
2754 if( mInheritLayoutDirection != inherit )
2756 mInheritLayoutDirection = inherit;
2758 if( inherit && mParent )
2760 InheritLayoutDirectionRecursively( this, mParent->mLayoutDirection );
2765 void Actor::InheritLayoutDirectionRecursively( ActorPtr actor, Dali::LayoutDirection::Type direction, bool set )
2767 if( actor && ( actor->mInheritLayoutDirection || set ) )
2769 if( actor->mLayoutDirection != direction )
2771 actor->mLayoutDirection = direction;
2772 actor->EmitLayoutDirectionChangedSignal( direction );
2773 actor->RelayoutRequest();
2776 if( actor->GetChildCount() > 0 )
2778 for( ActorPtr& child : actor->GetChildrenInternal() )
2780 InheritLayoutDirectionRecursively( child, direction );
2786 void Actor::SetUpdateSizeHint( const Vector2& updateSizeHint )
2788 // node is being used in a separate thread; queue a message to set the value & base value
2789 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mUpdateSizeHint, &AnimatableProperty<Vector3>::Bake, Vector3(updateSizeHint.width, updateSizeHint.height, 0.f ) );
2792 } // namespace Internal