2 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/event/actors/actor-impl.h>
27 #include <dali/devel-api/actors/layer-devel.h>
28 #include <dali/public-api/common/dali-common.h>
29 #include <dali/public-api/common/constants.h>
30 #include <dali/public-api/math/vector2.h>
31 #include <dali/public-api/math/vector3.h>
32 #include <dali/public-api/math/radian.h>
33 #include <dali/public-api/object/type-registry.h>
34 #include <dali/devel-api/actors/actor-devel.h>
35 #include <dali/internal/event/actors/actor-property-handler.h>
36 #include <dali/internal/event/actors/actor-relayouter.h>
37 #include <dali/internal/event/common/event-thread-services.h>
38 #include <dali/internal/event/render-tasks/render-task-impl.h>
39 #include <dali/internal/event/actors/camera-actor-impl.h>
40 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
41 #include <dali/internal/event/common/property-helper.h>
42 #include <dali/internal/event/common/stage-impl.h>
43 #include <dali/internal/event/common/type-info-impl.h>
44 #include <dali/internal/event/common/scene-impl.h>
45 #include <dali/internal/event/common/thread-local-storage.h>
46 #include <dali/internal/event/common/projection.h>
47 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
48 #include <dali/internal/update/nodes/node-messages.h>
49 #include <dali/internal/event/events/actor-gesture-data.h>
50 #include <dali/integration-api/debug.h>
52 using Dali::Internal::SceneGraph::Node;
53 using Dali::Internal::SceneGraph::AnimatableProperty;
54 using Dali::Internal::SceneGraph::PropertyBase;
56 #if defined(DEBUG_ENABLED)
57 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_DEPTH_TIMER" );
58 Debug::Filter* gLogRelayoutFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_TIMER" );
67 namespace // unnamed namespace
73 * We want to discourage the use of property strings (minimize string comparisons),
74 * particularly for the default properties.
75 * Name Type writable animatable constraint-input enum for index-checking
77 DALI_PROPERTY_TABLE_BEGIN
78 DALI_PROPERTY( "parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
79 DALI_PROPERTY( "parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
80 DALI_PROPERTY( "parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
81 DALI_PROPERTY( "parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
82 DALI_PROPERTY( "anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
83 DALI_PROPERTY( "anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
84 DALI_PROPERTY( "anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
85 DALI_PROPERTY( "anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
86 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
87 DALI_PROPERTY( "sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
88 DALI_PROPERTY( "sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
89 DALI_PROPERTY( "sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
90 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
91 DALI_PROPERTY( "positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
92 DALI_PROPERTY( "positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
93 DALI_PROPERTY( "positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
94 DALI_PROPERTY( "worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
95 DALI_PROPERTY( "worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
96 DALI_PROPERTY( "worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
97 DALI_PROPERTY( "worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
98 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
99 DALI_PROPERTY( "worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
100 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
101 DALI_PROPERTY( "scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
102 DALI_PROPERTY( "scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
103 DALI_PROPERTY( "scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
104 DALI_PROPERTY( "worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
105 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
106 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
107 DALI_PROPERTY( "colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
108 DALI_PROPERTY( "colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
109 DALI_PROPERTY( "colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
110 DALI_PROPERTY( "colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
111 DALI_PROPERTY( "worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
112 DALI_PROPERTY( "worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
113 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
114 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
115 DALI_PROPERTY( "leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
116 DALI_PROPERTY( "inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
117 DALI_PROPERTY( "inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
118 DALI_PROPERTY( "colorMode", INTEGER, true, false, false, Dali::Actor::Property::COLOR_MODE )
119 DALI_PROPERTY( "drawMode", INTEGER, true, false, false, Dali::Actor::Property::DRAW_MODE )
120 DALI_PROPERTY( "sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
121 DALI_PROPERTY( "widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
122 DALI_PROPERTY( "heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
123 DALI_PROPERTY( "sizeScalePolicy", INTEGER, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
124 DALI_PROPERTY( "widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
125 DALI_PROPERTY( "heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
126 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
127 DALI_PROPERTY( "minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
128 DALI_PROPERTY( "maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
129 DALI_PROPERTY( "inheritPosition", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_POSITION )
130 DALI_PROPERTY( "clippingMode", STRING, true, false, false, Dali::Actor::Property::CLIPPING_MODE )
131 DALI_PROPERTY( "layoutDirection", STRING, true, false, false, Dali::Actor::Property::LAYOUT_DIRECTION )
132 DALI_PROPERTY( "inheritLayoutDirection", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION )
133 DALI_PROPERTY( "opacity", FLOAT, true, true, true, Dali::Actor::Property::OPACITY )
134 DALI_PROPERTY( "screenPosition", VECTOR2, false, false, false, Dali::Actor::Property::SCREEN_POSITION )
135 DALI_PROPERTY( "positionUsesAnchorPoint", BOOLEAN, true, false, false, Dali::Actor::Property::POSITION_USES_ANCHOR_POINT )
136 DALI_PROPERTY( "culled", BOOLEAN, false, false, true, Dali::Actor::Property::CULLED )
137 DALI_PROPERTY( "id", INTEGER, false, false, false, Dali::Actor::Property::ID )
138 DALI_PROPERTY( "hierarchyDepth", INTEGER, false, false, false, Dali::Actor::Property::HIERARCHY_DEPTH )
139 DALI_PROPERTY( "isRoot", BOOLEAN, false, false, false, Dali::Actor::Property::IS_ROOT )
140 DALI_PROPERTY( "isLayer", BOOLEAN, false, false, false, Dali::Actor::Property::IS_LAYER )
141 DALI_PROPERTY( "connectedToScene", BOOLEAN, false, false, false, Dali::Actor::Property::CONNECTED_TO_SCENE )
142 DALI_PROPERTY( "keyboardFocusable", BOOLEAN, true, false, false, Dali::Actor::Property::KEYBOARD_FOCUSABLE )
143 DALI_PROPERTY( "siblingOrder", INTEGER, true, false, false, Dali::DevelActor::Property::SIBLING_ORDER )
144 DALI_PROPERTY( "updateSizeHint", VECTOR2, true, false, false, Dali::DevelActor::Property::UPDATE_SIZE_HINT )
145 DALI_PROPERTY( "captureAllTouchAfterStart", BOOLEAN, true, false, false, Dali::DevelActor::Property::CAPTURE_ALL_TOUCH_AFTER_START )
146 DALI_PROPERTY( "touchDelegateArea", VECTOR2, true, false, false, Dali::DevelActor::Property::TOUCH_DELEGATE_AREA )
147 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperties )
151 const char* const SIGNAL_HOVERED = "hovered";
152 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
153 const char* const SIGNAL_ON_SCENE = "onScene";
154 const char* const SIGNAL_OFF_SCENE = "offScene";
155 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
156 const char* const SIGNAL_TOUCHED = "touched";
157 const char* const SIGNAL_VISIBILITY_CHANGED = "visibilityChanged";
158 const char* const SIGNAL_LAYOUT_DIRECTION_CHANGED = "layoutDirectionChanged";
159 const char* const SIGNAL_CHILD_ADDED = "childAdded";
160 const char* const SIGNAL_CHILD_REMOVED = "childRemoved";
164 const char* const ACTION_SHOW = "show";
165 const char* const ACTION_HIDE = "hide";
167 BaseHandle CreateActor()
169 return Dali::Actor::New();
172 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor, ActorDefaultProperties );
174 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
175 SignalConnectorType signalConnector3( mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal );
176 SignalConnectorType signalConnector4( mType, SIGNAL_ON_SCENE, &Actor::DoConnectSignal );
177 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_SCENE, &Actor::DoConnectSignal );
178 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
179 SignalConnectorType signalConnector7( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
180 SignalConnectorType signalConnector8( mType, SIGNAL_VISIBILITY_CHANGED, &Actor::DoConnectSignal );
181 SignalConnectorType signalConnector9( mType, SIGNAL_LAYOUT_DIRECTION_CHANGED, &Actor::DoConnectSignal );
182 SignalConnectorType signalConnector10( mType, SIGNAL_CHILD_ADDED, &Actor::DoConnectSignal );
183 SignalConnectorType signalConnector11( mType, SIGNAL_CHILD_REMOVED, &Actor::DoConnectSignal );
185 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
186 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
189 * @brief Extract a given dimension from a Vector2
191 * @param[in] values The values to extract from
192 * @param[in] dimension The dimension to extract
193 * @return Return the value for the dimension
195 constexpr float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
199 case Dimension::WIDTH:
203 case Dimension::HEIGHT:
205 return values.height;
216 * @brief Extract a given dimension from a Vector3
218 * @param[in] values The values to extract from
219 * @param[in] dimension The dimension to extract
220 * @return Return the value for the dimension
222 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
224 return GetDimensionValue( values.GetVectorXY(), dimension );
228 * @brief Recursively emits the visibility-changed-signal on the actor tree.
229 * @param[in] actor The actor to emit the signal on
230 * @param[in] visible The new visibility of the actor
231 * @param[in] type Whether the actor's visible property has changed or a parent's
233 void EmitVisibilityChangedSignalRecursively( ActorPtr actor, bool visible, DevelActor::VisibilityChange::Type type )
237 actor->EmitVisibilityChangedSignal( visible, type );
239 if( actor->GetChildCount() > 0 )
241 for( auto& child : actor->GetChildrenInternal() )
243 EmitVisibilityChangedSignalRecursively( child, visible, DevelActor::VisibilityChange::PARENT );
249 /// Helper for emitting a signal
250 template<typename Signal, typename Event>
251 bool EmitConsumingSignal( Actor& actor, Signal& signal, const Event& event )
253 bool consumed = false;
255 if( !signal.Empty() )
257 Dali::Actor handle( &actor );
258 consumed = signal.Emit( handle, event );
264 /// Helper for emitting signals with multiple parameters
265 template<typename Signal, typename... Param>
266 void EmitSignal( Actor& actor, Signal& signal, Param... params)
268 if( !signal.Empty() )
270 Dali::Actor handle( &actor );
271 signal.Emit( handle, params... );
275 bool ScreenToLocalInternal(
276 const Matrix& viewMatrix,
277 const Matrix& projectionMatrix,
278 const Matrix& worldMatrix,
279 const Viewport& viewport,
280 const Vector3& currentSize,
286 // Get the ModelView matrix
288 Matrix::Multiply( modelView, worldMatrix, viewMatrix );
290 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
291 Matrix invertedMvp( false/*don't init*/);
292 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
293 bool success = invertedMvp.Invert();
295 // Convert to GL coordinates
296 Vector4 screenPos( screenX - static_cast<float>( viewport.x ), static_cast<float>( viewport.height ) - screenY - static_cast<float>( viewport.y ), 0.f, 1.f );
301 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), nearPos );
308 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), farPos );
314 if( XyPlaneIntersect( nearPos, farPos, local ) )
316 Vector3 size = currentSize;
317 localX = local.x + size.x * 0.5f;
318 localY = local.y + size.y * 0.5f;
329 } // unnamed namespace
331 ActorPtr Actor::New()
333 // pass a reference to actor, actor does not own its node
334 ActorPtr actor( new Actor( BASIC, *CreateNode() ) );
336 // Second-phase construction
342 const SceneGraph::Node* Actor::CreateNode()
344 // create node. Nodes are owned by the update manager
345 SceneGraph::Node* node = SceneGraph::Node::New();
346 OwnerPointer< SceneGraph::Node > transferOwnership( node );
347 Internal::ThreadLocalStorage* tls = Internal::ThreadLocalStorage::GetInternal();
349 DALI_ASSERT_ALWAYS( tls && "ThreadLocalStorage is null" );
351 AddNodeMessage( tls->GetUpdateManager(), transferOwnership );
356 void Actor::SetName( const std::string& name )
360 // ATTENTION: string for debug purposes is not thread safe.
361 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( &GetNode() ), name );
364 uint32_t Actor::GetId() const
366 return GetNode().GetId();
369 Dali::Layer Actor::GetLayer()
373 // Short-circuit for Layer derived actors
376 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
379 // Find the immediate Layer parent
380 for( Actor* parent = mParent; !layer && parent != nullptr; parent = parent->GetParent() )
382 if( parent->IsLayer() )
384 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
391 void Actor::Add( Actor& child )
393 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
394 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
398 mChildren = new ActorContainer;
401 Actor* const oldParent( child.mParent );
403 // child might already be ours
404 if( this != oldParent )
406 // if we already have parent, unparent us first
409 oldParent->Remove( child ); // This causes OnChildRemove callback & ChildRemoved signal
411 // Old parent may need to readjust to missing child
412 if( oldParent->RelayoutDependentOnChildren() )
414 oldParent->RelayoutRequest();
418 // Guard against Add() during previous OnChildRemove callback
421 // Do this first, since user callbacks from within SetParent() may need to remove child
422 mChildren->push_back( ActorPtr( &child ) );
424 // SetParent asserts that child can be added
425 child.SetParent( this );
427 // Notification for derived classes
429 EmitChildAddedSignal( child );
431 InheritLayoutDirectionRecursively( ActorPtr( &child ), mLayoutDirection );
433 // Only put in a relayout request if there is a suitable dependency
434 if( RelayoutDependentOnChildren() )
442 void Actor::Remove( Actor& child )
444 if( (this == &child) || (!mChildren) )
446 // no children or removing itself
452 // Find the child in mChildren, and unparent it
453 ActorIter end = mChildren->end();
454 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
456 ActorPtr actor = (*iter);
458 if( actor.Get() == &child )
460 // Keep handle for OnChildRemove notification
463 // Do this first, since user callbacks from within SetParent() may need to add the child
464 mChildren->erase( iter );
466 DALI_ASSERT_DEBUG( actor->GetParent() == this );
467 actor->SetParent( nullptr );
475 // Only put in a relayout request if there is a suitable dependency
476 if( RelayoutDependentOnChildren() )
482 // Notification for derived classes
483 OnChildRemove( child );
484 EmitChildRemovedSignal( child );
487 void Actor::Unparent()
491 // Remove this actor from the parent. The remove will put a relayout request in for
492 // the parent if required
493 mParent->Remove( *this );
494 // mParent is now NULL!
498 uint32_t Actor::GetChildCount() const
500 return ( nullptr != mChildren ) ? static_cast<uint32_t>( mChildren->size() ) : 0; // only 4,294,967,295 children per actor
503 ActorPtr Actor::GetChildAt( uint32_t index ) const
505 DALI_ASSERT_ALWAYS( index < GetChildCount() );
507 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
510 ActorPtr Actor::FindChildByName( const std::string& actorName )
512 ActorPtr child = nullptr;
513 if( actorName == mName )
519 for( const auto& actor : *mChildren )
521 child = actor->FindChildByName( actorName );
532 ActorPtr Actor::FindChildById( const uint32_t id )
534 ActorPtr child = nullptr;
541 for( const auto& actor : *mChildren )
543 child = actor->FindChildById( id );
554 void Actor::SetParentOrigin( const Vector3& origin )
556 // node is being used in a separate thread; queue a message to set the value & base value
557 SetParentOriginMessage( GetEventThreadServices(), GetNode(), origin );
559 // Cache for event-thread access
562 // not allocated, check if different from default
563 if( ParentOrigin::DEFAULT != origin )
565 mParentOrigin = new Vector3( origin );
570 // check if different from current costs more than just set
571 *mParentOrigin = origin;
575 const Vector3& Actor::GetCurrentParentOrigin() const
577 // Cached for event-thread access
578 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
581 void Actor::SetAnchorPoint( const Vector3& anchor )
583 // node is being used in a separate thread; queue a message to set the value & base value
584 SetAnchorPointMessage( GetEventThreadServices(), GetNode(), anchor );
586 // Cache for event-thread access
589 // not allocated, check if different from default
590 if( AnchorPoint::DEFAULT != anchor )
592 mAnchorPoint = new Vector3( anchor );
597 // check if different from current costs more than just set
598 *mAnchorPoint = anchor;
602 const Vector3& Actor::GetCurrentAnchorPoint() const
604 // Cached for event-thread access
605 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
608 void Actor::SetPosition( float x, float y )
610 SetPosition( Vector3( x, y, 0.0f ) );
613 void Actor::SetPosition( float x, float y, float z )
615 SetPosition( Vector3( x, y, z ) );
618 void Actor::SetPosition( const Vector3& position )
620 mTargetPosition = position;
622 // node is being used in a separate thread; queue a message to set the value & base value
623 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
626 void Actor::SetX( float x )
628 mTargetPosition.x = x;
630 // node is being used in a separate thread; queue a message to set the value & base value
631 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
634 void Actor::SetY( float y )
636 mTargetPosition.y = y;
638 // node is being used in a separate thread; queue a message to set the value & base value
639 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
642 void Actor::SetZ( float z )
644 mTargetPosition.z = z;
646 // node is being used in a separate thread; queue a message to set the value & base value
647 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
650 void Actor::TranslateBy( const Vector3& distance )
652 mTargetPosition += distance;
654 // node is being used in a separate thread; queue a message to set the value & base value
655 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
658 const Vector3& Actor::GetCurrentPosition() const
660 // node is being used in a separate thread; copy the value from the previous update
661 return GetNode().GetPosition(GetEventThreadServices().GetEventBufferIndex());
664 const Vector3& Actor::GetCurrentWorldPosition() const
666 // node is being used in a separate thread; copy the value from the previous update
667 return GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
670 const Vector2 Actor::GetCurrentScreenPosition() const
672 if( mScene && OnScene() )
674 Vector3 worldPosition = GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
675 Vector3 cameraPosition = mScene->GetDefaultCameraActor().GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
676 worldPosition -= cameraPosition;
678 Vector3 actorSize = GetCurrentSize() * GetCurrentWorldScale();
679 Vector2 halfSceneSize( mScene->GetSize() * 0.5f ); // World position origin is center of scene
680 Vector3 halfActorSize( actorSize * 0.5f );
681 Vector3 anchorPointOffSet = halfActorSize - actorSize * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
683 return Vector2( halfSceneSize.width + worldPosition.x - anchorPointOffSet.x,
684 halfSceneSize.height + worldPosition.y - anchorPointOffSet.y );
687 return Vector2::ZERO;
690 void Actor::SetInheritPosition( bool inherit )
692 if( mInheritPosition != inherit )
694 // non animatable so keep local copy
695 mInheritPosition = inherit;
696 SetInheritPositionMessage( GetEventThreadServices(), GetNode(), inherit );
700 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
702 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
703 normalizedAxis.Normalize();
705 Quaternion orientation( angle, normalizedAxis );
707 SetOrientation( orientation );
710 void Actor::SetOrientation( const Quaternion& orientation )
712 mTargetOrientation = orientation;
714 // node is being used in a separate thread; queue a message to set the value & base value
715 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation );
718 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
720 RotateBy( Quaternion(angle, axis) );
723 void Actor::RotateBy( const Quaternion& relativeRotation )
725 mTargetOrientation *= Quaternion( relativeRotation );
727 // node is being used in a separate thread; queue a message to set the value & base value
728 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
731 const Quaternion& Actor::GetCurrentOrientation() const
733 // node is being used in a separate thread; copy the value from the previous update
734 return GetNode().GetOrientation(GetEventThreadServices().GetEventBufferIndex());
737 const Quaternion& Actor::GetCurrentWorldOrientation() const
739 // node is being used in a separate thread; copy the value from the previous update
740 return GetNode().GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
743 void Actor::SetScale( float scale )
745 SetScale( Vector3( scale, scale, scale ) );
748 void Actor::SetScale( float x, float y, float z )
750 SetScale( Vector3( x, y, z ) );
753 void Actor::SetScale( const Vector3& scale )
755 mTargetScale = scale;
757 // node is being used in a separate thread; queue a message to set the value & base value
758 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
761 void Actor::SetScaleX( float x )
765 // node is being used in a separate thread; queue a message to set the value & base value
766 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
769 void Actor::SetScaleY( float y )
773 // node is being used in a separate thread; queue a message to set the value & base value
774 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
777 void Actor::SetScaleZ( float z )
781 // node is being used in a separate thread; queue a message to set the value & base value
782 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
785 void Actor::ScaleBy(const Vector3& relativeScale)
787 mTargetScale *= relativeScale;
789 // node is being used in a separate thread; queue a message to set the value & base value
790 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
793 const Vector3& Actor::GetCurrentScale() const
795 // node is being used in a separate thread; copy the value from the previous update
796 return GetNode().GetScale(GetEventThreadServices().GetEventBufferIndex());
799 const Vector3& Actor::GetCurrentWorldScale() const
801 // node is being used in a separate thread; copy the value from the previous update
802 return GetNode().GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
805 void Actor::SetInheritScale( bool inherit )
807 if( mInheritScale != inherit )
809 // non animatable so keep local copy
810 mInheritScale = inherit;
811 // node is being used in a separate thread; queue a message to set the value
812 SetInheritScaleMessage( GetEventThreadServices(), GetNode(), inherit );
816 Matrix Actor::GetCurrentWorldMatrix() const
818 return GetNode().GetWorldMatrix(0);
821 void Actor::SetVisible( bool visible )
823 SetVisibleInternal( visible, SendMessage::TRUE );
826 bool Actor::IsVisible() const
828 // node is being used in a separate thread; copy the value from the previous update
829 return GetNode().IsVisible( GetEventThreadServices().GetEventBufferIndex() );
832 void Actor::SetOpacity( float opacity )
834 mTargetColor.a = opacity;
836 // node is being used in a separate thread; queue a message to set the value & base value
837 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
840 float Actor::GetCurrentOpacity() const
842 // node is being used in a separate thread; copy the value from the previous update
843 return GetNode().GetOpacity(GetEventThreadServices().GetEventBufferIndex());
846 const Vector4& Actor::GetCurrentWorldColor() const
848 return GetNode().GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
851 void Actor::SetColor( const Vector4& color )
853 mTargetColor = color;
855 // node is being used in a separate thread; queue a message to set the value & base value
856 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::Bake, color );
859 void Actor::SetColorRed( float red )
861 mTargetColor.r = red;
863 // node is being used in a separate thread; queue a message to set the value & base value
864 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeX, red );
867 void Actor::SetColorGreen( float green )
869 mTargetColor.g = green;
871 // node is being used in a separate thread; queue a message to set the value & base value
872 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeY, green );
875 void Actor::SetColorBlue( float blue )
877 mTargetColor.b = blue;
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>::BakeZ, blue );
883 const Vector4& Actor::GetCurrentColor() const
885 // node is being used in a separate thread; copy the value from the previous update
886 return GetNode().GetColor(GetEventThreadServices().GetEventBufferIndex());
889 void Actor::SetInheritOrientation( bool inherit )
891 if( mInheritOrientation != inherit )
893 // non animatable so keep local copy
894 mInheritOrientation = inherit;
895 // node is being used in a separate thread; queue a message to set the value
896 SetInheritOrientationMessage( GetEventThreadServices(), GetNode(), inherit );
900 void Actor::SetSizeModeFactor( const Vector3& factor )
904 mRelayoutData->sizeModeFactor = factor;
907 const Vector3& Actor::GetSizeModeFactor() const
911 return mRelayoutData->sizeModeFactor;
914 return Relayouter::DEFAULT_SIZE_MODE_FACTOR;
917 void Actor::SetColorMode( ColorMode colorMode )
919 // non animatable so keep local copy
920 mColorMode = colorMode;
921 // node is being used in a separate thread; queue a message to set the value
922 SetColorModeMessage( GetEventThreadServices(), GetNode(), colorMode );
925 void Actor::SetSize( float width, float height )
927 SetSize( Vector2( width, height ) );
930 void Actor::SetSize( float width, float height, float depth )
932 SetSize( Vector3( width, height, depth ) );
935 void Actor::SetSize( const Vector2& size )
937 SetSize( Vector3( size.width, size.height, 0.f ) );
940 void Actor::SetSizeInternal( const Vector2& size )
942 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
945 void Actor::SetSize( const Vector3& size )
947 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
949 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
950 SetPreferredSize( size.GetVectorXY() );
954 SetSizeInternal( size );
958 void Actor::SetSizeInternal( const Vector3& size )
960 // dont allow recursive loop
961 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
962 // 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
963 if( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
964 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
965 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) )
969 // node is being used in a separate thread; queue a message to set the value & base value
970 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
972 // Notification for derived classes
973 mInsideOnSizeSet = true;
974 OnSizeSet( mTargetSize );
975 mInsideOnSizeSet = false;
977 // Raise a relayout request if the flag is not locked
978 if( mRelayoutData && !mRelayoutData->insideRelayout )
985 void Actor::SetWidth( float width )
987 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
989 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
990 mRelayoutData->preferredSize.width = width;
994 mTargetSize.width = width;
996 // node is being used in a separate thread; queue a message to set the value & base value
997 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1000 mUseAnimatedSize &= ~AnimatedSizeFlag::WIDTH;
1005 void Actor::SetHeight( float height )
1007 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1009 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
1010 mRelayoutData->preferredSize.height = height;
1014 mTargetSize.height = height;
1016 // node is being used in a separate thread; queue a message to set the value & base value
1017 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1020 mUseAnimatedSize &= ~AnimatedSizeFlag::HEIGHT;
1025 void Actor::SetDepth( float depth )
1027 mTargetSize.depth = depth;
1029 mUseAnimatedSize &= ~AnimatedSizeFlag::DEPTH;
1031 // node is being used in a separate thread; queue a message to set the value & base value
1032 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1035 Vector3 Actor::GetTargetSize() const
1037 Vector3 size = mTargetSize;
1039 if( mUseAnimatedSize & AnimatedSizeFlag::WIDTH )
1041 // Should return animated size if size is animated
1042 size.width = mAnimatedSize.width;
1046 // Should return preferred size if size is fixed as set by SetSize
1047 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
1049 size.width = GetPreferredSize().width;
1053 if( mUseAnimatedSize & AnimatedSizeFlag::HEIGHT )
1055 size.height = mAnimatedSize.height;
1059 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
1061 size.height = GetPreferredSize().height;
1065 if( mUseAnimatedSize & AnimatedSizeFlag::DEPTH )
1067 size.depth = mAnimatedSize.depth;
1073 const Vector3& Actor::GetCurrentSize() const
1075 // node is being used in a separate thread; copy the value from the previous update
1076 return GetNode().GetSize( GetEventThreadServices().GetEventBufferIndex() );
1079 Vector3 Actor::GetNaturalSize() const
1081 // It is up to deriving classes to return the appropriate natural size
1082 return Vector3( 0.0f, 0.0f, 0.0f );
1085 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1087 EnsureRelayouter().SetResizePolicy(policy, dimension, mTargetSize);
1089 OnSetResizePolicy( policy, dimension );
1091 // Trigger relayout on this control
1095 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1097 if ( mRelayoutData )
1099 return mRelayoutData->GetResizePolicy(dimension);
1102 return ResizePolicy::DEFAULT;
1105 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1109 mRelayoutData->sizeSetPolicy = policy;
1111 // Trigger relayout on this control
1115 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1117 if ( mRelayoutData )
1119 return mRelayoutData->sizeSetPolicy;
1122 return Relayouter::DEFAULT_SIZE_SCALE_POLICY;
1125 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1127 EnsureRelayouter().SetDimensionDependency(dimension, dependency);
1130 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1132 if ( mRelayoutData )
1134 return mRelayoutData->GetDimensionDependency(dimension);
1137 return Dimension::ALL_DIMENSIONS; // Default
1140 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1142 // If relayout data has not been allocated yet and the client is requesting
1143 // to disable it, do nothing
1144 if( mRelayoutData || relayoutEnabled )
1148 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1150 mRelayoutData->relayoutEnabled = relayoutEnabled;
1154 bool Actor::IsRelayoutEnabled() const
1156 // Assume that if relayout data has not been allocated yet then
1157 // relayout is disabled
1158 return mRelayoutData && mRelayoutData->relayoutEnabled;
1161 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1163 EnsureRelayouter().SetLayoutDirty(dirty, dimension);
1166 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1168 return mRelayoutData && mRelayoutData->IsLayoutDirty(dimension);
1171 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1173 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1176 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1178 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1181 uint32_t Actor::AddRenderer( Renderer& renderer )
1185 mRenderers = new RendererContainer;
1188 uint32_t index = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1189 RendererPtr rendererPtr = RendererPtr( &renderer );
1190 mRenderers->push_back( rendererPtr );
1191 AttachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1195 uint32_t Actor::GetRendererCount() const
1197 uint32_t rendererCount(0);
1200 rendererCount = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1203 return rendererCount;
1206 RendererPtr Actor::GetRendererAt( uint32_t index )
1208 RendererPtr renderer;
1209 if( index < GetRendererCount() )
1211 renderer = ( *mRenderers )[ index ];
1217 void Actor::RemoveRenderer( Renderer& renderer )
1221 RendererIter end = mRenderers->end();
1222 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1224 if( (*iter).Get() == &renderer )
1226 mRenderers->erase( iter );
1227 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1234 void Actor::RemoveRenderer( uint32_t index )
1236 if( index < GetRendererCount() )
1238 RendererPtr renderer = ( *mRenderers )[ index ];
1239 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.Get()->GetRendererSceneObject() );
1240 mRenderers->erase( mRenderers->begin()+index );
1244 void Actor::SetDrawMode( DrawMode::Type drawMode )
1246 // this flag is not animatable so keep the value
1247 mDrawMode = drawMode;
1249 // node is being used in a separate thread; queue a message to set the value
1250 SetDrawModeMessage( GetEventThreadServices(), GetNode(), drawMode );
1253 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1255 // only valid when on-stage
1256 if( mScene && OnScene() )
1258 const RenderTaskList& taskList = mScene->GetRenderTaskList();
1260 Vector2 converted( screenX, screenY );
1262 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1263 uint32_t taskCount = taskList.GetTaskCount();
1264 for( uint32_t i = taskCount; i > 0; --i )
1266 RenderTaskPtr task = taskList.GetTask( i - 1 );
1267 if( ScreenToLocal( *task, localX, localY, screenX, screenY ) )
1269 // found a task where this conversion was ok so return
1277 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1279 bool retval = false;
1280 // only valid when on-stage
1283 CameraActor* camera = renderTask.GetCameraActor();
1287 renderTask.GetViewport( viewport );
1289 // need to translate coordinates to render tasks coordinate space
1290 Vector2 converted( screenX, screenY );
1291 if( renderTask.TranslateCoordinates( converted ) )
1293 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1300 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1302 return OnScene() && ScreenToLocalInternal(viewMatrix, projectionMatrix, GetNode().GetWorldMatrix(0), viewport, GetCurrentSize(), localX, localY, screenX, screenY);
1305 ActorGestureData& Actor::GetGestureData()
1307 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1308 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1309 if( nullptr == mGestureData )
1311 mGestureData = new ActorGestureData;
1313 return *mGestureData;
1316 bool Actor::IsGestureRequired( GestureType::Value type ) const
1318 return mGestureData && mGestureData->IsGestureRequired( type );
1321 bool Actor::EmitInterceptTouchEventSignal( const Dali::TouchEvent& touch )
1323 return EmitConsumingSignal( *this, mInterceptTouchedSignal, touch );
1326 bool Actor::EmitTouchEventSignal( const Dali::TouchEvent& touch )
1328 return EmitConsumingSignal( *this, mTouchedSignal, touch );
1331 bool Actor::EmitHoverEventSignal( const Dali::HoverEvent& event )
1333 return EmitConsumingSignal( *this, mHoveredSignal, event );
1336 bool Actor::EmitWheelEventSignal( const Dali::WheelEvent& event )
1338 return EmitConsumingSignal( *this, mWheelEventSignal, event );
1341 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
1343 EmitSignal( *this, mVisibilityChangedSignal, visible, type );
1346 void Actor::EmitLayoutDirectionChangedSignal( LayoutDirection::Type type )
1348 EmitSignal( *this, mLayoutDirectionChangedSignal, type );
1351 void Actor::EmitChildAddedSignal( Actor& child )
1353 EmitSignal( child, mChildAddedSignal );
1356 void Actor::EmitChildRemovedSignal( Actor& child )
1358 EmitSignal( child, mChildRemovedSignal );
1361 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1363 bool connected( true );
1364 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
1366 if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1368 actor->HoveredSignal().Connect( tracker, functor );
1370 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1372 actor->WheelEventSignal().Connect( tracker, functor );
1374 else if( 0 == signalName.compare( SIGNAL_ON_SCENE ) )
1376 actor->OnSceneSignal().Connect( tracker, functor );
1378 else if( 0 == signalName.compare( SIGNAL_OFF_SCENE ) )
1380 actor->OffSceneSignal().Connect( tracker, functor );
1382 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
1384 actor->OnRelayoutSignal().Connect( tracker, functor );
1386 else if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1388 actor->TouchedSignal().Connect( tracker, functor );
1390 else if( 0 == signalName.compare( SIGNAL_VISIBILITY_CHANGED ) )
1392 actor->VisibilityChangedSignal().Connect( tracker, functor );
1394 else if( 0 == signalName.compare( SIGNAL_LAYOUT_DIRECTION_CHANGED ) )
1396 actor->LayoutDirectionChangedSignal().Connect( tracker, functor );
1398 else if( 0 == signalName.compare( SIGNAL_CHILD_ADDED ) )
1400 actor->ChildAddedSignal().Connect( tracker, functor );
1402 else if( 0 == signalName.compare( SIGNAL_CHILD_REMOVED ) )
1404 actor->ChildRemovedSignal().Connect( tracker, functor );
1408 // signalName does not match any signal
1415 Actor::Actor( DerivedType derivedType, const SceneGraph::Node& node )
1419 mChildren( nullptr ),
1420 mRenderers( nullptr ),
1421 mParentOrigin( nullptr ),
1422 mAnchorPoint( nullptr ),
1423 mRelayoutData( nullptr ),
1424 mGestureData( nullptr ),
1425 mInterceptTouchedSignal(),
1428 mWheelEventSignal(),
1431 mOnRelayoutSignal(),
1432 mVisibilityChangedSignal(),
1433 mLayoutDirectionChangedSignal(),
1434 mChildAddedSignal(),
1435 mChildRemovedSignal(),
1436 mChildOrderChangedSignal(),
1437 mTargetOrientation( Quaternion::IDENTITY ),
1438 mTargetColor( Color::WHITE ),
1439 mTargetSize( Vector3::ZERO ),
1440 mTargetPosition( Vector3::ZERO ),
1441 mTargetScale( Vector3::ONE ),
1442 mAnimatedSize( Vector3::ZERO ),
1443 mTouchDelegateArea( Vector2::ZERO ),
1447 mUseAnimatedSize( AnimatedSizeFlag::CLEAR ),
1448 mIsRoot( ROOT_LAYER == derivedType ),
1449 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
1450 mIsOnScene( false ),
1452 mLeaveRequired( false ),
1453 mKeyboardFocusable( false ),
1454 mOnSceneSignalled( false ),
1455 mInsideOnSizeSet( false ),
1456 mInheritPosition( true ),
1457 mInheritOrientation( true ),
1458 mInheritScale( true ),
1459 mPositionUsesAnchorPoint( true ),
1461 mInheritLayoutDirection( true ),
1462 mCaptureAllTouchAfterStart( false ),
1463 mLayoutDirection( LayoutDirection::LEFT_TO_RIGHT ),
1464 mDrawMode( DrawMode::NORMAL ),
1465 mColorMode( Node::DEFAULT_COLOR_MODE ),
1466 mClippingMode( ClippingMode::DISABLED )
1470 void Actor::Initialize()
1474 GetEventThreadServices().RegisterObject( this );
1479 // Remove mParent pointers from children even if we're destroying core,
1480 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1483 for( const auto& actor : *mChildren )
1485 actor->SetParent( nullptr );
1491 // Guard to allow handle destruction after Core has been destroyed
1492 if( EventThreadServices::IsCoreRunning() )
1494 // Root layer will destroy its node in its own destructor
1497 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
1499 GetEventThreadServices().UnregisterObject( this );
1503 // Cleanup optional gesture data
1504 delete mGestureData;
1506 // Cleanup optional parent origin and anchor
1507 delete mParentOrigin;
1508 delete mAnchorPoint;
1510 // Delete optional relayout data
1511 delete mRelayoutData;
1514 void Actor::ConnectToScene( uint32_t parentDepth )
1516 // This container is used instead of walking the Actor hierarchy.
1517 // It protects us when the Actor hierarchy is modified during OnSceneConnectionExternal callbacks.
1518 ActorContainer connectionList;
1522 mScene->RequestRebuildDepthTree();
1525 // This stage is atomic i.e. not interrupted by user callbacks.
1526 RecursiveConnectToScene( connectionList, parentDepth + 1 );
1528 // Notify applications about the newly connected actors.
1529 for( const auto& actor : connectionList )
1531 actor->NotifyStageConnection();
1537 void Actor::RecursiveConnectToScene( ActorContainer& connectionList, uint32_t depth )
1539 DALI_ASSERT_ALWAYS( !OnScene() );
1542 mDepth = static_cast< uint16_t >( depth ); // overflow ignored, not expected in practice
1544 ConnectToSceneGraph();
1546 // Notification for internal derived classes
1547 OnSceneConnectionInternal();
1549 // This stage is atomic; avoid emitting callbacks until all Actors are connected
1550 connectionList.push_back( ActorPtr( this ) );
1552 // Recursively connect children
1555 for( const auto& actor : *mChildren )
1557 actor->SetScene( *mScene );
1558 actor->RecursiveConnectToScene( connectionList, depth + 1 );
1564 * This method is called when the Actor is connected to the Stage.
1565 * The parent must have added its Node to the scene-graph.
1566 * The child must connect its Node to the parent's Node.
1567 * This is recursive; the child calls ConnectToScene() for its children.
1569 void Actor::ConnectToSceneGraph()
1571 DALI_ASSERT_DEBUG( mParent != NULL);
1573 // Reparent Node in next Update
1574 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), mParent->GetNode(), GetNode() );
1576 // Request relayout on all actors that are added to the scenegraph
1579 // Notification for Object::Observers
1583 void Actor::NotifyStageConnection()
1585 // Actors can be removed (in a callback), before the on-stage stage is reported.
1586 // The actor may also have been reparented, in which case mOnSceneSignalled will be true.
1587 if( OnScene() && !mOnSceneSignalled )
1589 // Notification for external (CustomActor) derived classes
1590 OnSceneConnectionExternal( mDepth );
1592 if( !mOnSceneSignal.Empty() )
1594 Dali::Actor handle( this );
1595 mOnSceneSignal.Emit( handle );
1598 // Guard against Remove during callbacks
1601 mOnSceneSignalled = true; // signal required next time Actor is removed
1606 void Actor::DisconnectFromStage()
1608 // This container is used instead of walking the Actor hierachy.
1609 // It protects us when the Actor hierachy is modified during OnSceneDisconnectionExternal callbacks.
1610 ActorContainer disconnectionList;
1614 mScene->RequestRebuildDepthTree();
1617 // This stage is atomic i.e. not interrupted by user callbacks
1618 RecursiveDisconnectFromStage( disconnectionList );
1620 // Notify applications about the newly disconnected actors.
1621 for( const auto& actor : disconnectionList )
1623 actor->NotifyStageDisconnection();
1627 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
1629 // need to change state first so that internals relying on IsOnScene() inside OnSceneDisconnectionInternal() get the correct value
1632 // Recursively disconnect children
1635 for( const auto& child : *mChildren )
1637 child->RecursiveDisconnectFromStage( disconnectionList );
1641 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
1642 disconnectionList.push_back( ActorPtr( this ) );
1644 // Notification for internal derived classes
1645 OnSceneDisconnectionInternal();
1647 DisconnectFromSceneGraph();
1651 * This method is called by an actor or its parent, before a node removal message is sent.
1652 * This is recursive; the child calls DisconnectFromStage() for its children.
1654 void Actor::DisconnectFromSceneGraph()
1656 // Notification for Object::Observers
1657 OnSceneObjectRemove();
1660 void Actor::NotifyStageDisconnection()
1662 // Actors can be added (in a callback), before the off-stage state is reported.
1663 // Also if the actor was added & removed before mOnSceneSignalled was set, then we don't notify here.
1664 // only do this step if there is a stage, i.e. Core is not being shut down
1665 if ( EventThreadServices::IsCoreRunning() && !OnScene() && mOnSceneSignalled )
1667 // Notification for external (CustomeActor) derived classes
1668 OnSceneDisconnectionExternal();
1670 if( !mOffSceneSignal.Empty() )
1672 Dali::Actor handle( this );
1673 mOffSceneSignal.Emit( handle );
1676 // Guard against Add during callbacks
1679 mOnSceneSignalled = false; // signal required next time Actor is added
1684 bool Actor::IsNodeConnected() const
1686 bool connected( false );
1690 if( IsRoot() || GetNode().GetParent() )
1699 // This method initiates traversal of the actor tree using depth-first
1700 // traversal to set a depth index based on traversal order. It sends a
1701 // single message to update manager to update all the actor's nodes in
1702 // this tree with the depth index. The sceneGraphNodeDepths vector's
1703 // elements are ordered by depth, and could be used to reduce sorting
1704 // in the update thread.
1705 void Actor::RebuildDepthTree()
1707 DALI_LOG_TIMER_START(depthTimer);
1709 // Vector of scene-graph nodes and their depths to send to UpdateManager
1710 // in a single message
1711 OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths( new SceneGraph::NodeDepths() );
1713 int32_t depthIndex = 1;
1714 DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
1716 SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths );
1717 DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
1720 void Actor::DepthTraverseActorTree( OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths, int32_t& depthIndex )
1722 mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
1723 sceneGraphNodeDepths->Add( const_cast<SceneGraph::Node*>( &GetNode() ), mSortedDepth );
1725 // Create/add to children of this node
1728 for( const auto& child : *mChildren )
1730 Actor* childActor = child.Get();
1732 childActor->DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
1737 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
1739 PropertyHandler::SetDefaultProperty(*this, index, property);
1742 // TODO: This method needs to be removed
1743 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
1745 PropertyHandler::SetSceneGraphProperty(index, entry, value, GetEventThreadServices(), GetNode());
1748 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
1750 Property::Value value;
1752 if( ! GetCachedPropertyValue( index, value ) )
1754 // If property value is not stored in the event-side, then it must be a scene-graph only property
1755 GetCurrentPropertyValue( index, value );
1761 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
1763 Property::Value value;
1765 if( ! GetCurrentPropertyValue( index, value ) )
1767 // If unable to retrieve scene-graph property value, then it must be an event-side only property
1768 GetCachedPropertyValue( index, value );
1774 void Actor::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
1776 PropertyHandler::OnNotifyDefaultPropertyAnimation(*this, animation, index, value, animationType);
1779 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
1781 const PropertyBase* property = PropertyHandler::GetSceneObjectAnimatableProperty(index, GetNode());
1784 // not our property, ask base
1785 property = Object::GetSceneObjectAnimatableProperty( index );
1791 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
1793 const PropertyInputImpl* property = PropertyHandler::GetSceneObjectInputProperty(index, GetNode());
1796 // reuse animatable property getter as animatable properties are inputs as well
1797 // animatable property chains back to Object::GetSceneObjectInputProperty() so all properties get covered
1798 property = GetSceneObjectAnimatableProperty( index );
1804 int32_t Actor::GetPropertyComponentIndex( Property::Index index ) const
1806 int32_t componentIndex = PropertyHandler::GetPropertyComponentIndex(index);
1807 if( Property::INVALID_COMPONENT_INDEX == componentIndex )
1810 componentIndex = Object::GetPropertyComponentIndex( index );
1813 return componentIndex;
1816 void Actor::SetParent( Actor* parent )
1820 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
1824 mScene = parent->mScene;
1826 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1829 // Instruct each actor to create a corresponding node in the scene graph
1830 ConnectToScene( parent->GetHierarchyDepth() );
1833 // Resolve the name and index for the child properties if any
1834 ResolveChildProperties();
1836 else // parent being set to NULL
1838 DALI_ASSERT_ALWAYS( mParent != nullptr && "Actor should have a parent" );
1842 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1845 // Disconnect the Node & its children from the scene-graph.
1846 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
1848 // Instruct each actor to discard pointers to the scene-graph
1849 DisconnectFromStage();
1856 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
1859 Actor* actor = dynamic_cast< Actor* >( object );
1863 if( 0 == actionName.compare( ACTION_SHOW ) )
1865 actor->SetVisible( true );
1868 else if( 0 == actionName.compare( ACTION_HIDE ) )
1870 actor->SetVisible( false );
1878 Rect<> Actor::CalculateScreenExtents( ) const
1880 auto screenPosition = GetCurrentScreenPosition();
1881 Vector3 size = GetCurrentSize() * GetCurrentWorldScale();
1882 Vector3 anchorPointOffSet = size * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
1883 Vector2 position = Vector2( screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y );
1884 return { position.x, position.y, size.x, size.y };
1887 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
1889 return PropertyHandler::GetCachedPropertyValue(*this, index, value);
1892 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
1894 return PropertyHandler::GetCurrentPropertyValue(*this, index, value);
1897 Actor::Relayouter& Actor::EnsureRelayouter()
1899 // Assign relayouter
1900 if( !mRelayoutData )
1902 mRelayoutData = new Relayouter();
1905 return *mRelayoutData;
1908 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
1910 // Check if actor is dependent on parent
1911 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1913 if( ( dimension & ( 1 << i ) ) )
1915 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
1916 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
1926 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
1928 // Check if actor is dependent on children
1929 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1931 if( ( dimension & ( 1 << i ) ) )
1933 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
1934 switch( resizePolicy )
1936 case ResizePolicy::FIT_TO_CHILDREN:
1937 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
1953 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
1955 return Actor::RelayoutDependentOnChildren( dimension );
1958 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
1960 // Check each possible dimension and see if it is dependent on the input one
1961 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1963 if( dimension & ( 1 << i ) )
1965 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
1972 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
1974 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1976 if( dimension & ( 1 << i ) )
1978 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
1983 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
1985 // If more than one dimension is requested, just return the first one found
1986 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1988 if( ( dimension & ( 1 << i ) ) )
1990 return mRelayoutData->negotiatedDimensions[ i ];
1994 return 0.0f; // Default
1997 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
1999 EnsureRelayouter().SetPadding( padding, dimension );
2002 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
2004 if ( mRelayoutData )
2006 // If more than one dimension is requested, just return the first one found
2007 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2009 if( ( dimension & ( 1 << i ) ) )
2011 return mRelayoutData->dimensionPadding[ i ];
2016 return Relayouter::DEFAULT_DIMENSION_PADDING;
2019 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
2021 EnsureRelayouter().SetLayoutNegotiated(negotiated, dimension);
2024 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
2026 return mRelayoutData && mRelayoutData->IsLayoutNegotiated(dimension);
2029 float Actor::GetHeightForWidthBase( float width )
2031 float height = 0.0f;
2033 const Vector3 naturalSize = GetNaturalSize();
2034 if( naturalSize.width > 0.0f )
2036 height = naturalSize.height * width / naturalSize.width;
2038 else // we treat 0 as 1:1 aspect ratio
2046 float Actor::GetWidthForHeightBase( float height )
2050 const Vector3 naturalSize = GetNaturalSize();
2051 if( naturalSize.height > 0.0f )
2053 width = naturalSize.width * height / naturalSize.height;
2055 else // we treat 0 as 1:1 aspect ratio
2063 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
2065 // Fill to parent, taking size mode factor into account
2066 switch( child.GetResizePolicy( dimension ) )
2068 case ResizePolicy::FILL_TO_PARENT:
2070 return GetLatestSize( dimension );
2073 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2075 return GetLatestSize( dimension ) * GetDimensionValue( child.GetProperty< Vector3 >( Dali::Actor::Property::SIZE_MODE_FACTOR ), dimension );
2078 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2080 return GetLatestSize( dimension ) + GetDimensionValue( child.GetProperty< Vector3 >( Dali::Actor::Property::SIZE_MODE_FACTOR ), dimension );
2085 return GetLatestSize( dimension );
2090 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
2092 // Can be overridden in derived class
2093 return CalculateChildSizeBase( child, dimension );
2096 float Actor::GetHeightForWidth( float width )
2098 // Can be overridden in derived class
2099 return GetHeightForWidthBase( width );
2102 float Actor::GetWidthForHeight( float height )
2104 // Can be overridden in derived class
2105 return GetWidthForHeightBase( height );
2108 float Actor::GetLatestSize( Dimension::Type dimension ) const
2110 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
2113 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
2115 Vector2 padding = GetPadding( dimension );
2117 return GetLatestSize( dimension ) + padding.x + padding.y;
2120 float Actor::NegotiateFromParent( Dimension::Type dimension )
2122 Actor* parent = GetParent();
2125 Vector2 padding( GetPadding( dimension ) );
2126 Vector2 parentPadding( parent->GetPadding( dimension ) );
2127 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
2133 float Actor::NegotiateFromChildren( Dimension::Type dimension )
2135 float maxDimensionPoint = 0.0f;
2137 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2139 ActorPtr child = GetChildAt( i );
2141 if( !child->RelayoutDependentOnParent( dimension ) )
2143 // Calculate the min and max points that the children range across
2144 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
2145 float dimensionSize = child->GetRelayoutSize( dimension );
2146 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
2150 return maxDimensionPoint;
2153 float Actor::GetSize( Dimension::Type dimension ) const
2155 return GetDimensionValue( mTargetSize, dimension );
2158 float Actor::GetNaturalSize( Dimension::Type dimension ) const
2160 return GetDimensionValue( GetNaturalSize(), dimension );
2163 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
2165 switch( GetResizePolicy( dimension ) )
2167 case ResizePolicy::USE_NATURAL_SIZE:
2169 return GetNaturalSize( dimension );
2172 case ResizePolicy::FIXED:
2174 return GetDimensionValue( GetPreferredSize(), dimension );
2177 case ResizePolicy::USE_ASSIGNED_SIZE:
2179 return GetDimensionValue( maximumSize, dimension );
2182 case ResizePolicy::FILL_TO_PARENT:
2183 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2184 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2186 return NegotiateFromParent( dimension );
2189 case ResizePolicy::FIT_TO_CHILDREN:
2191 return NegotiateFromChildren( dimension );
2194 case ResizePolicy::DIMENSION_DEPENDENCY:
2196 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
2199 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
2201 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
2204 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
2206 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
2218 return 0.0f; // Default
2221 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
2223 // Check if it needs to be negotiated
2224 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
2226 // Check that we havn't gotten into an infinite loop
2227 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
2228 bool recursionFound = false;
2229 for( auto& element : recursionStack )
2231 if( element == searchActor )
2233 recursionFound = true;
2238 if( !recursionFound )
2240 // Record the path that we have taken
2241 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
2243 // Dimension dependency check
2244 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2246 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
2248 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
2250 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
2254 // Parent dependency check
2255 Actor* parent = GetParent();
2256 if( parent && RelayoutDependentOnParent( dimension ) )
2258 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
2261 // Children dependency check
2262 if( RelayoutDependentOnChildren( dimension ) )
2264 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2266 ActorPtr child = GetChildAt( i );
2268 // Only relayout child first if it is not dependent on this actor
2269 if( !child->RelayoutDependentOnParent( dimension ) )
2271 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
2276 // For deriving classes
2277 OnCalculateRelayoutSize( dimension );
2279 // All dependencies checked, calculate the size and set negotiated flag
2280 const float newSize = Relayouter::ClampDimension( *this, CalculateSize( dimension, allocatedSize ), dimension );
2282 SetNegotiatedDimension( newSize, dimension );
2283 SetLayoutNegotiated( true, dimension );
2285 // For deriving classes
2286 OnLayoutNegotiated( newSize, dimension );
2288 // This actor has been successfully processed, pop it off the recursion stack
2289 recursionStack.pop_back();
2293 // TODO: Break infinite loop
2294 SetLayoutNegotiated( true, dimension );
2299 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
2301 // Negotiate all dimensions that require it
2302 ActorDimensionStack recursionStack;
2304 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2306 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
2309 NegotiateDimension( dimension, allocatedSize, recursionStack );
2313 Vector2 Actor::ApplySizeSetPolicy( const Vector2& size )
2315 return mRelayoutData->ApplySizeSetPolicy(*this, size);
2318 void Actor::SetNegotiatedSize( RelayoutContainer& container )
2320 // Do the set actor size
2321 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
2323 // Adjust for size set policy
2324 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
2326 // Lock the flag to stop recursive relayouts on set size
2327 mRelayoutData->insideRelayout = true;
2328 SetSize( negotiatedSize );
2329 mRelayoutData->insideRelayout = false;
2331 // Clear flags for all dimensions
2332 SetLayoutDirty( false );
2334 // Give deriving classes a chance to respond
2335 OnRelayout( negotiatedSize, container );
2337 if( !mOnRelayoutSignal.Empty() )
2339 Dali::Actor handle( this );
2340 mOnRelayoutSignal.Emit( handle );
2344 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
2346 // Force a size negotiation for actors that has assigned size during relayout
2347 // This is required as otherwise the flags that force a relayout will not
2348 // necessarilly be set. This will occur if the actor has already been laid out.
2349 // The dirty flags are then cleared. Then if the actor is added back into the
2350 // relayout container afterwards, the dirty flags would still be clear...
2351 // causing a relayout to be skipped. Here we force any actors added to the
2352 // container to be relayed out.
2353 DALI_LOG_TIMER_START( NegSizeTimer1 );
2355 if( GetUseAssignedSize(Dimension::WIDTH ) )
2357 SetLayoutNegotiated( false, Dimension::WIDTH );
2359 if( GetUseAssignedSize( Dimension::HEIGHT ) )
2361 SetLayoutNegotiated( false, Dimension::HEIGHT );
2364 // Do the negotiation
2365 NegotiateDimensions( allocatedSize );
2367 // Set the actor size
2368 SetNegotiatedSize( container );
2370 // Negotiate down to children
2371 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2373 ActorPtr child = GetChildAt( i );
2375 // Forces children that have already been laid out to be relayed out
2376 // if they have assigned size during relayout.
2377 if( child->GetUseAssignedSize(Dimension::WIDTH) )
2379 child->SetLayoutNegotiated(false, Dimension::WIDTH);
2380 child->SetLayoutDirty(true, Dimension::WIDTH);
2383 if( child->GetUseAssignedSize(Dimension::HEIGHT) )
2385 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
2386 child->SetLayoutDirty(true, Dimension::HEIGHT);
2389 // Only relayout if required
2390 if( child->RelayoutRequired() )
2392 container.Add( Dali::Actor( child.Get() ), mTargetSize.GetVectorXY() );
2395 DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
2398 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
2402 mRelayoutData->SetUseAssignedSize(use, dimension);
2406 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
2408 return mRelayoutData && mRelayoutData->GetUseAssignedSize(dimension);
2411 void Actor::RelayoutRequest( Dimension::Type dimension )
2413 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
2414 if( relayoutController )
2416 Dali::Actor self( this );
2417 relayoutController->RequestRelayout( self, dimension );
2421 void Actor::SetPreferredSize( const Vector2& size )
2425 // If valid width or height, then set the resize policy to FIXED
2426 // 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,
2427 // then change to FIXED as well
2429 if( size.width > 0.0f || GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DEFAULT )
2431 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
2434 if( size.height > 0.0f || GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DEFAULT )
2436 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
2439 mRelayoutData->preferredSize = size;
2441 mUseAnimatedSize = AnimatedSizeFlag::CLEAR;
2446 Vector2 Actor::GetPreferredSize() const
2448 if ( mRelayoutData )
2450 return Vector2( mRelayoutData->preferredSize );
2453 return Relayouter::DEFAULT_PREFERRED_SIZE;
2456 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
2458 EnsureRelayouter().SetMinimumSize(size, dimension);
2462 float Actor::GetMinimumSize( Dimension::Type dimension ) const
2464 if ( mRelayoutData )
2466 return mRelayoutData->GetMinimumSize(dimension);
2469 return 0.0f; // Default
2472 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
2474 EnsureRelayouter().SetMaximumSize(size, dimension);
2478 float Actor::GetMaximumSize( Dimension::Type dimension ) const
2480 if ( mRelayoutData )
2482 return mRelayoutData->GetMaximumSize(dimension);
2485 return FLT_MAX; // Default
2488 void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
2490 if( mVisible != visible )
2492 if( sendMessage == SendMessage::TRUE )
2494 // node is being used in a separate thread; queue a message to set the value & base value
2495 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible );
2500 // Emit the signal on this actor and all its children
2501 EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
2505 void Actor::SetSiblingOrder( uint32_t order )
2509 ActorContainer& siblings = *(mParent->mChildren);
2510 uint32_t currentOrder = GetSiblingOrder();
2512 if( order != currentOrder )
2518 else if( order < siblings.size() -1 )
2520 if( order > currentOrder )
2522 RaiseAbove( *siblings[order] );
2526 LowerBelow( *siblings[order] );
2537 uint32_t Actor::GetSiblingOrder() const
2543 ActorContainer& siblings = *(mParent->mChildren);
2544 for( std::size_t i = 0; i < siblings.size(); ++i )
2546 if( siblings[i] == this )
2548 order = static_cast<uint32_t>( i );
2557 void Actor::RequestRebuildDepthTree()
2563 mScene->RequestRebuildDepthTree();
2572 ActorContainer& siblings = *(mParent->mChildren);
2573 if( siblings.back() != this ) // If not already at end
2575 for( std::size_t i=0; i<siblings.size(); ++i )
2577 if( siblings[i] == this )
2580 ActorPtr next = siblings[i+1];
2581 siblings[i+1] = this;
2588 Dali::Actor handle( this );
2589 mParent->mChildOrderChangedSignal.Emit( handle );
2591 RequestRebuildDepthTree();
2595 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2603 ActorContainer& siblings = *(mParent->mChildren);
2604 if( siblings.front() != this ) // If not already at beginning
2606 for( std::size_t i=1; i<siblings.size(); ++i )
2608 if( siblings[i] == this )
2610 // Swap with previous
2611 ActorPtr previous = siblings[i-1];
2612 siblings[i-1] = this;
2613 siblings[i] = previous;
2619 Dali::Actor handle( this );
2620 mParent->mChildOrderChangedSignal.Emit( handle );
2622 RequestRebuildDepthTree();
2626 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2630 void Actor::RaiseToTop()
2634 ActorContainer& siblings = *(mParent->mChildren);
2635 if( siblings.back() != this ) // If not already at end
2637 auto iter = std::find( siblings.begin(), siblings.end(), this );
2638 if( iter != siblings.end() )
2640 siblings.erase(iter);
2641 siblings.push_back(ActorPtr(this));
2645 Dali::Actor handle( this );
2646 mParent->mChildOrderChangedSignal.Emit( handle );
2648 RequestRebuildDepthTree();
2652 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2656 void Actor::LowerToBottom()
2660 ActorContainer& siblings = *(mParent->mChildren);
2661 if( siblings.front() != this ) // If not already at bottom,
2663 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2665 auto iter = std::find( siblings.begin(), siblings.end(), this );
2666 if( iter != siblings.end() )
2668 siblings.erase(iter);
2669 siblings.insert(siblings.begin(), thisPtr);
2673 Dali::Actor handle( this );
2674 mParent->mChildOrderChangedSignal.Emit( handle );
2676 RequestRebuildDepthTree();
2680 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2684 void Actor::RaiseAbove( Internal::Actor& target )
2688 ActorContainer& siblings = *(mParent->mChildren);
2689 if( siblings.back() != this && target.mParent == mParent ) // If not already at top
2691 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2693 auto targetIter = std::find( siblings.begin(), siblings.end(), &target );
2694 auto thisIter = std::find( siblings.begin(), siblings.end(), this );
2695 if( thisIter < targetIter )
2697 siblings.erase(thisIter);
2698 // Erasing early invalidates the targetIter. (Conversely, inserting first may also
2699 // invalidate thisIter)
2700 targetIter = std::find( siblings.begin(), siblings.end(), &target );
2702 siblings.insert(targetIter, thisPtr);
2705 Dali::Actor handle( this );
2706 mParent->mChildOrderChangedSignal.Emit( handle );
2708 RequestRebuildDepthTree();
2713 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2717 void Actor::LowerBelow( Internal::Actor& target )
2721 ActorContainer& siblings = *(mParent->mChildren);
2722 if( siblings.front() != this && target.mParent == mParent ) // If not already at bottom
2724 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2726 auto targetIter = std::find( siblings.begin(), siblings.end(), &target );
2727 auto thisIter = std::find( siblings.begin(), siblings.end(), this );
2729 if( thisIter > targetIter )
2731 siblings.erase(thisIter); // this only invalidates iterators at or after this point.
2732 siblings.insert(targetIter, thisPtr);
2735 Dali::Actor handle( this );
2736 mParent->mChildOrderChangedSignal.Emit( handle );
2738 RequestRebuildDepthTree();
2743 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2747 void Actor::SetInheritLayoutDirection( bool inherit )
2749 if( mInheritLayoutDirection != inherit )
2751 mInheritLayoutDirection = inherit;
2753 if( inherit && mParent )
2755 InheritLayoutDirectionRecursively( this, mParent->mLayoutDirection );
2760 void Actor::InheritLayoutDirectionRecursively( ActorPtr actor, Dali::LayoutDirection::Type direction, bool set )
2762 if( actor && ( actor->mInheritLayoutDirection || set ) )
2764 if( actor->mLayoutDirection != direction )
2766 actor->mLayoutDirection = direction;
2767 actor->EmitLayoutDirectionChangedSignal( direction );
2768 actor->RelayoutRequest();
2771 if( actor->GetChildCount() > 0 )
2773 for( const auto& child : actor->GetChildrenInternal() )
2775 InheritLayoutDirectionRecursively( child, direction );
2781 void Actor::SetUpdateSizeHint( const Vector2& updateSizeHint )
2783 // node is being used in a separate thread; queue a message to set the value & base value
2784 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mUpdateSizeHint, &AnimatableProperty<Vector3>::Bake, Vector3(updateSizeHint.width, updateSizeHint.height, 0.f ) );
2787 } // namespace Internal