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/common/capabilities.h>
35 #include <dali/devel-api/actors/actor-devel.h>
36 #include <dali/internal/event/events/actor-gesture-data.h>
37 #include <dali/internal/event/actors/actor-property-handler.h>
38 #include <dali/internal/event/actors/actor-relayouter.h>
39 #include <dali/internal/event/actors/actor-siblings.h>
40 #include <dali/internal/event/actors/camera-actor-impl.h>
41 #include <dali/internal/event/common/event-thread-services.h>
42 #include <dali/internal/event/common/projection.h>
43 #include <dali/internal/event/common/property-helper.h>
44 #include <dali/internal/event/common/scene-impl.h>
45 #include <dali/internal/event/common/stage-impl.h>
46 #include <dali/internal/event/common/thread-local-storage.h>
47 #include <dali/internal/event/common/type-info-impl.h>
48 #include <dali/internal/event/render-tasks/render-task-impl.h>
49 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
50 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
51 #include <dali/internal/update/nodes/node-messages.h>
52 #include <dali/integration-api/debug.h>
54 using Dali::Internal::SceneGraph::Node;
55 using Dali::Internal::SceneGraph::AnimatableProperty;
56 using Dali::Internal::SceneGraph::PropertyBase;
58 #if defined(DEBUG_ENABLED)
59 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_DEPTH_TIMER" );
60 Debug::Filter* gLogRelayoutFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_TIMER" );
69 namespace // unnamed namespace
75 * We want to discourage the use of property strings (minimize string comparisons),
76 * particularly for the default properties.
77 * Name Type writable animatable constraint-input enum for index-checking
79 DALI_PROPERTY_TABLE_BEGIN
80 DALI_PROPERTY( "parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
81 DALI_PROPERTY( "parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
82 DALI_PROPERTY( "parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
83 DALI_PROPERTY( "parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
84 DALI_PROPERTY( "anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
85 DALI_PROPERTY( "anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
86 DALI_PROPERTY( "anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
87 DALI_PROPERTY( "anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
88 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
89 DALI_PROPERTY( "sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
90 DALI_PROPERTY( "sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
91 DALI_PROPERTY( "sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
92 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
93 DALI_PROPERTY( "positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
94 DALI_PROPERTY( "positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
95 DALI_PROPERTY( "positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
96 DALI_PROPERTY( "worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
97 DALI_PROPERTY( "worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
98 DALI_PROPERTY( "worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
99 DALI_PROPERTY( "worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
100 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
101 DALI_PROPERTY( "worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
102 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
103 DALI_PROPERTY( "scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
104 DALI_PROPERTY( "scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
105 DALI_PROPERTY( "scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
106 DALI_PROPERTY( "worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
107 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
108 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
109 DALI_PROPERTY( "colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
110 DALI_PROPERTY( "colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
111 DALI_PROPERTY( "colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
112 DALI_PROPERTY( "colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
113 DALI_PROPERTY( "worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
114 DALI_PROPERTY( "worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
115 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
116 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
117 DALI_PROPERTY( "leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
118 DALI_PROPERTY( "inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
119 DALI_PROPERTY( "inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
120 DALI_PROPERTY( "colorMode", INTEGER, true, false, false, Dali::Actor::Property::COLOR_MODE )
121 DALI_PROPERTY( "drawMode", INTEGER, true, false, false, Dali::Actor::Property::DRAW_MODE )
122 DALI_PROPERTY( "sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
123 DALI_PROPERTY( "widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
124 DALI_PROPERTY( "heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
125 DALI_PROPERTY( "sizeScalePolicy", INTEGER, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
126 DALI_PROPERTY( "widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
127 DALI_PROPERTY( "heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
128 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
129 DALI_PROPERTY( "minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
130 DALI_PROPERTY( "maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
131 DALI_PROPERTY( "inheritPosition", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_POSITION )
132 DALI_PROPERTY( "clippingMode", STRING, true, false, false, Dali::Actor::Property::CLIPPING_MODE )
133 DALI_PROPERTY( "layoutDirection", STRING, true, false, false, Dali::Actor::Property::LAYOUT_DIRECTION )
134 DALI_PROPERTY( "inheritLayoutDirection", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION )
135 DALI_PROPERTY( "opacity", FLOAT, true, true, true, Dali::Actor::Property::OPACITY )
136 DALI_PROPERTY( "screenPosition", VECTOR2, false, false, false, Dali::Actor::Property::SCREEN_POSITION )
137 DALI_PROPERTY( "positionUsesAnchorPoint", BOOLEAN, true, false, false, Dali::Actor::Property::POSITION_USES_ANCHOR_POINT )
138 DALI_PROPERTY( "culled", BOOLEAN, false, false, true, Dali::Actor::Property::CULLED )
139 DALI_PROPERTY( "id", INTEGER, false, false, false, Dali::Actor::Property::ID )
140 DALI_PROPERTY( "hierarchyDepth", INTEGER, false, false, false, Dali::Actor::Property::HIERARCHY_DEPTH )
141 DALI_PROPERTY( "isRoot", BOOLEAN, false, false, false, Dali::Actor::Property::IS_ROOT )
142 DALI_PROPERTY( "isLayer", BOOLEAN, false, false, false, Dali::Actor::Property::IS_LAYER )
143 DALI_PROPERTY( "connectedToScene", BOOLEAN, false, false, false, Dali::Actor::Property::CONNECTED_TO_SCENE )
144 DALI_PROPERTY( "keyboardFocusable", BOOLEAN, true, false, false, Dali::Actor::Property::KEYBOARD_FOCUSABLE )
145 DALI_PROPERTY( "siblingOrder", INTEGER, true, false, false, Dali::DevelActor::Property::SIBLING_ORDER )
146 DALI_PROPERTY( "updateSizeHint", VECTOR2, true, false, false, Dali::DevelActor::Property::UPDATE_SIZE_HINT )
147 DALI_PROPERTY( "captureAllTouchAfterStart", BOOLEAN, true, false, false, Dali::DevelActor::Property::CAPTURE_ALL_TOUCH_AFTER_START )
148 DALI_PROPERTY( "touchArea", VECTOR2, true, false, false, Dali::DevelActor::Property::TOUCH_AREA )
149 DALI_PROPERTY( "blendEquation", INTEGER, true, false, false, Dali::DevelActor::Property::BLEND_EQUATION )
150 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperties )
154 static constexpr std::string_view SIGNAL_HOVERED = "hovered";
155 static constexpr std::string_view SIGNAL_WHEEL_EVENT = "wheelEvent";
156 static constexpr std::string_view SIGNAL_ON_SCENE = "onScene";
157 static constexpr std::string_view SIGNAL_OFF_SCENE = "offScene";
158 static constexpr std::string_view SIGNAL_ON_RELAYOUT = "onRelayout";
159 static constexpr std::string_view SIGNAL_TOUCHED = "touched";
160 static constexpr std::string_view SIGNAL_VISIBILITY_CHANGED = "visibilityChanged";
161 static constexpr std::string_view SIGNAL_LAYOUT_DIRECTION_CHANGED = "layoutDirectionChanged";
162 static constexpr std::string_view SIGNAL_CHILD_ADDED = "childAdded";
163 static constexpr std::string_view SIGNAL_CHILD_REMOVED = "childRemoved";
167 static constexpr std::string_view ACTION_SHOW = "show";
168 static constexpr std::string_view ACTION_HIDE = "hide";
170 BaseHandle CreateActor()
172 return Dali::Actor::New();
175 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor, ActorDefaultProperties );
177 SignalConnectorType signalConnector2(mType, std::string(SIGNAL_HOVERED), &Actor::DoConnectSignal);
178 SignalConnectorType signalConnector3(mType, std::string(SIGNAL_WHEEL_EVENT), &Actor::DoConnectSignal);
179 SignalConnectorType signalConnector4(mType, std::string(SIGNAL_ON_SCENE), &Actor::DoConnectSignal);
180 SignalConnectorType signalConnector5(mType, std::string(SIGNAL_OFF_SCENE), &Actor::DoConnectSignal);
181 SignalConnectorType signalConnector6(mType, std::string(SIGNAL_ON_RELAYOUT), &Actor::DoConnectSignal);
182 SignalConnectorType signalConnector7(mType, std::string(SIGNAL_TOUCHED), &Actor::DoConnectSignal);
183 SignalConnectorType signalConnector8(mType, std::string(SIGNAL_VISIBILITY_CHANGED), &Actor::DoConnectSignal);
184 SignalConnectorType signalConnector9(mType, std::string(SIGNAL_LAYOUT_DIRECTION_CHANGED), &Actor::DoConnectSignal);
185 SignalConnectorType signalConnector10(mType, std::string(SIGNAL_CHILD_ADDED), &Actor::DoConnectSignal);
186 SignalConnectorType signalConnector11(mType, std::string(SIGNAL_CHILD_REMOVED), &Actor::DoConnectSignal);
188 TypeAction a1(mType, std::string(ACTION_SHOW), &Actor::DoAction);
189 TypeAction a2(mType, std::string(ACTION_HIDE), &Actor::DoAction);
192 * @brief Extract a given dimension from a Vector2
194 * @param[in] values The values to extract from
195 * @param[in] dimension The dimension to extract
196 * @return Return the value for the dimension
198 constexpr float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
202 case Dimension::WIDTH:
206 case Dimension::HEIGHT:
208 return values.height;
219 * @brief Extract a given dimension from a Vector3
221 * @param[in] values The values to extract from
222 * @param[in] dimension The dimension to extract
223 * @return Return the value for the dimension
225 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
227 return GetDimensionValue( values.GetVectorXY(), dimension );
231 * @brief Recursively emits the visibility-changed-signal on the actor tree.
232 * @param[in] actor The actor to emit the signal on
233 * @param[in] visible The new visibility of the actor
234 * @param[in] type Whether the actor's visible property has changed or a parent's
236 void EmitVisibilityChangedSignalRecursively( ActorPtr actor, bool visible, DevelActor::VisibilityChange::Type type )
240 actor->EmitVisibilityChangedSignal( visible, type );
242 if( actor->GetChildCount() > 0 )
244 for( auto& child : actor->GetChildrenInternal() )
246 EmitVisibilityChangedSignalRecursively( child, visible, DevelActor::VisibilityChange::PARENT );
252 /// Helper for emitting a signal
253 template<typename Signal, typename Event>
254 bool EmitConsumingSignal( Actor& actor, Signal& signal, const Event& event )
256 bool consumed = false;
258 if( !signal.Empty() )
260 Dali::Actor handle( &actor );
261 consumed = signal.Emit( handle, event );
267 /// Helper for emitting signals with multiple parameters
268 template<typename Signal, typename... Param>
269 void EmitSignal( Actor& actor, Signal& signal, Param... params)
271 if( !signal.Empty() )
273 Dali::Actor handle( &actor );
274 signal.Emit( handle, params... );
278 bool ScreenToLocalInternal(
279 const Matrix& viewMatrix,
280 const Matrix& projectionMatrix,
281 const Matrix& worldMatrix,
282 const Viewport& viewport,
283 const Vector3& currentSize,
289 // Get the ModelView matrix
291 Matrix::Multiply( modelView, worldMatrix, viewMatrix );
293 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
294 Matrix invertedMvp( false/*don't init*/);
295 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
296 bool success = invertedMvp.Invert();
298 // Convert to GL coordinates
299 Vector4 screenPos( screenX - static_cast<float>( viewport.x ), static_cast<float>( viewport.height ) - screenY - static_cast<float>( viewport.y ), 0.f, 1.f );
304 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), nearPos );
311 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), farPos );
317 if( XyPlaneIntersect( nearPos, farPos, local ) )
319 Vector3 size = currentSize;
320 localX = local.x + size.x * 0.5f;
321 localY = local.y + size.y * 0.5f;
332 } // unnamed namespace
334 ActorPtr Actor::New()
336 // pass a reference to actor, actor does not own its node
337 ActorPtr actor( new Actor( BASIC, *CreateNode() ) );
339 // Second-phase construction
345 const SceneGraph::Node* Actor::CreateNode()
347 // create node. Nodes are owned by the update manager
348 SceneGraph::Node* node = SceneGraph::Node::New();
349 OwnerPointer< SceneGraph::Node > transferOwnership( node );
350 Internal::ThreadLocalStorage* tls = Internal::ThreadLocalStorage::GetInternal();
352 DALI_ASSERT_ALWAYS( tls && "ThreadLocalStorage is null" );
354 AddNodeMessage( tls->GetUpdateManager(), transferOwnership );
359 void Actor::SetName( const std::string& name )
363 // ATTENTION: string for debug purposes is not thread safe.
364 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( &GetNode() ), name );
367 uint32_t Actor::GetId() const
369 return GetNode().GetId();
372 Dali::Layer Actor::GetLayer()
376 // Short-circuit for Layer derived actors
379 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
382 // Find the immediate Layer parent
383 for( Actor* parent = mParent; !layer && parent != nullptr; parent = parent->GetParent() )
385 if( parent->IsLayer() )
387 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
394 void Actor::Add( Actor& child )
396 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
397 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
401 mChildren = new ActorContainer;
404 Actor* const oldParent( child.mParent );
406 // child might already be ours
407 if( this != oldParent )
409 // if we already have parent, unparent us first
412 oldParent->Remove( child ); // This causes OnChildRemove callback & ChildRemoved signal
414 // Old parent may need to readjust to missing child
415 if( oldParent->RelayoutDependentOnChildren() )
417 oldParent->RelayoutRequest();
421 // Guard against Add() during previous OnChildRemove callback
424 // Do this first, since user callbacks from within SetParent() may need to remove child
425 mChildren->push_back( ActorPtr( &child ) );
427 // SetParent asserts that child can be added
428 child.SetParent( this );
430 // Notification for derived classes
432 EmitChildAddedSignal( child );
434 InheritLayoutDirectionRecursively( ActorPtr( &child ), mLayoutDirection );
436 // Only put in a relayout request if there is a suitable dependency
437 if( RelayoutDependentOnChildren() )
445 void Actor::Remove( Actor& child )
447 if( (this == &child) || (!mChildren) )
449 // no children or removing itself
455 // Find the child in mChildren, and unparent it
456 ActorIter end = mChildren->end();
457 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
459 ActorPtr actor = (*iter);
461 if( actor.Get() == &child )
463 // Keep handle for OnChildRemove notification
466 // Do this first, since user callbacks from within SetParent() may need to add the child
467 mChildren->erase( iter );
469 DALI_ASSERT_DEBUG( actor->GetParent() == this );
470 actor->SetParent( nullptr );
478 // Only put in a relayout request if there is a suitable dependency
479 if( RelayoutDependentOnChildren() )
485 // Notification for derived classes
486 OnChildRemove( child );
487 EmitChildRemovedSignal( child );
490 void Actor::Unparent()
494 // Remove this actor from the parent. The remove will put a relayout request in for
495 // the parent if required
496 mParent->Remove( *this );
497 // mParent is now NULL!
501 uint32_t Actor::GetChildCount() const
503 return ( nullptr != mChildren ) ? static_cast<uint32_t>( mChildren->size() ) : 0; // only 4,294,967,295 children per actor
506 ActorPtr Actor::GetChildAt( uint32_t index ) const
508 DALI_ASSERT_ALWAYS( index < GetChildCount() );
510 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
513 ActorPtr Actor::FindChildByName( const std::string& actorName )
515 ActorPtr child = nullptr;
516 if( actorName == mName )
522 for( const auto& actor : *mChildren )
524 child = actor->FindChildByName( actorName );
535 ActorPtr Actor::FindChildById( const uint32_t id )
537 ActorPtr child = nullptr;
544 for( const auto& actor : *mChildren )
546 child = actor->FindChildById( id );
557 void Actor::SetParentOrigin( const Vector3& origin )
559 // node is being used in a separate thread; queue a message to set the value & base value
560 SetParentOriginMessage( GetEventThreadServices(), GetNode(), origin );
562 // Cache for event-thread access
565 // not allocated, check if different from default
566 if( ParentOrigin::DEFAULT != origin )
568 mParentOrigin = new Vector3( origin );
573 // check if different from current costs more than just set
574 *mParentOrigin = origin;
578 const Vector3& Actor::GetCurrentParentOrigin() const
580 // Cached for event-thread access
581 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
584 void Actor::SetAnchorPoint( const Vector3& anchor )
586 // node is being used in a separate thread; queue a message to set the value & base value
587 SetAnchorPointMessage( GetEventThreadServices(), GetNode(), anchor );
589 // Cache for event-thread access
592 // not allocated, check if different from default
593 if( AnchorPoint::DEFAULT != anchor )
595 mAnchorPoint = new Vector3( anchor );
600 // check if different from current costs more than just set
601 *mAnchorPoint = anchor;
605 const Vector3& Actor::GetCurrentAnchorPoint() const
607 // Cached for event-thread access
608 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
611 void Actor::SetPosition( float x, float y )
613 SetPosition( Vector3( x, y, 0.0f ) );
616 void Actor::SetPosition( float x, float y, float z )
618 SetPosition( Vector3( x, y, z ) );
621 void Actor::SetPosition( const Vector3& position )
623 mTargetPosition = position;
625 // node is being used in a separate thread; queue a message to set the value & base value
626 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
629 void Actor::SetX( float x )
631 mTargetPosition.x = x;
633 // node is being used in a separate thread; queue a message to set the value & base value
634 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
637 void Actor::SetY( float y )
639 mTargetPosition.y = y;
641 // node is being used in a separate thread; queue a message to set the value & base value
642 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
645 void Actor::SetZ( float z )
647 mTargetPosition.z = z;
649 // node is being used in a separate thread; queue a message to set the value & base value
650 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
653 void Actor::TranslateBy( const Vector3& distance )
655 mTargetPosition += distance;
657 // node is being used in a separate thread; queue a message to set the value & base value
658 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
661 const Vector3& Actor::GetCurrentPosition() const
663 // node is being used in a separate thread; copy the value from the previous update
664 return GetNode().GetPosition(GetEventThreadServices().GetEventBufferIndex());
667 const Vector3& Actor::GetCurrentWorldPosition() const
669 // node is being used in a separate thread; copy the value from the previous update
670 return GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
673 const Vector2 Actor::GetCurrentScreenPosition() const
675 if( mScene && OnScene() )
677 Vector3 worldPosition = GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
678 Vector3 cameraPosition = mScene->GetDefaultCameraActor().GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
679 worldPosition -= cameraPosition;
681 Vector3 actorSize = GetCurrentSize() * GetCurrentWorldScale();
682 Vector2 halfSceneSize( mScene->GetSize() * 0.5f ); // World position origin is center of scene
683 Vector3 halfActorSize( actorSize * 0.5f );
684 Vector3 anchorPointOffSet = halfActorSize - actorSize * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
686 return Vector2( halfSceneSize.width + worldPosition.x - anchorPointOffSet.x,
687 halfSceneSize.height + worldPosition.y - anchorPointOffSet.y );
690 return Vector2::ZERO;
693 void Actor::SetInheritPosition( bool inherit )
695 if( mInheritPosition != inherit )
697 // non animatable so keep local copy
698 mInheritPosition = inherit;
699 SetInheritPositionMessage( GetEventThreadServices(), GetNode(), inherit );
703 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
705 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
706 normalizedAxis.Normalize();
708 Quaternion orientation( angle, normalizedAxis );
710 SetOrientation( orientation );
713 void Actor::SetOrientation( const Quaternion& orientation )
715 mTargetOrientation = orientation;
717 // node is being used in a separate thread; queue a message to set the value & base value
718 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation );
721 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
723 RotateBy( Quaternion(angle, axis) );
726 void Actor::RotateBy( const Quaternion& relativeRotation )
728 mTargetOrientation *= Quaternion( relativeRotation );
730 // node is being used in a separate thread; queue a message to set the value & base value
731 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
734 const Quaternion& Actor::GetCurrentOrientation() const
736 // node is being used in a separate thread; copy the value from the previous update
737 return GetNode().GetOrientation(GetEventThreadServices().GetEventBufferIndex());
740 const Quaternion& Actor::GetCurrentWorldOrientation() const
742 // node is being used in a separate thread; copy the value from the previous update
743 return GetNode().GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
746 void Actor::SetScale( float scale )
748 SetScale( Vector3( scale, scale, scale ) );
751 void Actor::SetScale( float x, float y, float z )
753 SetScale( Vector3( x, y, z ) );
756 void Actor::SetScale( const Vector3& scale )
758 mTargetScale = scale;
760 // node is being used in a separate thread; queue a message to set the value & base value
761 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
764 void Actor::SetScaleX( float x )
768 // node is being used in a separate thread; queue a message to set the value & base value
769 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
772 void Actor::SetScaleY( float y )
776 // node is being used in a separate thread; queue a message to set the value & base value
777 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
780 void Actor::SetScaleZ( float z )
784 // node is being used in a separate thread; queue a message to set the value & base value
785 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
788 void Actor::ScaleBy(const Vector3& relativeScale)
790 mTargetScale *= relativeScale;
792 // node is being used in a separate thread; queue a message to set the value & base value
793 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
796 const Vector3& Actor::GetCurrentScale() const
798 // node is being used in a separate thread; copy the value from the previous update
799 return GetNode().GetScale(GetEventThreadServices().GetEventBufferIndex());
802 const Vector3& Actor::GetCurrentWorldScale() const
804 // node is being used in a separate thread; copy the value from the previous update
805 return GetNode().GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
808 void Actor::SetInheritScale( bool inherit )
810 if( mInheritScale != inherit )
812 // non animatable so keep local copy
813 mInheritScale = inherit;
814 // node is being used in a separate thread; queue a message to set the value
815 SetInheritScaleMessage( GetEventThreadServices(), GetNode(), inherit );
819 Matrix Actor::GetCurrentWorldMatrix() const
821 return GetNode().GetWorldMatrix(0);
824 void Actor::SetVisible( bool visible )
826 SetVisibleInternal( visible, SendMessage::TRUE );
829 bool Actor::IsVisible() const
831 // node is being used in a separate thread; copy the value from the previous update
832 return GetNode().IsVisible( GetEventThreadServices().GetEventBufferIndex() );
835 void Actor::SetOpacity( float opacity )
837 mTargetColor.a = opacity;
839 // node is being used in a separate thread; queue a message to set the value & base value
840 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
842 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
845 float Actor::GetCurrentOpacity() const
847 // node is being used in a separate thread; copy the value from the previous update
848 return GetNode().GetOpacity(GetEventThreadServices().GetEventBufferIndex());
851 const Vector4& Actor::GetCurrentWorldColor() const
853 return GetNode().GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
856 void Actor::SetColor( const Vector4& color )
858 mTargetColor = color;
860 // node is being used in a separate thread; queue a message to set the value & base value
861 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::Bake, color );
863 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
866 void Actor::SetColorRed( float red )
868 mTargetColor.r = red;
870 // node is being used in a separate thread; queue a message to set the value & base value
871 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeX, red );
873 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
876 void Actor::SetColorGreen( float green )
878 mTargetColor.g = green;
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>::BakeY, green );
883 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
886 void Actor::SetColorBlue( float blue )
888 mTargetColor.b = blue;
890 // node is being used in a separate thread; queue a message to set the value & base value
891 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
893 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
896 const Vector4& Actor::GetCurrentColor() const
898 // node is being used in a separate thread; copy the value from the previous update
899 return GetNode().GetColor(GetEventThreadServices().GetEventBufferIndex());
902 void Actor::SetInheritOrientation( bool inherit )
904 if( mInheritOrientation != inherit )
906 // non animatable so keep local copy
907 mInheritOrientation = inherit;
908 // node is being used in a separate thread; queue a message to set the value
909 SetInheritOrientationMessage( GetEventThreadServices(), GetNode(), inherit );
913 void Actor::SetSizeModeFactor( const Vector3& factor )
917 mRelayoutData->sizeModeFactor = factor;
920 const Vector3& Actor::GetSizeModeFactor() const
924 return mRelayoutData->sizeModeFactor;
927 return Relayouter::DEFAULT_SIZE_MODE_FACTOR;
930 void Actor::SetColorMode( ColorMode colorMode )
932 // non animatable so keep local copy
933 mColorMode = colorMode;
934 // node is being used in a separate thread; queue a message to set the value
935 SetColorModeMessage( GetEventThreadServices(), GetNode(), colorMode );
938 void Actor::SetSize( float width, float height )
940 SetSize( Vector2( width, height ) );
943 void Actor::SetSize( float width, float height, float depth )
945 SetSize( Vector3( width, height, depth ) );
948 void Actor::SetSize( const Vector2& size )
950 SetSize( Vector3( size.width, size.height, 0.f ) );
953 void Actor::SetSizeInternal( const Vector2& size )
955 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
958 void Actor::SetSize( const Vector3& size )
960 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
962 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
963 SetPreferredSize( size.GetVectorXY() );
967 SetSizeInternal( size );
971 void Actor::SetSizeInternal( const Vector3& size )
973 // dont allow recursive loop
974 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
975 // 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
976 if( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
977 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
978 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) )
982 // node is being used in a separate thread; queue a message to set the value & base value
983 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
985 // Notification for derived classes
986 mInsideOnSizeSet = true;
987 OnSizeSet( mTargetSize );
988 mInsideOnSizeSet = false;
990 // Raise a relayout request if the flag is not locked
991 if( mRelayoutData && !mRelayoutData->insideRelayout )
998 void Actor::SetWidth( float width )
1000 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1002 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
1003 mRelayoutData->preferredSize.width = width;
1007 mTargetSize.width = width;
1009 // node is being used in a separate thread; queue a message to set the value & base value
1010 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1013 mUseAnimatedSize &= ~AnimatedSizeFlag::WIDTH;
1018 void Actor::SetHeight( float height )
1020 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1022 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
1023 mRelayoutData->preferredSize.height = height;
1027 mTargetSize.height = height;
1029 // node is being used in a separate thread; queue a message to set the value & base value
1030 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1033 mUseAnimatedSize &= ~AnimatedSizeFlag::HEIGHT;
1038 void Actor::SetDepth( float depth )
1040 mTargetSize.depth = depth;
1042 mUseAnimatedSize &= ~AnimatedSizeFlag::DEPTH;
1044 // node is being used in a separate thread; queue a message to set the value & base value
1045 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1048 Vector3 Actor::GetTargetSize() const
1050 Vector3 size = mTargetSize;
1052 if( mUseAnimatedSize & AnimatedSizeFlag::WIDTH )
1054 // Should return animated size if size is animated
1055 size.width = mAnimatedSize.width;
1059 // Should return preferred size if size is fixed as set by SetSize
1060 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
1062 size.width = GetPreferredSize().width;
1066 if( mUseAnimatedSize & AnimatedSizeFlag::HEIGHT )
1068 size.height = mAnimatedSize.height;
1072 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
1074 size.height = GetPreferredSize().height;
1078 if( mUseAnimatedSize & AnimatedSizeFlag::DEPTH )
1080 size.depth = mAnimatedSize.depth;
1086 const Vector3& Actor::GetCurrentSize() const
1088 // node is being used in a separate thread; copy the value from the previous update
1089 return GetNode().GetSize( GetEventThreadServices().GetEventBufferIndex() );
1092 Vector3 Actor::GetNaturalSize() const
1094 // It is up to deriving classes to return the appropriate natural size
1095 return Vector3( 0.0f, 0.0f, 0.0f );
1098 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1100 EnsureRelayouter().SetResizePolicy(policy, dimension, mTargetSize);
1102 OnSetResizePolicy( policy, dimension );
1104 // Trigger relayout on this control
1108 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1110 if ( mRelayoutData )
1112 return mRelayoutData->GetResizePolicy(dimension);
1115 return ResizePolicy::DEFAULT;
1118 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1122 mRelayoutData->sizeSetPolicy = policy;
1124 // Trigger relayout on this control
1128 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1130 if ( mRelayoutData )
1132 return mRelayoutData->sizeSetPolicy;
1135 return Relayouter::DEFAULT_SIZE_SCALE_POLICY;
1138 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1140 EnsureRelayouter().SetDimensionDependency(dimension, dependency);
1143 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1145 if ( mRelayoutData )
1147 return mRelayoutData->GetDimensionDependency(dimension);
1150 return Dimension::ALL_DIMENSIONS; // Default
1153 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1155 // If relayout data has not been allocated yet and the client is requesting
1156 // to disable it, do nothing
1157 if( mRelayoutData || relayoutEnabled )
1161 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1163 mRelayoutData->relayoutEnabled = relayoutEnabled;
1167 bool Actor::IsRelayoutEnabled() const
1169 // Assume that if relayout data has not been allocated yet then
1170 // relayout is disabled
1171 return mRelayoutData && mRelayoutData->relayoutEnabled;
1174 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1176 EnsureRelayouter().SetLayoutDirty(dirty, dimension);
1179 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1181 return mRelayoutData && mRelayoutData->IsLayoutDirty(dimension);
1184 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1186 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1189 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1191 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1194 uint32_t Actor::AddRenderer( Renderer& renderer )
1198 mRenderers = new RendererContainer;
1201 if(mIsBlendEquationSet)
1203 renderer.SetBlendEquation(static_cast<DevelBlendEquation::Type>(mBlendEquation));
1206 uint32_t index = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1207 RendererPtr rendererPtr = RendererPtr( &renderer );
1208 mRenderers->push_back( rendererPtr );
1209 AttachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1213 uint32_t Actor::GetRendererCount() const
1215 uint32_t rendererCount(0);
1218 rendererCount = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1221 return rendererCount;
1224 RendererPtr Actor::GetRendererAt( uint32_t index )
1226 RendererPtr renderer;
1227 if( index < GetRendererCount() )
1229 renderer = ( *mRenderers )[ index ];
1235 void Actor::RemoveRenderer( Renderer& renderer )
1239 RendererIter end = mRenderers->end();
1240 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1242 if( (*iter).Get() == &renderer )
1244 mRenderers->erase( iter );
1245 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1252 void Actor::RemoveRenderer( uint32_t index )
1254 if( index < GetRendererCount() )
1256 RendererPtr renderer = ( *mRenderers )[ index ];
1257 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.Get()->GetRendererSceneObject() );
1258 mRenderers->erase( mRenderers->begin()+index );
1262 void Actor::SetBlendEquation(DevelBlendEquation::Type blendEquation)
1264 if(Dali::Capabilities::IsBlendEquationSupported(blendEquation))
1266 if(mBlendEquation != blendEquation)
1268 mBlendEquation = blendEquation;
1269 uint32_t rendererCount = GetRendererCount();
1270 for(uint32_t i = 0; i < rendererCount; ++i)
1272 RendererPtr renderer = GetRendererAt(i);
1273 renderer->SetBlendEquation(static_cast<DevelBlendEquation::Type>(blendEquation));
1276 mIsBlendEquationSet = true;
1280 DALI_LOG_ERROR("Invalid blend equation is entered.\n");
1284 DevelBlendEquation::Type Actor::GetBlendEquation() const
1286 return mBlendEquation;
1289 void Actor::SetDrawMode( DrawMode::Type drawMode )
1291 // this flag is not animatable so keep the value
1292 mDrawMode = drawMode;
1294 // node is being used in a separate thread; queue a message to set the value
1295 SetDrawModeMessage( GetEventThreadServices(), GetNode(), drawMode );
1298 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1300 // only valid when on-stage
1301 if( mScene && OnScene() )
1303 const RenderTaskList& taskList = mScene->GetRenderTaskList();
1305 Vector2 converted( screenX, screenY );
1307 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1308 uint32_t taskCount = taskList.GetTaskCount();
1309 for( uint32_t i = taskCount; i > 0; --i )
1311 RenderTaskPtr task = taskList.GetTask( i - 1 );
1312 if( ScreenToLocal( *task, localX, localY, screenX, screenY ) )
1314 // found a task where this conversion was ok so return
1322 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1324 bool retval = false;
1325 // only valid when on-stage
1328 CameraActor* camera = renderTask.GetCameraActor();
1332 renderTask.GetViewport( viewport );
1334 // need to translate coordinates to render tasks coordinate space
1335 Vector2 converted( screenX, screenY );
1336 if( renderTask.TranslateCoordinates( converted ) )
1338 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1345 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1347 return OnScene() && ScreenToLocalInternal(viewMatrix, projectionMatrix, GetNode().GetWorldMatrix(0), viewport, GetCurrentSize(), localX, localY, screenX, screenY);
1350 ActorGestureData& Actor::GetGestureData()
1352 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1353 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1354 if( nullptr == mGestureData )
1356 mGestureData = new ActorGestureData;
1358 return *mGestureData;
1361 bool Actor::IsGestureRequired( GestureType::Value type ) const
1363 return mGestureData && mGestureData->IsGestureRequired( type );
1366 bool Actor::EmitInterceptTouchEventSignal( const Dali::TouchEvent& touch )
1368 return EmitConsumingSignal( *this, mInterceptTouchedSignal, touch );
1371 bool Actor::EmitTouchEventSignal( const Dali::TouchEvent& touch )
1373 return EmitConsumingSignal( *this, mTouchedSignal, touch );
1376 bool Actor::EmitHoverEventSignal( const Dali::HoverEvent& event )
1378 return EmitConsumingSignal( *this, mHoveredSignal, event );
1381 bool Actor::EmitWheelEventSignal( const Dali::WheelEvent& event )
1383 return EmitConsumingSignal( *this, mWheelEventSignal, event );
1386 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
1388 EmitSignal( *this, mVisibilityChangedSignal, visible, type );
1391 void Actor::EmitLayoutDirectionChangedSignal( LayoutDirection::Type type )
1393 EmitSignal( *this, mLayoutDirectionChangedSignal, type );
1396 void Actor::EmitChildAddedSignal( Actor& child )
1398 EmitSignal( child, mChildAddedSignal );
1401 void Actor::EmitChildRemovedSignal( Actor& child )
1403 EmitSignal( child, mChildRemovedSignal );
1406 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1408 bool connected( true );
1409 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
1411 std::string_view name(signalName);
1413 if(name == SIGNAL_HOVERED)
1415 actor->HoveredSignal().Connect( tracker, functor );
1417 else if(signalName == SIGNAL_WHEEL_EVENT)
1419 actor->WheelEventSignal().Connect( tracker, functor );
1421 else if(name == SIGNAL_ON_SCENE)
1423 actor->OnSceneSignal().Connect( tracker, functor );
1425 else if(name == SIGNAL_OFF_SCENE)
1427 actor->OffSceneSignal().Connect( tracker, functor );
1429 else if(name == SIGNAL_ON_RELAYOUT)
1431 actor->OnRelayoutSignal().Connect( tracker, functor );
1433 else if(name == SIGNAL_TOUCHED)
1435 actor->TouchedSignal().Connect( tracker, functor );
1437 else if(name == SIGNAL_VISIBILITY_CHANGED)
1439 actor->VisibilityChangedSignal().Connect( tracker, functor );
1441 else if(name == SIGNAL_LAYOUT_DIRECTION_CHANGED)
1443 actor->LayoutDirectionChangedSignal().Connect( tracker, functor );
1445 else if(name == SIGNAL_CHILD_ADDED)
1447 actor->ChildAddedSignal().Connect( tracker, functor );
1449 else if(name == SIGNAL_CHILD_REMOVED)
1451 actor->ChildRemovedSignal().Connect( tracker, functor );
1455 // signalName does not match any signal
1462 Actor::Actor( DerivedType derivedType, const SceneGraph::Node& node )
1466 mChildren( nullptr ),
1467 mRenderers( nullptr ),
1468 mParentOrigin( nullptr ),
1469 mAnchorPoint( nullptr ),
1470 mRelayoutData( nullptr ),
1471 mGestureData( nullptr ),
1472 mInterceptTouchedSignal(),
1475 mWheelEventSignal(),
1478 mOnRelayoutSignal(),
1479 mVisibilityChangedSignal(),
1480 mLayoutDirectionChangedSignal(),
1481 mChildAddedSignal(),
1482 mChildRemovedSignal(),
1483 mChildOrderChangedSignal(),
1484 mTargetOrientation( Quaternion::IDENTITY ),
1485 mTargetColor( Color::WHITE ),
1486 mTargetSize( Vector3::ZERO ),
1487 mTargetPosition( Vector3::ZERO ),
1488 mTargetScale( Vector3::ONE ),
1489 mAnimatedSize( Vector3::ZERO ),
1490 mTouchArea( Vector2::ZERO ),
1494 mUseAnimatedSize( AnimatedSizeFlag::CLEAR ),
1495 mIsRoot( ROOT_LAYER == derivedType ),
1496 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
1497 mIsOnScene( false ),
1499 mLeaveRequired( false ),
1500 mKeyboardFocusable( false ),
1501 mOnSceneSignalled( false ),
1502 mInsideOnSizeSet( false ),
1503 mInheritPosition( true ),
1504 mInheritOrientation( true ),
1505 mInheritScale( true ),
1506 mPositionUsesAnchorPoint( true ),
1508 mInheritLayoutDirection( true ),
1509 mCaptureAllTouchAfterStart( false ),
1510 mLayoutDirection( LayoutDirection::LEFT_TO_RIGHT ),
1511 mDrawMode( DrawMode::NORMAL ),
1512 mColorMode( Node::DEFAULT_COLOR_MODE ),
1513 mClippingMode( ClippingMode::DISABLED ),
1514 mBlendEquation( DevelBlendEquation::ADD ),
1515 mIsBlendEquationSet( false )
1519 void Actor::Initialize()
1523 GetEventThreadServices().RegisterObject( this );
1528 // Remove mParent pointers from children even if we're destroying core,
1529 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1532 for( const auto& actor : *mChildren )
1534 actor->SetParent( nullptr );
1540 // Guard to allow handle destruction after Core has been destroyed
1541 if( EventThreadServices::IsCoreRunning() )
1543 // Root layer will destroy its node in its own destructor
1546 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
1548 GetEventThreadServices().UnregisterObject( this );
1552 // Cleanup optional gesture data
1553 delete mGestureData;
1555 // Cleanup optional parent origin and anchor
1556 delete mParentOrigin;
1557 delete mAnchorPoint;
1559 // Delete optional relayout data
1560 delete mRelayoutData;
1563 void Actor::ConnectToScene( uint32_t parentDepth )
1565 // This container is used instead of walking the Actor hierarchy.
1566 // It protects us when the Actor hierarchy is modified during OnSceneConnectionExternal callbacks.
1567 ActorContainer connectionList;
1571 mScene->RequestRebuildDepthTree();
1574 // This stage is atomic i.e. not interrupted by user callbacks.
1575 RecursiveConnectToScene( connectionList, parentDepth + 1 );
1577 // Notify applications about the newly connected actors.
1578 for( const auto& actor : connectionList )
1580 actor->NotifyStageConnection();
1586 void Actor::RecursiveConnectToScene( ActorContainer& connectionList, uint32_t depth )
1588 DALI_ASSERT_ALWAYS( !OnScene() );
1591 mDepth = static_cast< uint16_t >( depth ); // overflow ignored, not expected in practice
1593 ConnectToSceneGraph();
1595 // Notification for internal derived classes
1596 OnSceneConnectionInternal();
1598 // This stage is atomic; avoid emitting callbacks until all Actors are connected
1599 connectionList.push_back( ActorPtr( this ) );
1601 // Recursively connect children
1604 for( const auto& actor : *mChildren )
1606 actor->SetScene( *mScene );
1607 actor->RecursiveConnectToScene( connectionList, depth + 1 );
1613 * This method is called when the Actor is connected to the Stage.
1614 * The parent must have added its Node to the scene-graph.
1615 * The child must connect its Node to the parent's Node.
1616 * This is recursive; the child calls ConnectToScene() for its children.
1618 void Actor::ConnectToSceneGraph()
1620 DALI_ASSERT_DEBUG( mParent != NULL);
1622 // Reparent Node in next Update
1623 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), mParent->GetNode(), GetNode() );
1625 // Request relayout on all actors that are added to the scenegraph
1628 // Notification for Object::Observers
1632 void Actor::NotifyStageConnection()
1634 // Actors can be removed (in a callback), before the on-stage stage is reported.
1635 // The actor may also have been reparented, in which case mOnSceneSignalled will be true.
1636 if( OnScene() && !mOnSceneSignalled )
1638 // Notification for external (CustomActor) derived classes
1639 OnSceneConnectionExternal( mDepth );
1641 if( !mOnSceneSignal.Empty() )
1643 Dali::Actor handle( this );
1644 mOnSceneSignal.Emit( handle );
1647 // Guard against Remove during callbacks
1650 mOnSceneSignalled = true; // signal required next time Actor is removed
1655 void Actor::DisconnectFromStage()
1657 // This container is used instead of walking the Actor hierachy.
1658 // It protects us when the Actor hierachy is modified during OnSceneDisconnectionExternal callbacks.
1659 ActorContainer disconnectionList;
1663 mScene->RequestRebuildDepthTree();
1666 // This stage is atomic i.e. not interrupted by user callbacks
1667 RecursiveDisconnectFromStage( disconnectionList );
1669 // Notify applications about the newly disconnected actors.
1670 for( const auto& actor : disconnectionList )
1672 actor->NotifyStageDisconnection();
1676 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
1678 // need to change state first so that internals relying on IsOnScene() inside OnSceneDisconnectionInternal() get the correct value
1681 // Recursively disconnect children
1684 for( const auto& child : *mChildren )
1686 child->RecursiveDisconnectFromStage( disconnectionList );
1690 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
1691 disconnectionList.push_back( ActorPtr( this ) );
1693 // Notification for internal derived classes
1694 OnSceneDisconnectionInternal();
1696 DisconnectFromSceneGraph();
1700 * This method is called by an actor or its parent, before a node removal message is sent.
1701 * This is recursive; the child calls DisconnectFromStage() for its children.
1703 void Actor::DisconnectFromSceneGraph()
1705 // Notification for Object::Observers
1706 OnSceneObjectRemove();
1709 void Actor::NotifyStageDisconnection()
1711 // Actors can be added (in a callback), before the off-stage state is reported.
1712 // Also if the actor was added & removed before mOnSceneSignalled was set, then we don't notify here.
1713 // only do this step if there is a stage, i.e. Core is not being shut down
1714 if ( EventThreadServices::IsCoreRunning() && !OnScene() && mOnSceneSignalled )
1716 // Notification for external (CustomeActor) derived classes
1717 OnSceneDisconnectionExternal();
1719 if( !mOffSceneSignal.Empty() )
1721 Dali::Actor handle( this );
1722 mOffSceneSignal.Emit( handle );
1725 // Guard against Add during callbacks
1728 mOnSceneSignalled = false; // signal required next time Actor is added
1733 bool Actor::IsNodeConnected() const
1735 bool connected( false );
1739 if( IsRoot() || GetNode().GetParent() )
1748 // This method initiates traversal of the actor tree using depth-first
1749 // traversal to set a depth index based on traversal order. It sends a
1750 // single message to update manager to update all the actor's nodes in
1751 // this tree with the depth index. The sceneGraphNodeDepths vector's
1752 // elements are ordered by depth, and could be used to reduce sorting
1753 // in the update thread.
1754 void Actor::RebuildDepthTree()
1756 DALI_LOG_TIMER_START(depthTimer);
1758 // Vector of scene-graph nodes and their depths to send to UpdateManager
1759 // in a single message
1760 OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths( new SceneGraph::NodeDepths() );
1762 int32_t depthIndex = 1;
1763 DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
1765 SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths );
1766 DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
1769 void Actor::DepthTraverseActorTree( OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths, int32_t& depthIndex )
1771 mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
1772 sceneGraphNodeDepths->Add( const_cast<SceneGraph::Node*>( &GetNode() ), mSortedDepth );
1774 // Create/add to children of this node
1777 for( const auto& child : *mChildren )
1779 Actor* childActor = child.Get();
1781 childActor->DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
1786 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
1788 PropertyHandler::SetDefaultProperty(*this, index, property);
1791 // TODO: This method needs to be removed
1792 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
1794 PropertyHandler::SetSceneGraphProperty(index, entry, value, GetEventThreadServices(), GetNode());
1797 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
1799 Property::Value value;
1801 if( ! GetCachedPropertyValue( index, value ) )
1803 // If property value is not stored in the event-side, then it must be a scene-graph only property
1804 GetCurrentPropertyValue( index, value );
1810 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
1812 Property::Value value;
1814 if( ! GetCurrentPropertyValue( index, value ) )
1816 // If unable to retrieve scene-graph property value, then it must be an event-side only property
1817 GetCachedPropertyValue( index, value );
1823 void Actor::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
1825 PropertyHandler::OnNotifyDefaultPropertyAnimation(*this, animation, index, value, animationType);
1828 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
1830 const PropertyBase* property = PropertyHandler::GetSceneObjectAnimatableProperty(index, GetNode());
1833 // not our property, ask base
1834 property = Object::GetSceneObjectAnimatableProperty( index );
1840 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
1842 const PropertyInputImpl* property = PropertyHandler::GetSceneObjectInputProperty(index, GetNode());
1845 // reuse animatable property getter as animatable properties are inputs as well
1846 // animatable property chains back to Object::GetSceneObjectInputProperty() so all properties get covered
1847 property = GetSceneObjectAnimatableProperty( index );
1853 int32_t Actor::GetPropertyComponentIndex( Property::Index index ) const
1855 int32_t componentIndex = PropertyHandler::GetPropertyComponentIndex(index);
1856 if( Property::INVALID_COMPONENT_INDEX == componentIndex )
1859 componentIndex = Object::GetPropertyComponentIndex( index );
1862 return componentIndex;
1865 void Actor::SetParent( Actor* parent )
1869 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
1873 mScene = parent->mScene;
1875 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1878 // Instruct each actor to create a corresponding node in the scene graph
1879 ConnectToScene( parent->GetHierarchyDepth() );
1882 // Resolve the name and index for the child properties if any
1883 ResolveChildProperties();
1885 else // parent being set to NULL
1887 DALI_ASSERT_ALWAYS( mParent != nullptr && "Actor should have a parent" );
1891 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1894 // Disconnect the Node & its children from the scene-graph.
1895 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
1897 // Instruct each actor to discard pointers to the scene-graph
1898 DisconnectFromStage();
1905 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
1908 Actor* actor = dynamic_cast< Actor* >( object );
1912 std::string_view name(actionName);
1913 if(name == ACTION_SHOW)
1915 actor->SetVisible( true );
1918 else if(name == ACTION_HIDE)
1920 actor->SetVisible( false );
1928 Rect<> Actor::CalculateScreenExtents( ) const
1930 auto screenPosition = GetCurrentScreenPosition();
1931 Vector3 size = GetCurrentSize() * GetCurrentWorldScale();
1932 Vector3 anchorPointOffSet = size * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
1933 Vector2 position = Vector2( screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y );
1934 return { position.x, position.y, size.x, size.y };
1937 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
1939 return PropertyHandler::GetCachedPropertyValue(*this, index, value);
1942 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
1944 return PropertyHandler::GetCurrentPropertyValue(*this, index, value);
1947 Actor::Relayouter& Actor::EnsureRelayouter()
1949 // Assign relayouter
1950 if( !mRelayoutData )
1952 mRelayoutData = new Relayouter();
1955 return *mRelayoutData;
1958 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
1960 // Check if actor is dependent on parent
1961 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1963 if( ( dimension & ( 1 << i ) ) )
1965 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
1966 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
1976 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
1978 // Check if actor is dependent on children
1979 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1981 if( ( dimension & ( 1 << i ) ) )
1983 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
1984 switch( resizePolicy )
1986 case ResizePolicy::FIT_TO_CHILDREN:
1987 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
2003 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
2005 return Actor::RelayoutDependentOnChildren( dimension );
2008 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
2010 // Check each possible dimension and see if it is dependent on the input one
2011 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2013 if( dimension & ( 1 << i ) )
2015 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
2022 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
2024 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2026 if( dimension & ( 1 << i ) )
2028 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
2033 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
2035 // If more than one dimension is requested, just return the first one found
2036 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2038 if( ( dimension & ( 1 << i ) ) )
2040 return mRelayoutData->negotiatedDimensions[ i ];
2044 return 0.0f; // Default
2047 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
2049 EnsureRelayouter().SetPadding( padding, dimension );
2052 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
2054 if ( mRelayoutData )
2056 // If more than one dimension is requested, just return the first one found
2057 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2059 if( ( dimension & ( 1 << i ) ) )
2061 return mRelayoutData->dimensionPadding[ i ];
2066 return Relayouter::DEFAULT_DIMENSION_PADDING;
2069 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
2071 EnsureRelayouter().SetLayoutNegotiated(negotiated, dimension);
2074 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
2076 return mRelayoutData && mRelayoutData->IsLayoutNegotiated(dimension);
2079 float Actor::GetHeightForWidthBase( float width )
2081 float height = 0.0f;
2083 const Vector3 naturalSize = GetNaturalSize();
2084 if( naturalSize.width > 0.0f )
2086 height = naturalSize.height * width / naturalSize.width;
2088 else // we treat 0 as 1:1 aspect ratio
2096 float Actor::GetWidthForHeightBase( float height )
2100 const Vector3 naturalSize = GetNaturalSize();
2101 if( naturalSize.height > 0.0f )
2103 width = naturalSize.width * height / naturalSize.height;
2105 else // we treat 0 as 1:1 aspect ratio
2113 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
2115 // Fill to parent, taking size mode factor into account
2116 switch( child.GetResizePolicy( dimension ) )
2118 case ResizePolicy::FILL_TO_PARENT:
2120 return GetLatestSize( dimension );
2123 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2125 return GetLatestSize( dimension ) * GetDimensionValue( child.GetProperty< Vector3 >( Dali::Actor::Property::SIZE_MODE_FACTOR ), dimension );
2128 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2130 return GetLatestSize( dimension ) + GetDimensionValue( child.GetProperty< Vector3 >( Dali::Actor::Property::SIZE_MODE_FACTOR ), dimension );
2135 return GetLatestSize( dimension );
2140 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
2142 // Can be overridden in derived class
2143 return CalculateChildSizeBase( child, dimension );
2146 float Actor::GetHeightForWidth( float width )
2148 // Can be overridden in derived class
2149 return GetHeightForWidthBase( width );
2152 float Actor::GetWidthForHeight( float height )
2154 // Can be overridden in derived class
2155 return GetWidthForHeightBase( height );
2158 float Actor::GetLatestSize( Dimension::Type dimension ) const
2160 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
2163 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
2165 Vector2 padding = GetPadding( dimension );
2167 return GetLatestSize( dimension ) + padding.x + padding.y;
2170 float Actor::NegotiateFromParent( Dimension::Type dimension )
2172 Actor* parent = GetParent();
2175 Vector2 padding( GetPadding( dimension ) );
2176 Vector2 parentPadding( parent->GetPadding( dimension ) );
2177 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
2183 float Actor::NegotiateFromChildren( Dimension::Type dimension )
2185 float maxDimensionPoint = 0.0f;
2187 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2189 ActorPtr child = GetChildAt( i );
2191 if( !child->RelayoutDependentOnParent( dimension ) )
2193 // Calculate the min and max points that the children range across
2194 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
2195 float dimensionSize = child->GetRelayoutSize( dimension );
2196 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
2200 return maxDimensionPoint;
2203 float Actor::GetSize( Dimension::Type dimension ) const
2205 return GetDimensionValue( mTargetSize, dimension );
2208 float Actor::GetNaturalSize( Dimension::Type dimension ) const
2210 return GetDimensionValue( GetNaturalSize(), dimension );
2213 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
2215 switch( GetResizePolicy( dimension ) )
2217 case ResizePolicy::USE_NATURAL_SIZE:
2219 return GetNaturalSize( dimension );
2222 case ResizePolicy::FIXED:
2224 return GetDimensionValue( GetPreferredSize(), dimension );
2227 case ResizePolicy::USE_ASSIGNED_SIZE:
2229 return GetDimensionValue( maximumSize, dimension );
2232 case ResizePolicy::FILL_TO_PARENT:
2233 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2234 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2236 return NegotiateFromParent( dimension );
2239 case ResizePolicy::FIT_TO_CHILDREN:
2241 return NegotiateFromChildren( dimension );
2244 case ResizePolicy::DIMENSION_DEPENDENCY:
2246 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
2249 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
2251 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
2254 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
2256 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
2268 return 0.0f; // Default
2271 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
2273 // Check if it needs to be negotiated
2274 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
2276 // Check that we havn't gotten into an infinite loop
2277 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
2278 bool recursionFound = false;
2279 for( auto& element : recursionStack )
2281 if( element == searchActor )
2283 recursionFound = true;
2288 if( !recursionFound )
2290 // Record the path that we have taken
2291 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
2293 // Dimension dependency check
2294 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2296 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
2298 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
2300 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
2304 // Parent dependency check
2305 Actor* parent = GetParent();
2306 if( parent && RelayoutDependentOnParent( dimension ) )
2308 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
2311 // Children dependency check
2312 if( RelayoutDependentOnChildren( dimension ) )
2314 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2316 ActorPtr child = GetChildAt( i );
2318 // Only relayout child first if it is not dependent on this actor
2319 if( !child->RelayoutDependentOnParent( dimension ) )
2321 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
2326 // For deriving classes
2327 OnCalculateRelayoutSize( dimension );
2329 // All dependencies checked, calculate the size and set negotiated flag
2330 const float newSize = Relayouter::ClampDimension( *this, CalculateSize( dimension, allocatedSize ), dimension );
2332 SetNegotiatedDimension( newSize, dimension );
2333 SetLayoutNegotiated( true, dimension );
2335 // For deriving classes
2336 OnLayoutNegotiated( newSize, dimension );
2338 // This actor has been successfully processed, pop it off the recursion stack
2339 recursionStack.pop_back();
2343 // TODO: Break infinite loop
2344 SetLayoutNegotiated( true, dimension );
2349 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
2351 // Negotiate all dimensions that require it
2352 ActorDimensionStack recursionStack;
2354 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2356 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
2359 NegotiateDimension( dimension, allocatedSize, recursionStack );
2363 Vector2 Actor::ApplySizeSetPolicy( const Vector2& size )
2365 return mRelayoutData->ApplySizeSetPolicy(*this, size);
2368 void Actor::SetNegotiatedSize( RelayoutContainer& container )
2370 // Do the set actor size
2371 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
2373 // Adjust for size set policy
2374 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
2376 // Lock the flag to stop recursive relayouts on set size
2377 mRelayoutData->insideRelayout = true;
2378 SetSize( negotiatedSize );
2379 mRelayoutData->insideRelayout = false;
2381 // Clear flags for all dimensions
2382 SetLayoutDirty( false );
2384 // Give deriving classes a chance to respond
2385 OnRelayout( negotiatedSize, container );
2387 if( !mOnRelayoutSignal.Empty() )
2389 Dali::Actor handle( this );
2390 mOnRelayoutSignal.Emit( handle );
2394 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
2396 // Force a size negotiation for actors that has assigned size during relayout
2397 // This is required as otherwise the flags that force a relayout will not
2398 // necessarilly be set. This will occur if the actor has already been laid out.
2399 // The dirty flags are then cleared. Then if the actor is added back into the
2400 // relayout container afterwards, the dirty flags would still be clear...
2401 // causing a relayout to be skipped. Here we force any actors added to the
2402 // container to be relayed out.
2403 DALI_LOG_TIMER_START( NegSizeTimer1 );
2405 if( GetUseAssignedSize(Dimension::WIDTH ) )
2407 SetLayoutNegotiated( false, Dimension::WIDTH );
2409 if( GetUseAssignedSize( Dimension::HEIGHT ) )
2411 SetLayoutNegotiated( false, Dimension::HEIGHT );
2414 // Do the negotiation
2415 NegotiateDimensions( allocatedSize );
2417 // Set the actor size
2418 SetNegotiatedSize( container );
2420 // Negotiate down to children
2421 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2423 ActorPtr child = GetChildAt( i );
2425 // Forces children that have already been laid out to be relayed out
2426 // if they have assigned size during relayout.
2427 if( child->GetUseAssignedSize(Dimension::WIDTH) )
2429 child->SetLayoutNegotiated(false, Dimension::WIDTH);
2430 child->SetLayoutDirty(true, Dimension::WIDTH);
2433 if( child->GetUseAssignedSize(Dimension::HEIGHT) )
2435 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
2436 child->SetLayoutDirty(true, Dimension::HEIGHT);
2439 // Only relayout if required
2440 if( child->RelayoutRequired() )
2442 container.Add( Dali::Actor( child.Get() ), mTargetSize.GetVectorXY() );
2445 DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
2448 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
2452 mRelayoutData->SetUseAssignedSize(use, dimension);
2456 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
2458 return mRelayoutData && mRelayoutData->GetUseAssignedSize(dimension);
2461 void Actor::RelayoutRequest( Dimension::Type dimension )
2463 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
2464 if( relayoutController )
2466 Dali::Actor self( this );
2467 relayoutController->RequestRelayout( self, dimension );
2471 void Actor::SetPreferredSize( const Vector2& size )
2475 // If valid width or height, then set the resize policy to FIXED
2476 // 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,
2477 // then change to FIXED as well
2479 if( size.width > 0.0f || GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DEFAULT )
2481 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
2484 if( size.height > 0.0f || GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DEFAULT )
2486 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
2489 mRelayoutData->preferredSize = size;
2491 mUseAnimatedSize = AnimatedSizeFlag::CLEAR;
2496 Vector2 Actor::GetPreferredSize() const
2498 if ( mRelayoutData )
2500 return Vector2( mRelayoutData->preferredSize );
2503 return Relayouter::DEFAULT_PREFERRED_SIZE;
2506 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
2508 EnsureRelayouter().SetMinimumSize(size, dimension);
2512 float Actor::GetMinimumSize( Dimension::Type dimension ) const
2514 if ( mRelayoutData )
2516 return mRelayoutData->GetMinimumSize(dimension);
2519 return 0.0f; // Default
2522 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
2524 EnsureRelayouter().SetMaximumSize(size, dimension);
2528 float Actor::GetMaximumSize( Dimension::Type dimension ) const
2530 if ( mRelayoutData )
2532 return mRelayoutData->GetMaximumSize(dimension);
2535 return FLT_MAX; // Default
2538 void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
2540 if( mVisible != visible )
2542 if( sendMessage == SendMessage::TRUE )
2544 // node is being used in a separate thread; queue a message to set the value & base value
2545 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible );
2547 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
2552 // Emit the signal on this actor and all its children
2553 EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
2557 void Actor::EmitOrderChangedAndRebuild()
2559 Dali::Actor handle( this );
2560 mParent->mChildOrderChangedSignal.Emit( handle );
2561 if( mIsOnScene && mScene )
2563 mScene->RequestRebuildDepthTree();
2567 void Actor::SetSiblingOrder( uint32_t order )
2569 if( mParent && SiblingHandler::SetSiblingOrder(*(mParent->mChildren), *this, order))
2571 EmitOrderChangedAndRebuild();
2575 uint32_t Actor::GetSiblingOrder() const
2580 order = SiblingHandler::GetSiblingOrder(*(mParent->mChildren), *this);
2587 if( mParent && SiblingHandler::Raise(*(mParent->mChildren), *this) )
2589 EmitOrderChangedAndRebuild();
2593 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2599 if( mParent && SiblingHandler::Lower(*(mParent->mChildren), *this) )
2601 EmitOrderChangedAndRebuild();
2605 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2609 void Actor::RaiseToTop()
2611 if( mParent && SiblingHandler::RaiseToTop(*(mParent->mChildren), *this) )
2613 EmitOrderChangedAndRebuild();
2617 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2621 void Actor::LowerToBottom()
2623 if( mParent && SiblingHandler::LowerToBottom(*(mParent->mChildren), *this) )
2625 EmitOrderChangedAndRebuild();
2629 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2633 void Actor::RaiseAbove( Internal::Actor& target )
2635 if( mParent && SiblingHandler::RaiseAbove( *(mParent->mChildren), *this, target ))
2637 EmitOrderChangedAndRebuild();
2641 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2645 void Actor::LowerBelow( Internal::Actor& target )
2647 if( mParent && SiblingHandler::LowerBelow(*(mParent->mChildren), *this, target ) )
2649 EmitOrderChangedAndRebuild();
2653 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2657 void Actor::SetInheritLayoutDirection( bool inherit )
2659 if( mInheritLayoutDirection != inherit )
2661 mInheritLayoutDirection = inherit;
2663 if( inherit && mParent )
2665 InheritLayoutDirectionRecursively( this, mParent->mLayoutDirection );
2670 void Actor::InheritLayoutDirectionRecursively( ActorPtr actor, Dali::LayoutDirection::Type direction, bool set )
2672 if( actor && ( actor->mInheritLayoutDirection || set ) )
2674 if( actor->mLayoutDirection != direction )
2676 actor->mLayoutDirection = direction;
2677 actor->EmitLayoutDirectionChangedSignal( direction );
2678 actor->RelayoutRequest();
2681 if( actor->GetChildCount() > 0 )
2683 for( const auto& child : actor->GetChildrenInternal() )
2685 InheritLayoutDirectionRecursively( child, direction );
2691 void Actor::SetUpdateSizeHint( const Vector2& updateSizeHint )
2693 // node is being used in a separate thread; queue a message to set the value & base value
2694 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mUpdateSizeHint, &AnimatableProperty<Vector3>::Bake, Vector3(updateSizeHint.width, updateSizeHint.height, 0.f ) );
2697 } // namespace Internal