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::EmitTouchEventSignal( const Dali::TouchEvent& touch )
1324 return EmitConsumingSignal( *this, mTouchedSignal, touch );
1327 bool Actor::EmitHoverEventSignal( const Dali::HoverEvent& event )
1329 return EmitConsumingSignal( *this, mHoveredSignal, event );
1332 bool Actor::EmitWheelEventSignal( const Dali::WheelEvent& event )
1334 return EmitConsumingSignal( *this, mWheelEventSignal, event );
1337 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
1339 EmitSignal( *this, mVisibilityChangedSignal, visible, type );
1342 void Actor::EmitLayoutDirectionChangedSignal( LayoutDirection::Type type )
1344 EmitSignal( *this, mLayoutDirectionChangedSignal, type );
1347 void Actor::EmitChildAddedSignal( Actor& child )
1349 EmitSignal( child, mChildAddedSignal );
1352 void Actor::EmitChildRemovedSignal( Actor& child )
1354 EmitSignal( child, mChildRemovedSignal );
1357 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1359 bool connected( true );
1360 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
1362 if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1364 actor->HoveredSignal().Connect( tracker, functor );
1366 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1368 actor->WheelEventSignal().Connect( tracker, functor );
1370 else if( 0 == signalName.compare( SIGNAL_ON_SCENE ) )
1372 actor->OnSceneSignal().Connect( tracker, functor );
1374 else if( 0 == signalName.compare( SIGNAL_OFF_SCENE ) )
1376 actor->OffSceneSignal().Connect( tracker, functor );
1378 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
1380 actor->OnRelayoutSignal().Connect( tracker, functor );
1382 else if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1384 actor->TouchedSignal().Connect( tracker, functor );
1386 else if( 0 == signalName.compare( SIGNAL_VISIBILITY_CHANGED ) )
1388 actor->VisibilityChangedSignal().Connect( tracker, functor );
1390 else if( 0 == signalName.compare( SIGNAL_LAYOUT_DIRECTION_CHANGED ) )
1392 actor->LayoutDirectionChangedSignal().Connect( tracker, functor );
1394 else if( 0 == signalName.compare( SIGNAL_CHILD_ADDED ) )
1396 actor->ChildAddedSignal().Connect( tracker, functor );
1398 else if( 0 == signalName.compare( SIGNAL_CHILD_REMOVED ) )
1400 actor->ChildRemovedSignal().Connect( tracker, functor );
1404 // signalName does not match any signal
1411 Actor::Actor( DerivedType derivedType, const SceneGraph::Node& node )
1415 mChildren( nullptr ),
1416 mRenderers( nullptr ),
1417 mParentOrigin( nullptr ),
1418 mAnchorPoint( nullptr ),
1419 mRelayoutData( nullptr ),
1420 mGestureData( nullptr ),
1423 mWheelEventSignal(),
1426 mOnRelayoutSignal(),
1427 mVisibilityChangedSignal(),
1428 mLayoutDirectionChangedSignal(),
1429 mChildAddedSignal(),
1430 mChildRemovedSignal(),
1431 mChildOrderChangedSignal(),
1432 mTargetOrientation( Quaternion::IDENTITY ),
1433 mTargetColor( Color::WHITE ),
1434 mTargetSize( Vector3::ZERO ),
1435 mTargetPosition( Vector3::ZERO ),
1436 mTargetScale( Vector3::ONE ),
1437 mAnimatedSize( Vector3::ZERO ),
1441 mUseAnimatedSize( AnimatedSizeFlag::CLEAR ),
1442 mIsRoot( ROOT_LAYER == derivedType ),
1443 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
1444 mIsOnScene( false ),
1446 mLeaveRequired( false ),
1447 mKeyboardFocusable( false ),
1448 mOnSceneSignalled( false ),
1449 mInsideOnSizeSet( false ),
1450 mInheritPosition( true ),
1451 mInheritOrientation( true ),
1452 mInheritScale( true ),
1453 mPositionUsesAnchorPoint( true ),
1455 mInheritLayoutDirection( true ),
1456 mCaptureAllTouchAfterStart( false ),
1457 mLayoutDirection( LayoutDirection::LEFT_TO_RIGHT ),
1458 mDrawMode( DrawMode::NORMAL ),
1459 mColorMode( Node::DEFAULT_COLOR_MODE ),
1460 mClippingMode( ClippingMode::DISABLED )
1464 void Actor::Initialize()
1468 GetEventThreadServices().RegisterObject( this );
1473 // Remove mParent pointers from children even if we're destroying core,
1474 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1477 ActorConstIter endIter = mChildren->end();
1478 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1480 (*iter)->SetParent( nullptr );
1486 // Guard to allow handle destruction after Core has been destroyed
1487 if( EventThreadServices::IsCoreRunning() )
1489 // Root layer will destroy its node in its own destructor
1492 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
1494 GetEventThreadServices().UnregisterObject( this );
1498 // Cleanup optional gesture data
1499 delete mGestureData;
1501 // Cleanup optional parent origin and anchor
1502 delete mParentOrigin;
1503 delete mAnchorPoint;
1505 // Delete optional relayout data
1506 delete mRelayoutData;
1509 void Actor::ConnectToScene( uint32_t parentDepth )
1511 // This container is used instead of walking the Actor hierarchy.
1512 // It protects us when the Actor hierarchy is modified during OnSceneConnectionExternal callbacks.
1513 ActorContainer connectionList;
1517 mScene->RequestRebuildDepthTree();
1520 // This stage is atomic i.e. not interrupted by user callbacks.
1521 RecursiveConnectToScene( connectionList, parentDepth + 1 );
1523 // Notify applications about the newly connected actors.
1524 const ActorIter endIter = connectionList.end();
1525 for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
1527 (*iter)->NotifyStageConnection();
1533 void Actor::RecursiveConnectToScene( ActorContainer& connectionList, uint32_t depth )
1535 DALI_ASSERT_ALWAYS( !OnScene() );
1538 mDepth = static_cast< uint16_t >( depth ); // overflow ignored, not expected in practice
1540 ConnectToSceneGraph();
1542 // Notification for internal derived classes
1543 OnSceneConnectionInternal();
1545 // This stage is atomic; avoid emitting callbacks until all Actors are connected
1546 connectionList.push_back( ActorPtr( this ) );
1548 // Recursively connect children
1551 ActorConstIter endIter = mChildren->end();
1552 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1554 (*iter)->SetScene( *mScene );
1555 (*iter)->RecursiveConnectToScene( connectionList, depth + 1 );
1561 * This method is called when the Actor is connected to the Stage.
1562 * The parent must have added its Node to the scene-graph.
1563 * The child must connect its Node to the parent's Node.
1564 * This is recursive; the child calls ConnectToScene() for its children.
1566 void Actor::ConnectToSceneGraph()
1568 DALI_ASSERT_DEBUG( mParent != NULL);
1570 // Reparent Node in next Update
1571 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), mParent->GetNode(), GetNode() );
1573 // Request relayout on all actors that are added to the scenegraph
1576 // Notification for Object::Observers
1580 void Actor::NotifyStageConnection()
1582 // Actors can be removed (in a callback), before the on-stage stage is reported.
1583 // The actor may also have been reparented, in which case mOnSceneSignalled will be true.
1584 if( OnScene() && !mOnSceneSignalled )
1586 // Notification for external (CustomActor) derived classes
1587 OnSceneConnectionExternal( mDepth );
1589 if( !mOnSceneSignal.Empty() )
1591 Dali::Actor handle( this );
1592 mOnSceneSignal.Emit( handle );
1595 // Guard against Remove during callbacks
1598 mOnSceneSignalled = true; // signal required next time Actor is removed
1603 void Actor::DisconnectFromStage()
1605 // This container is used instead of walking the Actor hierachy.
1606 // It protects us when the Actor hierachy is modified during OnSceneDisconnectionExternal callbacks.
1607 ActorContainer disconnectionList;
1611 mScene->RequestRebuildDepthTree();
1614 // This stage is atomic i.e. not interrupted by user callbacks
1615 RecursiveDisconnectFromStage( disconnectionList );
1617 // Notify applications about the newly disconnected actors.
1618 const ActorIter endIter = disconnectionList.end();
1619 for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
1621 (*iter)->NotifyStageDisconnection();
1625 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
1627 // need to change state first so that internals relying on IsOnScene() inside OnSceneDisconnectionInternal() get the correct value
1630 // Recursively disconnect children
1633 ActorConstIter endIter = mChildren->end();
1634 for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
1636 (*iter)->RecursiveDisconnectFromStage( disconnectionList );
1640 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
1641 disconnectionList.push_back( ActorPtr( this ) );
1643 // Notification for internal derived classes
1644 OnSceneDisconnectionInternal();
1646 DisconnectFromSceneGraph();
1650 * This method is called by an actor or its parent, before a node removal message is sent.
1651 * This is recursive; the child calls DisconnectFromStage() for its children.
1653 void Actor::DisconnectFromSceneGraph()
1655 // Notification for Object::Observers
1656 OnSceneObjectRemove();
1659 void Actor::NotifyStageDisconnection()
1661 // Actors can be added (in a callback), before the off-stage state is reported.
1662 // Also if the actor was added & removed before mOnSceneSignalled was set, then we don't notify here.
1663 // only do this step if there is a stage, i.e. Core is not being shut down
1664 if ( EventThreadServices::IsCoreRunning() && !OnScene() && mOnSceneSignalled )
1666 // Notification for external (CustomeActor) derived classes
1667 OnSceneDisconnectionExternal();
1669 if( !mOffSceneSignal.Empty() )
1671 Dali::Actor handle( this );
1672 mOffSceneSignal.Emit( handle );
1675 // Guard against Add during callbacks
1678 mOnSceneSignalled = false; // signal required next time Actor is added
1683 bool Actor::IsNodeConnected() const
1685 bool connected( false );
1689 if( IsRoot() || GetNode().GetParent() )
1698 // This method initiates traversal of the actor tree using depth-first
1699 // traversal to set a depth index based on traversal order. It sends a
1700 // single message to update manager to update all the actor's nodes in
1701 // this tree with the depth index. The sceneGraphNodeDepths vector's
1702 // elements are ordered by depth, and could be used to reduce sorting
1703 // in the update thread.
1704 void Actor::RebuildDepthTree()
1706 DALI_LOG_TIMER_START(depthTimer);
1708 // Vector of scene-graph nodes and their depths to send to UpdateManager
1709 // in a single message
1710 OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths( new SceneGraph::NodeDepths() );
1712 int32_t depthIndex = 1;
1713 DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
1715 SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths );
1716 DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
1719 void Actor::DepthTraverseActorTree( OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths, int32_t& depthIndex )
1721 mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
1722 sceneGraphNodeDepths->Add( const_cast<SceneGraph::Node*>( &GetNode() ), mSortedDepth );
1724 // Create/add to children of this node
1727 for( ActorContainer::iterator it = mChildren->begin(); it != mChildren->end(); ++it )
1729 Actor* childActor = (*it).Get();
1731 childActor->DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
1736 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
1738 PropertyHandler::SetDefaultProperty(*this, index, property);
1741 // TODO: This method needs to be removed
1742 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
1744 PropertyHandler::SetSceneGraphProperty(index, entry, value, GetEventThreadServices(), GetNode());
1747 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
1749 Property::Value value;
1751 if( ! GetCachedPropertyValue( index, value ) )
1753 // If property value is not stored in the event-side, then it must be a scene-graph only property
1754 GetCurrentPropertyValue( index, value );
1760 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
1762 Property::Value value;
1764 if( ! GetCurrentPropertyValue( index, value ) )
1766 // If unable to retrieve scene-graph property value, then it must be an event-side only property
1767 GetCachedPropertyValue( index, value );
1773 void Actor::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
1775 PropertyHandler::OnNotifyDefaultPropertyAnimation(*this, animation, index, value, animationType);
1778 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
1780 const PropertyBase* property = PropertyHandler::GetSceneObjectAnimatableProperty(index, GetNode());
1783 // not our property, ask base
1784 property = Object::GetSceneObjectAnimatableProperty( index );
1790 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
1792 const PropertyInputImpl* property = PropertyHandler::GetSceneObjectInputProperty(index, GetNode());
1795 // reuse animatable property getter as animatable properties are inputs as well
1796 // animatable property chains back to Object::GetSceneObjectInputProperty() so all properties get covered
1797 property = GetSceneObjectAnimatableProperty( index );
1803 int32_t Actor::GetPropertyComponentIndex( Property::Index index ) const
1805 int32_t componentIndex = PropertyHandler::GetPropertyComponentIndex(index);
1806 if( Property::INVALID_COMPONENT_INDEX == componentIndex )
1809 componentIndex = Object::GetPropertyComponentIndex( index );
1812 return componentIndex;
1815 void Actor::SetParent( Actor* parent )
1819 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
1823 mScene = parent->mScene;
1825 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1828 // Instruct each actor to create a corresponding node in the scene graph
1829 ConnectToScene( parent->GetHierarchyDepth() );
1832 // Resolve the name and index for the child properties if any
1833 ResolveChildProperties();
1835 else // parent being set to NULL
1837 DALI_ASSERT_ALWAYS( mParent != nullptr && "Actor should have a parent" );
1841 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1844 // Disconnect the Node & its children from the scene-graph.
1845 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
1847 // Instruct each actor to discard pointers to the scene-graph
1848 DisconnectFromStage();
1855 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
1858 Actor* actor = dynamic_cast< Actor* >( object );
1862 if( 0 == actionName.compare( ACTION_SHOW ) )
1864 actor->SetVisible( true );
1867 else if( 0 == actionName.compare( ACTION_HIDE ) )
1869 actor->SetVisible( false );
1877 Rect<> Actor::CalculateScreenExtents( ) const
1879 auto screenPosition = GetCurrentScreenPosition();
1880 Vector3 size = GetCurrentSize() * GetCurrentWorldScale();
1881 Vector3 anchorPointOffSet = size * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
1882 Vector2 position = Vector2( screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y );
1883 return { position.x, position.y, size.x, size.y };
1886 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
1888 return PropertyHandler::GetCachedPropertyValue(*this, index, value);
1891 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
1893 return PropertyHandler::GetCurrentPropertyValue(*this, index, value);
1896 Actor::Relayouter& Actor::EnsureRelayouter()
1898 // Assign relayouter
1899 if( !mRelayoutData )
1901 mRelayoutData = new Relayouter();
1904 return *mRelayoutData;
1907 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
1909 // Check if actor is dependent on parent
1910 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1912 if( ( dimension & ( 1 << i ) ) )
1914 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
1915 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
1925 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
1927 // Check if actor is dependent on children
1928 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1930 if( ( dimension & ( 1 << i ) ) )
1932 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
1933 switch( resizePolicy )
1935 case ResizePolicy::FIT_TO_CHILDREN:
1936 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
1952 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
1954 return Actor::RelayoutDependentOnChildren( dimension );
1957 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
1959 // Check each possible dimension and see if it is dependent on the input one
1960 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1962 if( dimension & ( 1 << i ) )
1964 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
1971 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
1973 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1975 if( dimension & ( 1 << i ) )
1977 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
1982 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
1984 // If more than one dimension is requested, just return the first one found
1985 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1987 if( ( dimension & ( 1 << i ) ) )
1989 return mRelayoutData->negotiatedDimensions[ i ];
1993 return 0.0f; // Default
1996 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
1998 EnsureRelayouter().SetPadding( padding, dimension );
2001 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
2003 if ( mRelayoutData )
2005 // If more than one dimension is requested, just return the first one found
2006 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2008 if( ( dimension & ( 1 << i ) ) )
2010 return mRelayoutData->dimensionPadding[ i ];
2015 return Relayouter::DEFAULT_DIMENSION_PADDING;
2018 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
2020 EnsureRelayouter().SetLayoutNegotiated(negotiated, dimension);
2023 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
2025 return mRelayoutData && mRelayoutData->IsLayoutNegotiated(dimension);
2028 float Actor::GetHeightForWidthBase( float width )
2030 float height = 0.0f;
2032 const Vector3 naturalSize = GetNaturalSize();
2033 if( naturalSize.width > 0.0f )
2035 height = naturalSize.height * width / naturalSize.width;
2037 else // we treat 0 as 1:1 aspect ratio
2045 float Actor::GetWidthForHeightBase( float height )
2049 const Vector3 naturalSize = GetNaturalSize();
2050 if( naturalSize.height > 0.0f )
2052 width = naturalSize.width * height / naturalSize.height;
2054 else // we treat 0 as 1:1 aspect ratio
2062 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
2064 // Fill to parent, taking size mode factor into account
2065 switch( child.GetResizePolicy( dimension ) )
2067 case ResizePolicy::FILL_TO_PARENT:
2069 return GetLatestSize( dimension );
2072 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2074 return GetLatestSize( dimension ) * GetDimensionValue( child.GetProperty< Vector3 >( Dali::Actor::Property::SIZE_MODE_FACTOR ), dimension );
2077 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2079 return GetLatestSize( dimension ) + GetDimensionValue( child.GetProperty< Vector3 >( Dali::Actor::Property::SIZE_MODE_FACTOR ), dimension );
2084 return GetLatestSize( dimension );
2089 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
2091 // Can be overridden in derived class
2092 return CalculateChildSizeBase( child, dimension );
2095 float Actor::GetHeightForWidth( float width )
2097 // Can be overridden in derived class
2098 return GetHeightForWidthBase( width );
2101 float Actor::GetWidthForHeight( float height )
2103 // Can be overridden in derived class
2104 return GetWidthForHeightBase( height );
2107 float Actor::GetLatestSize( Dimension::Type dimension ) const
2109 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
2112 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
2114 Vector2 padding = GetPadding( dimension );
2116 return GetLatestSize( dimension ) + padding.x + padding.y;
2119 float Actor::NegotiateFromParent( Dimension::Type dimension )
2121 Actor* parent = GetParent();
2124 Vector2 padding( GetPadding( dimension ) );
2125 Vector2 parentPadding( parent->GetPadding( dimension ) );
2126 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
2132 float Actor::NegotiateFromChildren( Dimension::Type dimension )
2134 float maxDimensionPoint = 0.0f;
2136 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2138 ActorPtr child = GetChildAt( i );
2140 if( !child->RelayoutDependentOnParent( dimension ) )
2142 // Calculate the min and max points that the children range across
2143 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
2144 float dimensionSize = child->GetRelayoutSize( dimension );
2145 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
2149 return maxDimensionPoint;
2152 float Actor::GetSize( Dimension::Type dimension ) const
2154 return GetDimensionValue( mTargetSize, dimension );
2157 float Actor::GetNaturalSize( Dimension::Type dimension ) const
2159 return GetDimensionValue( GetNaturalSize(), dimension );
2162 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
2164 switch( GetResizePolicy( dimension ) )
2166 case ResizePolicy::USE_NATURAL_SIZE:
2168 return GetNaturalSize( dimension );
2171 case ResizePolicy::FIXED:
2173 return GetDimensionValue( GetPreferredSize(), dimension );
2176 case ResizePolicy::USE_ASSIGNED_SIZE:
2178 return GetDimensionValue( maximumSize, dimension );
2181 case ResizePolicy::FILL_TO_PARENT:
2182 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2183 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2185 return NegotiateFromParent( dimension );
2188 case ResizePolicy::FIT_TO_CHILDREN:
2190 return NegotiateFromChildren( dimension );
2193 case ResizePolicy::DIMENSION_DEPENDENCY:
2195 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
2198 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
2200 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
2203 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
2205 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
2217 return 0.0f; // Default
2220 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
2222 // Check if it needs to be negotiated
2223 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
2225 // Check that we havn't gotten into an infinite loop
2226 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
2227 bool recursionFound = false;
2228 for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
2230 if( *it == searchActor )
2232 recursionFound = true;
2237 if( !recursionFound )
2239 // Record the path that we have taken
2240 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
2242 // Dimension dependency check
2243 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2245 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
2247 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
2249 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
2253 // Parent dependency check
2254 Actor* parent = GetParent();
2255 if( parent && RelayoutDependentOnParent( dimension ) )
2257 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
2260 // Children dependency check
2261 if( RelayoutDependentOnChildren( dimension ) )
2263 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2265 ActorPtr child = GetChildAt( i );
2267 // Only relayout child first if it is not dependent on this actor
2268 if( !child->RelayoutDependentOnParent( dimension ) )
2270 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
2275 // For deriving classes
2276 OnCalculateRelayoutSize( dimension );
2278 // All dependencies checked, calculate the size and set negotiated flag
2279 const float newSize = Relayouter::ClampDimension( *this, CalculateSize( dimension, allocatedSize ), dimension );
2281 SetNegotiatedDimension( newSize, dimension );
2282 SetLayoutNegotiated( true, dimension );
2284 // For deriving classes
2285 OnLayoutNegotiated( newSize, dimension );
2287 // This actor has been successfully processed, pop it off the recursion stack
2288 recursionStack.pop_back();
2292 // TODO: Break infinite loop
2293 SetLayoutNegotiated( true, dimension );
2298 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
2300 // Negotiate all dimensions that require it
2301 ActorDimensionStack recursionStack;
2303 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2305 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
2308 NegotiateDimension( dimension, allocatedSize, recursionStack );
2312 Vector2 Actor::ApplySizeSetPolicy( const Vector2& size )
2314 return mRelayoutData->ApplySizeSetPolicy(*this, size);
2317 void Actor::SetNegotiatedSize( RelayoutContainer& container )
2319 // Do the set actor size
2320 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
2322 // Adjust for size set policy
2323 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
2325 // Lock the flag to stop recursive relayouts on set size
2326 mRelayoutData->insideRelayout = true;
2327 SetSize( negotiatedSize );
2328 mRelayoutData->insideRelayout = false;
2330 // Clear flags for all dimensions
2331 SetLayoutDirty( false );
2333 // Give deriving classes a chance to respond
2334 OnRelayout( negotiatedSize, container );
2336 if( !mOnRelayoutSignal.Empty() )
2338 Dali::Actor handle( this );
2339 mOnRelayoutSignal.Emit( handle );
2343 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
2345 // Force a size negotiation for actors that has assigned size during relayout
2346 // This is required as otherwise the flags that force a relayout will not
2347 // necessarilly be set. This will occur if the actor has already been laid out.
2348 // The dirty flags are then cleared. Then if the actor is added back into the
2349 // relayout container afterwards, the dirty flags would still be clear...
2350 // causing a relayout to be skipped. Here we force any actors added to the
2351 // container to be relayed out.
2352 DALI_LOG_TIMER_START( NegSizeTimer1 );
2354 if( GetUseAssignedSize(Dimension::WIDTH ) )
2356 SetLayoutNegotiated( false, Dimension::WIDTH );
2358 if( GetUseAssignedSize( Dimension::HEIGHT ) )
2360 SetLayoutNegotiated( false, Dimension::HEIGHT );
2363 // Do the negotiation
2364 NegotiateDimensions( allocatedSize );
2366 // Set the actor size
2367 SetNegotiatedSize( container );
2369 // Negotiate down to children
2370 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2372 ActorPtr child = GetChildAt( i );
2374 // Forces children that have already been laid out to be relayed out
2375 // if they have assigned size during relayout.
2376 if( child->GetUseAssignedSize(Dimension::WIDTH) )
2378 child->SetLayoutNegotiated(false, Dimension::WIDTH);
2379 child->SetLayoutDirty(true, Dimension::WIDTH);
2382 if( child->GetUseAssignedSize(Dimension::HEIGHT) )
2384 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
2385 child->SetLayoutDirty(true, Dimension::HEIGHT);
2388 // Only relayout if required
2389 if( child->RelayoutRequired() )
2391 container.Add( Dali::Actor( child.Get() ), mTargetSize.GetVectorXY() );
2394 DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
2397 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
2401 mRelayoutData->SetUseAssignedSize(use, dimension);
2405 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
2407 return mRelayoutData && mRelayoutData->GetUseAssignedSize(dimension);
2410 void Actor::RelayoutRequest( Dimension::Type dimension )
2412 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
2413 if( relayoutController )
2415 Dali::Actor self( this );
2416 relayoutController->RequestRelayout( self, dimension );
2420 void Actor::SetPreferredSize( const Vector2& size )
2424 // If valid width or height, then set the resize policy to FIXED
2425 // 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,
2426 // then change to FIXED as well
2428 if( size.width > 0.0f || GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DEFAULT )
2430 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
2433 if( size.height > 0.0f || GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DEFAULT )
2435 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
2438 mRelayoutData->preferredSize = size;
2440 mUseAnimatedSize = AnimatedSizeFlag::CLEAR;
2445 Vector2 Actor::GetPreferredSize() const
2447 if ( mRelayoutData )
2449 return Vector2( mRelayoutData->preferredSize );
2452 return Relayouter::DEFAULT_PREFERRED_SIZE;
2455 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
2457 EnsureRelayouter().SetMinimumSize(size, dimension);
2461 float Actor::GetMinimumSize( Dimension::Type dimension ) const
2463 if ( mRelayoutData )
2465 return mRelayoutData->GetMinimumSize(dimension);
2468 return 0.0f; // Default
2471 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
2473 EnsureRelayouter().SetMaximumSize(size, dimension);
2477 float Actor::GetMaximumSize( Dimension::Type dimension ) const
2479 if ( mRelayoutData )
2481 return mRelayoutData->GetMaximumSize(dimension);
2484 return FLT_MAX; // Default
2487 void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
2489 if( mVisible != visible )
2491 if( sendMessage == SendMessage::TRUE )
2493 // node is being used in a separate thread; queue a message to set the value & base value
2494 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible );
2499 // Emit the signal on this actor and all its children
2500 EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
2504 void Actor::SetSiblingOrder( uint32_t order )
2508 ActorContainer& siblings = *(mParent->mChildren);
2509 uint32_t currentOrder = GetSiblingOrder();
2511 if( order != currentOrder )
2517 else if( order < siblings.size() -1 )
2519 if( order > currentOrder )
2521 RaiseAbove( *siblings[order] );
2525 LowerBelow( *siblings[order] );
2536 uint32_t Actor::GetSiblingOrder() const
2542 ActorContainer& siblings = *(mParent->mChildren);
2543 for( std::size_t i = 0; i < siblings.size(); ++i )
2545 if( siblings[i] == this )
2547 order = static_cast<uint32_t>( i );
2556 void Actor::RequestRebuildDepthTree()
2562 mScene->RequestRebuildDepthTree();
2571 ActorContainer& siblings = *(mParent->mChildren);
2572 if( siblings.back() != this ) // If not already at end
2574 for( std::size_t i=0; i<siblings.size(); ++i )
2576 if( siblings[i] == this )
2579 ActorPtr next = siblings[i+1];
2580 siblings[i+1] = this;
2587 Dali::Actor handle( this );
2588 mParent->mChildOrderChangedSignal.Emit( handle );
2590 RequestRebuildDepthTree();
2594 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2602 ActorContainer& siblings = *(mParent->mChildren);
2603 if( siblings.front() != this ) // If not already at beginning
2605 for( std::size_t i=1; i<siblings.size(); ++i )
2607 if( siblings[i] == this )
2609 // Swap with previous
2610 ActorPtr previous = siblings[i-1];
2611 siblings[i-1] = this;
2612 siblings[i] = previous;
2618 Dali::Actor handle( this );
2619 mParent->mChildOrderChangedSignal.Emit( handle );
2621 RequestRebuildDepthTree();
2625 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2629 void Actor::RaiseToTop()
2633 ActorContainer& siblings = *(mParent->mChildren);
2634 if( siblings.back() != this ) // If not already at end
2636 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
2637 if( iter != siblings.end() )
2639 siblings.erase(iter);
2640 siblings.push_back(ActorPtr(this));
2644 Dali::Actor handle( this );
2645 mParent->mChildOrderChangedSignal.Emit( handle );
2647 RequestRebuildDepthTree();
2651 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2655 void Actor::LowerToBottom()
2659 ActorContainer& siblings = *(mParent->mChildren);
2660 if( siblings.front() != this ) // If not already at bottom,
2662 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2664 ActorContainer::iterator iter = std::find( siblings.begin(), siblings.end(), this );
2665 if( iter != siblings.end() )
2667 siblings.erase(iter);
2668 siblings.insert(siblings.begin(), thisPtr);
2672 Dali::Actor handle( this );
2673 mParent->mChildOrderChangedSignal.Emit( handle );
2675 RequestRebuildDepthTree();
2679 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2683 void Actor::RaiseAbove( Internal::Actor& target )
2687 ActorContainer& siblings = *(mParent->mChildren);
2688 if( siblings.back() != this && target.mParent == mParent ) // If not already at top
2690 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2692 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
2693 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
2694 if( thisIter < targetIter )
2696 siblings.erase(thisIter);
2697 // Erasing early invalidates the targetIter. (Conversely, inserting first may also
2698 // invalidate thisIter)
2699 targetIter = std::find( siblings.begin(), siblings.end(), &target );
2701 siblings.insert(targetIter, thisPtr);
2704 Dali::Actor handle( this );
2705 mParent->mChildOrderChangedSignal.Emit( handle );
2707 RequestRebuildDepthTree();
2712 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2716 void Actor::LowerBelow( Internal::Actor& target )
2720 ActorContainer& siblings = *(mParent->mChildren);
2721 if( siblings.front() != this && target.mParent == mParent ) // If not already at bottom
2723 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2725 ActorContainer::iterator targetIter = std::find( siblings.begin(), siblings.end(), &target );
2726 ActorContainer::iterator thisIter = std::find( siblings.begin(), siblings.end(), this );
2728 if( thisIter > targetIter )
2730 siblings.erase(thisIter); // this only invalidates iterators at or after this point.
2731 siblings.insert(targetIter, thisPtr);
2734 Dali::Actor handle( this );
2735 mParent->mChildOrderChangedSignal.Emit( handle );
2737 RequestRebuildDepthTree();
2742 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2746 void Actor::SetInheritLayoutDirection( bool inherit )
2748 if( mInheritLayoutDirection != inherit )
2750 mInheritLayoutDirection = inherit;
2752 if( inherit && mParent )
2754 InheritLayoutDirectionRecursively( this, mParent->mLayoutDirection );
2759 void Actor::InheritLayoutDirectionRecursively( ActorPtr actor, Dali::LayoutDirection::Type direction, bool set )
2761 if( actor && ( actor->mInheritLayoutDirection || set ) )
2763 if( actor->mLayoutDirection != direction )
2765 actor->mLayoutDirection = direction;
2766 actor->EmitLayoutDirectionChangedSignal( direction );
2767 actor->RelayoutRequest();
2770 if( actor->GetChildCount() > 0 )
2772 for( ActorPtr& child : actor->GetChildrenInternal() )
2774 InheritLayoutDirectionRecursively( child, direction );
2780 void Actor::SetUpdateSizeHint( const Vector2& updateSizeHint )
2782 // node is being used in a separate thread; queue a message to set the value & base value
2783 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mUpdateSizeHint, &AnimatableProperty<Vector3>::Bake, Vector3(updateSizeHint.width, updateSizeHint.height, 0.f ) );
2786 } // namespace Internal