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.SetBlendMode(Dali::BlendMode::ON);
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->SetBlendMode(Dali::BlendMode::ON);
1274 renderer->SetBlendEquation(static_cast<DevelBlendEquation::Type>(blendEquation));
1277 mIsBlendEquationSet = true;
1281 DALI_LOG_ERROR("Invalid blend equation is entered.\n");
1285 DevelBlendEquation::Type Actor::GetBlendEquation() const
1287 return mBlendEquation;
1290 void Actor::SetDrawMode( DrawMode::Type drawMode )
1292 // this flag is not animatable so keep the value
1293 mDrawMode = drawMode;
1295 // node is being used in a separate thread; queue a message to set the value
1296 SetDrawModeMessage( GetEventThreadServices(), GetNode(), drawMode );
1299 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1301 // only valid when on-stage
1302 if( mScene && OnScene() )
1304 const RenderTaskList& taskList = mScene->GetRenderTaskList();
1306 Vector2 converted( screenX, screenY );
1308 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1309 uint32_t taskCount = taskList.GetTaskCount();
1310 for( uint32_t i = taskCount; i > 0; --i )
1312 RenderTaskPtr task = taskList.GetTask( i - 1 );
1313 if( ScreenToLocal( *task, localX, localY, screenX, screenY ) )
1315 // found a task where this conversion was ok so return
1323 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1325 bool retval = false;
1326 // only valid when on-stage
1329 CameraActor* camera = renderTask.GetCameraActor();
1333 renderTask.GetViewport( viewport );
1335 // need to translate coordinates to render tasks coordinate space
1336 Vector2 converted( screenX, screenY );
1337 if( renderTask.TranslateCoordinates( converted ) )
1339 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1346 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1348 return OnScene() && ScreenToLocalInternal(viewMatrix, projectionMatrix, GetNode().GetWorldMatrix(0), viewport, GetCurrentSize(), localX, localY, screenX, screenY);
1351 ActorGestureData& Actor::GetGestureData()
1353 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1354 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1355 if( nullptr == mGestureData )
1357 mGestureData = new ActorGestureData;
1359 return *mGestureData;
1362 bool Actor::IsGestureRequired( GestureType::Value type ) const
1364 return mGestureData && mGestureData->IsGestureRequired( type );
1367 bool Actor::EmitInterceptTouchEventSignal( const Dali::TouchEvent& touch )
1369 return EmitConsumingSignal( *this, mInterceptTouchedSignal, touch );
1372 bool Actor::EmitTouchEventSignal( const Dali::TouchEvent& touch )
1374 return EmitConsumingSignal( *this, mTouchedSignal, touch );
1377 bool Actor::EmitHoverEventSignal( const Dali::HoverEvent& event )
1379 return EmitConsumingSignal( *this, mHoveredSignal, event );
1382 bool Actor::EmitWheelEventSignal( const Dali::WheelEvent& event )
1384 return EmitConsumingSignal( *this, mWheelEventSignal, event );
1387 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
1389 EmitSignal( *this, mVisibilityChangedSignal, visible, type );
1392 void Actor::EmitLayoutDirectionChangedSignal( LayoutDirection::Type type )
1394 EmitSignal( *this, mLayoutDirectionChangedSignal, type );
1397 void Actor::EmitChildAddedSignal( Actor& child )
1399 EmitSignal( child, mChildAddedSignal );
1402 void Actor::EmitChildRemovedSignal( Actor& child )
1404 EmitSignal( child, mChildRemovedSignal );
1407 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1409 bool connected( true );
1410 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
1412 std::string_view name(signalName);
1414 if(name == SIGNAL_HOVERED)
1416 actor->HoveredSignal().Connect( tracker, functor );
1418 else if(signalName == SIGNAL_WHEEL_EVENT)
1420 actor->WheelEventSignal().Connect( tracker, functor );
1422 else if(name == SIGNAL_ON_SCENE)
1424 actor->OnSceneSignal().Connect( tracker, functor );
1426 else if(name == SIGNAL_OFF_SCENE)
1428 actor->OffSceneSignal().Connect( tracker, functor );
1430 else if(name == SIGNAL_ON_RELAYOUT)
1432 actor->OnRelayoutSignal().Connect( tracker, functor );
1434 else if(name == SIGNAL_TOUCHED)
1436 actor->TouchedSignal().Connect( tracker, functor );
1438 else if(name == SIGNAL_VISIBILITY_CHANGED)
1440 actor->VisibilityChangedSignal().Connect( tracker, functor );
1442 else if(name == SIGNAL_LAYOUT_DIRECTION_CHANGED)
1444 actor->LayoutDirectionChangedSignal().Connect( tracker, functor );
1446 else if(name == SIGNAL_CHILD_ADDED)
1448 actor->ChildAddedSignal().Connect( tracker, functor );
1450 else if(name == SIGNAL_CHILD_REMOVED)
1452 actor->ChildRemovedSignal().Connect( tracker, functor );
1456 // signalName does not match any signal
1463 Actor::Actor( DerivedType derivedType, const SceneGraph::Node& node )
1467 mChildren( nullptr ),
1468 mRenderers( nullptr ),
1469 mParentOrigin( nullptr ),
1470 mAnchorPoint( nullptr ),
1471 mRelayoutData( nullptr ),
1472 mGestureData( nullptr ),
1473 mInterceptTouchedSignal(),
1476 mWheelEventSignal(),
1479 mOnRelayoutSignal(),
1480 mVisibilityChangedSignal(),
1481 mLayoutDirectionChangedSignal(),
1482 mChildAddedSignal(),
1483 mChildRemovedSignal(),
1484 mChildOrderChangedSignal(),
1485 mTargetOrientation( Quaternion::IDENTITY ),
1486 mTargetColor( Color::WHITE ),
1487 mTargetSize( Vector3::ZERO ),
1488 mTargetPosition( Vector3::ZERO ),
1489 mTargetScale( Vector3::ONE ),
1490 mAnimatedSize( Vector3::ZERO ),
1491 mTouchArea( Vector2::ZERO ),
1495 mUseAnimatedSize( AnimatedSizeFlag::CLEAR ),
1496 mIsRoot( ROOT_LAYER == derivedType ),
1497 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
1498 mIsOnScene( false ),
1500 mLeaveRequired( false ),
1501 mKeyboardFocusable( false ),
1502 mOnSceneSignalled( false ),
1503 mInsideOnSizeSet( false ),
1504 mInheritPosition( true ),
1505 mInheritOrientation( true ),
1506 mInheritScale( true ),
1507 mPositionUsesAnchorPoint( true ),
1509 mInheritLayoutDirection( true ),
1510 mCaptureAllTouchAfterStart( false ),
1511 mLayoutDirection( LayoutDirection::LEFT_TO_RIGHT ),
1512 mDrawMode( DrawMode::NORMAL ),
1513 mColorMode( Node::DEFAULT_COLOR_MODE ),
1514 mClippingMode( ClippingMode::DISABLED ),
1515 mBlendEquation( DevelBlendEquation::ADD ),
1516 mIsBlendEquationSet( false )
1520 void Actor::Initialize()
1524 GetEventThreadServices().RegisterObject( this );
1529 // Remove mParent pointers from children even if we're destroying core,
1530 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1533 for( const auto& actor : *mChildren )
1535 actor->SetParent( nullptr );
1541 // Guard to allow handle destruction after Core has been destroyed
1542 if( EventThreadServices::IsCoreRunning() )
1544 // Root layer will destroy its node in its own destructor
1547 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
1549 GetEventThreadServices().UnregisterObject( this );
1553 // Cleanup optional gesture data
1554 delete mGestureData;
1556 // Cleanup optional parent origin and anchor
1557 delete mParentOrigin;
1558 delete mAnchorPoint;
1560 // Delete optional relayout data
1561 delete mRelayoutData;
1564 void Actor::ConnectToScene( uint32_t parentDepth )
1566 // This container is used instead of walking the Actor hierarchy.
1567 // It protects us when the Actor hierarchy is modified during OnSceneConnectionExternal callbacks.
1568 ActorContainer connectionList;
1572 mScene->RequestRebuildDepthTree();
1575 // This stage is atomic i.e. not interrupted by user callbacks.
1576 RecursiveConnectToScene( connectionList, parentDepth + 1 );
1578 // Notify applications about the newly connected actors.
1579 for( const auto& actor : connectionList )
1581 actor->NotifyStageConnection();
1587 void Actor::RecursiveConnectToScene( ActorContainer& connectionList, uint32_t depth )
1589 DALI_ASSERT_ALWAYS( !OnScene() );
1592 mDepth = static_cast< uint16_t >( depth ); // overflow ignored, not expected in practice
1594 ConnectToSceneGraph();
1596 // Notification for internal derived classes
1597 OnSceneConnectionInternal();
1599 // This stage is atomic; avoid emitting callbacks until all Actors are connected
1600 connectionList.push_back( ActorPtr( this ) );
1602 // Recursively connect children
1605 for( const auto& actor : *mChildren )
1607 actor->SetScene( *mScene );
1608 actor->RecursiveConnectToScene( connectionList, depth + 1 );
1614 * This method is called when the Actor is connected to the Stage.
1615 * The parent must have added its Node to the scene-graph.
1616 * The child must connect its Node to the parent's Node.
1617 * This is recursive; the child calls ConnectToScene() for its children.
1619 void Actor::ConnectToSceneGraph()
1621 DALI_ASSERT_DEBUG( mParent != NULL);
1623 // Reparent Node in next Update
1624 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), mParent->GetNode(), GetNode() );
1626 // Request relayout on all actors that are added to the scenegraph
1629 // Notification for Object::Observers
1633 void Actor::NotifyStageConnection()
1635 // Actors can be removed (in a callback), before the on-stage stage is reported.
1636 // The actor may also have been reparented, in which case mOnSceneSignalled will be true.
1637 if( OnScene() && !mOnSceneSignalled )
1639 // Notification for external (CustomActor) derived classes
1640 OnSceneConnectionExternal( mDepth );
1642 if( !mOnSceneSignal.Empty() )
1644 Dali::Actor handle( this );
1645 mOnSceneSignal.Emit( handle );
1648 // Guard against Remove during callbacks
1651 mOnSceneSignalled = true; // signal required next time Actor is removed
1656 void Actor::DisconnectFromStage()
1658 // This container is used instead of walking the Actor hierachy.
1659 // It protects us when the Actor hierachy is modified during OnSceneDisconnectionExternal callbacks.
1660 ActorContainer disconnectionList;
1664 mScene->RequestRebuildDepthTree();
1667 // This stage is atomic i.e. not interrupted by user callbacks
1668 RecursiveDisconnectFromStage( disconnectionList );
1670 // Notify applications about the newly disconnected actors.
1671 for( const auto& actor : disconnectionList )
1673 actor->NotifyStageDisconnection();
1677 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
1679 // need to change state first so that internals relying on IsOnScene() inside OnSceneDisconnectionInternal() get the correct value
1682 // Recursively disconnect children
1685 for( const auto& child : *mChildren )
1687 child->RecursiveDisconnectFromStage( disconnectionList );
1691 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
1692 disconnectionList.push_back( ActorPtr( this ) );
1694 // Notification for internal derived classes
1695 OnSceneDisconnectionInternal();
1697 DisconnectFromSceneGraph();
1701 * This method is called by an actor or its parent, before a node removal message is sent.
1702 * This is recursive; the child calls DisconnectFromStage() for its children.
1704 void Actor::DisconnectFromSceneGraph()
1706 // Notification for Object::Observers
1707 OnSceneObjectRemove();
1710 void Actor::NotifyStageDisconnection()
1712 // Actors can be added (in a callback), before the off-stage state is reported.
1713 // Also if the actor was added & removed before mOnSceneSignalled was set, then we don't notify here.
1714 // only do this step if there is a stage, i.e. Core is not being shut down
1715 if ( EventThreadServices::IsCoreRunning() && !OnScene() && mOnSceneSignalled )
1717 // Notification for external (CustomeActor) derived classes
1718 OnSceneDisconnectionExternal();
1720 if( !mOffSceneSignal.Empty() )
1722 Dali::Actor handle( this );
1723 mOffSceneSignal.Emit( handle );
1726 // Guard against Add during callbacks
1729 mOnSceneSignalled = false; // signal required next time Actor is added
1734 bool Actor::IsNodeConnected() const
1736 bool connected( false );
1740 if( IsRoot() || GetNode().GetParent() )
1749 // This method initiates traversal of the actor tree using depth-first
1750 // traversal to set a depth index based on traversal order. It sends a
1751 // single message to update manager to update all the actor's nodes in
1752 // this tree with the depth index. The sceneGraphNodeDepths vector's
1753 // elements are ordered by depth, and could be used to reduce sorting
1754 // in the update thread.
1755 void Actor::RebuildDepthTree()
1757 DALI_LOG_TIMER_START(depthTimer);
1759 // Vector of scene-graph nodes and their depths to send to UpdateManager
1760 // in a single message
1761 OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths( new SceneGraph::NodeDepths() );
1763 int32_t depthIndex = 1;
1764 DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
1766 SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths );
1767 DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
1770 void Actor::DepthTraverseActorTree( OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths, int32_t& depthIndex )
1772 mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
1773 sceneGraphNodeDepths->Add( const_cast<SceneGraph::Node*>( &GetNode() ), mSortedDepth );
1775 // Create/add to children of this node
1778 for( const auto& child : *mChildren )
1780 Actor* childActor = child.Get();
1782 childActor->DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
1787 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
1789 PropertyHandler::SetDefaultProperty(*this, index, property);
1792 // TODO: This method needs to be removed
1793 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
1795 PropertyHandler::SetSceneGraphProperty(index, entry, value, GetEventThreadServices(), GetNode());
1798 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
1800 Property::Value value;
1802 if( ! GetCachedPropertyValue( index, value ) )
1804 // If property value is not stored in the event-side, then it must be a scene-graph only property
1805 GetCurrentPropertyValue( index, value );
1811 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
1813 Property::Value value;
1815 if( ! GetCurrentPropertyValue( index, value ) )
1817 // If unable to retrieve scene-graph property value, then it must be an event-side only property
1818 GetCachedPropertyValue( index, value );
1824 void Actor::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
1826 PropertyHandler::OnNotifyDefaultPropertyAnimation(*this, animation, index, value, animationType);
1829 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
1831 const PropertyBase* property = PropertyHandler::GetSceneObjectAnimatableProperty(index, GetNode());
1834 // not our property, ask base
1835 property = Object::GetSceneObjectAnimatableProperty( index );
1841 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
1843 const PropertyInputImpl* property = PropertyHandler::GetSceneObjectInputProperty(index, GetNode());
1846 // reuse animatable property getter as animatable properties are inputs as well
1847 // animatable property chains back to Object::GetSceneObjectInputProperty() so all properties get covered
1848 property = GetSceneObjectAnimatableProperty( index );
1854 int32_t Actor::GetPropertyComponentIndex( Property::Index index ) const
1856 int32_t componentIndex = PropertyHandler::GetPropertyComponentIndex(index);
1857 if( Property::INVALID_COMPONENT_INDEX == componentIndex )
1860 componentIndex = Object::GetPropertyComponentIndex( index );
1863 return componentIndex;
1866 void Actor::SetParent( Actor* parent )
1870 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
1874 mScene = parent->mScene;
1876 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1879 // Instruct each actor to create a corresponding node in the scene graph
1880 ConnectToScene( parent->GetHierarchyDepth() );
1883 // Resolve the name and index for the child properties if any
1884 ResolveChildProperties();
1886 else // parent being set to NULL
1888 DALI_ASSERT_ALWAYS( mParent != nullptr && "Actor should have a parent" );
1892 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1895 // Disconnect the Node & its children from the scene-graph.
1896 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
1898 // Instruct each actor to discard pointers to the scene-graph
1899 DisconnectFromStage();
1906 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
1909 Actor* actor = dynamic_cast< Actor* >( object );
1913 std::string_view name(actionName);
1914 if(name == ACTION_SHOW)
1916 actor->SetVisible( true );
1919 else if(name == ACTION_HIDE)
1921 actor->SetVisible( false );
1929 Rect<> Actor::CalculateScreenExtents( ) const
1931 auto screenPosition = GetCurrentScreenPosition();
1932 Vector3 size = GetCurrentSize() * GetCurrentWorldScale();
1933 Vector3 anchorPointOffSet = size * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
1934 Vector2 position = Vector2( screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y );
1935 return { position.x, position.y, size.x, size.y };
1938 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
1940 return PropertyHandler::GetCachedPropertyValue(*this, index, value);
1943 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
1945 return PropertyHandler::GetCurrentPropertyValue(*this, index, value);
1948 Actor::Relayouter& Actor::EnsureRelayouter()
1950 // Assign relayouter
1951 if( !mRelayoutData )
1953 mRelayoutData = new Relayouter();
1956 return *mRelayoutData;
1959 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
1961 // Check if actor is dependent on parent
1962 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1964 if( ( dimension & ( 1 << i ) ) )
1966 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
1967 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
1977 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
1979 // Check if actor is dependent on children
1980 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1982 if( ( dimension & ( 1 << i ) ) )
1984 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
1985 switch( resizePolicy )
1987 case ResizePolicy::FIT_TO_CHILDREN:
1988 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
2004 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
2006 return Actor::RelayoutDependentOnChildren( dimension );
2009 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
2011 // Check each possible dimension and see if it is dependent on the input one
2012 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2014 if( dimension & ( 1 << i ) )
2016 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
2023 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
2025 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2027 if( dimension & ( 1 << i ) )
2029 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
2034 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
2036 // If more than one dimension is requested, just return the first one found
2037 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2039 if( ( dimension & ( 1 << i ) ) )
2041 return mRelayoutData->negotiatedDimensions[ i ];
2045 return 0.0f; // Default
2048 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
2050 EnsureRelayouter().SetPadding( padding, dimension );
2053 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
2055 if ( mRelayoutData )
2057 // If more than one dimension is requested, just return the first one found
2058 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2060 if( ( dimension & ( 1 << i ) ) )
2062 return mRelayoutData->dimensionPadding[ i ];
2067 return Relayouter::DEFAULT_DIMENSION_PADDING;
2070 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
2072 EnsureRelayouter().SetLayoutNegotiated(negotiated, dimension);
2075 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
2077 return mRelayoutData && mRelayoutData->IsLayoutNegotiated(dimension);
2080 float Actor::GetHeightForWidthBase( float width )
2082 float height = 0.0f;
2084 const Vector3 naturalSize = GetNaturalSize();
2085 if( naturalSize.width > 0.0f )
2087 height = naturalSize.height * width / naturalSize.width;
2089 else // we treat 0 as 1:1 aspect ratio
2097 float Actor::GetWidthForHeightBase( float height )
2101 const Vector3 naturalSize = GetNaturalSize();
2102 if( naturalSize.height > 0.0f )
2104 width = naturalSize.width * height / naturalSize.height;
2106 else // we treat 0 as 1:1 aspect ratio
2114 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
2116 // Fill to parent, taking size mode factor into account
2117 switch( child.GetResizePolicy( dimension ) )
2119 case ResizePolicy::FILL_TO_PARENT:
2121 return GetLatestSize( dimension );
2124 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2126 return GetLatestSize( dimension ) * GetDimensionValue( child.GetProperty< Vector3 >( Dali::Actor::Property::SIZE_MODE_FACTOR ), dimension );
2129 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2131 return GetLatestSize( dimension ) + GetDimensionValue( child.GetProperty< Vector3 >( Dali::Actor::Property::SIZE_MODE_FACTOR ), dimension );
2136 return GetLatestSize( dimension );
2141 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
2143 // Can be overridden in derived class
2144 return CalculateChildSizeBase( child, dimension );
2147 float Actor::GetHeightForWidth( float width )
2149 // Can be overridden in derived class
2150 return GetHeightForWidthBase( width );
2153 float Actor::GetWidthForHeight( float height )
2155 // Can be overridden in derived class
2156 return GetWidthForHeightBase( height );
2159 float Actor::GetLatestSize( Dimension::Type dimension ) const
2161 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
2164 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
2166 Vector2 padding = GetPadding( dimension );
2168 return GetLatestSize( dimension ) + padding.x + padding.y;
2171 float Actor::NegotiateFromParent( Dimension::Type dimension )
2173 Actor* parent = GetParent();
2176 Vector2 padding( GetPadding( dimension ) );
2177 Vector2 parentPadding( parent->GetPadding( dimension ) );
2178 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
2184 float Actor::NegotiateFromChildren( Dimension::Type dimension )
2186 float maxDimensionPoint = 0.0f;
2188 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2190 ActorPtr child = GetChildAt( i );
2192 if( !child->RelayoutDependentOnParent( dimension ) )
2194 // Calculate the min and max points that the children range across
2195 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
2196 float dimensionSize = child->GetRelayoutSize( dimension );
2197 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
2201 return maxDimensionPoint;
2204 float Actor::GetSize( Dimension::Type dimension ) const
2206 return GetDimensionValue( mTargetSize, dimension );
2209 float Actor::GetNaturalSize( Dimension::Type dimension ) const
2211 return GetDimensionValue( GetNaturalSize(), dimension );
2214 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
2216 switch( GetResizePolicy( dimension ) )
2218 case ResizePolicy::USE_NATURAL_SIZE:
2220 return GetNaturalSize( dimension );
2223 case ResizePolicy::FIXED:
2225 return GetDimensionValue( GetPreferredSize(), dimension );
2228 case ResizePolicy::USE_ASSIGNED_SIZE:
2230 return GetDimensionValue( maximumSize, dimension );
2233 case ResizePolicy::FILL_TO_PARENT:
2234 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2235 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2237 return NegotiateFromParent( dimension );
2240 case ResizePolicy::FIT_TO_CHILDREN:
2242 return NegotiateFromChildren( dimension );
2245 case ResizePolicy::DIMENSION_DEPENDENCY:
2247 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
2250 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
2252 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
2255 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
2257 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
2269 return 0.0f; // Default
2272 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
2274 // Check if it needs to be negotiated
2275 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
2277 // Check that we havn't gotten into an infinite loop
2278 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
2279 bool recursionFound = false;
2280 for( auto& element : recursionStack )
2282 if( element == searchActor )
2284 recursionFound = true;
2289 if( !recursionFound )
2291 // Record the path that we have taken
2292 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
2294 // Dimension dependency check
2295 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2297 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
2299 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
2301 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
2305 // Parent dependency check
2306 Actor* parent = GetParent();
2307 if( parent && RelayoutDependentOnParent( dimension ) )
2309 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
2312 // Children dependency check
2313 if( RelayoutDependentOnChildren( dimension ) )
2315 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2317 ActorPtr child = GetChildAt( i );
2319 // Only relayout child first if it is not dependent on this actor
2320 if( !child->RelayoutDependentOnParent( dimension ) )
2322 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
2327 // For deriving classes
2328 OnCalculateRelayoutSize( dimension );
2330 // All dependencies checked, calculate the size and set negotiated flag
2331 const float newSize = Relayouter::ClampDimension( *this, CalculateSize( dimension, allocatedSize ), dimension );
2333 SetNegotiatedDimension( newSize, dimension );
2334 SetLayoutNegotiated( true, dimension );
2336 // For deriving classes
2337 OnLayoutNegotiated( newSize, dimension );
2339 // This actor has been successfully processed, pop it off the recursion stack
2340 recursionStack.pop_back();
2344 // TODO: Break infinite loop
2345 SetLayoutNegotiated( true, dimension );
2350 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
2352 // Negotiate all dimensions that require it
2353 ActorDimensionStack recursionStack;
2355 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2357 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
2360 NegotiateDimension( dimension, allocatedSize, recursionStack );
2364 Vector2 Actor::ApplySizeSetPolicy( const Vector2& size )
2366 return mRelayoutData->ApplySizeSetPolicy(*this, size);
2369 void Actor::SetNegotiatedSize( RelayoutContainer& container )
2371 // Do the set actor size
2372 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
2374 // Adjust for size set policy
2375 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
2377 // Lock the flag to stop recursive relayouts on set size
2378 mRelayoutData->insideRelayout = true;
2379 SetSize( negotiatedSize );
2380 mRelayoutData->insideRelayout = false;
2382 // Clear flags for all dimensions
2383 SetLayoutDirty( false );
2385 // Give deriving classes a chance to respond
2386 OnRelayout( negotiatedSize, container );
2388 if( !mOnRelayoutSignal.Empty() )
2390 Dali::Actor handle( this );
2391 mOnRelayoutSignal.Emit( handle );
2395 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
2397 // Force a size negotiation for actors that has assigned size during relayout
2398 // This is required as otherwise the flags that force a relayout will not
2399 // necessarilly be set. This will occur if the actor has already been laid out.
2400 // The dirty flags are then cleared. Then if the actor is added back into the
2401 // relayout container afterwards, the dirty flags would still be clear...
2402 // causing a relayout to be skipped. Here we force any actors added to the
2403 // container to be relayed out.
2404 DALI_LOG_TIMER_START( NegSizeTimer1 );
2406 if( GetUseAssignedSize(Dimension::WIDTH ) )
2408 SetLayoutNegotiated( false, Dimension::WIDTH );
2410 if( GetUseAssignedSize( Dimension::HEIGHT ) )
2412 SetLayoutNegotiated( false, Dimension::HEIGHT );
2415 // Do the negotiation
2416 NegotiateDimensions( allocatedSize );
2418 // Set the actor size
2419 SetNegotiatedSize( container );
2421 // Negotiate down to children
2422 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2424 ActorPtr child = GetChildAt( i );
2426 // Forces children that have already been laid out to be relayed out
2427 // if they have assigned size during relayout.
2428 if( child->GetUseAssignedSize(Dimension::WIDTH) )
2430 child->SetLayoutNegotiated(false, Dimension::WIDTH);
2431 child->SetLayoutDirty(true, Dimension::WIDTH);
2434 if( child->GetUseAssignedSize(Dimension::HEIGHT) )
2436 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
2437 child->SetLayoutDirty(true, Dimension::HEIGHT);
2440 // Only relayout if required
2441 if( child->RelayoutRequired() )
2443 container.Add( Dali::Actor( child.Get() ), mTargetSize.GetVectorXY() );
2446 DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
2449 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
2453 mRelayoutData->SetUseAssignedSize(use, dimension);
2457 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
2459 return mRelayoutData && mRelayoutData->GetUseAssignedSize(dimension);
2462 void Actor::RelayoutRequest( Dimension::Type dimension )
2464 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
2465 if( relayoutController )
2467 Dali::Actor self( this );
2468 relayoutController->RequestRelayout( self, dimension );
2472 void Actor::SetPreferredSize( const Vector2& size )
2476 // If valid width or height, then set the resize policy to FIXED
2477 // 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,
2478 // then change to FIXED as well
2480 if( size.width > 0.0f || GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DEFAULT )
2482 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
2485 if( size.height > 0.0f || GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DEFAULT )
2487 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
2490 mRelayoutData->preferredSize = size;
2492 mUseAnimatedSize = AnimatedSizeFlag::CLEAR;
2497 Vector2 Actor::GetPreferredSize() const
2499 if ( mRelayoutData )
2501 return Vector2( mRelayoutData->preferredSize );
2504 return Relayouter::DEFAULT_PREFERRED_SIZE;
2507 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
2509 EnsureRelayouter().SetMinimumSize(size, dimension);
2513 float Actor::GetMinimumSize( Dimension::Type dimension ) const
2515 if ( mRelayoutData )
2517 return mRelayoutData->GetMinimumSize(dimension);
2520 return 0.0f; // Default
2523 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
2525 EnsureRelayouter().SetMaximumSize(size, dimension);
2529 float Actor::GetMaximumSize( Dimension::Type dimension ) const
2531 if ( mRelayoutData )
2533 return mRelayoutData->GetMaximumSize(dimension);
2536 return FLT_MAX; // Default
2539 void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
2541 if( mVisible != visible )
2543 if( sendMessage == SendMessage::TRUE )
2545 // node is being used in a separate thread; queue a message to set the value & base value
2546 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible );
2548 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
2553 // Emit the signal on this actor and all its children
2554 EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
2558 void Actor::SetSiblingOrder( uint32_t order )
2562 ActorContainer& siblings = *(mParent->mChildren);
2563 uint32_t currentOrder = GetSiblingOrder();
2565 if( order != currentOrder )
2571 else if( order < siblings.size() -1 )
2573 if( order > currentOrder )
2575 RaiseAbove( *siblings[order] );
2579 LowerBelow( *siblings[order] );
2590 uint32_t Actor::GetSiblingOrder() const
2596 ActorContainer& siblings = *(mParent->mChildren);
2597 for( std::size_t i = 0; i < siblings.size(); ++i )
2599 if( siblings[i] == this )
2601 order = static_cast<uint32_t>( i );
2610 void Actor::RequestRebuildDepthTree()
2616 mScene->RequestRebuildDepthTree();
2625 ActorContainer& siblings = *(mParent->mChildren);
2626 if( siblings.back() != this ) // If not already at end
2628 for( std::size_t i=0; i<siblings.size(); ++i )
2630 if( siblings[i] == this )
2633 ActorPtr next = siblings[i+1];
2634 siblings[i+1] = this;
2641 Dali::Actor handle( this );
2642 mParent->mChildOrderChangedSignal.Emit( handle );
2644 RequestRebuildDepthTree();
2648 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2656 ActorContainer& siblings = *(mParent->mChildren);
2657 if( siblings.front() != this ) // If not already at beginning
2659 for( std::size_t i=1; i<siblings.size(); ++i )
2661 if( siblings[i] == this )
2663 // Swap with previous
2664 ActorPtr previous = siblings[i-1];
2665 siblings[i-1] = this;
2666 siblings[i] = previous;
2672 Dali::Actor handle( this );
2673 mParent->mChildOrderChangedSignal.Emit( handle );
2675 RequestRebuildDepthTree();
2679 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2683 void Actor::RaiseToTop()
2687 ActorContainer& siblings = *(mParent->mChildren);
2688 if( siblings.back() != this ) // If not already at end
2690 auto iter = std::find( siblings.begin(), siblings.end(), this );
2691 if( iter != siblings.end() )
2693 siblings.erase(iter);
2694 siblings.push_back(ActorPtr(this));
2698 Dali::Actor handle( this );
2699 mParent->mChildOrderChangedSignal.Emit( handle );
2701 RequestRebuildDepthTree();
2705 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2709 void Actor::LowerToBottom()
2713 ActorContainer& siblings = *(mParent->mChildren);
2714 if( siblings.front() != this ) // If not already at bottom,
2716 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2718 auto iter = std::find( siblings.begin(), siblings.end(), this );
2719 if( iter != siblings.end() )
2721 siblings.erase(iter);
2722 siblings.insert(siblings.begin(), thisPtr);
2726 Dali::Actor handle( this );
2727 mParent->mChildOrderChangedSignal.Emit( handle );
2729 RequestRebuildDepthTree();
2733 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2737 void Actor::RaiseAbove( Internal::Actor& target )
2741 ActorContainer& siblings = *(mParent->mChildren);
2742 if( siblings.back() != this && target.mParent == mParent ) // If not already at top
2744 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2746 auto targetIter = std::find( siblings.begin(), siblings.end(), &target );
2747 auto thisIter = std::find( siblings.begin(), siblings.end(), this );
2748 if( thisIter < targetIter )
2750 siblings.erase(thisIter);
2751 // Erasing early invalidates the targetIter. (Conversely, inserting first may also
2752 // invalidate thisIter)
2753 targetIter = std::find( siblings.begin(), siblings.end(), &target );
2755 siblings.insert(targetIter, thisPtr);
2758 Dali::Actor handle( this );
2759 mParent->mChildOrderChangedSignal.Emit( handle );
2761 RequestRebuildDepthTree();
2766 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2770 void Actor::LowerBelow( Internal::Actor& target )
2774 ActorContainer& siblings = *(mParent->mChildren);
2775 if( siblings.front() != this && target.mParent == mParent ) // If not already at bottom
2777 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2779 auto targetIter = std::find( siblings.begin(), siblings.end(), &target );
2780 auto thisIter = std::find( siblings.begin(), siblings.end(), this );
2782 if( thisIter > targetIter )
2784 siblings.erase(thisIter); // this only invalidates iterators at or after this point.
2785 siblings.insert(targetIter, thisPtr);
2788 Dali::Actor handle( this );
2789 mParent->mChildOrderChangedSignal.Emit( handle );
2791 RequestRebuildDepthTree();
2796 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2800 void Actor::SetInheritLayoutDirection( bool inherit )
2802 if( mInheritLayoutDirection != inherit )
2804 mInheritLayoutDirection = inherit;
2806 if( inherit && mParent )
2808 InheritLayoutDirectionRecursively( this, mParent->mLayoutDirection );
2813 void Actor::InheritLayoutDirectionRecursively( ActorPtr actor, Dali::LayoutDirection::Type direction, bool set )
2815 if( actor && ( actor->mInheritLayoutDirection || set ) )
2817 if( actor->mLayoutDirection != direction )
2819 actor->mLayoutDirection = direction;
2820 actor->EmitLayoutDirectionChangedSignal( direction );
2821 actor->RelayoutRequest();
2824 if( actor->GetChildCount() > 0 )
2826 for( const auto& child : actor->GetChildrenInternal() )
2828 InheritLayoutDirectionRecursively( child, direction );
2834 void Actor::SetUpdateSizeHint( const Vector2& updateSizeHint )
2836 // node is being used in a separate thread; queue a message to set the value & base value
2837 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mUpdateSizeHint, &AnimatableProperty<Vector3>::Bake, Vector3(updateSizeHint.width, updateSizeHint.height, 0.f ) );
2840 } // namespace Internal