2 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/event/actors/actor-impl.h>
27 #include <dali/devel-api/actors/layer-devel.h>
28 #include <dali/public-api/common/dali-common.h>
29 #include <dali/public-api/common/constants.h>
30 #include <dali/public-api/math/vector2.h>
31 #include <dali/public-api/math/vector3.h>
32 #include <dali/public-api/math/radian.h>
33 #include <dali/public-api/object/type-registry.h>
34 #include <dali/devel-api/actors/actor-devel.h>
35 #include <dali/internal/event/actors/actor-property-handler.h>
36 #include <dali/internal/event/actors/actor-relayouter.h>
37 #include <dali/internal/event/common/event-thread-services.h>
38 #include <dali/internal/event/render-tasks/render-task-impl.h>
39 #include <dali/internal/event/actors/camera-actor-impl.h>
40 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
41 #include <dali/internal/event/common/property-helper.h>
42 #include <dali/internal/event/common/stage-impl.h>
43 #include <dali/internal/event/common/type-info-impl.h>
44 #include <dali/internal/event/common/scene-impl.h>
45 #include <dali/internal/event/common/thread-local-storage.h>
46 #include <dali/internal/event/common/projection.h>
47 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
48 #include <dali/internal/update/nodes/node-messages.h>
49 #include <dali/internal/event/events/actor-gesture-data.h>
50 #include <dali/integration-api/debug.h>
52 using Dali::Internal::SceneGraph::Node;
53 using Dali::Internal::SceneGraph::AnimatableProperty;
54 using Dali::Internal::SceneGraph::PropertyBase;
56 #if defined(DEBUG_ENABLED)
57 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_DEPTH_TIMER" );
58 Debug::Filter* gLogRelayoutFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_TIMER" );
67 namespace // unnamed namespace
73 * We want to discourage the use of property strings (minimize string comparisons),
74 * particularly for the default properties.
75 * Name Type writable animatable constraint-input enum for index-checking
77 DALI_PROPERTY_TABLE_BEGIN
78 DALI_PROPERTY( "parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
79 DALI_PROPERTY( "parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
80 DALI_PROPERTY( "parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
81 DALI_PROPERTY( "parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
82 DALI_PROPERTY( "anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
83 DALI_PROPERTY( "anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
84 DALI_PROPERTY( "anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
85 DALI_PROPERTY( "anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
86 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
87 DALI_PROPERTY( "sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
88 DALI_PROPERTY( "sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
89 DALI_PROPERTY( "sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
90 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
91 DALI_PROPERTY( "positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
92 DALI_PROPERTY( "positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
93 DALI_PROPERTY( "positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
94 DALI_PROPERTY( "worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
95 DALI_PROPERTY( "worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
96 DALI_PROPERTY( "worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
97 DALI_PROPERTY( "worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
98 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
99 DALI_PROPERTY( "worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
100 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
101 DALI_PROPERTY( "scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
102 DALI_PROPERTY( "scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
103 DALI_PROPERTY( "scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
104 DALI_PROPERTY( "worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
105 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
106 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
107 DALI_PROPERTY( "colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
108 DALI_PROPERTY( "colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
109 DALI_PROPERTY( "colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
110 DALI_PROPERTY( "colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
111 DALI_PROPERTY( "worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
112 DALI_PROPERTY( "worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
113 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
114 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
115 DALI_PROPERTY( "leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
116 DALI_PROPERTY( "inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
117 DALI_PROPERTY( "inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
118 DALI_PROPERTY( "colorMode", INTEGER, true, false, false, Dali::Actor::Property::COLOR_MODE )
119 DALI_PROPERTY( "drawMode", INTEGER, true, false, false, Dali::Actor::Property::DRAW_MODE )
120 DALI_PROPERTY( "sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
121 DALI_PROPERTY( "widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
122 DALI_PROPERTY( "heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
123 DALI_PROPERTY( "sizeScalePolicy", INTEGER, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
124 DALI_PROPERTY( "widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
125 DALI_PROPERTY( "heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
126 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
127 DALI_PROPERTY( "minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
128 DALI_PROPERTY( "maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
129 DALI_PROPERTY( "inheritPosition", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_POSITION )
130 DALI_PROPERTY( "clippingMode", STRING, true, false, false, Dali::Actor::Property::CLIPPING_MODE )
131 DALI_PROPERTY( "layoutDirection", STRING, true, false, false, Dali::Actor::Property::LAYOUT_DIRECTION )
132 DALI_PROPERTY( "inheritLayoutDirection", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION )
133 DALI_PROPERTY( "opacity", FLOAT, true, true, true, Dali::Actor::Property::OPACITY )
134 DALI_PROPERTY( "screenPosition", VECTOR2, false, false, false, Dali::Actor::Property::SCREEN_POSITION )
135 DALI_PROPERTY( "positionUsesAnchorPoint", BOOLEAN, true, false, false, Dali::Actor::Property::POSITION_USES_ANCHOR_POINT )
136 DALI_PROPERTY( "culled", BOOLEAN, false, false, true, Dali::Actor::Property::CULLED )
137 DALI_PROPERTY( "id", INTEGER, false, false, false, Dali::Actor::Property::ID )
138 DALI_PROPERTY( "hierarchyDepth", INTEGER, false, false, false, Dali::Actor::Property::HIERARCHY_DEPTH )
139 DALI_PROPERTY( "isRoot", BOOLEAN, false, false, false, Dali::Actor::Property::IS_ROOT )
140 DALI_PROPERTY( "isLayer", BOOLEAN, false, false, false, Dali::Actor::Property::IS_LAYER )
141 DALI_PROPERTY( "connectedToScene", BOOLEAN, false, false, false, Dali::Actor::Property::CONNECTED_TO_SCENE )
142 DALI_PROPERTY( "keyboardFocusable", BOOLEAN, true, false, false, Dali::Actor::Property::KEYBOARD_FOCUSABLE )
143 DALI_PROPERTY( "siblingOrder", INTEGER, true, false, false, Dali::DevelActor::Property::SIBLING_ORDER )
144 DALI_PROPERTY( "updateSizeHint", VECTOR2, true, false, false, Dali::DevelActor::Property::UPDATE_SIZE_HINT )
145 DALI_PROPERTY( "captureAllTouchAfterStart", BOOLEAN, true, false, false, Dali::DevelActor::Property::CAPTURE_ALL_TOUCH_AFTER_START )
146 DALI_PROPERTY( "touchArea", VECTOR2, true, false, false, Dali::DevelActor::Property::TOUCH_AREA )
147 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperties )
151 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 );
839 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
842 float Actor::GetCurrentOpacity() const
844 // node is being used in a separate thread; copy the value from the previous update
845 return GetNode().GetOpacity(GetEventThreadServices().GetEventBufferIndex());
848 const Vector4& Actor::GetCurrentWorldColor() const
850 return GetNode().GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
853 void Actor::SetColor( const Vector4& color )
855 mTargetColor = color;
857 // node is being used in a separate thread; queue a message to set the value & base value
858 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::Bake, color );
860 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
863 void Actor::SetColorRed( float red )
865 mTargetColor.r = red;
867 // node is being used in a separate thread; queue a message to set the value & base value
868 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeX, red );
870 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
873 void Actor::SetColorGreen( float green )
875 mTargetColor.g = green;
877 // node is being used in a separate thread; queue a message to set the value & base value
878 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeY, green );
880 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
883 void Actor::SetColorBlue( float blue )
885 mTargetColor.b = blue;
887 // node is being used in a separate thread; queue a message to set the value & base value
888 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
890 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
893 const Vector4& Actor::GetCurrentColor() const
895 // node is being used in a separate thread; copy the value from the previous update
896 return GetNode().GetColor(GetEventThreadServices().GetEventBufferIndex());
899 void Actor::SetInheritOrientation( bool inherit )
901 if( mInheritOrientation != inherit )
903 // non animatable so keep local copy
904 mInheritOrientation = inherit;
905 // node is being used in a separate thread; queue a message to set the value
906 SetInheritOrientationMessage( GetEventThreadServices(), GetNode(), inherit );
910 void Actor::SetSizeModeFactor( const Vector3& factor )
914 mRelayoutData->sizeModeFactor = factor;
917 const Vector3& Actor::GetSizeModeFactor() const
921 return mRelayoutData->sizeModeFactor;
924 return Relayouter::DEFAULT_SIZE_MODE_FACTOR;
927 void Actor::SetColorMode( ColorMode colorMode )
929 // non animatable so keep local copy
930 mColorMode = colorMode;
931 // node is being used in a separate thread; queue a message to set the value
932 SetColorModeMessage( GetEventThreadServices(), GetNode(), colorMode );
935 void Actor::SetSize( float width, float height )
937 SetSize( Vector2( width, height ) );
940 void Actor::SetSize( float width, float height, float depth )
942 SetSize( Vector3( width, height, depth ) );
945 void Actor::SetSize( const Vector2& size )
947 SetSize( Vector3( size.width, size.height, 0.f ) );
950 void Actor::SetSizeInternal( const Vector2& size )
952 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
955 void Actor::SetSize( const Vector3& size )
957 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
959 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
960 SetPreferredSize( size.GetVectorXY() );
964 SetSizeInternal( size );
968 void Actor::SetSizeInternal( const Vector3& size )
970 // dont allow recursive loop
971 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
972 // check that we have a node AND the new size width, height or depth is at least a little bit different from the old one
973 if( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
974 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
975 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) )
979 // node is being used in a separate thread; queue a message to set the value & base value
980 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
982 // Notification for derived classes
983 mInsideOnSizeSet = true;
984 OnSizeSet( mTargetSize );
985 mInsideOnSizeSet = false;
987 // Raise a relayout request if the flag is not locked
988 if( mRelayoutData && !mRelayoutData->insideRelayout )
995 void Actor::SetWidth( float width )
997 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
999 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
1000 mRelayoutData->preferredSize.width = width;
1004 mTargetSize.width = width;
1006 // node is being used in a separate thread; queue a message to set the value & base value
1007 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1010 mUseAnimatedSize &= ~AnimatedSizeFlag::WIDTH;
1015 void Actor::SetHeight( float height )
1017 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1019 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
1020 mRelayoutData->preferredSize.height = height;
1024 mTargetSize.height = height;
1026 // node is being used in a separate thread; queue a message to set the value & base value
1027 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1030 mUseAnimatedSize &= ~AnimatedSizeFlag::HEIGHT;
1035 void Actor::SetDepth( float depth )
1037 mTargetSize.depth = depth;
1039 mUseAnimatedSize &= ~AnimatedSizeFlag::DEPTH;
1041 // node is being used in a separate thread; queue a message to set the value & base value
1042 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1045 Vector3 Actor::GetTargetSize() const
1047 Vector3 size = mTargetSize;
1049 if( mUseAnimatedSize & AnimatedSizeFlag::WIDTH )
1051 // Should return animated size if size is animated
1052 size.width = mAnimatedSize.width;
1056 // Should return preferred size if size is fixed as set by SetSize
1057 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
1059 size.width = GetPreferredSize().width;
1063 if( mUseAnimatedSize & AnimatedSizeFlag::HEIGHT )
1065 size.height = mAnimatedSize.height;
1069 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
1071 size.height = GetPreferredSize().height;
1075 if( mUseAnimatedSize & AnimatedSizeFlag::DEPTH )
1077 size.depth = mAnimatedSize.depth;
1083 const Vector3& Actor::GetCurrentSize() const
1085 // node is being used in a separate thread; copy the value from the previous update
1086 return GetNode().GetSize( GetEventThreadServices().GetEventBufferIndex() );
1089 Vector3 Actor::GetNaturalSize() const
1091 // It is up to deriving classes to return the appropriate natural size
1092 return Vector3( 0.0f, 0.0f, 0.0f );
1095 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1097 EnsureRelayouter().SetResizePolicy(policy, dimension, mTargetSize);
1099 OnSetResizePolicy( policy, dimension );
1101 // Trigger relayout on this control
1105 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1107 if ( mRelayoutData )
1109 return mRelayoutData->GetResizePolicy(dimension);
1112 return ResizePolicy::DEFAULT;
1115 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1119 mRelayoutData->sizeSetPolicy = policy;
1121 // Trigger relayout on this control
1125 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1127 if ( mRelayoutData )
1129 return mRelayoutData->sizeSetPolicy;
1132 return Relayouter::DEFAULT_SIZE_SCALE_POLICY;
1135 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1137 EnsureRelayouter().SetDimensionDependency(dimension, dependency);
1140 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1142 if ( mRelayoutData )
1144 return mRelayoutData->GetDimensionDependency(dimension);
1147 return Dimension::ALL_DIMENSIONS; // Default
1150 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1152 // If relayout data has not been allocated yet and the client is requesting
1153 // to disable it, do nothing
1154 if( mRelayoutData || relayoutEnabled )
1158 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1160 mRelayoutData->relayoutEnabled = relayoutEnabled;
1164 bool Actor::IsRelayoutEnabled() const
1166 // Assume that if relayout data has not been allocated yet then
1167 // relayout is disabled
1168 return mRelayoutData && mRelayoutData->relayoutEnabled;
1171 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1173 EnsureRelayouter().SetLayoutDirty(dirty, dimension);
1176 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1178 return mRelayoutData && mRelayoutData->IsLayoutDirty(dimension);
1181 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1183 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1186 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1188 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1191 uint32_t Actor::AddRenderer( Renderer& renderer )
1195 mRenderers = new RendererContainer;
1198 uint32_t index = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1199 RendererPtr rendererPtr = RendererPtr( &renderer );
1200 mRenderers->push_back( rendererPtr );
1201 AttachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1205 uint32_t Actor::GetRendererCount() const
1207 uint32_t rendererCount(0);
1210 rendererCount = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1213 return rendererCount;
1216 RendererPtr Actor::GetRendererAt( uint32_t index )
1218 RendererPtr renderer;
1219 if( index < GetRendererCount() )
1221 renderer = ( *mRenderers )[ index ];
1227 void Actor::RemoveRenderer( Renderer& renderer )
1231 RendererIter end = mRenderers->end();
1232 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1234 if( (*iter).Get() == &renderer )
1236 mRenderers->erase( iter );
1237 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1244 void Actor::RemoveRenderer( uint32_t index )
1246 if( index < GetRendererCount() )
1248 RendererPtr renderer = ( *mRenderers )[ index ];
1249 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.Get()->GetRendererSceneObject() );
1250 mRenderers->erase( mRenderers->begin()+index );
1254 void Actor::SetDrawMode( DrawMode::Type drawMode )
1256 // this flag is not animatable so keep the value
1257 mDrawMode = drawMode;
1259 // node is being used in a separate thread; queue a message to set the value
1260 SetDrawModeMessage( GetEventThreadServices(), GetNode(), drawMode );
1263 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1265 // only valid when on-stage
1266 if( mScene && OnScene() )
1268 const RenderTaskList& taskList = mScene->GetRenderTaskList();
1270 Vector2 converted( screenX, screenY );
1272 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1273 uint32_t taskCount = taskList.GetTaskCount();
1274 for( uint32_t i = taskCount; i > 0; --i )
1276 RenderTaskPtr task = taskList.GetTask( i - 1 );
1277 if( ScreenToLocal( *task, localX, localY, screenX, screenY ) )
1279 // found a task where this conversion was ok so return
1287 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1289 bool retval = false;
1290 // only valid when on-stage
1293 CameraActor* camera = renderTask.GetCameraActor();
1297 renderTask.GetViewport( viewport );
1299 // need to translate coordinates to render tasks coordinate space
1300 Vector2 converted( screenX, screenY );
1301 if( renderTask.TranslateCoordinates( converted ) )
1303 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1310 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1312 return OnScene() && ScreenToLocalInternal(viewMatrix, projectionMatrix, GetNode().GetWorldMatrix(0), viewport, GetCurrentSize(), localX, localY, screenX, screenY);
1315 ActorGestureData& Actor::GetGestureData()
1317 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1318 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1319 if( nullptr == mGestureData )
1321 mGestureData = new ActorGestureData;
1323 return *mGestureData;
1326 bool Actor::IsGestureRequired( GestureType::Value type ) const
1328 return mGestureData && mGestureData->IsGestureRequired( type );
1331 bool Actor::EmitInterceptTouchEventSignal( const Dali::TouchEvent& touch )
1333 return EmitConsumingSignal( *this, mInterceptTouchedSignal, touch );
1336 bool Actor::EmitTouchEventSignal( const Dali::TouchEvent& touch )
1338 return EmitConsumingSignal( *this, mTouchedSignal, touch );
1341 bool Actor::EmitHoverEventSignal( const Dali::HoverEvent& event )
1343 return EmitConsumingSignal( *this, mHoveredSignal, event );
1346 bool Actor::EmitWheelEventSignal( const Dali::WheelEvent& event )
1348 return EmitConsumingSignal( *this, mWheelEventSignal, event );
1351 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
1353 EmitSignal( *this, mVisibilityChangedSignal, visible, type );
1356 void Actor::EmitLayoutDirectionChangedSignal( LayoutDirection::Type type )
1358 EmitSignal( *this, mLayoutDirectionChangedSignal, type );
1361 void Actor::EmitChildAddedSignal( Actor& child )
1363 EmitSignal( child, mChildAddedSignal );
1366 void Actor::EmitChildRemovedSignal( Actor& child )
1368 EmitSignal( child, mChildRemovedSignal );
1371 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1373 bool connected( true );
1374 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
1376 if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1378 actor->HoveredSignal().Connect( tracker, functor );
1380 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1382 actor->WheelEventSignal().Connect( tracker, functor );
1384 else if( 0 == signalName.compare( SIGNAL_ON_SCENE ) )
1386 actor->OnSceneSignal().Connect( tracker, functor );
1388 else if( 0 == signalName.compare( SIGNAL_OFF_SCENE ) )
1390 actor->OffSceneSignal().Connect( tracker, functor );
1392 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
1394 actor->OnRelayoutSignal().Connect( tracker, functor );
1396 else if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1398 actor->TouchedSignal().Connect( tracker, functor );
1400 else if( 0 == signalName.compare( SIGNAL_VISIBILITY_CHANGED ) )
1402 actor->VisibilityChangedSignal().Connect( tracker, functor );
1404 else if( 0 == signalName.compare( SIGNAL_LAYOUT_DIRECTION_CHANGED ) )
1406 actor->LayoutDirectionChangedSignal().Connect( tracker, functor );
1408 else if( 0 == signalName.compare( SIGNAL_CHILD_ADDED ) )
1410 actor->ChildAddedSignal().Connect( tracker, functor );
1412 else if( 0 == signalName.compare( SIGNAL_CHILD_REMOVED ) )
1414 actor->ChildRemovedSignal().Connect( tracker, functor );
1418 // signalName does not match any signal
1425 Actor::Actor( DerivedType derivedType, const SceneGraph::Node& node )
1429 mChildren( nullptr ),
1430 mRenderers( nullptr ),
1431 mParentOrigin( nullptr ),
1432 mAnchorPoint( nullptr ),
1433 mRelayoutData( nullptr ),
1434 mGestureData( nullptr ),
1435 mInterceptTouchedSignal(),
1438 mWheelEventSignal(),
1441 mOnRelayoutSignal(),
1442 mVisibilityChangedSignal(),
1443 mLayoutDirectionChangedSignal(),
1444 mChildAddedSignal(),
1445 mChildRemovedSignal(),
1446 mChildOrderChangedSignal(),
1447 mTargetOrientation( Quaternion::IDENTITY ),
1448 mTargetColor( Color::WHITE ),
1449 mTargetSize( Vector3::ZERO ),
1450 mTargetPosition( Vector3::ZERO ),
1451 mTargetScale( Vector3::ONE ),
1452 mAnimatedSize( Vector3::ZERO ),
1453 mTouchArea( Vector2::ZERO ),
1457 mUseAnimatedSize( AnimatedSizeFlag::CLEAR ),
1458 mIsRoot( ROOT_LAYER == derivedType ),
1459 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
1460 mIsOnScene( false ),
1462 mLeaveRequired( false ),
1463 mKeyboardFocusable( false ),
1464 mOnSceneSignalled( false ),
1465 mInsideOnSizeSet( false ),
1466 mInheritPosition( true ),
1467 mInheritOrientation( true ),
1468 mInheritScale( true ),
1469 mPositionUsesAnchorPoint( true ),
1471 mInheritLayoutDirection( true ),
1472 mCaptureAllTouchAfterStart( false ),
1473 mLayoutDirection( LayoutDirection::LEFT_TO_RIGHT ),
1474 mDrawMode( DrawMode::NORMAL ),
1475 mColorMode( Node::DEFAULT_COLOR_MODE ),
1476 mClippingMode( ClippingMode::DISABLED )
1480 void Actor::Initialize()
1484 GetEventThreadServices().RegisterObject( this );
1489 // Remove mParent pointers from children even if we're destroying core,
1490 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1493 for( const auto& actor : *mChildren )
1495 actor->SetParent( nullptr );
1501 // Guard to allow handle destruction after Core has been destroyed
1502 if( EventThreadServices::IsCoreRunning() )
1504 // Root layer will destroy its node in its own destructor
1507 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
1509 GetEventThreadServices().UnregisterObject( this );
1513 // Cleanup optional gesture data
1514 delete mGestureData;
1516 // Cleanup optional parent origin and anchor
1517 delete mParentOrigin;
1518 delete mAnchorPoint;
1520 // Delete optional relayout data
1521 delete mRelayoutData;
1524 void Actor::ConnectToScene( uint32_t parentDepth )
1526 // This container is used instead of walking the Actor hierarchy.
1527 // It protects us when the Actor hierarchy is modified during OnSceneConnectionExternal callbacks.
1528 ActorContainer connectionList;
1532 mScene->RequestRebuildDepthTree();
1535 // This stage is atomic i.e. not interrupted by user callbacks.
1536 RecursiveConnectToScene( connectionList, parentDepth + 1 );
1538 // Notify applications about the newly connected actors.
1539 for( const auto& actor : connectionList )
1541 actor->NotifyStageConnection();
1547 void Actor::RecursiveConnectToScene( ActorContainer& connectionList, uint32_t depth )
1549 DALI_ASSERT_ALWAYS( !OnScene() );
1552 mDepth = static_cast< uint16_t >( depth ); // overflow ignored, not expected in practice
1554 ConnectToSceneGraph();
1556 // Notification for internal derived classes
1557 OnSceneConnectionInternal();
1559 // This stage is atomic; avoid emitting callbacks until all Actors are connected
1560 connectionList.push_back( ActorPtr( this ) );
1562 // Recursively connect children
1565 for( const auto& actor : *mChildren )
1567 actor->SetScene( *mScene );
1568 actor->RecursiveConnectToScene( connectionList, depth + 1 );
1574 * This method is called when the Actor is connected to the Stage.
1575 * The parent must have added its Node to the scene-graph.
1576 * The child must connect its Node to the parent's Node.
1577 * This is recursive; the child calls ConnectToScene() for its children.
1579 void Actor::ConnectToSceneGraph()
1581 DALI_ASSERT_DEBUG( mParent != NULL);
1583 // Reparent Node in next Update
1584 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), mParent->GetNode(), GetNode() );
1586 // Request relayout on all actors that are added to the scenegraph
1589 // Notification for Object::Observers
1593 void Actor::NotifyStageConnection()
1595 // Actors can be removed (in a callback), before the on-stage stage is reported.
1596 // The actor may also have been reparented, in which case mOnSceneSignalled will be true.
1597 if( OnScene() && !mOnSceneSignalled )
1599 // Notification for external (CustomActor) derived classes
1600 OnSceneConnectionExternal( mDepth );
1602 if( !mOnSceneSignal.Empty() )
1604 Dali::Actor handle( this );
1605 mOnSceneSignal.Emit( handle );
1608 // Guard against Remove during callbacks
1611 mOnSceneSignalled = true; // signal required next time Actor is removed
1616 void Actor::DisconnectFromStage()
1618 // This container is used instead of walking the Actor hierachy.
1619 // It protects us when the Actor hierachy is modified during OnSceneDisconnectionExternal callbacks.
1620 ActorContainer disconnectionList;
1624 mScene->RequestRebuildDepthTree();
1627 // This stage is atomic i.e. not interrupted by user callbacks
1628 RecursiveDisconnectFromStage( disconnectionList );
1630 // Notify applications about the newly disconnected actors.
1631 for( const auto& actor : disconnectionList )
1633 actor->NotifyStageDisconnection();
1637 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
1639 // need to change state first so that internals relying on IsOnScene() inside OnSceneDisconnectionInternal() get the correct value
1642 // Recursively disconnect children
1645 for( const auto& child : *mChildren )
1647 child->RecursiveDisconnectFromStage( disconnectionList );
1651 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
1652 disconnectionList.push_back( ActorPtr( this ) );
1654 // Notification for internal derived classes
1655 OnSceneDisconnectionInternal();
1657 DisconnectFromSceneGraph();
1661 * This method is called by an actor or its parent, before a node removal message is sent.
1662 * This is recursive; the child calls DisconnectFromStage() for its children.
1664 void Actor::DisconnectFromSceneGraph()
1666 // Notification for Object::Observers
1667 OnSceneObjectRemove();
1670 void Actor::NotifyStageDisconnection()
1672 // Actors can be added (in a callback), before the off-stage state is reported.
1673 // Also if the actor was added & removed before mOnSceneSignalled was set, then we don't notify here.
1674 // only do this step if there is a stage, i.e. Core is not being shut down
1675 if ( EventThreadServices::IsCoreRunning() && !OnScene() && mOnSceneSignalled )
1677 // Notification for external (CustomeActor) derived classes
1678 OnSceneDisconnectionExternal();
1680 if( !mOffSceneSignal.Empty() )
1682 Dali::Actor handle( this );
1683 mOffSceneSignal.Emit( handle );
1686 // Guard against Add during callbacks
1689 mOnSceneSignalled = false; // signal required next time Actor is added
1694 bool Actor::IsNodeConnected() const
1696 bool connected( false );
1700 if( IsRoot() || GetNode().GetParent() )
1709 // This method initiates traversal of the actor tree using depth-first
1710 // traversal to set a depth index based on traversal order. It sends a
1711 // single message to update manager to update all the actor's nodes in
1712 // this tree with the depth index. The sceneGraphNodeDepths vector's
1713 // elements are ordered by depth, and could be used to reduce sorting
1714 // in the update thread.
1715 void Actor::RebuildDepthTree()
1717 DALI_LOG_TIMER_START(depthTimer);
1719 // Vector of scene-graph nodes and their depths to send to UpdateManager
1720 // in a single message
1721 OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths( new SceneGraph::NodeDepths() );
1723 int32_t depthIndex = 1;
1724 DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
1726 SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths );
1727 DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
1730 void Actor::DepthTraverseActorTree( OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths, int32_t& depthIndex )
1732 mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
1733 sceneGraphNodeDepths->Add( const_cast<SceneGraph::Node*>( &GetNode() ), mSortedDepth );
1735 // Create/add to children of this node
1738 for( const auto& child : *mChildren )
1740 Actor* childActor = child.Get();
1742 childActor->DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
1747 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
1749 PropertyHandler::SetDefaultProperty(*this, index, property);
1752 // TODO: This method needs to be removed
1753 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
1755 PropertyHandler::SetSceneGraphProperty(index, entry, value, GetEventThreadServices(), GetNode());
1758 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
1760 Property::Value value;
1762 if( ! GetCachedPropertyValue( index, value ) )
1764 // If property value is not stored in the event-side, then it must be a scene-graph only property
1765 GetCurrentPropertyValue( index, value );
1771 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
1773 Property::Value value;
1775 if( ! GetCurrentPropertyValue( index, value ) )
1777 // If unable to retrieve scene-graph property value, then it must be an event-side only property
1778 GetCachedPropertyValue( index, value );
1784 void Actor::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
1786 PropertyHandler::OnNotifyDefaultPropertyAnimation(*this, animation, index, value, animationType);
1789 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
1791 const PropertyBase* property = PropertyHandler::GetSceneObjectAnimatableProperty(index, GetNode());
1794 // not our property, ask base
1795 property = Object::GetSceneObjectAnimatableProperty( index );
1801 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
1803 const PropertyInputImpl* property = PropertyHandler::GetSceneObjectInputProperty(index, GetNode());
1806 // reuse animatable property getter as animatable properties are inputs as well
1807 // animatable property chains back to Object::GetSceneObjectInputProperty() so all properties get covered
1808 property = GetSceneObjectAnimatableProperty( index );
1814 int32_t Actor::GetPropertyComponentIndex( Property::Index index ) const
1816 int32_t componentIndex = PropertyHandler::GetPropertyComponentIndex(index);
1817 if( Property::INVALID_COMPONENT_INDEX == componentIndex )
1820 componentIndex = Object::GetPropertyComponentIndex( index );
1823 return componentIndex;
1826 void Actor::SetParent( Actor* parent )
1830 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
1834 mScene = parent->mScene;
1836 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1839 // Instruct each actor to create a corresponding node in the scene graph
1840 ConnectToScene( parent->GetHierarchyDepth() );
1843 // Resolve the name and index for the child properties if any
1844 ResolveChildProperties();
1846 else // parent being set to NULL
1848 DALI_ASSERT_ALWAYS( mParent != nullptr && "Actor should have a parent" );
1852 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1855 // Disconnect the Node & its children from the scene-graph.
1856 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
1858 // Instruct each actor to discard pointers to the scene-graph
1859 DisconnectFromStage();
1866 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
1869 Actor* actor = dynamic_cast< Actor* >( object );
1873 if( 0 == actionName.compare( ACTION_SHOW ) )
1875 actor->SetVisible( true );
1878 else if( 0 == actionName.compare( ACTION_HIDE ) )
1880 actor->SetVisible( false );
1888 Rect<> Actor::CalculateScreenExtents( ) const
1890 auto screenPosition = GetCurrentScreenPosition();
1891 Vector3 size = GetCurrentSize() * GetCurrentWorldScale();
1892 Vector3 anchorPointOffSet = size * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
1893 Vector2 position = Vector2( screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y );
1894 return { position.x, position.y, size.x, size.y };
1897 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
1899 return PropertyHandler::GetCachedPropertyValue(*this, index, value);
1902 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
1904 return PropertyHandler::GetCurrentPropertyValue(*this, index, value);
1907 Actor::Relayouter& Actor::EnsureRelayouter()
1909 // Assign relayouter
1910 if( !mRelayoutData )
1912 mRelayoutData = new Relayouter();
1915 return *mRelayoutData;
1918 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
1920 // Check if actor is dependent on parent
1921 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1923 if( ( dimension & ( 1 << i ) ) )
1925 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
1926 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
1936 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
1938 // Check if actor is dependent on children
1939 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1941 if( ( dimension & ( 1 << i ) ) )
1943 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
1944 switch( resizePolicy )
1946 case ResizePolicy::FIT_TO_CHILDREN:
1947 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
1963 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
1965 return Actor::RelayoutDependentOnChildren( dimension );
1968 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
1970 // Check each possible dimension and see if it is dependent on the input one
1971 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1973 if( dimension & ( 1 << i ) )
1975 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
1982 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
1984 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1986 if( dimension & ( 1 << i ) )
1988 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
1993 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
1995 // If more than one dimension is requested, just return the first one found
1996 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1998 if( ( dimension & ( 1 << i ) ) )
2000 return mRelayoutData->negotiatedDimensions[ i ];
2004 return 0.0f; // Default
2007 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
2009 EnsureRelayouter().SetPadding( padding, dimension );
2012 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
2014 if ( mRelayoutData )
2016 // If more than one dimension is requested, just return the first one found
2017 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2019 if( ( dimension & ( 1 << i ) ) )
2021 return mRelayoutData->dimensionPadding[ i ];
2026 return Relayouter::DEFAULT_DIMENSION_PADDING;
2029 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
2031 EnsureRelayouter().SetLayoutNegotiated(negotiated, dimension);
2034 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
2036 return mRelayoutData && mRelayoutData->IsLayoutNegotiated(dimension);
2039 float Actor::GetHeightForWidthBase( float width )
2041 float height = 0.0f;
2043 const Vector3 naturalSize = GetNaturalSize();
2044 if( naturalSize.width > 0.0f )
2046 height = naturalSize.height * width / naturalSize.width;
2048 else // we treat 0 as 1:1 aspect ratio
2056 float Actor::GetWidthForHeightBase( float height )
2060 const Vector3 naturalSize = GetNaturalSize();
2061 if( naturalSize.height > 0.0f )
2063 width = naturalSize.width * height / naturalSize.height;
2065 else // we treat 0 as 1:1 aspect ratio
2073 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
2075 // Fill to parent, taking size mode factor into account
2076 switch( child.GetResizePolicy( dimension ) )
2078 case ResizePolicy::FILL_TO_PARENT:
2080 return GetLatestSize( dimension );
2083 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2085 return GetLatestSize( dimension ) * GetDimensionValue( child.GetProperty< Vector3 >( Dali::Actor::Property::SIZE_MODE_FACTOR ), dimension );
2088 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2090 return GetLatestSize( dimension ) + GetDimensionValue( child.GetProperty< Vector3 >( Dali::Actor::Property::SIZE_MODE_FACTOR ), dimension );
2095 return GetLatestSize( dimension );
2100 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
2102 // Can be overridden in derived class
2103 return CalculateChildSizeBase( child, dimension );
2106 float Actor::GetHeightForWidth( float width )
2108 // Can be overridden in derived class
2109 return GetHeightForWidthBase( width );
2112 float Actor::GetWidthForHeight( float height )
2114 // Can be overridden in derived class
2115 return GetWidthForHeightBase( height );
2118 float Actor::GetLatestSize( Dimension::Type dimension ) const
2120 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
2123 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
2125 Vector2 padding = GetPadding( dimension );
2127 return GetLatestSize( dimension ) + padding.x + padding.y;
2130 float Actor::NegotiateFromParent( Dimension::Type dimension )
2132 Actor* parent = GetParent();
2135 Vector2 padding( GetPadding( dimension ) );
2136 Vector2 parentPadding( parent->GetPadding( dimension ) );
2137 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
2143 float Actor::NegotiateFromChildren( Dimension::Type dimension )
2145 float maxDimensionPoint = 0.0f;
2147 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2149 ActorPtr child = GetChildAt( i );
2151 if( !child->RelayoutDependentOnParent( dimension ) )
2153 // Calculate the min and max points that the children range across
2154 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
2155 float dimensionSize = child->GetRelayoutSize( dimension );
2156 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
2160 return maxDimensionPoint;
2163 float Actor::GetSize( Dimension::Type dimension ) const
2165 return GetDimensionValue( mTargetSize, dimension );
2168 float Actor::GetNaturalSize( Dimension::Type dimension ) const
2170 return GetDimensionValue( GetNaturalSize(), dimension );
2173 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
2175 switch( GetResizePolicy( dimension ) )
2177 case ResizePolicy::USE_NATURAL_SIZE:
2179 return GetNaturalSize( dimension );
2182 case ResizePolicy::FIXED:
2184 return GetDimensionValue( GetPreferredSize(), dimension );
2187 case ResizePolicy::USE_ASSIGNED_SIZE:
2189 return GetDimensionValue( maximumSize, dimension );
2192 case ResizePolicy::FILL_TO_PARENT:
2193 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2194 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2196 return NegotiateFromParent( dimension );
2199 case ResizePolicy::FIT_TO_CHILDREN:
2201 return NegotiateFromChildren( dimension );
2204 case ResizePolicy::DIMENSION_DEPENDENCY:
2206 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
2209 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
2211 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
2214 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
2216 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
2228 return 0.0f; // Default
2231 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
2233 // Check if it needs to be negotiated
2234 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
2236 // Check that we havn't gotten into an infinite loop
2237 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
2238 bool recursionFound = false;
2239 for( auto& element : recursionStack )
2241 if( element == searchActor )
2243 recursionFound = true;
2248 if( !recursionFound )
2250 // Record the path that we have taken
2251 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
2253 // Dimension dependency check
2254 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2256 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
2258 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
2260 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
2264 // Parent dependency check
2265 Actor* parent = GetParent();
2266 if( parent && RelayoutDependentOnParent( dimension ) )
2268 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
2271 // Children dependency check
2272 if( RelayoutDependentOnChildren( dimension ) )
2274 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2276 ActorPtr child = GetChildAt( i );
2278 // Only relayout child first if it is not dependent on this actor
2279 if( !child->RelayoutDependentOnParent( dimension ) )
2281 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
2286 // For deriving classes
2287 OnCalculateRelayoutSize( dimension );
2289 // All dependencies checked, calculate the size and set negotiated flag
2290 const float newSize = Relayouter::ClampDimension( *this, CalculateSize( dimension, allocatedSize ), dimension );
2292 SetNegotiatedDimension( newSize, dimension );
2293 SetLayoutNegotiated( true, dimension );
2295 // For deriving classes
2296 OnLayoutNegotiated( newSize, dimension );
2298 // This actor has been successfully processed, pop it off the recursion stack
2299 recursionStack.pop_back();
2303 // TODO: Break infinite loop
2304 SetLayoutNegotiated( true, dimension );
2309 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
2311 // Negotiate all dimensions that require it
2312 ActorDimensionStack recursionStack;
2314 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2316 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
2319 NegotiateDimension( dimension, allocatedSize, recursionStack );
2323 Vector2 Actor::ApplySizeSetPolicy( const Vector2& size )
2325 return mRelayoutData->ApplySizeSetPolicy(*this, size);
2328 void Actor::SetNegotiatedSize( RelayoutContainer& container )
2330 // Do the set actor size
2331 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
2333 // Adjust for size set policy
2334 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
2336 // Lock the flag to stop recursive relayouts on set size
2337 mRelayoutData->insideRelayout = true;
2338 SetSize( negotiatedSize );
2339 mRelayoutData->insideRelayout = false;
2341 // Clear flags for all dimensions
2342 SetLayoutDirty( false );
2344 // Give deriving classes a chance to respond
2345 OnRelayout( negotiatedSize, container );
2347 if( !mOnRelayoutSignal.Empty() )
2349 Dali::Actor handle( this );
2350 mOnRelayoutSignal.Emit( handle );
2354 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
2356 // Force a size negotiation for actors that has assigned size during relayout
2357 // This is required as otherwise the flags that force a relayout will not
2358 // necessarilly be set. This will occur if the actor has already been laid out.
2359 // The dirty flags are then cleared. Then if the actor is added back into the
2360 // relayout container afterwards, the dirty flags would still be clear...
2361 // causing a relayout to be skipped. Here we force any actors added to the
2362 // container to be relayed out.
2363 DALI_LOG_TIMER_START( NegSizeTimer1 );
2365 if( GetUseAssignedSize(Dimension::WIDTH ) )
2367 SetLayoutNegotiated( false, Dimension::WIDTH );
2369 if( GetUseAssignedSize( Dimension::HEIGHT ) )
2371 SetLayoutNegotiated( false, Dimension::HEIGHT );
2374 // Do the negotiation
2375 NegotiateDimensions( allocatedSize );
2377 // Set the actor size
2378 SetNegotiatedSize( container );
2380 // Negotiate down to children
2381 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2383 ActorPtr child = GetChildAt( i );
2385 // Forces children that have already been laid out to be relayed out
2386 // if they have assigned size during relayout.
2387 if( child->GetUseAssignedSize(Dimension::WIDTH) )
2389 child->SetLayoutNegotiated(false, Dimension::WIDTH);
2390 child->SetLayoutDirty(true, Dimension::WIDTH);
2393 if( child->GetUseAssignedSize(Dimension::HEIGHT) )
2395 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
2396 child->SetLayoutDirty(true, Dimension::HEIGHT);
2399 // Only relayout if required
2400 if( child->RelayoutRequired() )
2402 container.Add( Dali::Actor( child.Get() ), mTargetSize.GetVectorXY() );
2405 DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
2408 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
2412 mRelayoutData->SetUseAssignedSize(use, dimension);
2416 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
2418 return mRelayoutData && mRelayoutData->GetUseAssignedSize(dimension);
2421 void Actor::RelayoutRequest( Dimension::Type dimension )
2423 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
2424 if( relayoutController )
2426 Dali::Actor self( this );
2427 relayoutController->RequestRelayout( self, dimension );
2431 void Actor::SetPreferredSize( const Vector2& size )
2435 // If valid width or height, then set the resize policy to FIXED
2436 // 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,
2437 // then change to FIXED as well
2439 if( size.width > 0.0f || GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DEFAULT )
2441 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
2444 if( size.height > 0.0f || GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DEFAULT )
2446 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
2449 mRelayoutData->preferredSize = size;
2451 mUseAnimatedSize = AnimatedSizeFlag::CLEAR;
2456 Vector2 Actor::GetPreferredSize() const
2458 if ( mRelayoutData )
2460 return Vector2( mRelayoutData->preferredSize );
2463 return Relayouter::DEFAULT_PREFERRED_SIZE;
2466 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
2468 EnsureRelayouter().SetMinimumSize(size, dimension);
2472 float Actor::GetMinimumSize( Dimension::Type dimension ) const
2474 if ( mRelayoutData )
2476 return mRelayoutData->GetMinimumSize(dimension);
2479 return 0.0f; // Default
2482 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
2484 EnsureRelayouter().SetMaximumSize(size, dimension);
2488 float Actor::GetMaximumSize( Dimension::Type dimension ) const
2490 if ( mRelayoutData )
2492 return mRelayoutData->GetMaximumSize(dimension);
2495 return FLT_MAX; // Default
2498 void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
2500 if( mVisible != visible )
2502 if( sendMessage == SendMessage::TRUE )
2504 // node is being used in a separate thread; queue a message to set the value & base value
2505 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible );
2507 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
2512 // Emit the signal on this actor and all its children
2513 EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
2517 void Actor::SetSiblingOrder( uint32_t order )
2521 ActorContainer& siblings = *(mParent->mChildren);
2522 uint32_t currentOrder = GetSiblingOrder();
2524 if( order != currentOrder )
2530 else if( order < siblings.size() -1 )
2532 if( order > currentOrder )
2534 RaiseAbove( *siblings[order] );
2538 LowerBelow( *siblings[order] );
2549 uint32_t Actor::GetSiblingOrder() const
2555 ActorContainer& siblings = *(mParent->mChildren);
2556 for( std::size_t i = 0; i < siblings.size(); ++i )
2558 if( siblings[i] == this )
2560 order = static_cast<uint32_t>( i );
2569 void Actor::RequestRebuildDepthTree()
2575 mScene->RequestRebuildDepthTree();
2584 ActorContainer& siblings = *(mParent->mChildren);
2585 if( siblings.back() != this ) // If not already at end
2587 for( std::size_t i=0; i<siblings.size(); ++i )
2589 if( siblings[i] == this )
2592 ActorPtr next = siblings[i+1];
2593 siblings[i+1] = this;
2600 Dali::Actor handle( this );
2601 mParent->mChildOrderChangedSignal.Emit( handle );
2603 RequestRebuildDepthTree();
2607 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2615 ActorContainer& siblings = *(mParent->mChildren);
2616 if( siblings.front() != this ) // If not already at beginning
2618 for( std::size_t i=1; i<siblings.size(); ++i )
2620 if( siblings[i] == this )
2622 // Swap with previous
2623 ActorPtr previous = siblings[i-1];
2624 siblings[i-1] = this;
2625 siblings[i] = previous;
2631 Dali::Actor handle( this );
2632 mParent->mChildOrderChangedSignal.Emit( handle );
2634 RequestRebuildDepthTree();
2638 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2642 void Actor::RaiseToTop()
2646 ActorContainer& siblings = *(mParent->mChildren);
2647 if( siblings.back() != this ) // If not already at end
2649 auto iter = std::find( siblings.begin(), siblings.end(), this );
2650 if( iter != siblings.end() )
2652 siblings.erase(iter);
2653 siblings.push_back(ActorPtr(this));
2657 Dali::Actor handle( this );
2658 mParent->mChildOrderChangedSignal.Emit( handle );
2660 RequestRebuildDepthTree();
2664 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2668 void Actor::LowerToBottom()
2672 ActorContainer& siblings = *(mParent->mChildren);
2673 if( siblings.front() != this ) // If not already at bottom,
2675 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2677 auto iter = std::find( siblings.begin(), siblings.end(), this );
2678 if( iter != siblings.end() )
2680 siblings.erase(iter);
2681 siblings.insert(siblings.begin(), thisPtr);
2685 Dali::Actor handle( this );
2686 mParent->mChildOrderChangedSignal.Emit( handle );
2688 RequestRebuildDepthTree();
2692 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2696 void Actor::RaiseAbove( Internal::Actor& target )
2700 ActorContainer& siblings = *(mParent->mChildren);
2701 if( siblings.back() != this && target.mParent == mParent ) // If not already at top
2703 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2705 auto targetIter = std::find( siblings.begin(), siblings.end(), &target );
2706 auto thisIter = std::find( siblings.begin(), siblings.end(), this );
2707 if( thisIter < targetIter )
2709 siblings.erase(thisIter);
2710 // Erasing early invalidates the targetIter. (Conversely, inserting first may also
2711 // invalidate thisIter)
2712 targetIter = std::find( siblings.begin(), siblings.end(), &target );
2714 siblings.insert(targetIter, thisPtr);
2717 Dali::Actor handle( this );
2718 mParent->mChildOrderChangedSignal.Emit( handle );
2720 RequestRebuildDepthTree();
2725 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2729 void Actor::LowerBelow( Internal::Actor& target )
2733 ActorContainer& siblings = *(mParent->mChildren);
2734 if( siblings.front() != this && target.mParent == mParent ) // If not already at bottom
2736 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2738 auto targetIter = std::find( siblings.begin(), siblings.end(), &target );
2739 auto thisIter = std::find( siblings.begin(), siblings.end(), this );
2741 if( thisIter > targetIter )
2743 siblings.erase(thisIter); // this only invalidates iterators at or after this point.
2744 siblings.insert(targetIter, thisPtr);
2747 Dali::Actor handle( this );
2748 mParent->mChildOrderChangedSignal.Emit( handle );
2750 RequestRebuildDepthTree();
2755 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2759 void Actor::SetInheritLayoutDirection( bool inherit )
2761 if( mInheritLayoutDirection != inherit )
2763 mInheritLayoutDirection = inherit;
2765 if( inherit && mParent )
2767 InheritLayoutDirectionRecursively( this, mParent->mLayoutDirection );
2772 void Actor::InheritLayoutDirectionRecursively( ActorPtr actor, Dali::LayoutDirection::Type direction, bool set )
2774 if( actor && ( actor->mInheritLayoutDirection || set ) )
2776 if( actor->mLayoutDirection != direction )
2778 actor->mLayoutDirection = direction;
2779 actor->EmitLayoutDirectionChangedSignal( direction );
2780 actor->RelayoutRequest();
2783 if( actor->GetChildCount() > 0 )
2785 for( const auto& child : actor->GetChildrenInternal() )
2787 InheritLayoutDirectionRecursively( child, direction );
2793 void Actor::SetUpdateSizeHint( const Vector2& updateSizeHint )
2795 // node is being used in a separate thread; queue a message to set the value & base value
2796 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mUpdateSizeHint, &AnimatableProperty<Vector3>::Bake, Vector3(updateSizeHint.width, updateSizeHint.height, 0.f ) );
2799 } // namespace Internal