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( "touchArea", VECTOR2, true, false, false, Dali::DevelActor::Property::TOUCH_AREA )
147 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperties )
151 static constexpr std::string_view SIGNAL_HOVERED = "hovered";
152 static constexpr std::string_view SIGNAL_WHEEL_EVENT = "wheelEvent";
153 static constexpr std::string_view SIGNAL_ON_SCENE = "onScene";
154 static constexpr std::string_view SIGNAL_OFF_SCENE = "offScene";
155 static constexpr std::string_view SIGNAL_ON_RELAYOUT = "onRelayout";
156 static constexpr std::string_view SIGNAL_TOUCHED = "touched";
157 static constexpr std::string_view SIGNAL_VISIBILITY_CHANGED = "visibilityChanged";
158 static constexpr std::string_view SIGNAL_LAYOUT_DIRECTION_CHANGED = "layoutDirectionChanged";
159 static constexpr std::string_view SIGNAL_CHILD_ADDED = "childAdded";
160 static constexpr std::string_view SIGNAL_CHILD_REMOVED = "childRemoved";
164 static constexpr std::string_view ACTION_SHOW = "show";
165 static constexpr std::string_view ACTION_HIDE = "hide";
167 BaseHandle CreateActor()
169 return Dali::Actor::New();
172 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor, ActorDefaultProperties );
174 SignalConnectorType signalConnector2(mType, std::string(SIGNAL_HOVERED), &Actor::DoConnectSignal);
175 SignalConnectorType signalConnector3(mType, std::string(SIGNAL_WHEEL_EVENT), &Actor::DoConnectSignal);
176 SignalConnectorType signalConnector4(mType, std::string(SIGNAL_ON_SCENE), &Actor::DoConnectSignal);
177 SignalConnectorType signalConnector5(mType, std::string(SIGNAL_OFF_SCENE), &Actor::DoConnectSignal);
178 SignalConnectorType signalConnector6(mType, std::string(SIGNAL_ON_RELAYOUT), &Actor::DoConnectSignal);
179 SignalConnectorType signalConnector7(mType, std::string(SIGNAL_TOUCHED), &Actor::DoConnectSignal);
180 SignalConnectorType signalConnector8(mType, std::string(SIGNAL_VISIBILITY_CHANGED), &Actor::DoConnectSignal);
181 SignalConnectorType signalConnector9(mType, std::string(SIGNAL_LAYOUT_DIRECTION_CHANGED), &Actor::DoConnectSignal);
182 SignalConnectorType signalConnector10(mType, std::string(SIGNAL_CHILD_ADDED), &Actor::DoConnectSignal);
183 SignalConnectorType signalConnector11(mType, std::string(SIGNAL_CHILD_REMOVED), &Actor::DoConnectSignal);
185 TypeAction a1(mType, std::string(ACTION_SHOW), &Actor::DoAction);
186 TypeAction a2(mType, std::string(ACTION_HIDE), &Actor::DoAction);
189 * @brief Extract a given dimension from a Vector2
191 * @param[in] values The values to extract from
192 * @param[in] dimension The dimension to extract
193 * @return Return the value for the dimension
195 constexpr float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
199 case Dimension::WIDTH:
203 case Dimension::HEIGHT:
205 return values.height;
216 * @brief Extract a given dimension from a Vector3
218 * @param[in] values The values to extract from
219 * @param[in] dimension The dimension to extract
220 * @return Return the value for the dimension
222 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
224 return GetDimensionValue( values.GetVectorXY(), dimension );
228 * @brief Recursively emits the visibility-changed-signal on the actor tree.
229 * @param[in] actor The actor to emit the signal on
230 * @param[in] visible The new visibility of the actor
231 * @param[in] type Whether the actor's visible property has changed or a parent's
233 void EmitVisibilityChangedSignalRecursively( ActorPtr actor, bool visible, DevelActor::VisibilityChange::Type type )
237 actor->EmitVisibilityChangedSignal( visible, type );
239 if( actor->GetChildCount() > 0 )
241 for( auto& child : actor->GetChildrenInternal() )
243 EmitVisibilityChangedSignalRecursively( child, visible, DevelActor::VisibilityChange::PARENT );
249 /// Helper for emitting a signal
250 template<typename Signal, typename Event>
251 bool EmitConsumingSignal( Actor& actor, Signal& signal, const Event& event )
253 bool consumed = false;
255 if( !signal.Empty() )
257 Dali::Actor handle( &actor );
258 consumed = signal.Emit( handle, event );
264 /// Helper for emitting signals with multiple parameters
265 template<typename Signal, typename... Param>
266 void EmitSignal( Actor& actor, Signal& signal, Param... params)
268 if( !signal.Empty() )
270 Dali::Actor handle( &actor );
271 signal.Emit( handle, params... );
275 bool ScreenToLocalInternal(
276 const Matrix& viewMatrix,
277 const Matrix& projectionMatrix,
278 const Matrix& worldMatrix,
279 const Viewport& viewport,
280 const Vector3& currentSize,
286 // Get the ModelView matrix
288 Matrix::Multiply( modelView, worldMatrix, viewMatrix );
290 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
291 Matrix invertedMvp( false/*don't init*/);
292 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
293 bool success = invertedMvp.Invert();
295 // Convert to GL coordinates
296 Vector4 screenPos( screenX - static_cast<float>( viewport.x ), static_cast<float>( viewport.height ) - screenY - static_cast<float>( viewport.y ), 0.f, 1.f );
301 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), nearPos );
308 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), farPos );
314 if( XyPlaneIntersect( nearPos, farPos, local ) )
316 Vector3 size = currentSize;
317 localX = local.x + size.x * 0.5f;
318 localY = local.y + size.y * 0.5f;
329 } // unnamed namespace
331 ActorPtr Actor::New()
333 // pass a reference to actor, actor does not own its node
334 ActorPtr actor( new Actor( BASIC, *CreateNode() ) );
336 // Second-phase construction
342 const SceneGraph::Node* Actor::CreateNode()
344 // create node. Nodes are owned by the update manager
345 SceneGraph::Node* node = SceneGraph::Node::New();
346 OwnerPointer< SceneGraph::Node > transferOwnership( node );
347 Internal::ThreadLocalStorage* tls = Internal::ThreadLocalStorage::GetInternal();
349 DALI_ASSERT_ALWAYS( tls && "ThreadLocalStorage is null" );
351 AddNodeMessage( tls->GetUpdateManager(), transferOwnership );
356 void Actor::SetName( const std::string& name )
360 // ATTENTION: string for debug purposes is not thread safe.
361 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( &GetNode() ), name );
364 uint32_t Actor::GetId() const
366 return GetNode().GetId();
369 Dali::Layer Actor::GetLayer()
373 // Short-circuit for Layer derived actors
376 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
379 // Find the immediate Layer parent
380 for( Actor* parent = mParent; !layer && parent != nullptr; parent = parent->GetParent() )
382 if( parent->IsLayer() )
384 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
391 void Actor::Add( Actor& child )
393 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
394 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
398 mChildren = new ActorContainer;
401 Actor* const oldParent( child.mParent );
403 // child might already be ours
404 if( this != oldParent )
406 // if we already have parent, unparent us first
409 oldParent->Remove( child ); // This causes OnChildRemove callback & ChildRemoved signal
411 // Old parent may need to readjust to missing child
412 if( oldParent->RelayoutDependentOnChildren() )
414 oldParent->RelayoutRequest();
418 // Guard against Add() during previous OnChildRemove callback
421 // Do this first, since user callbacks from within SetParent() may need to remove child
422 mChildren->push_back( ActorPtr( &child ) );
424 // SetParent asserts that child can be added
425 child.SetParent( this );
427 // Notification for derived classes
429 EmitChildAddedSignal( child );
431 InheritLayoutDirectionRecursively( ActorPtr( &child ), mLayoutDirection );
433 // Only put in a relayout request if there is a suitable dependency
434 if( RelayoutDependentOnChildren() )
442 void Actor::Remove( Actor& child )
444 if( (this == &child) || (!mChildren) )
446 // no children or removing itself
452 // Find the child in mChildren, and unparent it
453 ActorIter end = mChildren->end();
454 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
456 ActorPtr actor = (*iter);
458 if( actor.Get() == &child )
460 // Keep handle for OnChildRemove notification
463 // Do this first, since user callbacks from within SetParent() may need to add the child
464 mChildren->erase( iter );
466 DALI_ASSERT_DEBUG( actor->GetParent() == this );
467 actor->SetParent( nullptr );
475 // Only put in a relayout request if there is a suitable dependency
476 if( RelayoutDependentOnChildren() )
482 // Notification for derived classes
483 OnChildRemove( child );
484 EmitChildRemovedSignal( child );
487 void Actor::Unparent()
491 // Remove this actor from the parent. The remove will put a relayout request in for
492 // the parent if required
493 mParent->Remove( *this );
494 // mParent is now NULL!
498 uint32_t Actor::GetChildCount() const
500 return ( nullptr != mChildren ) ? static_cast<uint32_t>( mChildren->size() ) : 0; // only 4,294,967,295 children per actor
503 ActorPtr Actor::GetChildAt( uint32_t index ) const
505 DALI_ASSERT_ALWAYS( index < GetChildCount() );
507 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
510 ActorPtr Actor::FindChildByName( const std::string& actorName )
512 ActorPtr child = nullptr;
513 if( actorName == mName )
519 for( const auto& actor : *mChildren )
521 child = actor->FindChildByName( actorName );
532 ActorPtr Actor::FindChildById( const uint32_t id )
534 ActorPtr child = nullptr;
541 for( const auto& actor : *mChildren )
543 child = actor->FindChildById( id );
554 void Actor::SetParentOrigin( const Vector3& origin )
556 // node is being used in a separate thread; queue a message to set the value & base value
557 SetParentOriginMessage( GetEventThreadServices(), GetNode(), origin );
559 // Cache for event-thread access
562 // not allocated, check if different from default
563 if( ParentOrigin::DEFAULT != origin )
565 mParentOrigin = new Vector3( origin );
570 // check if different from current costs more than just set
571 *mParentOrigin = origin;
575 const Vector3& Actor::GetCurrentParentOrigin() const
577 // Cached for event-thread access
578 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
581 void Actor::SetAnchorPoint( const Vector3& anchor )
583 // node is being used in a separate thread; queue a message to set the value & base value
584 SetAnchorPointMessage( GetEventThreadServices(), GetNode(), anchor );
586 // Cache for event-thread access
589 // not allocated, check if different from default
590 if( AnchorPoint::DEFAULT != anchor )
592 mAnchorPoint = new Vector3( anchor );
597 // check if different from current costs more than just set
598 *mAnchorPoint = anchor;
602 const Vector3& Actor::GetCurrentAnchorPoint() const
604 // Cached for event-thread access
605 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
608 void Actor::SetPosition( float x, float y )
610 SetPosition( Vector3( x, y, 0.0f ) );
613 void Actor::SetPosition( float x, float y, float z )
615 SetPosition( Vector3( x, y, z ) );
618 void Actor::SetPosition( const Vector3& position )
620 mTargetPosition = position;
622 // node is being used in a separate thread; queue a message to set the value & base value
623 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
626 void Actor::SetX( float x )
628 mTargetPosition.x = x;
630 // node is being used in a separate thread; queue a message to set the value & base value
631 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
634 void Actor::SetY( float y )
636 mTargetPosition.y = y;
638 // node is being used in a separate thread; queue a message to set the value & base value
639 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
642 void Actor::SetZ( float z )
644 mTargetPosition.z = z;
646 // node is being used in a separate thread; queue a message to set the value & base value
647 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
650 void Actor::TranslateBy( const Vector3& distance )
652 mTargetPosition += distance;
654 // node is being used in a separate thread; queue a message to set the value & base value
655 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
658 const Vector3& Actor::GetCurrentPosition() const
660 // node is being used in a separate thread; copy the value from the previous update
661 return GetNode().GetPosition(GetEventThreadServices().GetEventBufferIndex());
664 const Vector3& Actor::GetCurrentWorldPosition() const
666 // node is being used in a separate thread; copy the value from the previous update
667 return GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
670 const Vector2 Actor::GetCurrentScreenPosition() const
672 if( mScene && OnScene() )
674 Vector3 worldPosition = GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
675 Vector3 cameraPosition = mScene->GetDefaultCameraActor().GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
676 worldPosition -= cameraPosition;
678 Vector3 actorSize = GetCurrentSize() * GetCurrentWorldScale();
679 Vector2 halfSceneSize( mScene->GetSize() * 0.5f ); // World position origin is center of scene
680 Vector3 halfActorSize( actorSize * 0.5f );
681 Vector3 anchorPointOffSet = halfActorSize - actorSize * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
683 return Vector2( halfSceneSize.width + worldPosition.x - anchorPointOffSet.x,
684 halfSceneSize.height + worldPosition.y - anchorPointOffSet.y );
687 return Vector2::ZERO;
690 void Actor::SetInheritPosition( bool inherit )
692 if( mInheritPosition != inherit )
694 // non animatable so keep local copy
695 mInheritPosition = inherit;
696 SetInheritPositionMessage( GetEventThreadServices(), GetNode(), inherit );
700 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
702 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
703 normalizedAxis.Normalize();
705 Quaternion orientation( angle, normalizedAxis );
707 SetOrientation( orientation );
710 void Actor::SetOrientation( const Quaternion& orientation )
712 mTargetOrientation = orientation;
714 // node is being used in a separate thread; queue a message to set the value & base value
715 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation );
718 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
720 RotateBy( Quaternion(angle, axis) );
723 void Actor::RotateBy( const Quaternion& relativeRotation )
725 mTargetOrientation *= Quaternion( relativeRotation );
727 // node is being used in a separate thread; queue a message to set the value & base value
728 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
731 const Quaternion& Actor::GetCurrentOrientation() const
733 // node is being used in a separate thread; copy the value from the previous update
734 return GetNode().GetOrientation(GetEventThreadServices().GetEventBufferIndex());
737 const Quaternion& Actor::GetCurrentWorldOrientation() const
739 // node is being used in a separate thread; copy the value from the previous update
740 return GetNode().GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
743 void Actor::SetScale( float scale )
745 SetScale( Vector3( scale, scale, scale ) );
748 void Actor::SetScale( float x, float y, float z )
750 SetScale( Vector3( x, y, z ) );
753 void Actor::SetScale( const Vector3& scale )
755 mTargetScale = scale;
757 // node is being used in a separate thread; queue a message to set the value & base value
758 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
761 void Actor::SetScaleX( float x )
765 // node is being used in a separate thread; queue a message to set the value & base value
766 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
769 void Actor::SetScaleY( float y )
773 // node is being used in a separate thread; queue a message to set the value & base value
774 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
777 void Actor::SetScaleZ( float z )
781 // node is being used in a separate thread; queue a message to set the value & base value
782 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
785 void Actor::ScaleBy(const Vector3& relativeScale)
787 mTargetScale *= relativeScale;
789 // node is being used in a separate thread; queue a message to set the value & base value
790 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
793 const Vector3& Actor::GetCurrentScale() const
795 // node is being used in a separate thread; copy the value from the previous update
796 return GetNode().GetScale(GetEventThreadServices().GetEventBufferIndex());
799 const Vector3& Actor::GetCurrentWorldScale() const
801 // node is being used in a separate thread; copy the value from the previous update
802 return GetNode().GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
805 void Actor::SetInheritScale( bool inherit )
807 if( mInheritScale != inherit )
809 // non animatable so keep local copy
810 mInheritScale = inherit;
811 // node is being used in a separate thread; queue a message to set the value
812 SetInheritScaleMessage( GetEventThreadServices(), GetNode(), inherit );
816 Matrix Actor::GetCurrentWorldMatrix() const
818 return GetNode().GetWorldMatrix(0);
821 void Actor::SetVisible( bool visible )
823 SetVisibleInternal( visible, SendMessage::TRUE );
826 bool Actor::IsVisible() const
828 // node is being used in a separate thread; copy the value from the previous update
829 return GetNode().IsVisible( GetEventThreadServices().GetEventBufferIndex() );
832 void Actor::SetOpacity( float opacity )
834 mTargetColor.a = opacity;
836 // node is being used in a separate thread; queue a message to set the value & base value
837 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
839 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
842 float Actor::GetCurrentOpacity() const
844 // node is being used in a separate thread; copy the value from the previous update
845 return GetNode().GetOpacity(GetEventThreadServices().GetEventBufferIndex());
848 const Vector4& Actor::GetCurrentWorldColor() const
850 return GetNode().GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
853 void Actor::SetColor( const Vector4& color )
855 mTargetColor = color;
857 // node is being used in a separate thread; queue a message to set the value & base value
858 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::Bake, color );
860 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
863 void Actor::SetColorRed( float red )
865 mTargetColor.r = red;
867 // node is being used in a separate thread; queue a message to set the value & base value
868 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeX, red );
870 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
873 void Actor::SetColorGreen( float green )
875 mTargetColor.g = green;
877 // node is being used in a separate thread; queue a message to set the value & base value
878 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeY, green );
880 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
883 void Actor::SetColorBlue( float blue )
885 mTargetColor.b = blue;
887 // node is being used in a separate thread; queue a message to set the value & base value
888 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
890 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
893 const Vector4& Actor::GetCurrentColor() const
895 // node is being used in a separate thread; copy the value from the previous update
896 return GetNode().GetColor(GetEventThreadServices().GetEventBufferIndex());
899 void Actor::SetInheritOrientation( bool inherit )
901 if( mInheritOrientation != inherit )
903 // non animatable so keep local copy
904 mInheritOrientation = inherit;
905 // node is being used in a separate thread; queue a message to set the value
906 SetInheritOrientationMessage( GetEventThreadServices(), GetNode(), inherit );
910 void Actor::SetSizeModeFactor( const Vector3& factor )
914 mRelayoutData->sizeModeFactor = factor;
917 const Vector3& Actor::GetSizeModeFactor() const
921 return mRelayoutData->sizeModeFactor;
924 return Relayouter::DEFAULT_SIZE_MODE_FACTOR;
927 void Actor::SetColorMode( ColorMode colorMode )
929 // non animatable so keep local copy
930 mColorMode = colorMode;
931 // node is being used in a separate thread; queue a message to set the value
932 SetColorModeMessage( GetEventThreadServices(), GetNode(), colorMode );
935 void Actor::SetSize( float width, float height )
937 SetSize( Vector2( width, height ) );
940 void Actor::SetSize( float width, float height, float depth )
942 SetSize( Vector3( width, height, depth ) );
945 void Actor::SetSize( const Vector2& size )
947 SetSize( Vector3( size.width, size.height, 0.f ) );
950 void Actor::SetSizeInternal( const Vector2& size )
952 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
955 void Actor::SetSize( const Vector3& size )
957 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
959 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
960 SetPreferredSize( size.GetVectorXY() );
964 SetSizeInternal( size );
968 void Actor::SetSizeInternal( const Vector3& size )
970 // dont allow recursive loop
971 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
972 // 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
973 if( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
974 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
975 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) )
979 // node is being used in a separate thread; queue a message to set the value & base value
980 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
982 // Notification for derived classes
983 mInsideOnSizeSet = true;
984 OnSizeSet( mTargetSize );
985 mInsideOnSizeSet = false;
987 // Raise a relayout request if the flag is not locked
988 if( mRelayoutData && !mRelayoutData->insideRelayout )
995 void Actor::SetWidth( float width )
997 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
999 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
1000 mRelayoutData->preferredSize.width = width;
1004 mTargetSize.width = width;
1006 // node is being used in a separate thread; queue a message to set the value & base value
1007 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1010 mUseAnimatedSize &= ~AnimatedSizeFlag::WIDTH;
1015 void Actor::SetHeight( float height )
1017 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1019 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
1020 mRelayoutData->preferredSize.height = height;
1024 mTargetSize.height = height;
1026 // node is being used in a separate thread; queue a message to set the value & base value
1027 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1030 mUseAnimatedSize &= ~AnimatedSizeFlag::HEIGHT;
1035 void Actor::SetDepth( float depth )
1037 mTargetSize.depth = depth;
1039 mUseAnimatedSize &= ~AnimatedSizeFlag::DEPTH;
1041 // node is being used in a separate thread; queue a message to set the value & base value
1042 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1045 Vector3 Actor::GetTargetSize() const
1047 Vector3 size = mTargetSize;
1049 if( mUseAnimatedSize & AnimatedSizeFlag::WIDTH )
1051 // Should return animated size if size is animated
1052 size.width = mAnimatedSize.width;
1056 // Should return preferred size if size is fixed as set by SetSize
1057 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
1059 size.width = GetPreferredSize().width;
1063 if( mUseAnimatedSize & AnimatedSizeFlag::HEIGHT )
1065 size.height = mAnimatedSize.height;
1069 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
1071 size.height = GetPreferredSize().height;
1075 if( mUseAnimatedSize & AnimatedSizeFlag::DEPTH )
1077 size.depth = mAnimatedSize.depth;
1083 const Vector3& Actor::GetCurrentSize() const
1085 // node is being used in a separate thread; copy the value from the previous update
1086 return GetNode().GetSize( GetEventThreadServices().GetEventBufferIndex() );
1089 Vector3 Actor::GetNaturalSize() const
1091 // It is up to deriving classes to return the appropriate natural size
1092 return Vector3( 0.0f, 0.0f, 0.0f );
1095 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1097 EnsureRelayouter().SetResizePolicy(policy, dimension, mTargetSize);
1099 OnSetResizePolicy( policy, dimension );
1101 // Trigger relayout on this control
1105 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1107 if ( mRelayoutData )
1109 return mRelayoutData->GetResizePolicy(dimension);
1112 return ResizePolicy::DEFAULT;
1115 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1119 mRelayoutData->sizeSetPolicy = policy;
1121 // Trigger relayout on this control
1125 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1127 if ( mRelayoutData )
1129 return mRelayoutData->sizeSetPolicy;
1132 return Relayouter::DEFAULT_SIZE_SCALE_POLICY;
1135 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1137 EnsureRelayouter().SetDimensionDependency(dimension, dependency);
1140 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1142 if ( mRelayoutData )
1144 return mRelayoutData->GetDimensionDependency(dimension);
1147 return Dimension::ALL_DIMENSIONS; // Default
1150 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1152 // If relayout data has not been allocated yet and the client is requesting
1153 // to disable it, do nothing
1154 if( mRelayoutData || relayoutEnabled )
1158 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1160 mRelayoutData->relayoutEnabled = relayoutEnabled;
1164 bool Actor::IsRelayoutEnabled() const
1166 // Assume that if relayout data has not been allocated yet then
1167 // relayout is disabled
1168 return mRelayoutData && mRelayoutData->relayoutEnabled;
1171 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1173 EnsureRelayouter().SetLayoutDirty(dirty, dimension);
1176 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1178 return mRelayoutData && mRelayoutData->IsLayoutDirty(dimension);
1181 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1183 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1186 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1188 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1191 uint32_t Actor::AddRenderer( Renderer& renderer )
1195 mRenderers = new RendererContainer;
1198 uint32_t index = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1199 RendererPtr rendererPtr = RendererPtr( &renderer );
1200 mRenderers->push_back( rendererPtr );
1201 AttachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1205 uint32_t Actor::GetRendererCount() const
1207 uint32_t rendererCount(0);
1210 rendererCount = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1213 return rendererCount;
1216 RendererPtr Actor::GetRendererAt( uint32_t index )
1218 RendererPtr renderer;
1219 if( index < GetRendererCount() )
1221 renderer = ( *mRenderers )[ index ];
1227 void Actor::RemoveRenderer( Renderer& renderer )
1231 RendererIter end = mRenderers->end();
1232 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1234 if( (*iter).Get() == &renderer )
1236 mRenderers->erase( iter );
1237 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1244 void Actor::RemoveRenderer( uint32_t index )
1246 if( index < GetRendererCount() )
1248 RendererPtr renderer = ( *mRenderers )[ index ];
1249 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.Get()->GetRendererSceneObject() );
1250 mRenderers->erase( mRenderers->begin()+index );
1254 void Actor::SetDrawMode( DrawMode::Type drawMode )
1256 // this flag is not animatable so keep the value
1257 mDrawMode = drawMode;
1259 // node is being used in a separate thread; queue a message to set the value
1260 SetDrawModeMessage( GetEventThreadServices(), GetNode(), drawMode );
1263 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1265 // only valid when on-stage
1266 if( mScene && OnScene() )
1268 const RenderTaskList& taskList = mScene->GetRenderTaskList();
1270 Vector2 converted( screenX, screenY );
1272 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1273 uint32_t taskCount = taskList.GetTaskCount();
1274 for( uint32_t i = taskCount; i > 0; --i )
1276 RenderTaskPtr task = taskList.GetTask( i - 1 );
1277 if( ScreenToLocal( *task, localX, localY, screenX, screenY ) )
1279 // found a task where this conversion was ok so return
1287 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1289 bool retval = false;
1290 // only valid when on-stage
1293 CameraActor* camera = renderTask.GetCameraActor();
1297 renderTask.GetViewport( viewport );
1299 // need to translate coordinates to render tasks coordinate space
1300 Vector2 converted( screenX, screenY );
1301 if( renderTask.TranslateCoordinates( converted ) )
1303 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1310 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1312 return OnScene() && ScreenToLocalInternal(viewMatrix, projectionMatrix, GetNode().GetWorldMatrix(0), viewport, GetCurrentSize(), localX, localY, screenX, screenY);
1315 ActorGestureData& Actor::GetGestureData()
1317 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1318 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1319 if( nullptr == mGestureData )
1321 mGestureData = new ActorGestureData;
1323 return *mGestureData;
1326 bool Actor::IsGestureRequired( GestureType::Value type ) const
1328 return mGestureData && mGestureData->IsGestureRequired( type );
1331 bool Actor::EmitInterceptTouchEventSignal( const Dali::TouchEvent& touch )
1333 return EmitConsumingSignal( *this, mInterceptTouchedSignal, touch );
1336 bool Actor::EmitTouchEventSignal( const Dali::TouchEvent& touch )
1338 return EmitConsumingSignal( *this, mTouchedSignal, touch );
1341 bool Actor::EmitHoverEventSignal( const Dali::HoverEvent& event )
1343 return EmitConsumingSignal( *this, mHoveredSignal, event );
1346 bool Actor::EmitWheelEventSignal( const Dali::WheelEvent& event )
1348 return EmitConsumingSignal( *this, mWheelEventSignal, event );
1351 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
1353 EmitSignal( *this, mVisibilityChangedSignal, visible, type );
1356 void Actor::EmitLayoutDirectionChangedSignal( LayoutDirection::Type type )
1358 EmitSignal( *this, mLayoutDirectionChangedSignal, type );
1361 void Actor::EmitChildAddedSignal( Actor& child )
1363 EmitSignal( child, mChildAddedSignal );
1366 void Actor::EmitChildRemovedSignal( Actor& child )
1368 EmitSignal( child, mChildRemovedSignal );
1371 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1373 bool connected( true );
1374 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
1376 std::string_view name(signalName);
1378 if(name == SIGNAL_HOVERED)
1380 actor->HoveredSignal().Connect( tracker, functor );
1382 else if(signalName == SIGNAL_WHEEL_EVENT)
1384 actor->WheelEventSignal().Connect( tracker, functor );
1386 else if(name == SIGNAL_ON_SCENE)
1388 actor->OnSceneSignal().Connect( tracker, functor );
1390 else if(name == SIGNAL_OFF_SCENE)
1392 actor->OffSceneSignal().Connect( tracker, functor );
1394 else if(name == SIGNAL_ON_RELAYOUT)
1396 actor->OnRelayoutSignal().Connect( tracker, functor );
1398 else if(name == SIGNAL_TOUCHED)
1400 actor->TouchedSignal().Connect( tracker, functor );
1402 else if(name == SIGNAL_VISIBILITY_CHANGED)
1404 actor->VisibilityChangedSignal().Connect( tracker, functor );
1406 else if(name == SIGNAL_LAYOUT_DIRECTION_CHANGED)
1408 actor->LayoutDirectionChangedSignal().Connect( tracker, functor );
1410 else if(name == SIGNAL_CHILD_ADDED)
1412 actor->ChildAddedSignal().Connect( tracker, functor );
1414 else if(name == SIGNAL_CHILD_REMOVED)
1416 actor->ChildRemovedSignal().Connect( tracker, functor );
1420 // signalName does not match any signal
1427 Actor::Actor( DerivedType derivedType, const SceneGraph::Node& node )
1431 mChildren( nullptr ),
1432 mRenderers( nullptr ),
1433 mParentOrigin( nullptr ),
1434 mAnchorPoint( nullptr ),
1435 mRelayoutData( nullptr ),
1436 mGestureData( nullptr ),
1437 mInterceptTouchedSignal(),
1440 mWheelEventSignal(),
1443 mOnRelayoutSignal(),
1444 mVisibilityChangedSignal(),
1445 mLayoutDirectionChangedSignal(),
1446 mChildAddedSignal(),
1447 mChildRemovedSignal(),
1448 mChildOrderChangedSignal(),
1449 mTargetOrientation( Quaternion::IDENTITY ),
1450 mTargetColor( Color::WHITE ),
1451 mTargetSize( Vector3::ZERO ),
1452 mTargetPosition( Vector3::ZERO ),
1453 mTargetScale( Vector3::ONE ),
1454 mAnimatedSize( Vector3::ZERO ),
1455 mTouchArea( Vector2::ZERO ),
1459 mUseAnimatedSize( AnimatedSizeFlag::CLEAR ),
1460 mIsRoot( ROOT_LAYER == derivedType ),
1461 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
1462 mIsOnScene( false ),
1464 mLeaveRequired( false ),
1465 mKeyboardFocusable( false ),
1466 mOnSceneSignalled( false ),
1467 mInsideOnSizeSet( false ),
1468 mInheritPosition( true ),
1469 mInheritOrientation( true ),
1470 mInheritScale( true ),
1471 mPositionUsesAnchorPoint( true ),
1473 mInheritLayoutDirection( true ),
1474 mCaptureAllTouchAfterStart( false ),
1475 mLayoutDirection( LayoutDirection::LEFT_TO_RIGHT ),
1476 mDrawMode( DrawMode::NORMAL ),
1477 mColorMode( Node::DEFAULT_COLOR_MODE ),
1478 mClippingMode( ClippingMode::DISABLED )
1482 void Actor::Initialize()
1486 GetEventThreadServices().RegisterObject( this );
1491 // Remove mParent pointers from children even if we're destroying core,
1492 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1495 for( const auto& actor : *mChildren )
1497 actor->SetParent( nullptr );
1503 // Guard to allow handle destruction after Core has been destroyed
1504 if( EventThreadServices::IsCoreRunning() )
1506 // Root layer will destroy its node in its own destructor
1509 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
1511 GetEventThreadServices().UnregisterObject( this );
1515 // Cleanup optional gesture data
1516 delete mGestureData;
1518 // Cleanup optional parent origin and anchor
1519 delete mParentOrigin;
1520 delete mAnchorPoint;
1522 // Delete optional relayout data
1523 delete mRelayoutData;
1526 void Actor::ConnectToScene( uint32_t parentDepth )
1528 // This container is used instead of walking the Actor hierarchy.
1529 // It protects us when the Actor hierarchy is modified during OnSceneConnectionExternal callbacks.
1530 ActorContainer connectionList;
1534 mScene->RequestRebuildDepthTree();
1537 // This stage is atomic i.e. not interrupted by user callbacks.
1538 RecursiveConnectToScene( connectionList, parentDepth + 1 );
1540 // Notify applications about the newly connected actors.
1541 for( const auto& actor : connectionList )
1543 actor->NotifyStageConnection();
1549 void Actor::RecursiveConnectToScene( ActorContainer& connectionList, uint32_t depth )
1551 DALI_ASSERT_ALWAYS( !OnScene() );
1554 mDepth = static_cast< uint16_t >( depth ); // overflow ignored, not expected in practice
1556 ConnectToSceneGraph();
1558 // Notification for internal derived classes
1559 OnSceneConnectionInternal();
1561 // This stage is atomic; avoid emitting callbacks until all Actors are connected
1562 connectionList.push_back( ActorPtr( this ) );
1564 // Recursively connect children
1567 for( const auto& actor : *mChildren )
1569 actor->SetScene( *mScene );
1570 actor->RecursiveConnectToScene( connectionList, depth + 1 );
1576 * This method is called when the Actor is connected to the Stage.
1577 * The parent must have added its Node to the scene-graph.
1578 * The child must connect its Node to the parent's Node.
1579 * This is recursive; the child calls ConnectToScene() for its children.
1581 void Actor::ConnectToSceneGraph()
1583 DALI_ASSERT_DEBUG( mParent != NULL);
1585 // Reparent Node in next Update
1586 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), mParent->GetNode(), GetNode() );
1588 // Request relayout on all actors that are added to the scenegraph
1591 // Notification for Object::Observers
1595 void Actor::NotifyStageConnection()
1597 // Actors can be removed (in a callback), before the on-stage stage is reported.
1598 // The actor may also have been reparented, in which case mOnSceneSignalled will be true.
1599 if( OnScene() && !mOnSceneSignalled )
1601 // Notification for external (CustomActor) derived classes
1602 OnSceneConnectionExternal( mDepth );
1604 if( !mOnSceneSignal.Empty() )
1606 Dali::Actor handle( this );
1607 mOnSceneSignal.Emit( handle );
1610 // Guard against Remove during callbacks
1613 mOnSceneSignalled = true; // signal required next time Actor is removed
1618 void Actor::DisconnectFromStage()
1620 // This container is used instead of walking the Actor hierachy.
1621 // It protects us when the Actor hierachy is modified during OnSceneDisconnectionExternal callbacks.
1622 ActorContainer disconnectionList;
1626 mScene->RequestRebuildDepthTree();
1629 // This stage is atomic i.e. not interrupted by user callbacks
1630 RecursiveDisconnectFromStage( disconnectionList );
1632 // Notify applications about the newly disconnected actors.
1633 for( const auto& actor : disconnectionList )
1635 actor->NotifyStageDisconnection();
1639 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
1641 // need to change state first so that internals relying on IsOnScene() inside OnSceneDisconnectionInternal() get the correct value
1644 // Recursively disconnect children
1647 for( const auto& child : *mChildren )
1649 child->RecursiveDisconnectFromStage( disconnectionList );
1653 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
1654 disconnectionList.push_back( ActorPtr( this ) );
1656 // Notification for internal derived classes
1657 OnSceneDisconnectionInternal();
1659 DisconnectFromSceneGraph();
1663 * This method is called by an actor or its parent, before a node removal message is sent.
1664 * This is recursive; the child calls DisconnectFromStage() for its children.
1666 void Actor::DisconnectFromSceneGraph()
1668 // Notification for Object::Observers
1669 OnSceneObjectRemove();
1672 void Actor::NotifyStageDisconnection()
1674 // Actors can be added (in a callback), before the off-stage state is reported.
1675 // Also if the actor was added & removed before mOnSceneSignalled was set, then we don't notify here.
1676 // only do this step if there is a stage, i.e. Core is not being shut down
1677 if ( EventThreadServices::IsCoreRunning() && !OnScene() && mOnSceneSignalled )
1679 // Notification for external (CustomeActor) derived classes
1680 OnSceneDisconnectionExternal();
1682 if( !mOffSceneSignal.Empty() )
1684 Dali::Actor handle( this );
1685 mOffSceneSignal.Emit( handle );
1688 // Guard against Add during callbacks
1691 mOnSceneSignalled = false; // signal required next time Actor is added
1696 bool Actor::IsNodeConnected() const
1698 bool connected( false );
1702 if( IsRoot() || GetNode().GetParent() )
1711 // This method initiates traversal of the actor tree using depth-first
1712 // traversal to set a depth index based on traversal order. It sends a
1713 // single message to update manager to update all the actor's nodes in
1714 // this tree with the depth index. The sceneGraphNodeDepths vector's
1715 // elements are ordered by depth, and could be used to reduce sorting
1716 // in the update thread.
1717 void Actor::RebuildDepthTree()
1719 DALI_LOG_TIMER_START(depthTimer);
1721 // Vector of scene-graph nodes and their depths to send to UpdateManager
1722 // in a single message
1723 OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths( new SceneGraph::NodeDepths() );
1725 int32_t depthIndex = 1;
1726 DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
1728 SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths );
1729 DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
1732 void Actor::DepthTraverseActorTree( OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths, int32_t& depthIndex )
1734 mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
1735 sceneGraphNodeDepths->Add( const_cast<SceneGraph::Node*>( &GetNode() ), mSortedDepth );
1737 // Create/add to children of this node
1740 for( const auto& child : *mChildren )
1742 Actor* childActor = child.Get();
1744 childActor->DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
1749 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
1751 PropertyHandler::SetDefaultProperty(*this, index, property);
1754 // TODO: This method needs to be removed
1755 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
1757 PropertyHandler::SetSceneGraphProperty(index, entry, value, GetEventThreadServices(), GetNode());
1760 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
1762 Property::Value value;
1764 if( ! GetCachedPropertyValue( index, value ) )
1766 // If property value is not stored in the event-side, then it must be a scene-graph only property
1767 GetCurrentPropertyValue( index, value );
1773 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
1775 Property::Value value;
1777 if( ! GetCurrentPropertyValue( index, value ) )
1779 // If unable to retrieve scene-graph property value, then it must be an event-side only property
1780 GetCachedPropertyValue( index, value );
1786 void Actor::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
1788 PropertyHandler::OnNotifyDefaultPropertyAnimation(*this, animation, index, value, animationType);
1791 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
1793 const PropertyBase* property = PropertyHandler::GetSceneObjectAnimatableProperty(index, GetNode());
1796 // not our property, ask base
1797 property = Object::GetSceneObjectAnimatableProperty( index );
1803 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
1805 const PropertyInputImpl* property = PropertyHandler::GetSceneObjectInputProperty(index, GetNode());
1808 // reuse animatable property getter as animatable properties are inputs as well
1809 // animatable property chains back to Object::GetSceneObjectInputProperty() so all properties get covered
1810 property = GetSceneObjectAnimatableProperty( index );
1816 int32_t Actor::GetPropertyComponentIndex( Property::Index index ) const
1818 int32_t componentIndex = PropertyHandler::GetPropertyComponentIndex(index);
1819 if( Property::INVALID_COMPONENT_INDEX == componentIndex )
1822 componentIndex = Object::GetPropertyComponentIndex( index );
1825 return componentIndex;
1828 void Actor::SetParent( Actor* parent )
1832 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
1836 mScene = parent->mScene;
1838 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1841 // Instruct each actor to create a corresponding node in the scene graph
1842 ConnectToScene( parent->GetHierarchyDepth() );
1845 // Resolve the name and index for the child properties if any
1846 ResolveChildProperties();
1848 else // parent being set to NULL
1850 DALI_ASSERT_ALWAYS( mParent != nullptr && "Actor should have a parent" );
1854 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1857 // Disconnect the Node & its children from the scene-graph.
1858 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
1860 // Instruct each actor to discard pointers to the scene-graph
1861 DisconnectFromStage();
1868 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
1871 Actor* actor = dynamic_cast< Actor* >( object );
1875 std::string_view name(actionName);
1876 if(name == ACTION_SHOW)
1878 actor->SetVisible( true );
1881 else if(name == ACTION_HIDE)
1883 actor->SetVisible( false );
1891 Rect<> Actor::CalculateScreenExtents( ) const
1893 auto screenPosition = GetCurrentScreenPosition();
1894 Vector3 size = GetCurrentSize() * GetCurrentWorldScale();
1895 Vector3 anchorPointOffSet = size * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
1896 Vector2 position = Vector2( screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y );
1897 return { position.x, position.y, size.x, size.y };
1900 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
1902 return PropertyHandler::GetCachedPropertyValue(*this, index, value);
1905 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
1907 return PropertyHandler::GetCurrentPropertyValue(*this, index, value);
1910 Actor::Relayouter& Actor::EnsureRelayouter()
1912 // Assign relayouter
1913 if( !mRelayoutData )
1915 mRelayoutData = new Relayouter();
1918 return *mRelayoutData;
1921 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
1923 // Check if actor is dependent on parent
1924 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1926 if( ( dimension & ( 1 << i ) ) )
1928 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
1929 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
1939 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
1941 // Check if actor is dependent on children
1942 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1944 if( ( dimension & ( 1 << i ) ) )
1946 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
1947 switch( resizePolicy )
1949 case ResizePolicy::FIT_TO_CHILDREN:
1950 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
1966 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
1968 return Actor::RelayoutDependentOnChildren( dimension );
1971 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
1973 // Check each possible dimension and see if it is dependent on the input one
1974 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1976 if( dimension & ( 1 << i ) )
1978 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
1985 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
1987 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1989 if( dimension & ( 1 << i ) )
1991 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
1996 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
1998 // If more than one dimension is requested, just return the first one found
1999 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2001 if( ( dimension & ( 1 << i ) ) )
2003 return mRelayoutData->negotiatedDimensions[ i ];
2007 return 0.0f; // Default
2010 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
2012 EnsureRelayouter().SetPadding( padding, dimension );
2015 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
2017 if ( mRelayoutData )
2019 // If more than one dimension is requested, just return the first one found
2020 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2022 if( ( dimension & ( 1 << i ) ) )
2024 return mRelayoutData->dimensionPadding[ i ];
2029 return Relayouter::DEFAULT_DIMENSION_PADDING;
2032 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
2034 EnsureRelayouter().SetLayoutNegotiated(negotiated, dimension);
2037 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
2039 return mRelayoutData && mRelayoutData->IsLayoutNegotiated(dimension);
2042 float Actor::GetHeightForWidthBase( float width )
2044 float height = 0.0f;
2046 const Vector3 naturalSize = GetNaturalSize();
2047 if( naturalSize.width > 0.0f )
2049 height = naturalSize.height * width / naturalSize.width;
2051 else // we treat 0 as 1:1 aspect ratio
2059 float Actor::GetWidthForHeightBase( float height )
2063 const Vector3 naturalSize = GetNaturalSize();
2064 if( naturalSize.height > 0.0f )
2066 width = naturalSize.width * height / naturalSize.height;
2068 else // we treat 0 as 1:1 aspect ratio
2076 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
2078 // Fill to parent, taking size mode factor into account
2079 switch( child.GetResizePolicy( dimension ) )
2081 case ResizePolicy::FILL_TO_PARENT:
2083 return GetLatestSize( dimension );
2086 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2088 return GetLatestSize( dimension ) * GetDimensionValue( child.GetProperty< Vector3 >( Dali::Actor::Property::SIZE_MODE_FACTOR ), dimension );
2091 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2093 return GetLatestSize( dimension ) + GetDimensionValue( child.GetProperty< Vector3 >( Dali::Actor::Property::SIZE_MODE_FACTOR ), dimension );
2098 return GetLatestSize( dimension );
2103 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
2105 // Can be overridden in derived class
2106 return CalculateChildSizeBase( child, dimension );
2109 float Actor::GetHeightForWidth( float width )
2111 // Can be overridden in derived class
2112 return GetHeightForWidthBase( width );
2115 float Actor::GetWidthForHeight( float height )
2117 // Can be overridden in derived class
2118 return GetWidthForHeightBase( height );
2121 float Actor::GetLatestSize( Dimension::Type dimension ) const
2123 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
2126 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
2128 Vector2 padding = GetPadding( dimension );
2130 return GetLatestSize( dimension ) + padding.x + padding.y;
2133 float Actor::NegotiateFromParent( Dimension::Type dimension )
2135 Actor* parent = GetParent();
2138 Vector2 padding( GetPadding( dimension ) );
2139 Vector2 parentPadding( parent->GetPadding( dimension ) );
2140 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
2146 float Actor::NegotiateFromChildren( Dimension::Type dimension )
2148 float maxDimensionPoint = 0.0f;
2150 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2152 ActorPtr child = GetChildAt( i );
2154 if( !child->RelayoutDependentOnParent( dimension ) )
2156 // Calculate the min and max points that the children range across
2157 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
2158 float dimensionSize = child->GetRelayoutSize( dimension );
2159 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
2163 return maxDimensionPoint;
2166 float Actor::GetSize( Dimension::Type dimension ) const
2168 return GetDimensionValue( mTargetSize, dimension );
2171 float Actor::GetNaturalSize( Dimension::Type dimension ) const
2173 return GetDimensionValue( GetNaturalSize(), dimension );
2176 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
2178 switch( GetResizePolicy( dimension ) )
2180 case ResizePolicy::USE_NATURAL_SIZE:
2182 return GetNaturalSize( dimension );
2185 case ResizePolicy::FIXED:
2187 return GetDimensionValue( GetPreferredSize(), dimension );
2190 case ResizePolicy::USE_ASSIGNED_SIZE:
2192 return GetDimensionValue( maximumSize, dimension );
2195 case ResizePolicy::FILL_TO_PARENT:
2196 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2197 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2199 return NegotiateFromParent( dimension );
2202 case ResizePolicy::FIT_TO_CHILDREN:
2204 return NegotiateFromChildren( dimension );
2207 case ResizePolicy::DIMENSION_DEPENDENCY:
2209 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
2212 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
2214 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
2217 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
2219 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
2231 return 0.0f; // Default
2234 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
2236 // Check if it needs to be negotiated
2237 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
2239 // Check that we havn't gotten into an infinite loop
2240 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
2241 bool recursionFound = false;
2242 for( auto& element : recursionStack )
2244 if( element == searchActor )
2246 recursionFound = true;
2251 if( !recursionFound )
2253 // Record the path that we have taken
2254 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
2256 // Dimension dependency check
2257 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2259 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
2261 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
2263 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
2267 // Parent dependency check
2268 Actor* parent = GetParent();
2269 if( parent && RelayoutDependentOnParent( dimension ) )
2271 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
2274 // Children dependency check
2275 if( RelayoutDependentOnChildren( dimension ) )
2277 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2279 ActorPtr child = GetChildAt( i );
2281 // Only relayout child first if it is not dependent on this actor
2282 if( !child->RelayoutDependentOnParent( dimension ) )
2284 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
2289 // For deriving classes
2290 OnCalculateRelayoutSize( dimension );
2292 // All dependencies checked, calculate the size and set negotiated flag
2293 const float newSize = Relayouter::ClampDimension( *this, CalculateSize( dimension, allocatedSize ), dimension );
2295 SetNegotiatedDimension( newSize, dimension );
2296 SetLayoutNegotiated( true, dimension );
2298 // For deriving classes
2299 OnLayoutNegotiated( newSize, dimension );
2301 // This actor has been successfully processed, pop it off the recursion stack
2302 recursionStack.pop_back();
2306 // TODO: Break infinite loop
2307 SetLayoutNegotiated( true, dimension );
2312 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
2314 // Negotiate all dimensions that require it
2315 ActorDimensionStack recursionStack;
2317 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2319 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
2322 NegotiateDimension( dimension, allocatedSize, recursionStack );
2326 Vector2 Actor::ApplySizeSetPolicy( const Vector2& size )
2328 return mRelayoutData->ApplySizeSetPolicy(*this, size);
2331 void Actor::SetNegotiatedSize( RelayoutContainer& container )
2333 // Do the set actor size
2334 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
2336 // Adjust for size set policy
2337 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
2339 // Lock the flag to stop recursive relayouts on set size
2340 mRelayoutData->insideRelayout = true;
2341 SetSize( negotiatedSize );
2342 mRelayoutData->insideRelayout = false;
2344 // Clear flags for all dimensions
2345 SetLayoutDirty( false );
2347 // Give deriving classes a chance to respond
2348 OnRelayout( negotiatedSize, container );
2350 if( !mOnRelayoutSignal.Empty() )
2352 Dali::Actor handle( this );
2353 mOnRelayoutSignal.Emit( handle );
2357 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
2359 // Force a size negotiation for actors that has assigned size during relayout
2360 // This is required as otherwise the flags that force a relayout will not
2361 // necessarilly be set. This will occur if the actor has already been laid out.
2362 // The dirty flags are then cleared. Then if the actor is added back into the
2363 // relayout container afterwards, the dirty flags would still be clear...
2364 // causing a relayout to be skipped. Here we force any actors added to the
2365 // container to be relayed out.
2366 DALI_LOG_TIMER_START( NegSizeTimer1 );
2368 if( GetUseAssignedSize(Dimension::WIDTH ) )
2370 SetLayoutNegotiated( false, Dimension::WIDTH );
2372 if( GetUseAssignedSize( Dimension::HEIGHT ) )
2374 SetLayoutNegotiated( false, Dimension::HEIGHT );
2377 // Do the negotiation
2378 NegotiateDimensions( allocatedSize );
2380 // Set the actor size
2381 SetNegotiatedSize( container );
2383 // Negotiate down to children
2384 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2386 ActorPtr child = GetChildAt( i );
2388 // Forces children that have already been laid out to be relayed out
2389 // if they have assigned size during relayout.
2390 if( child->GetUseAssignedSize(Dimension::WIDTH) )
2392 child->SetLayoutNegotiated(false, Dimension::WIDTH);
2393 child->SetLayoutDirty(true, Dimension::WIDTH);
2396 if( child->GetUseAssignedSize(Dimension::HEIGHT) )
2398 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
2399 child->SetLayoutDirty(true, Dimension::HEIGHT);
2402 // Only relayout if required
2403 if( child->RelayoutRequired() )
2405 container.Add( Dali::Actor( child.Get() ), mTargetSize.GetVectorXY() );
2408 DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
2411 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
2415 mRelayoutData->SetUseAssignedSize(use, dimension);
2419 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
2421 return mRelayoutData && mRelayoutData->GetUseAssignedSize(dimension);
2424 void Actor::RelayoutRequest( Dimension::Type dimension )
2426 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
2427 if( relayoutController )
2429 Dali::Actor self( this );
2430 relayoutController->RequestRelayout( self, dimension );
2434 void Actor::SetPreferredSize( const Vector2& size )
2438 // If valid width or height, then set the resize policy to FIXED
2439 // 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,
2440 // then change to FIXED as well
2442 if( size.width > 0.0f || GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DEFAULT )
2444 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
2447 if( size.height > 0.0f || GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DEFAULT )
2449 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
2452 mRelayoutData->preferredSize = size;
2454 mUseAnimatedSize = AnimatedSizeFlag::CLEAR;
2459 Vector2 Actor::GetPreferredSize() const
2461 if ( mRelayoutData )
2463 return Vector2( mRelayoutData->preferredSize );
2466 return Relayouter::DEFAULT_PREFERRED_SIZE;
2469 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
2471 EnsureRelayouter().SetMinimumSize(size, dimension);
2475 float Actor::GetMinimumSize( Dimension::Type dimension ) const
2477 if ( mRelayoutData )
2479 return mRelayoutData->GetMinimumSize(dimension);
2482 return 0.0f; // Default
2485 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
2487 EnsureRelayouter().SetMaximumSize(size, dimension);
2491 float Actor::GetMaximumSize( Dimension::Type dimension ) const
2493 if ( mRelayoutData )
2495 return mRelayoutData->GetMaximumSize(dimension);
2498 return FLT_MAX; // Default
2501 void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
2503 if( mVisible != visible )
2505 if( sendMessage == SendMessage::TRUE )
2507 // node is being used in a separate thread; queue a message to set the value & base value
2508 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible );
2510 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
2515 // Emit the signal on this actor and all its children
2516 EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
2520 void Actor::SetSiblingOrder( uint32_t order )
2524 ActorContainer& siblings = *(mParent->mChildren);
2525 uint32_t currentOrder = GetSiblingOrder();
2527 if( order != currentOrder )
2533 else if( order < siblings.size() -1 )
2535 if( order > currentOrder )
2537 RaiseAbove( *siblings[order] );
2541 LowerBelow( *siblings[order] );
2552 uint32_t Actor::GetSiblingOrder() const
2558 ActorContainer& siblings = *(mParent->mChildren);
2559 for( std::size_t i = 0; i < siblings.size(); ++i )
2561 if( siblings[i] == this )
2563 order = static_cast<uint32_t>( i );
2572 void Actor::RequestRebuildDepthTree()
2578 mScene->RequestRebuildDepthTree();
2587 ActorContainer& siblings = *(mParent->mChildren);
2588 if( siblings.back() != this ) // If not already at end
2590 for( std::size_t i=0; i<siblings.size(); ++i )
2592 if( siblings[i] == this )
2595 ActorPtr next = siblings[i+1];
2596 siblings[i+1] = this;
2603 Dali::Actor handle( this );
2604 mParent->mChildOrderChangedSignal.Emit( handle );
2606 RequestRebuildDepthTree();
2610 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2618 ActorContainer& siblings = *(mParent->mChildren);
2619 if( siblings.front() != this ) // If not already at beginning
2621 for( std::size_t i=1; i<siblings.size(); ++i )
2623 if( siblings[i] == this )
2625 // Swap with previous
2626 ActorPtr previous = siblings[i-1];
2627 siblings[i-1] = this;
2628 siblings[i] = previous;
2634 Dali::Actor handle( this );
2635 mParent->mChildOrderChangedSignal.Emit( handle );
2637 RequestRebuildDepthTree();
2641 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2645 void Actor::RaiseToTop()
2649 ActorContainer& siblings = *(mParent->mChildren);
2650 if( siblings.back() != this ) // If not already at end
2652 auto iter = std::find( siblings.begin(), siblings.end(), this );
2653 if( iter != siblings.end() )
2655 siblings.erase(iter);
2656 siblings.push_back(ActorPtr(this));
2660 Dali::Actor handle( this );
2661 mParent->mChildOrderChangedSignal.Emit( handle );
2663 RequestRebuildDepthTree();
2667 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2671 void Actor::LowerToBottom()
2675 ActorContainer& siblings = *(mParent->mChildren);
2676 if( siblings.front() != this ) // If not already at bottom,
2678 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2680 auto iter = std::find( siblings.begin(), siblings.end(), this );
2681 if( iter != siblings.end() )
2683 siblings.erase(iter);
2684 siblings.insert(siblings.begin(), thisPtr);
2688 Dali::Actor handle( this );
2689 mParent->mChildOrderChangedSignal.Emit( handle );
2691 RequestRebuildDepthTree();
2695 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2699 void Actor::RaiseAbove( Internal::Actor& target )
2703 ActorContainer& siblings = *(mParent->mChildren);
2704 if( siblings.back() != this && target.mParent == mParent ) // If not already at top
2706 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2708 auto targetIter = std::find( siblings.begin(), siblings.end(), &target );
2709 auto thisIter = std::find( siblings.begin(), siblings.end(), this );
2710 if( thisIter < targetIter )
2712 siblings.erase(thisIter);
2713 // Erasing early invalidates the targetIter. (Conversely, inserting first may also
2714 // invalidate thisIter)
2715 targetIter = std::find( siblings.begin(), siblings.end(), &target );
2717 siblings.insert(targetIter, thisPtr);
2720 Dali::Actor handle( this );
2721 mParent->mChildOrderChangedSignal.Emit( handle );
2723 RequestRebuildDepthTree();
2728 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2732 void Actor::LowerBelow( Internal::Actor& target )
2736 ActorContainer& siblings = *(mParent->mChildren);
2737 if( siblings.front() != this && target.mParent == mParent ) // If not already at bottom
2739 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2741 auto targetIter = std::find( siblings.begin(), siblings.end(), &target );
2742 auto thisIter = std::find( siblings.begin(), siblings.end(), this );
2744 if( thisIter > targetIter )
2746 siblings.erase(thisIter); // this only invalidates iterators at or after this point.
2747 siblings.insert(targetIter, thisPtr);
2750 Dali::Actor handle( this );
2751 mParent->mChildOrderChangedSignal.Emit( handle );
2753 RequestRebuildDepthTree();
2758 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2762 void Actor::SetInheritLayoutDirection( bool inherit )
2764 if( mInheritLayoutDirection != inherit )
2766 mInheritLayoutDirection = inherit;
2768 if( inherit && mParent )
2770 InheritLayoutDirectionRecursively( this, mParent->mLayoutDirection );
2775 void Actor::InheritLayoutDirectionRecursively( ActorPtr actor, Dali::LayoutDirection::Type direction, bool set )
2777 if( actor && ( actor->mInheritLayoutDirection || set ) )
2779 if( actor->mLayoutDirection != direction )
2781 actor->mLayoutDirection = direction;
2782 actor->EmitLayoutDirectionChangedSignal( direction );
2783 actor->RelayoutRequest();
2786 if( actor->GetChildCount() > 0 )
2788 for( const auto& child : actor->GetChildrenInternal() )
2790 InheritLayoutDirectionRecursively( child, direction );
2796 void Actor::SetUpdateSizeHint( const Vector2& updateSizeHint )
2798 // node is being used in a separate thread; queue a message to set the value & base value
2799 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mUpdateSizeHint, &AnimatableProperty<Vector3>::Bake, Vector3(updateSizeHint.width, updateSizeHint.height, 0.f ) );
2802 } // namespace Internal