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/actors/actor-property-handler.h>
37 #include <dali/internal/event/actors/actor-relayouter.h>
38 #include <dali/internal/event/common/event-thread-services.h>
39 #include <dali/internal/event/render-tasks/render-task-impl.h>
40 #include <dali/internal/event/actors/camera-actor-impl.h>
41 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
42 #include <dali/internal/event/common/property-helper.h>
43 #include <dali/internal/event/common/stage-impl.h>
44 #include <dali/internal/event/common/type-info-impl.h>
45 #include <dali/internal/event/common/scene-impl.h>
46 #include <dali/internal/event/common/thread-local-storage.h>
47 #include <dali/internal/event/common/projection.h>
48 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
49 #include <dali/internal/update/nodes/node-messages.h>
50 #include <dali/internal/event/events/actor-gesture-data.h>
51 #include <dali/integration-api/debug.h>
53 using Dali::Internal::SceneGraph::Node;
54 using Dali::Internal::SceneGraph::AnimatableProperty;
55 using Dali::Internal::SceneGraph::PropertyBase;
57 #if defined(DEBUG_ENABLED)
58 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_DEPTH_TIMER" );
59 Debug::Filter* gLogRelayoutFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_TIMER" );
68 namespace // unnamed namespace
74 * We want to discourage the use of property strings (minimize string comparisons),
75 * particularly for the default properties.
76 * Name Type writable animatable constraint-input enum for index-checking
78 DALI_PROPERTY_TABLE_BEGIN
79 DALI_PROPERTY( "parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
80 DALI_PROPERTY( "parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
81 DALI_PROPERTY( "parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
82 DALI_PROPERTY( "parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
83 DALI_PROPERTY( "anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
84 DALI_PROPERTY( "anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
85 DALI_PROPERTY( "anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
86 DALI_PROPERTY( "anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
87 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
88 DALI_PROPERTY( "sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
89 DALI_PROPERTY( "sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
90 DALI_PROPERTY( "sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
91 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
92 DALI_PROPERTY( "positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
93 DALI_PROPERTY( "positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
94 DALI_PROPERTY( "positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
95 DALI_PROPERTY( "worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
96 DALI_PROPERTY( "worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
97 DALI_PROPERTY( "worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
98 DALI_PROPERTY( "worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
99 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
100 DALI_PROPERTY( "worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
101 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
102 DALI_PROPERTY( "scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
103 DALI_PROPERTY( "scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
104 DALI_PROPERTY( "scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
105 DALI_PROPERTY( "worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
106 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
107 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
108 DALI_PROPERTY( "colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
109 DALI_PROPERTY( "colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
110 DALI_PROPERTY( "colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
111 DALI_PROPERTY( "colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
112 DALI_PROPERTY( "worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
113 DALI_PROPERTY( "worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
114 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
115 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
116 DALI_PROPERTY( "leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
117 DALI_PROPERTY( "inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
118 DALI_PROPERTY( "inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
119 DALI_PROPERTY( "colorMode", INTEGER, true, false, false, Dali::Actor::Property::COLOR_MODE )
120 DALI_PROPERTY( "drawMode", INTEGER, true, false, false, Dali::Actor::Property::DRAW_MODE )
121 DALI_PROPERTY( "sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
122 DALI_PROPERTY( "widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
123 DALI_PROPERTY( "heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
124 DALI_PROPERTY( "sizeScalePolicy", INTEGER, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
125 DALI_PROPERTY( "widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
126 DALI_PROPERTY( "heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
127 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
128 DALI_PROPERTY( "minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
129 DALI_PROPERTY( "maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
130 DALI_PROPERTY( "inheritPosition", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_POSITION )
131 DALI_PROPERTY( "clippingMode", STRING, true, false, false, Dali::Actor::Property::CLIPPING_MODE )
132 DALI_PROPERTY( "layoutDirection", STRING, true, false, false, Dali::Actor::Property::LAYOUT_DIRECTION )
133 DALI_PROPERTY( "inheritLayoutDirection", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION )
134 DALI_PROPERTY( "opacity", FLOAT, true, true, true, Dali::Actor::Property::OPACITY )
135 DALI_PROPERTY( "screenPosition", VECTOR2, false, false, false, Dali::Actor::Property::SCREEN_POSITION )
136 DALI_PROPERTY( "positionUsesAnchorPoint", BOOLEAN, true, false, false, Dali::Actor::Property::POSITION_USES_ANCHOR_POINT )
137 DALI_PROPERTY( "culled", BOOLEAN, false, false, true, Dali::Actor::Property::CULLED )
138 DALI_PROPERTY( "id", INTEGER, false, false, false, Dali::Actor::Property::ID )
139 DALI_PROPERTY( "hierarchyDepth", INTEGER, false, false, false, Dali::Actor::Property::HIERARCHY_DEPTH )
140 DALI_PROPERTY( "isRoot", BOOLEAN, false, false, false, Dali::Actor::Property::IS_ROOT )
141 DALI_PROPERTY( "isLayer", BOOLEAN, false, false, false, Dali::Actor::Property::IS_LAYER )
142 DALI_PROPERTY( "connectedToScene", BOOLEAN, false, false, false, Dali::Actor::Property::CONNECTED_TO_SCENE )
143 DALI_PROPERTY( "keyboardFocusable", BOOLEAN, true, false, false, Dali::Actor::Property::KEYBOARD_FOCUSABLE )
144 DALI_PROPERTY( "siblingOrder", INTEGER, true, false, false, Dali::DevelActor::Property::SIBLING_ORDER )
145 DALI_PROPERTY( "updateSizeHint", VECTOR2, true, false, false, Dali::DevelActor::Property::UPDATE_SIZE_HINT )
146 DALI_PROPERTY( "captureAllTouchAfterStart", BOOLEAN, true, false, false, Dali::DevelActor::Property::CAPTURE_ALL_TOUCH_AFTER_START )
147 DALI_PROPERTY( "touchArea", VECTOR2, true, false, false, Dali::DevelActor::Property::TOUCH_AREA )
148 DALI_PROPERTY( "blendEquation", INTEGER, true, false, false, Dali::DevelActor::Property::BLEND_EQUATION )
149 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperties )
153 static constexpr std::string_view SIGNAL_HOVERED = "hovered";
154 static constexpr std::string_view SIGNAL_WHEEL_EVENT = "wheelEvent";
155 static constexpr std::string_view SIGNAL_ON_SCENE = "onScene";
156 static constexpr std::string_view SIGNAL_OFF_SCENE = "offScene";
157 static constexpr std::string_view SIGNAL_ON_RELAYOUT = "onRelayout";
158 static constexpr std::string_view SIGNAL_TOUCHED = "touched";
159 static constexpr std::string_view SIGNAL_VISIBILITY_CHANGED = "visibilityChanged";
160 static constexpr std::string_view SIGNAL_LAYOUT_DIRECTION_CHANGED = "layoutDirectionChanged";
161 static constexpr std::string_view SIGNAL_CHILD_ADDED = "childAdded";
162 static constexpr std::string_view SIGNAL_CHILD_REMOVED = "childRemoved";
166 static constexpr std::string_view ACTION_SHOW = "show";
167 static constexpr std::string_view ACTION_HIDE = "hide";
169 BaseHandle CreateActor()
171 return Dali::Actor::New();
174 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor, ActorDefaultProperties );
176 SignalConnectorType signalConnector2(mType, std::string(SIGNAL_HOVERED), &Actor::DoConnectSignal);
177 SignalConnectorType signalConnector3(mType, std::string(SIGNAL_WHEEL_EVENT), &Actor::DoConnectSignal);
178 SignalConnectorType signalConnector4(mType, std::string(SIGNAL_ON_SCENE), &Actor::DoConnectSignal);
179 SignalConnectorType signalConnector5(mType, std::string(SIGNAL_OFF_SCENE), &Actor::DoConnectSignal);
180 SignalConnectorType signalConnector6(mType, std::string(SIGNAL_ON_RELAYOUT), &Actor::DoConnectSignal);
181 SignalConnectorType signalConnector7(mType, std::string(SIGNAL_TOUCHED), &Actor::DoConnectSignal);
182 SignalConnectorType signalConnector8(mType, std::string(SIGNAL_VISIBILITY_CHANGED), &Actor::DoConnectSignal);
183 SignalConnectorType signalConnector9(mType, std::string(SIGNAL_LAYOUT_DIRECTION_CHANGED), &Actor::DoConnectSignal);
184 SignalConnectorType signalConnector10(mType, std::string(SIGNAL_CHILD_ADDED), &Actor::DoConnectSignal);
185 SignalConnectorType signalConnector11(mType, std::string(SIGNAL_CHILD_REMOVED), &Actor::DoConnectSignal);
187 TypeAction a1(mType, std::string(ACTION_SHOW), &Actor::DoAction);
188 TypeAction a2(mType, std::string(ACTION_HIDE), &Actor::DoAction);
191 * @brief Extract a given dimension from a Vector2
193 * @param[in] values The values to extract from
194 * @param[in] dimension The dimension to extract
195 * @return Return the value for the dimension
197 constexpr float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
201 case Dimension::WIDTH:
205 case Dimension::HEIGHT:
207 return values.height;
218 * @brief Extract a given dimension from a Vector3
220 * @param[in] values The values to extract from
221 * @param[in] dimension The dimension to extract
222 * @return Return the value for the dimension
224 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
226 return GetDimensionValue( values.GetVectorXY(), dimension );
230 * @brief Recursively emits the visibility-changed-signal on the actor tree.
231 * @param[in] actor The actor to emit the signal on
232 * @param[in] visible The new visibility of the actor
233 * @param[in] type Whether the actor's visible property has changed or a parent's
235 void EmitVisibilityChangedSignalRecursively( ActorPtr actor, bool visible, DevelActor::VisibilityChange::Type type )
239 actor->EmitVisibilityChangedSignal( visible, type );
241 if( actor->GetChildCount() > 0 )
243 for( auto& child : actor->GetChildrenInternal() )
245 EmitVisibilityChangedSignalRecursively( child, visible, DevelActor::VisibilityChange::PARENT );
251 /// Helper for emitting a signal
252 template<typename Signal, typename Event>
253 bool EmitConsumingSignal( Actor& actor, Signal& signal, const Event& event )
255 bool consumed = false;
257 if( !signal.Empty() )
259 Dali::Actor handle( &actor );
260 consumed = signal.Emit( handle, event );
266 /// Helper for emitting signals with multiple parameters
267 template<typename Signal, typename... Param>
268 void EmitSignal( Actor& actor, Signal& signal, Param... params)
270 if( !signal.Empty() )
272 Dali::Actor handle( &actor );
273 signal.Emit( handle, params... );
277 bool ScreenToLocalInternal(
278 const Matrix& viewMatrix,
279 const Matrix& projectionMatrix,
280 const Matrix& worldMatrix,
281 const Viewport& viewport,
282 const Vector3& currentSize,
288 // Get the ModelView matrix
290 Matrix::Multiply( modelView, worldMatrix, viewMatrix );
292 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
293 Matrix invertedMvp( false/*don't init*/);
294 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
295 bool success = invertedMvp.Invert();
297 // Convert to GL coordinates
298 Vector4 screenPos( screenX - static_cast<float>( viewport.x ), static_cast<float>( viewport.height ) - screenY - static_cast<float>( viewport.y ), 0.f, 1.f );
303 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), nearPos );
310 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), farPos );
316 if( XyPlaneIntersect( nearPos, farPos, local ) )
318 Vector3 size = currentSize;
319 localX = local.x + size.x * 0.5f;
320 localY = local.y + size.y * 0.5f;
331 } // unnamed namespace
333 ActorPtr Actor::New()
335 // pass a reference to actor, actor does not own its node
336 ActorPtr actor( new Actor( BASIC, *CreateNode() ) );
338 // Second-phase construction
344 const SceneGraph::Node* Actor::CreateNode()
346 // create node. Nodes are owned by the update manager
347 SceneGraph::Node* node = SceneGraph::Node::New();
348 OwnerPointer< SceneGraph::Node > transferOwnership( node );
349 Internal::ThreadLocalStorage* tls = Internal::ThreadLocalStorage::GetInternal();
351 DALI_ASSERT_ALWAYS( tls && "ThreadLocalStorage is null" );
353 AddNodeMessage( tls->GetUpdateManager(), transferOwnership );
358 void Actor::SetName( const std::string& name )
362 // ATTENTION: string for debug purposes is not thread safe.
363 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( &GetNode() ), name );
366 uint32_t Actor::GetId() const
368 return GetNode().GetId();
371 Dali::Layer Actor::GetLayer()
375 // Short-circuit for Layer derived actors
378 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
381 // Find the immediate Layer parent
382 for( Actor* parent = mParent; !layer && parent != nullptr; parent = parent->GetParent() )
384 if( parent->IsLayer() )
386 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
393 void Actor::Add( Actor& child )
395 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
396 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
400 mChildren = new ActorContainer;
403 Actor* const oldParent( child.mParent );
405 // child might already be ours
406 if( this != oldParent )
408 // if we already have parent, unparent us first
411 oldParent->Remove( child ); // This causes OnChildRemove callback & ChildRemoved signal
413 // Old parent may need to readjust to missing child
414 if( oldParent->RelayoutDependentOnChildren() )
416 oldParent->RelayoutRequest();
420 // Guard against Add() during previous OnChildRemove callback
423 // Do this first, since user callbacks from within SetParent() may need to remove child
424 mChildren->push_back( ActorPtr( &child ) );
426 // SetParent asserts that child can be added
427 child.SetParent( this );
429 // Notification for derived classes
431 EmitChildAddedSignal( child );
433 InheritLayoutDirectionRecursively( ActorPtr( &child ), mLayoutDirection );
435 // Only put in a relayout request if there is a suitable dependency
436 if( RelayoutDependentOnChildren() )
444 void Actor::Remove( Actor& child )
446 if( (this == &child) || (!mChildren) )
448 // no children or removing itself
454 // Find the child in mChildren, and unparent it
455 ActorIter end = mChildren->end();
456 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
458 ActorPtr actor = (*iter);
460 if( actor.Get() == &child )
462 // Keep handle for OnChildRemove notification
465 // Do this first, since user callbacks from within SetParent() may need to add the child
466 mChildren->erase( iter );
468 DALI_ASSERT_DEBUG( actor->GetParent() == this );
469 actor->SetParent( nullptr );
477 // Only put in a relayout request if there is a suitable dependency
478 if( RelayoutDependentOnChildren() )
484 // Notification for derived classes
485 OnChildRemove( child );
486 EmitChildRemovedSignal( child );
489 void Actor::Unparent()
493 // Remove this actor from the parent. The remove will put a relayout request in for
494 // the parent if required
495 mParent->Remove( *this );
496 // mParent is now NULL!
500 uint32_t Actor::GetChildCount() const
502 return ( nullptr != mChildren ) ? static_cast<uint32_t>( mChildren->size() ) : 0; // only 4,294,967,295 children per actor
505 ActorPtr Actor::GetChildAt( uint32_t index ) const
507 DALI_ASSERT_ALWAYS( index < GetChildCount() );
509 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
512 ActorPtr Actor::FindChildByName( const std::string& actorName )
514 ActorPtr child = nullptr;
515 if( actorName == mName )
521 for( const auto& actor : *mChildren )
523 child = actor->FindChildByName( actorName );
534 ActorPtr Actor::FindChildById( const uint32_t id )
536 ActorPtr child = nullptr;
543 for( const auto& actor : *mChildren )
545 child = actor->FindChildById( id );
556 void Actor::SetParentOrigin( const Vector3& origin )
558 // node is being used in a separate thread; queue a message to set the value & base value
559 SetParentOriginMessage( GetEventThreadServices(), GetNode(), origin );
561 // Cache for event-thread access
564 // not allocated, check if different from default
565 if( ParentOrigin::DEFAULT != origin )
567 mParentOrigin = new Vector3( origin );
572 // check if different from current costs more than just set
573 *mParentOrigin = origin;
577 const Vector3& Actor::GetCurrentParentOrigin() const
579 // Cached for event-thread access
580 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
583 void Actor::SetAnchorPoint( const Vector3& anchor )
585 // node is being used in a separate thread; queue a message to set the value & base value
586 SetAnchorPointMessage( GetEventThreadServices(), GetNode(), anchor );
588 // Cache for event-thread access
591 // not allocated, check if different from default
592 if( AnchorPoint::DEFAULT != anchor )
594 mAnchorPoint = new Vector3( anchor );
599 // check if different from current costs more than just set
600 *mAnchorPoint = anchor;
604 const Vector3& Actor::GetCurrentAnchorPoint() const
606 // Cached for event-thread access
607 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
610 void Actor::SetPosition( float x, float y )
612 SetPosition( Vector3( x, y, 0.0f ) );
615 void Actor::SetPosition( float x, float y, float z )
617 SetPosition( Vector3( x, y, z ) );
620 void Actor::SetPosition( const Vector3& position )
622 mTargetPosition = position;
624 // node is being used in a separate thread; queue a message to set the value & base value
625 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
628 void Actor::SetX( float x )
630 mTargetPosition.x = x;
632 // node is being used in a separate thread; queue a message to set the value & base value
633 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
636 void Actor::SetY( float y )
638 mTargetPosition.y = y;
640 // node is being used in a separate thread; queue a message to set the value & base value
641 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
644 void Actor::SetZ( float z )
646 mTargetPosition.z = z;
648 // node is being used in a separate thread; queue a message to set the value & base value
649 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
652 void Actor::TranslateBy( const Vector3& distance )
654 mTargetPosition += distance;
656 // node is being used in a separate thread; queue a message to set the value & base value
657 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
660 const Vector3& Actor::GetCurrentPosition() const
662 // node is being used in a separate thread; copy the value from the previous update
663 return GetNode().GetPosition(GetEventThreadServices().GetEventBufferIndex());
666 const Vector3& Actor::GetCurrentWorldPosition() const
668 // node is being used in a separate thread; copy the value from the previous update
669 return GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
672 const Vector2 Actor::GetCurrentScreenPosition() const
674 if( mScene && OnScene() )
676 Vector3 worldPosition = GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
677 Vector3 cameraPosition = mScene->GetDefaultCameraActor().GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
678 worldPosition -= cameraPosition;
680 Vector3 actorSize = GetCurrentSize() * GetCurrentWorldScale();
681 Vector2 halfSceneSize( mScene->GetSize() * 0.5f ); // World position origin is center of scene
682 Vector3 halfActorSize( actorSize * 0.5f );
683 Vector3 anchorPointOffSet = halfActorSize - actorSize * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
685 return Vector2( halfSceneSize.width + worldPosition.x - anchorPointOffSet.x,
686 halfSceneSize.height + worldPosition.y - anchorPointOffSet.y );
689 return Vector2::ZERO;
692 void Actor::SetInheritPosition( bool inherit )
694 if( mInheritPosition != inherit )
696 // non animatable so keep local copy
697 mInheritPosition = inherit;
698 SetInheritPositionMessage( GetEventThreadServices(), GetNode(), inherit );
702 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
704 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
705 normalizedAxis.Normalize();
707 Quaternion orientation( angle, normalizedAxis );
709 SetOrientation( orientation );
712 void Actor::SetOrientation( const Quaternion& orientation )
714 mTargetOrientation = orientation;
716 // node is being used in a separate thread; queue a message to set the value & base value
717 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation );
720 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
722 RotateBy( Quaternion(angle, axis) );
725 void Actor::RotateBy( const Quaternion& relativeRotation )
727 mTargetOrientation *= Quaternion( relativeRotation );
729 // node is being used in a separate thread; queue a message to set the value & base value
730 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
733 const Quaternion& Actor::GetCurrentOrientation() const
735 // node is being used in a separate thread; copy the value from the previous update
736 return GetNode().GetOrientation(GetEventThreadServices().GetEventBufferIndex());
739 const Quaternion& Actor::GetCurrentWorldOrientation() const
741 // node is being used in a separate thread; copy the value from the previous update
742 return GetNode().GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
745 void Actor::SetScale( float scale )
747 SetScale( Vector3( scale, scale, scale ) );
750 void Actor::SetScale( float x, float y, float z )
752 SetScale( Vector3( x, y, z ) );
755 void Actor::SetScale( const Vector3& scale )
757 mTargetScale = scale;
759 // node is being used in a separate thread; queue a message to set the value & base value
760 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
763 void Actor::SetScaleX( float x )
767 // node is being used in a separate thread; queue a message to set the value & base value
768 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
771 void Actor::SetScaleY( float y )
775 // node is being used in a separate thread; queue a message to set the value & base value
776 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
779 void Actor::SetScaleZ( float z )
783 // node is being used in a separate thread; queue a message to set the value & base value
784 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
787 void Actor::ScaleBy(const Vector3& relativeScale)
789 mTargetScale *= relativeScale;
791 // node is being used in a separate thread; queue a message to set the value & base value
792 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
795 const Vector3& Actor::GetCurrentScale() const
797 // node is being used in a separate thread; copy the value from the previous update
798 return GetNode().GetScale(GetEventThreadServices().GetEventBufferIndex());
801 const Vector3& Actor::GetCurrentWorldScale() const
803 // node is being used in a separate thread; copy the value from the previous update
804 return GetNode().GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
807 void Actor::SetInheritScale( bool inherit )
809 if( mInheritScale != inherit )
811 // non animatable so keep local copy
812 mInheritScale = inherit;
813 // node is being used in a separate thread; queue a message to set the value
814 SetInheritScaleMessage( GetEventThreadServices(), GetNode(), inherit );
818 Matrix Actor::GetCurrentWorldMatrix() const
820 return GetNode().GetWorldMatrix(0);
823 void Actor::SetVisible( bool visible )
825 SetVisibleInternal( visible, SendMessage::TRUE );
828 bool Actor::IsVisible() const
830 // node is being used in a separate thread; copy the value from the previous update
831 return GetNode().IsVisible( GetEventThreadServices().GetEventBufferIndex() );
834 void Actor::SetOpacity( float opacity )
836 mTargetColor.a = opacity;
838 // node is being used in a separate thread; queue a message to set the value & base value
839 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
841 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
844 float Actor::GetCurrentOpacity() const
846 // node is being used in a separate thread; copy the value from the previous update
847 return GetNode().GetOpacity(GetEventThreadServices().GetEventBufferIndex());
850 const Vector4& Actor::GetCurrentWorldColor() const
852 return GetNode().GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
855 void Actor::SetColor( const Vector4& color )
857 mTargetColor = color;
859 // node is being used in a separate thread; queue a message to set the value & base value
860 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::Bake, color );
862 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
865 void Actor::SetColorRed( float red )
867 mTargetColor.r = red;
869 // node is being used in a separate thread; queue a message to set the value & base value
870 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeX, red );
872 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
875 void Actor::SetColorGreen( float green )
877 mTargetColor.g = green;
879 // node is being used in a separate thread; queue a message to set the value & base value
880 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeY, green );
882 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
885 void Actor::SetColorBlue( float blue )
887 mTargetColor.b = blue;
889 // node is being used in a separate thread; queue a message to set the value & base value
890 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
892 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
895 const Vector4& Actor::GetCurrentColor() const
897 // node is being used in a separate thread; copy the value from the previous update
898 return GetNode().GetColor(GetEventThreadServices().GetEventBufferIndex());
901 void Actor::SetInheritOrientation( bool inherit )
903 if( mInheritOrientation != inherit )
905 // non animatable so keep local copy
906 mInheritOrientation = inherit;
907 // node is being used in a separate thread; queue a message to set the value
908 SetInheritOrientationMessage( GetEventThreadServices(), GetNode(), inherit );
912 void Actor::SetSizeModeFactor( const Vector3& factor )
916 mRelayoutData->sizeModeFactor = factor;
919 const Vector3& Actor::GetSizeModeFactor() const
923 return mRelayoutData->sizeModeFactor;
926 return Relayouter::DEFAULT_SIZE_MODE_FACTOR;
929 void Actor::SetColorMode( ColorMode colorMode )
931 // non animatable so keep local copy
932 mColorMode = colorMode;
933 // node is being used in a separate thread; queue a message to set the value
934 SetColorModeMessage( GetEventThreadServices(), GetNode(), colorMode );
937 void Actor::SetSize( float width, float height )
939 SetSize( Vector2( width, height ) );
942 void Actor::SetSize( float width, float height, float depth )
944 SetSize( Vector3( width, height, depth ) );
947 void Actor::SetSize( const Vector2& size )
949 SetSize( Vector3( size.width, size.height, 0.f ) );
952 void Actor::SetSizeInternal( const Vector2& size )
954 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
957 void Actor::SetSize( const Vector3& size )
959 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
961 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
962 SetPreferredSize( size.GetVectorXY() );
966 SetSizeInternal( size );
970 void Actor::SetSizeInternal( const Vector3& size )
972 // dont allow recursive loop
973 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
974 // 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
975 if( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
976 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
977 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) )
981 // node is being used in a separate thread; queue a message to set the value & base value
982 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
984 // Notification for derived classes
985 mInsideOnSizeSet = true;
986 OnSizeSet( mTargetSize );
987 mInsideOnSizeSet = false;
989 // Raise a relayout request if the flag is not locked
990 if( mRelayoutData && !mRelayoutData->insideRelayout )
997 void Actor::SetWidth( float width )
999 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1001 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
1002 mRelayoutData->preferredSize.width = width;
1006 mTargetSize.width = width;
1008 // node is being used in a separate thread; queue a message to set the value & base value
1009 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1012 mUseAnimatedSize &= ~AnimatedSizeFlag::WIDTH;
1017 void Actor::SetHeight( float height )
1019 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1021 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
1022 mRelayoutData->preferredSize.height = height;
1026 mTargetSize.height = height;
1028 // node is being used in a separate thread; queue a message to set the value & base value
1029 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1032 mUseAnimatedSize &= ~AnimatedSizeFlag::HEIGHT;
1037 void Actor::SetDepth( float depth )
1039 mTargetSize.depth = depth;
1041 mUseAnimatedSize &= ~AnimatedSizeFlag::DEPTH;
1043 // node is being used in a separate thread; queue a message to set the value & base value
1044 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1047 Vector3 Actor::GetTargetSize() const
1049 Vector3 size = mTargetSize;
1051 if( mUseAnimatedSize & AnimatedSizeFlag::WIDTH )
1053 // Should return animated size if size is animated
1054 size.width = mAnimatedSize.width;
1058 // Should return preferred size if size is fixed as set by SetSize
1059 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
1061 size.width = GetPreferredSize().width;
1065 if( mUseAnimatedSize & AnimatedSizeFlag::HEIGHT )
1067 size.height = mAnimatedSize.height;
1071 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
1073 size.height = GetPreferredSize().height;
1077 if( mUseAnimatedSize & AnimatedSizeFlag::DEPTH )
1079 size.depth = mAnimatedSize.depth;
1085 const Vector3& Actor::GetCurrentSize() const
1087 // node is being used in a separate thread; copy the value from the previous update
1088 return GetNode().GetSize( GetEventThreadServices().GetEventBufferIndex() );
1091 Vector3 Actor::GetNaturalSize() const
1093 // It is up to deriving classes to return the appropriate natural size
1094 return Vector3( 0.0f, 0.0f, 0.0f );
1097 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1099 EnsureRelayouter().SetResizePolicy(policy, dimension, mTargetSize);
1101 OnSetResizePolicy( policy, dimension );
1103 // Trigger relayout on this control
1107 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1109 if ( mRelayoutData )
1111 return mRelayoutData->GetResizePolicy(dimension);
1114 return ResizePolicy::DEFAULT;
1117 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1121 mRelayoutData->sizeSetPolicy = policy;
1123 // Trigger relayout on this control
1127 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1129 if ( mRelayoutData )
1131 return mRelayoutData->sizeSetPolicy;
1134 return Relayouter::DEFAULT_SIZE_SCALE_POLICY;
1137 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1139 EnsureRelayouter().SetDimensionDependency(dimension, dependency);
1142 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1144 if ( mRelayoutData )
1146 return mRelayoutData->GetDimensionDependency(dimension);
1149 return Dimension::ALL_DIMENSIONS; // Default
1152 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1154 // If relayout data has not been allocated yet and the client is requesting
1155 // to disable it, do nothing
1156 if( mRelayoutData || relayoutEnabled )
1160 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1162 mRelayoutData->relayoutEnabled = relayoutEnabled;
1166 bool Actor::IsRelayoutEnabled() const
1168 // Assume that if relayout data has not been allocated yet then
1169 // relayout is disabled
1170 return mRelayoutData && mRelayoutData->relayoutEnabled;
1173 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1175 EnsureRelayouter().SetLayoutDirty(dirty, dimension);
1178 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1180 return mRelayoutData && mRelayoutData->IsLayoutDirty(dimension);
1183 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1185 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1188 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1190 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1193 uint32_t Actor::AddRenderer( Renderer& renderer )
1197 mRenderers = new RendererContainer;
1200 if(mIsBlendEquationSet)
1202 renderer.SetBlendEquation(static_cast<DevelBlendEquation::Type>(mBlendEquation));
1205 uint32_t index = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1206 RendererPtr rendererPtr = RendererPtr( &renderer );
1207 mRenderers->push_back( rendererPtr );
1208 AttachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1212 uint32_t Actor::GetRendererCount() const
1214 uint32_t rendererCount(0);
1217 rendererCount = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1220 return rendererCount;
1223 RendererPtr Actor::GetRendererAt( uint32_t index )
1225 RendererPtr renderer;
1226 if( index < GetRendererCount() )
1228 renderer = ( *mRenderers )[ index ];
1234 void Actor::RemoveRenderer( Renderer& renderer )
1238 RendererIter end = mRenderers->end();
1239 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1241 if( (*iter).Get() == &renderer )
1243 mRenderers->erase( iter );
1244 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1251 void Actor::RemoveRenderer( uint32_t index )
1253 if( index < GetRendererCount() )
1255 RendererPtr renderer = ( *mRenderers )[ index ];
1256 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.Get()->GetRendererSceneObject() );
1257 mRenderers->erase( mRenderers->begin()+index );
1261 void Actor::SetBlendEquation(DevelBlendEquation::Type blendEquation)
1263 if(Dali::Capabilities::IsBlendEquationSupported(blendEquation))
1265 if(mBlendEquation != blendEquation)
1267 mBlendEquation = blendEquation;
1268 uint32_t rendererCount = GetRendererCount();
1269 for(uint32_t i = 0; i < rendererCount; ++i)
1271 RendererPtr renderer = GetRendererAt(i);
1272 renderer->SetBlendEquation(static_cast<DevelBlendEquation::Type>(blendEquation));
1275 mIsBlendEquationSet = true;
1279 DALI_LOG_ERROR("Invalid blend equation is entered.\n");
1283 DevelBlendEquation::Type Actor::GetBlendEquation() const
1285 return mBlendEquation;
1288 void Actor::SetDrawMode( DrawMode::Type drawMode )
1290 // this flag is not animatable so keep the value
1291 mDrawMode = drawMode;
1293 // node is being used in a separate thread; queue a message to set the value
1294 SetDrawModeMessage( GetEventThreadServices(), GetNode(), drawMode );
1297 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1299 // only valid when on-stage
1300 if( mScene && OnScene() )
1302 const RenderTaskList& taskList = mScene->GetRenderTaskList();
1304 Vector2 converted( screenX, screenY );
1306 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1307 uint32_t taskCount = taskList.GetTaskCount();
1308 for( uint32_t i = taskCount; i > 0; --i )
1310 RenderTaskPtr task = taskList.GetTask( i - 1 );
1311 if( ScreenToLocal( *task, localX, localY, screenX, screenY ) )
1313 // found a task where this conversion was ok so return
1321 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1323 bool retval = false;
1324 // only valid when on-stage
1327 CameraActor* camera = renderTask.GetCameraActor();
1331 renderTask.GetViewport( viewport );
1333 // need to translate coordinates to render tasks coordinate space
1334 Vector2 converted( screenX, screenY );
1335 if( renderTask.TranslateCoordinates( converted ) )
1337 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1344 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1346 return OnScene() && ScreenToLocalInternal(viewMatrix, projectionMatrix, GetNode().GetWorldMatrix(0), viewport, GetCurrentSize(), localX, localY, screenX, screenY);
1349 ActorGestureData& Actor::GetGestureData()
1351 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1352 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1353 if( nullptr == mGestureData )
1355 mGestureData = new ActorGestureData;
1357 return *mGestureData;
1360 bool Actor::IsGestureRequired( GestureType::Value type ) const
1362 return mGestureData && mGestureData->IsGestureRequired( type );
1365 bool Actor::EmitInterceptTouchEventSignal( const Dali::TouchEvent& touch )
1367 return EmitConsumingSignal( *this, mInterceptTouchedSignal, touch );
1370 bool Actor::EmitTouchEventSignal( const Dali::TouchEvent& touch )
1372 return EmitConsumingSignal( *this, mTouchedSignal, touch );
1375 bool Actor::EmitHoverEventSignal( const Dali::HoverEvent& event )
1377 return EmitConsumingSignal( *this, mHoveredSignal, event );
1380 bool Actor::EmitWheelEventSignal( const Dali::WheelEvent& event )
1382 return EmitConsumingSignal( *this, mWheelEventSignal, event );
1385 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
1387 EmitSignal( *this, mVisibilityChangedSignal, visible, type );
1390 void Actor::EmitLayoutDirectionChangedSignal( LayoutDirection::Type type )
1392 EmitSignal( *this, mLayoutDirectionChangedSignal, type );
1395 void Actor::EmitChildAddedSignal( Actor& child )
1397 EmitSignal( child, mChildAddedSignal );
1400 void Actor::EmitChildRemovedSignal( Actor& child )
1402 EmitSignal( child, mChildRemovedSignal );
1405 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1407 bool connected( true );
1408 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
1410 std::string_view name(signalName);
1412 if(name == SIGNAL_HOVERED)
1414 actor->HoveredSignal().Connect( tracker, functor );
1416 else if(signalName == SIGNAL_WHEEL_EVENT)
1418 actor->WheelEventSignal().Connect( tracker, functor );
1420 else if(name == SIGNAL_ON_SCENE)
1422 actor->OnSceneSignal().Connect( tracker, functor );
1424 else if(name == SIGNAL_OFF_SCENE)
1426 actor->OffSceneSignal().Connect( tracker, functor );
1428 else if(name == SIGNAL_ON_RELAYOUT)
1430 actor->OnRelayoutSignal().Connect( tracker, functor );
1432 else if(name == SIGNAL_TOUCHED)
1434 actor->TouchedSignal().Connect( tracker, functor );
1436 else if(name == SIGNAL_VISIBILITY_CHANGED)
1438 actor->VisibilityChangedSignal().Connect( tracker, functor );
1440 else if(name == SIGNAL_LAYOUT_DIRECTION_CHANGED)
1442 actor->LayoutDirectionChangedSignal().Connect( tracker, functor );
1444 else if(name == SIGNAL_CHILD_ADDED)
1446 actor->ChildAddedSignal().Connect( tracker, functor );
1448 else if(name == SIGNAL_CHILD_REMOVED)
1450 actor->ChildRemovedSignal().Connect( tracker, functor );
1454 // signalName does not match any signal
1461 Actor::Actor( DerivedType derivedType, const SceneGraph::Node& node )
1465 mChildren( nullptr ),
1466 mRenderers( nullptr ),
1467 mParentOrigin( nullptr ),
1468 mAnchorPoint( nullptr ),
1469 mRelayoutData( nullptr ),
1470 mGestureData( nullptr ),
1471 mInterceptTouchedSignal(),
1474 mWheelEventSignal(),
1477 mOnRelayoutSignal(),
1478 mVisibilityChangedSignal(),
1479 mLayoutDirectionChangedSignal(),
1480 mChildAddedSignal(),
1481 mChildRemovedSignal(),
1482 mChildOrderChangedSignal(),
1483 mTargetOrientation( Quaternion::IDENTITY ),
1484 mTargetColor( Color::WHITE ),
1485 mTargetSize( Vector3::ZERO ),
1486 mTargetPosition( Vector3::ZERO ),
1487 mTargetScale( Vector3::ONE ),
1488 mAnimatedSize( Vector3::ZERO ),
1489 mTouchArea( Vector2::ZERO ),
1493 mUseAnimatedSize( AnimatedSizeFlag::CLEAR ),
1494 mIsRoot( ROOT_LAYER == derivedType ),
1495 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
1496 mIsOnScene( false ),
1498 mLeaveRequired( false ),
1499 mKeyboardFocusable( false ),
1500 mOnSceneSignalled( false ),
1501 mInsideOnSizeSet( false ),
1502 mInheritPosition( true ),
1503 mInheritOrientation( true ),
1504 mInheritScale( true ),
1505 mPositionUsesAnchorPoint( true ),
1507 mInheritLayoutDirection( true ),
1508 mCaptureAllTouchAfterStart( false ),
1509 mLayoutDirection( LayoutDirection::LEFT_TO_RIGHT ),
1510 mDrawMode( DrawMode::NORMAL ),
1511 mColorMode( Node::DEFAULT_COLOR_MODE ),
1512 mClippingMode( ClippingMode::DISABLED ),
1513 mBlendEquation( DevelBlendEquation::ADD ),
1514 mIsBlendEquationSet( false )
1518 void Actor::Initialize()
1522 GetEventThreadServices().RegisterObject( this );
1527 // Remove mParent pointers from children even if we're destroying core,
1528 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1531 for( const auto& actor : *mChildren )
1533 actor->SetParent( nullptr );
1539 // Guard to allow handle destruction after Core has been destroyed
1540 if( EventThreadServices::IsCoreRunning() )
1542 // Root layer will destroy its node in its own destructor
1545 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
1547 GetEventThreadServices().UnregisterObject( this );
1551 // Cleanup optional gesture data
1552 delete mGestureData;
1554 // Cleanup optional parent origin and anchor
1555 delete mParentOrigin;
1556 delete mAnchorPoint;
1558 // Delete optional relayout data
1559 delete mRelayoutData;
1562 void Actor::ConnectToScene( uint32_t parentDepth )
1564 // This container is used instead of walking the Actor hierarchy.
1565 // It protects us when the Actor hierarchy is modified during OnSceneConnectionExternal callbacks.
1566 ActorContainer connectionList;
1570 mScene->RequestRebuildDepthTree();
1573 // This stage is atomic i.e. not interrupted by user callbacks.
1574 RecursiveConnectToScene( connectionList, parentDepth + 1 );
1576 // Notify applications about the newly connected actors.
1577 for( const auto& actor : connectionList )
1579 actor->NotifyStageConnection();
1585 void Actor::RecursiveConnectToScene( ActorContainer& connectionList, uint32_t depth )
1587 DALI_ASSERT_ALWAYS( !OnScene() );
1590 mDepth = static_cast< uint16_t >( depth ); // overflow ignored, not expected in practice
1592 ConnectToSceneGraph();
1594 // Notification for internal derived classes
1595 OnSceneConnectionInternal();
1597 // This stage is atomic; avoid emitting callbacks until all Actors are connected
1598 connectionList.push_back( ActorPtr( this ) );
1600 // Recursively connect children
1603 for( const auto& actor : *mChildren )
1605 actor->SetScene( *mScene );
1606 actor->RecursiveConnectToScene( connectionList, depth + 1 );
1612 * This method is called when the Actor is connected to the Stage.
1613 * The parent must have added its Node to the scene-graph.
1614 * The child must connect its Node to the parent's Node.
1615 * This is recursive; the child calls ConnectToScene() for its children.
1617 void Actor::ConnectToSceneGraph()
1619 DALI_ASSERT_DEBUG( mParent != NULL);
1621 // Reparent Node in next Update
1622 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), mParent->GetNode(), GetNode() );
1624 // Request relayout on all actors that are added to the scenegraph
1627 // Notification for Object::Observers
1631 void Actor::NotifyStageConnection()
1633 // Actors can be removed (in a callback), before the on-stage stage is reported.
1634 // The actor may also have been reparented, in which case mOnSceneSignalled will be true.
1635 if( OnScene() && !mOnSceneSignalled )
1637 // Notification for external (CustomActor) derived classes
1638 OnSceneConnectionExternal( mDepth );
1640 if( !mOnSceneSignal.Empty() )
1642 Dali::Actor handle( this );
1643 mOnSceneSignal.Emit( handle );
1646 // Guard against Remove during callbacks
1649 mOnSceneSignalled = true; // signal required next time Actor is removed
1654 void Actor::DisconnectFromStage()
1656 // This container is used instead of walking the Actor hierachy.
1657 // It protects us when the Actor hierachy is modified during OnSceneDisconnectionExternal callbacks.
1658 ActorContainer disconnectionList;
1662 mScene->RequestRebuildDepthTree();
1665 // This stage is atomic i.e. not interrupted by user callbacks
1666 RecursiveDisconnectFromStage( disconnectionList );
1668 // Notify applications about the newly disconnected actors.
1669 for( const auto& actor : disconnectionList )
1671 actor->NotifyStageDisconnection();
1675 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
1677 // need to change state first so that internals relying on IsOnScene() inside OnSceneDisconnectionInternal() get the correct value
1680 // Recursively disconnect children
1683 for( const auto& child : *mChildren )
1685 child->RecursiveDisconnectFromStage( disconnectionList );
1689 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
1690 disconnectionList.push_back( ActorPtr( this ) );
1692 // Notification for internal derived classes
1693 OnSceneDisconnectionInternal();
1695 DisconnectFromSceneGraph();
1699 * This method is called by an actor or its parent, before a node removal message is sent.
1700 * This is recursive; the child calls DisconnectFromStage() for its children.
1702 void Actor::DisconnectFromSceneGraph()
1704 // Notification for Object::Observers
1705 OnSceneObjectRemove();
1708 void Actor::NotifyStageDisconnection()
1710 // Actors can be added (in a callback), before the off-stage state is reported.
1711 // Also if the actor was added & removed before mOnSceneSignalled was set, then we don't notify here.
1712 // only do this step if there is a stage, i.e. Core is not being shut down
1713 if ( EventThreadServices::IsCoreRunning() && !OnScene() && mOnSceneSignalled )
1715 // Notification for external (CustomeActor) derived classes
1716 OnSceneDisconnectionExternal();
1718 if( !mOffSceneSignal.Empty() )
1720 Dali::Actor handle( this );
1721 mOffSceneSignal.Emit( handle );
1724 // Guard against Add during callbacks
1727 mOnSceneSignalled = false; // signal required next time Actor is added
1732 bool Actor::IsNodeConnected() const
1734 bool connected( false );
1738 if( IsRoot() || GetNode().GetParent() )
1747 // This method initiates traversal of the actor tree using depth-first
1748 // traversal to set a depth index based on traversal order. It sends a
1749 // single message to update manager to update all the actor's nodes in
1750 // this tree with the depth index. The sceneGraphNodeDepths vector's
1751 // elements are ordered by depth, and could be used to reduce sorting
1752 // in the update thread.
1753 void Actor::RebuildDepthTree()
1755 DALI_LOG_TIMER_START(depthTimer);
1757 // Vector of scene-graph nodes and their depths to send to UpdateManager
1758 // in a single message
1759 OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths( new SceneGraph::NodeDepths() );
1761 int32_t depthIndex = 1;
1762 DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
1764 SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths );
1765 DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
1768 void Actor::DepthTraverseActorTree( OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths, int32_t& depthIndex )
1770 mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
1771 sceneGraphNodeDepths->Add( const_cast<SceneGraph::Node*>( &GetNode() ), mSortedDepth );
1773 // Create/add to children of this node
1776 for( const auto& child : *mChildren )
1778 Actor* childActor = child.Get();
1780 childActor->DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
1785 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
1787 PropertyHandler::SetDefaultProperty(*this, index, property);
1790 // TODO: This method needs to be removed
1791 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
1793 PropertyHandler::SetSceneGraphProperty(index, entry, value, GetEventThreadServices(), GetNode());
1796 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
1798 Property::Value value;
1800 if( ! GetCachedPropertyValue( index, value ) )
1802 // If property value is not stored in the event-side, then it must be a scene-graph only property
1803 GetCurrentPropertyValue( index, value );
1809 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
1811 Property::Value value;
1813 if( ! GetCurrentPropertyValue( index, value ) )
1815 // If unable to retrieve scene-graph property value, then it must be an event-side only property
1816 GetCachedPropertyValue( index, value );
1822 void Actor::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
1824 PropertyHandler::OnNotifyDefaultPropertyAnimation(*this, animation, index, value, animationType);
1827 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
1829 const PropertyBase* property = PropertyHandler::GetSceneObjectAnimatableProperty(index, GetNode());
1832 // not our property, ask base
1833 property = Object::GetSceneObjectAnimatableProperty( index );
1839 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
1841 const PropertyInputImpl* property = PropertyHandler::GetSceneObjectInputProperty(index, GetNode());
1844 // reuse animatable property getter as animatable properties are inputs as well
1845 // animatable property chains back to Object::GetSceneObjectInputProperty() so all properties get covered
1846 property = GetSceneObjectAnimatableProperty( index );
1852 int32_t Actor::GetPropertyComponentIndex( Property::Index index ) const
1854 int32_t componentIndex = PropertyHandler::GetPropertyComponentIndex(index);
1855 if( Property::INVALID_COMPONENT_INDEX == componentIndex )
1858 componentIndex = Object::GetPropertyComponentIndex( index );
1861 return componentIndex;
1864 void Actor::SetParent( Actor* parent )
1868 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
1872 mScene = parent->mScene;
1874 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1877 // Instruct each actor to create a corresponding node in the scene graph
1878 ConnectToScene( parent->GetHierarchyDepth() );
1881 // Resolve the name and index for the child properties if any
1882 ResolveChildProperties();
1884 else // parent being set to NULL
1886 DALI_ASSERT_ALWAYS( mParent != nullptr && "Actor should have a parent" );
1890 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1893 // Disconnect the Node & its children from the scene-graph.
1894 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
1896 // Instruct each actor to discard pointers to the scene-graph
1897 DisconnectFromStage();
1904 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
1907 Actor* actor = dynamic_cast< Actor* >( object );
1911 std::string_view name(actionName);
1912 if(name == ACTION_SHOW)
1914 actor->SetVisible( true );
1917 else if(name == ACTION_HIDE)
1919 actor->SetVisible( false );
1927 Rect<> Actor::CalculateScreenExtents( ) const
1929 auto screenPosition = GetCurrentScreenPosition();
1930 Vector3 size = GetCurrentSize() * GetCurrentWorldScale();
1931 Vector3 anchorPointOffSet = size * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
1932 Vector2 position = Vector2( screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y );
1933 return { position.x, position.y, size.x, size.y };
1936 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
1938 return PropertyHandler::GetCachedPropertyValue(*this, index, value);
1941 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
1943 return PropertyHandler::GetCurrentPropertyValue(*this, index, value);
1946 Actor::Relayouter& Actor::EnsureRelayouter()
1948 // Assign relayouter
1949 if( !mRelayoutData )
1951 mRelayoutData = new Relayouter();
1954 return *mRelayoutData;
1957 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
1959 // Check if actor is dependent on parent
1960 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1962 if( ( dimension & ( 1 << i ) ) )
1964 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
1965 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
1975 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
1977 // Check if actor is dependent on children
1978 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1980 if( ( dimension & ( 1 << i ) ) )
1982 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
1983 switch( resizePolicy )
1985 case ResizePolicy::FIT_TO_CHILDREN:
1986 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
2002 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
2004 return Actor::RelayoutDependentOnChildren( dimension );
2007 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
2009 // Check each possible dimension and see if it is dependent on the input one
2010 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2012 if( dimension & ( 1 << i ) )
2014 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
2021 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
2023 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2025 if( dimension & ( 1 << i ) )
2027 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
2032 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
2034 // If more than one dimension is requested, just return the first one found
2035 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2037 if( ( dimension & ( 1 << i ) ) )
2039 return mRelayoutData->negotiatedDimensions[ i ];
2043 return 0.0f; // Default
2046 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
2048 EnsureRelayouter().SetPadding( padding, dimension );
2051 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
2053 if ( mRelayoutData )
2055 // If more than one dimension is requested, just return the first one found
2056 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2058 if( ( dimension & ( 1 << i ) ) )
2060 return mRelayoutData->dimensionPadding[ i ];
2065 return Relayouter::DEFAULT_DIMENSION_PADDING;
2068 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
2070 EnsureRelayouter().SetLayoutNegotiated(negotiated, dimension);
2073 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
2075 return mRelayoutData && mRelayoutData->IsLayoutNegotiated(dimension);
2078 float Actor::GetHeightForWidthBase( float width )
2080 float height = 0.0f;
2082 const Vector3 naturalSize = GetNaturalSize();
2083 if( naturalSize.width > 0.0f )
2085 height = naturalSize.height * width / naturalSize.width;
2087 else // we treat 0 as 1:1 aspect ratio
2095 float Actor::GetWidthForHeightBase( float height )
2099 const Vector3 naturalSize = GetNaturalSize();
2100 if( naturalSize.height > 0.0f )
2102 width = naturalSize.width * height / naturalSize.height;
2104 else // we treat 0 as 1:1 aspect ratio
2112 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
2114 // Fill to parent, taking size mode factor into account
2115 switch( child.GetResizePolicy( dimension ) )
2117 case ResizePolicy::FILL_TO_PARENT:
2119 return GetLatestSize( dimension );
2122 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2124 return GetLatestSize( dimension ) * GetDimensionValue( child.GetProperty< Vector3 >( Dali::Actor::Property::SIZE_MODE_FACTOR ), dimension );
2127 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2129 return GetLatestSize( dimension ) + GetDimensionValue( child.GetProperty< Vector3 >( Dali::Actor::Property::SIZE_MODE_FACTOR ), dimension );
2134 return GetLatestSize( dimension );
2139 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
2141 // Can be overridden in derived class
2142 return CalculateChildSizeBase( child, dimension );
2145 float Actor::GetHeightForWidth( float width )
2147 // Can be overridden in derived class
2148 return GetHeightForWidthBase( width );
2151 float Actor::GetWidthForHeight( float height )
2153 // Can be overridden in derived class
2154 return GetWidthForHeightBase( height );
2157 float Actor::GetLatestSize( Dimension::Type dimension ) const
2159 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
2162 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
2164 Vector2 padding = GetPadding( dimension );
2166 return GetLatestSize( dimension ) + padding.x + padding.y;
2169 float Actor::NegotiateFromParent( Dimension::Type dimension )
2171 Actor* parent = GetParent();
2174 Vector2 padding( GetPadding( dimension ) );
2175 Vector2 parentPadding( parent->GetPadding( dimension ) );
2176 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
2182 float Actor::NegotiateFromChildren( Dimension::Type dimension )
2184 float maxDimensionPoint = 0.0f;
2186 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2188 ActorPtr child = GetChildAt( i );
2190 if( !child->RelayoutDependentOnParent( dimension ) )
2192 // Calculate the min and max points that the children range across
2193 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
2194 float dimensionSize = child->GetRelayoutSize( dimension );
2195 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
2199 return maxDimensionPoint;
2202 float Actor::GetSize( Dimension::Type dimension ) const
2204 return GetDimensionValue( mTargetSize, dimension );
2207 float Actor::GetNaturalSize( Dimension::Type dimension ) const
2209 return GetDimensionValue( GetNaturalSize(), dimension );
2212 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
2214 switch( GetResizePolicy( dimension ) )
2216 case ResizePolicy::USE_NATURAL_SIZE:
2218 return GetNaturalSize( dimension );
2221 case ResizePolicy::FIXED:
2223 return GetDimensionValue( GetPreferredSize(), dimension );
2226 case ResizePolicy::USE_ASSIGNED_SIZE:
2228 return GetDimensionValue( maximumSize, dimension );
2231 case ResizePolicy::FILL_TO_PARENT:
2232 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2233 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2235 return NegotiateFromParent( dimension );
2238 case ResizePolicy::FIT_TO_CHILDREN:
2240 return NegotiateFromChildren( dimension );
2243 case ResizePolicy::DIMENSION_DEPENDENCY:
2245 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
2248 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
2250 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
2253 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
2255 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
2267 return 0.0f; // Default
2270 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
2272 // Check if it needs to be negotiated
2273 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
2275 // Check that we havn't gotten into an infinite loop
2276 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
2277 bool recursionFound = false;
2278 for( auto& element : recursionStack )
2280 if( element == searchActor )
2282 recursionFound = true;
2287 if( !recursionFound )
2289 // Record the path that we have taken
2290 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
2292 // Dimension dependency check
2293 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2295 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
2297 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
2299 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
2303 // Parent dependency check
2304 Actor* parent = GetParent();
2305 if( parent && RelayoutDependentOnParent( dimension ) )
2307 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
2310 // Children dependency check
2311 if( RelayoutDependentOnChildren( dimension ) )
2313 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2315 ActorPtr child = GetChildAt( i );
2317 // Only relayout child first if it is not dependent on this actor
2318 if( !child->RelayoutDependentOnParent( dimension ) )
2320 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
2325 // For deriving classes
2326 OnCalculateRelayoutSize( dimension );
2328 // All dependencies checked, calculate the size and set negotiated flag
2329 const float newSize = Relayouter::ClampDimension( *this, CalculateSize( dimension, allocatedSize ), dimension );
2331 SetNegotiatedDimension( newSize, dimension );
2332 SetLayoutNegotiated( true, dimension );
2334 // For deriving classes
2335 OnLayoutNegotiated( newSize, dimension );
2337 // This actor has been successfully processed, pop it off the recursion stack
2338 recursionStack.pop_back();
2342 // TODO: Break infinite loop
2343 SetLayoutNegotiated( true, dimension );
2348 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
2350 // Negotiate all dimensions that require it
2351 ActorDimensionStack recursionStack;
2353 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2355 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
2358 NegotiateDimension( dimension, allocatedSize, recursionStack );
2362 Vector2 Actor::ApplySizeSetPolicy( const Vector2& size )
2364 return mRelayoutData->ApplySizeSetPolicy(*this, size);
2367 void Actor::SetNegotiatedSize( RelayoutContainer& container )
2369 // Do the set actor size
2370 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
2372 // Adjust for size set policy
2373 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
2375 // Lock the flag to stop recursive relayouts on set size
2376 mRelayoutData->insideRelayout = true;
2377 SetSize( negotiatedSize );
2378 mRelayoutData->insideRelayout = false;
2380 // Clear flags for all dimensions
2381 SetLayoutDirty( false );
2383 // Give deriving classes a chance to respond
2384 OnRelayout( negotiatedSize, container );
2386 if( !mOnRelayoutSignal.Empty() )
2388 Dali::Actor handle( this );
2389 mOnRelayoutSignal.Emit( handle );
2393 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
2395 // Force a size negotiation for actors that has assigned size during relayout
2396 // This is required as otherwise the flags that force a relayout will not
2397 // necessarilly be set. This will occur if the actor has already been laid out.
2398 // The dirty flags are then cleared. Then if the actor is added back into the
2399 // relayout container afterwards, the dirty flags would still be clear...
2400 // causing a relayout to be skipped. Here we force any actors added to the
2401 // container to be relayed out.
2402 DALI_LOG_TIMER_START( NegSizeTimer1 );
2404 if( GetUseAssignedSize(Dimension::WIDTH ) )
2406 SetLayoutNegotiated( false, Dimension::WIDTH );
2408 if( GetUseAssignedSize( Dimension::HEIGHT ) )
2410 SetLayoutNegotiated( false, Dimension::HEIGHT );
2413 // Do the negotiation
2414 NegotiateDimensions( allocatedSize );
2416 // Set the actor size
2417 SetNegotiatedSize( container );
2419 // Negotiate down to children
2420 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2422 ActorPtr child = GetChildAt( i );
2424 // Forces children that have already been laid out to be relayed out
2425 // if they have assigned size during relayout.
2426 if( child->GetUseAssignedSize(Dimension::WIDTH) )
2428 child->SetLayoutNegotiated(false, Dimension::WIDTH);
2429 child->SetLayoutDirty(true, Dimension::WIDTH);
2432 if( child->GetUseAssignedSize(Dimension::HEIGHT) )
2434 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
2435 child->SetLayoutDirty(true, Dimension::HEIGHT);
2438 // Only relayout if required
2439 if( child->RelayoutRequired() )
2441 container.Add( Dali::Actor( child.Get() ), mTargetSize.GetVectorXY() );
2444 DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
2447 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
2451 mRelayoutData->SetUseAssignedSize(use, dimension);
2455 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
2457 return mRelayoutData && mRelayoutData->GetUseAssignedSize(dimension);
2460 void Actor::RelayoutRequest( Dimension::Type dimension )
2462 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
2463 if( relayoutController )
2465 Dali::Actor self( this );
2466 relayoutController->RequestRelayout( self, dimension );
2470 void Actor::SetPreferredSize( const Vector2& size )
2474 // If valid width or height, then set the resize policy to FIXED
2475 // 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,
2476 // then change to FIXED as well
2478 if( size.width > 0.0f || GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DEFAULT )
2480 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
2483 if( size.height > 0.0f || GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DEFAULT )
2485 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
2488 mRelayoutData->preferredSize = size;
2490 mUseAnimatedSize = AnimatedSizeFlag::CLEAR;
2495 Vector2 Actor::GetPreferredSize() const
2497 if ( mRelayoutData )
2499 return Vector2( mRelayoutData->preferredSize );
2502 return Relayouter::DEFAULT_PREFERRED_SIZE;
2505 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
2507 EnsureRelayouter().SetMinimumSize(size, dimension);
2511 float Actor::GetMinimumSize( Dimension::Type dimension ) const
2513 if ( mRelayoutData )
2515 return mRelayoutData->GetMinimumSize(dimension);
2518 return 0.0f; // Default
2521 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
2523 EnsureRelayouter().SetMaximumSize(size, dimension);
2527 float Actor::GetMaximumSize( Dimension::Type dimension ) const
2529 if ( mRelayoutData )
2531 return mRelayoutData->GetMaximumSize(dimension);
2534 return FLT_MAX; // Default
2537 void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
2539 if( mVisible != visible )
2541 if( sendMessage == SendMessage::TRUE )
2543 // node is being used in a separate thread; queue a message to set the value & base value
2544 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible );
2546 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
2551 // Emit the signal on this actor and all its children
2552 EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
2556 void Actor::SetSiblingOrder( uint32_t order )
2560 ActorContainer& siblings = *(mParent->mChildren);
2561 uint32_t currentOrder = GetSiblingOrder();
2563 if( order != currentOrder )
2569 else if( order < siblings.size() -1 )
2571 if( order > currentOrder )
2573 RaiseAbove( *siblings[order] );
2577 LowerBelow( *siblings[order] );
2588 uint32_t Actor::GetSiblingOrder() const
2594 ActorContainer& siblings = *(mParent->mChildren);
2595 for( std::size_t i = 0; i < siblings.size(); ++i )
2597 if( siblings[i] == this )
2599 order = static_cast<uint32_t>( i );
2608 void Actor::RequestRebuildDepthTree()
2614 mScene->RequestRebuildDepthTree();
2623 ActorContainer& siblings = *(mParent->mChildren);
2624 if( siblings.back() != this ) // If not already at end
2626 for( std::size_t i=0; i<siblings.size(); ++i )
2628 if( siblings[i] == this )
2631 ActorPtr next = siblings[i+1];
2632 siblings[i+1] = this;
2639 Dali::Actor handle( this );
2640 mParent->mChildOrderChangedSignal.Emit( handle );
2642 RequestRebuildDepthTree();
2646 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2654 ActorContainer& siblings = *(mParent->mChildren);
2655 if( siblings.front() != this ) // If not already at beginning
2657 for( std::size_t i=1; i<siblings.size(); ++i )
2659 if( siblings[i] == this )
2661 // Swap with previous
2662 ActorPtr previous = siblings[i-1];
2663 siblings[i-1] = this;
2664 siblings[i] = previous;
2670 Dali::Actor handle( this );
2671 mParent->mChildOrderChangedSignal.Emit( handle );
2673 RequestRebuildDepthTree();
2677 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2681 void Actor::RaiseToTop()
2685 ActorContainer& siblings = *(mParent->mChildren);
2686 if( siblings.back() != this ) // If not already at end
2688 auto iter = std::find( siblings.begin(), siblings.end(), this );
2689 if( iter != siblings.end() )
2691 siblings.erase(iter);
2692 siblings.push_back(ActorPtr(this));
2696 Dali::Actor handle( this );
2697 mParent->mChildOrderChangedSignal.Emit( handle );
2699 RequestRebuildDepthTree();
2703 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2707 void Actor::LowerToBottom()
2711 ActorContainer& siblings = *(mParent->mChildren);
2712 if( siblings.front() != this ) // If not already at bottom,
2714 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2716 auto iter = std::find( siblings.begin(), siblings.end(), this );
2717 if( iter != siblings.end() )
2719 siblings.erase(iter);
2720 siblings.insert(siblings.begin(), thisPtr);
2724 Dali::Actor handle( this );
2725 mParent->mChildOrderChangedSignal.Emit( handle );
2727 RequestRebuildDepthTree();
2731 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2735 void Actor::RaiseAbove( Internal::Actor& target )
2739 ActorContainer& siblings = *(mParent->mChildren);
2740 if( siblings.back() != this && target.mParent == mParent ) // If not already at top
2742 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2744 auto targetIter = std::find( siblings.begin(), siblings.end(), &target );
2745 auto thisIter = std::find( siblings.begin(), siblings.end(), this );
2746 if( thisIter < targetIter )
2748 siblings.erase(thisIter);
2749 // Erasing early invalidates the targetIter. (Conversely, inserting first may also
2750 // invalidate thisIter)
2751 targetIter = std::find( siblings.begin(), siblings.end(), &target );
2753 siblings.insert(targetIter, thisPtr);
2756 Dali::Actor handle( this );
2757 mParent->mChildOrderChangedSignal.Emit( handle );
2759 RequestRebuildDepthTree();
2764 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2768 void Actor::LowerBelow( Internal::Actor& target )
2772 ActorContainer& siblings = *(mParent->mChildren);
2773 if( siblings.front() != this && target.mParent == mParent ) // If not already at bottom
2775 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2777 auto targetIter = std::find( siblings.begin(), siblings.end(), &target );
2778 auto thisIter = std::find( siblings.begin(), siblings.end(), this );
2780 if( thisIter > targetIter )
2782 siblings.erase(thisIter); // this only invalidates iterators at or after this point.
2783 siblings.insert(targetIter, thisPtr);
2786 Dali::Actor handle( this );
2787 mParent->mChildOrderChangedSignal.Emit( handle );
2789 RequestRebuildDepthTree();
2794 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2798 void Actor::SetInheritLayoutDirection( bool inherit )
2800 if( mInheritLayoutDirection != inherit )
2802 mInheritLayoutDirection = inherit;
2804 if( inherit && mParent )
2806 InheritLayoutDirectionRecursively( this, mParent->mLayoutDirection );
2811 void Actor::InheritLayoutDirectionRecursively( ActorPtr actor, Dali::LayoutDirection::Type direction, bool set )
2813 if( actor && ( actor->mInheritLayoutDirection || set ) )
2815 if( actor->mLayoutDirection != direction )
2817 actor->mLayoutDirection = direction;
2818 actor->EmitLayoutDirectionChangedSignal( direction );
2819 actor->RelayoutRequest();
2822 if( actor->GetChildCount() > 0 )
2824 for( const auto& child : actor->GetChildrenInternal() )
2826 InheritLayoutDirectionRecursively( child, direction );
2832 void Actor::SetUpdateSizeHint( const Vector2& updateSizeHint )
2834 // node is being used in a separate thread; queue a message to set the value & base value
2835 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mUpdateSizeHint, &AnimatableProperty<Vector3>::Bake, Vector3(updateSizeHint.width, updateSizeHint.height, 0.f ) );
2838 } // namespace Internal