2 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/event/actors/actor-impl.h>
27 #include <dali/devel-api/actors/layer-devel.h>
28 #include <dali/public-api/common/dali-common.h>
29 #include <dali/public-api/common/constants.h>
30 #include <dali/public-api/math/vector2.h>
31 #include <dali/public-api/math/vector3.h>
32 #include <dali/public-api/math/radian.h>
33 #include <dali/public-api/object/type-registry.h>
34 #include <dali/devel-api/common/capabilities.h>
35 #include <dali/devel-api/actors/actor-devel.h>
36 #include <dali/internal/event/actors/actor-property-handler.h>
37 #include <dali/internal/event/actors/actor-relayouter.h>
38 #include <dali/internal/event/common/event-thread-services.h>
39 #include <dali/internal/event/render-tasks/render-task-impl.h>
40 #include <dali/internal/event/actors/camera-actor-impl.h>
41 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
42 #include <dali/internal/event/common/property-helper.h>
43 #include <dali/internal/event/common/stage-impl.h>
44 #include <dali/internal/event/common/type-info-impl.h>
45 #include <dali/internal/event/common/scene-impl.h>
46 #include <dali/internal/event/common/thread-local-storage.h>
47 #include <dali/internal/event/common/projection.h>
48 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
49 #include <dali/internal/update/nodes/node-messages.h>
50 #include <dali/internal/event/events/actor-gesture-data.h>
51 #include <dali/integration-api/debug.h>
53 using Dali::Internal::SceneGraph::Node;
54 using Dali::Internal::SceneGraph::AnimatableProperty;
55 using Dali::Internal::SceneGraph::PropertyBase;
57 #if defined(DEBUG_ENABLED)
58 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_DEPTH_TIMER" );
59 Debug::Filter* gLogRelayoutFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_TIMER" );
68 namespace // unnamed namespace
74 * We want to discourage the use of property strings (minimize string comparisons),
75 * particularly for the default properties.
76 * Name Type writable animatable constraint-input enum for index-checking
78 DALI_PROPERTY_TABLE_BEGIN
79 DALI_PROPERTY( "parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN )
80 DALI_PROPERTY( "parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X )
81 DALI_PROPERTY( "parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y )
82 DALI_PROPERTY( "parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z )
83 DALI_PROPERTY( "anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT )
84 DALI_PROPERTY( "anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X )
85 DALI_PROPERTY( "anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y )
86 DALI_PROPERTY( "anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z )
87 DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE )
88 DALI_PROPERTY( "sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH )
89 DALI_PROPERTY( "sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT )
90 DALI_PROPERTY( "sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH )
91 DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION )
92 DALI_PROPERTY( "positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X )
93 DALI_PROPERTY( "positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y )
94 DALI_PROPERTY( "positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z )
95 DALI_PROPERTY( "worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION )
96 DALI_PROPERTY( "worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X )
97 DALI_PROPERTY( "worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y )
98 DALI_PROPERTY( "worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z )
99 DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION )
100 DALI_PROPERTY( "worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION )
101 DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE )
102 DALI_PROPERTY( "scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X )
103 DALI_PROPERTY( "scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y )
104 DALI_PROPERTY( "scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z )
105 DALI_PROPERTY( "worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE )
106 DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE )
107 DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR )
108 DALI_PROPERTY( "colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED )
109 DALI_PROPERTY( "colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN )
110 DALI_PROPERTY( "colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE )
111 DALI_PROPERTY( "colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA )
112 DALI_PROPERTY( "worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR )
113 DALI_PROPERTY( "worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX )
114 DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME )
115 DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE )
116 DALI_PROPERTY( "leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED )
117 DALI_PROPERTY( "inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
118 DALI_PROPERTY( "inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE )
119 DALI_PROPERTY( "colorMode", INTEGER, true, false, false, Dali::Actor::Property::COLOR_MODE )
120 DALI_PROPERTY( "drawMode", INTEGER, true, false, false, Dali::Actor::Property::DRAW_MODE )
121 DALI_PROPERTY( "sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
122 DALI_PROPERTY( "widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
123 DALI_PROPERTY( "heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
124 DALI_PROPERTY( "sizeScalePolicy", INTEGER, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
125 DALI_PROPERTY( "widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
126 DALI_PROPERTY( "heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
127 DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING )
128 DALI_PROPERTY( "minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE )
129 DALI_PROPERTY( "maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE )
130 DALI_PROPERTY( "inheritPosition", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_POSITION )
131 DALI_PROPERTY( "clippingMode", STRING, true, false, false, Dali::Actor::Property::CLIPPING_MODE )
132 DALI_PROPERTY( "layoutDirection", STRING, true, false, false, Dali::Actor::Property::LAYOUT_DIRECTION )
133 DALI_PROPERTY( "inheritLayoutDirection", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION )
134 DALI_PROPERTY( "opacity", FLOAT, true, true, true, Dali::Actor::Property::OPACITY )
135 DALI_PROPERTY( "screenPosition", VECTOR2, false, false, false, Dali::Actor::Property::SCREEN_POSITION )
136 DALI_PROPERTY( "positionUsesAnchorPoint", BOOLEAN, true, false, false, Dali::Actor::Property::POSITION_USES_ANCHOR_POINT )
137 DALI_PROPERTY( "culled", BOOLEAN, false, false, true, Dali::Actor::Property::CULLED )
138 DALI_PROPERTY( "id", INTEGER, false, false, false, Dali::Actor::Property::ID )
139 DALI_PROPERTY( "hierarchyDepth", INTEGER, false, false, false, Dali::Actor::Property::HIERARCHY_DEPTH )
140 DALI_PROPERTY( "isRoot", BOOLEAN, false, false, false, Dali::Actor::Property::IS_ROOT )
141 DALI_PROPERTY( "isLayer", BOOLEAN, false, false, false, Dali::Actor::Property::IS_LAYER )
142 DALI_PROPERTY( "connectedToScene", BOOLEAN, false, false, false, Dali::Actor::Property::CONNECTED_TO_SCENE )
143 DALI_PROPERTY( "keyboardFocusable", BOOLEAN, true, false, false, Dali::Actor::Property::KEYBOARD_FOCUSABLE )
144 DALI_PROPERTY( "siblingOrder", INTEGER, true, false, false, Dali::DevelActor::Property::SIBLING_ORDER )
145 DALI_PROPERTY( "updateSizeHint", VECTOR2, true, false, false, Dali::DevelActor::Property::UPDATE_SIZE_HINT )
146 DALI_PROPERTY( "captureAllTouchAfterStart", BOOLEAN, true, false, false, Dali::DevelActor::Property::CAPTURE_ALL_TOUCH_AFTER_START )
147 DALI_PROPERTY( "touchArea", VECTOR2, true, false, false, Dali::DevelActor::Property::TOUCH_AREA )
148 DALI_PROPERTY( "blendEquation", INTEGER, true, false, false, Dali::DevelActor::Property::BLEND_EQUATION )
149 DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperties )
153 const char* const SIGNAL_HOVERED = "hovered";
154 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
155 const char* const SIGNAL_ON_SCENE = "onScene";
156 const char* const SIGNAL_OFF_SCENE = "offScene";
157 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
158 const char* const SIGNAL_TOUCHED = "touched";
159 const char* const SIGNAL_VISIBILITY_CHANGED = "visibilityChanged";
160 const char* const SIGNAL_LAYOUT_DIRECTION_CHANGED = "layoutDirectionChanged";
161 const char* const SIGNAL_CHILD_ADDED = "childAdded";
162 const char* const SIGNAL_CHILD_REMOVED = "childRemoved";
166 const char* const ACTION_SHOW = "show";
167 const char* const ACTION_HIDE = "hide";
169 BaseHandle CreateActor()
171 return Dali::Actor::New();
174 TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor, ActorDefaultProperties );
176 SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
177 SignalConnectorType signalConnector3( mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal );
178 SignalConnectorType signalConnector4( mType, SIGNAL_ON_SCENE, &Actor::DoConnectSignal );
179 SignalConnectorType signalConnector5( mType, SIGNAL_OFF_SCENE, &Actor::DoConnectSignal );
180 SignalConnectorType signalConnector6( mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal );
181 SignalConnectorType signalConnector7( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
182 SignalConnectorType signalConnector8( mType, SIGNAL_VISIBILITY_CHANGED, &Actor::DoConnectSignal );
183 SignalConnectorType signalConnector9( mType, SIGNAL_LAYOUT_DIRECTION_CHANGED, &Actor::DoConnectSignal );
184 SignalConnectorType signalConnector10( mType, SIGNAL_CHILD_ADDED, &Actor::DoConnectSignal );
185 SignalConnectorType signalConnector11( mType, SIGNAL_CHILD_REMOVED, &Actor::DoConnectSignal );
187 TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
188 TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
191 * @brief Extract a given dimension from a Vector2
193 * @param[in] values The values to extract from
194 * @param[in] dimension The dimension to extract
195 * @return Return the value for the dimension
197 constexpr float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
201 case Dimension::WIDTH:
205 case Dimension::HEIGHT:
207 return values.height;
218 * @brief Extract a given dimension from a Vector3
220 * @param[in] values The values to extract from
221 * @param[in] dimension The dimension to extract
222 * @return Return the value for the dimension
224 float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
226 return GetDimensionValue( values.GetVectorXY(), dimension );
230 * @brief Recursively emits the visibility-changed-signal on the actor tree.
231 * @param[in] actor The actor to emit the signal on
232 * @param[in] visible The new visibility of the actor
233 * @param[in] type Whether the actor's visible property has changed or a parent's
235 void EmitVisibilityChangedSignalRecursively( ActorPtr actor, bool visible, DevelActor::VisibilityChange::Type type )
239 actor->EmitVisibilityChangedSignal( visible, type );
241 if( actor->GetChildCount() > 0 )
243 for( auto& child : actor->GetChildrenInternal() )
245 EmitVisibilityChangedSignalRecursively( child, visible, DevelActor::VisibilityChange::PARENT );
251 /// Helper for emitting a signal
252 template<typename Signal, typename Event>
253 bool EmitConsumingSignal( Actor& actor, Signal& signal, const Event& event )
255 bool consumed = false;
257 if( !signal.Empty() )
259 Dali::Actor handle( &actor );
260 consumed = signal.Emit( handle, event );
266 /// Helper for emitting signals with multiple parameters
267 template<typename Signal, typename... Param>
268 void EmitSignal( Actor& actor, Signal& signal, Param... params)
270 if( !signal.Empty() )
272 Dali::Actor handle( &actor );
273 signal.Emit( handle, params... );
277 bool ScreenToLocalInternal(
278 const Matrix& viewMatrix,
279 const Matrix& projectionMatrix,
280 const Matrix& worldMatrix,
281 const Viewport& viewport,
282 const Vector3& currentSize,
288 // Get the ModelView matrix
290 Matrix::Multiply( modelView, worldMatrix, viewMatrix );
292 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
293 Matrix invertedMvp( false/*don't init*/);
294 Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
295 bool success = invertedMvp.Invert();
297 // Convert to GL coordinates
298 Vector4 screenPos( screenX - static_cast<float>( viewport.x ), static_cast<float>( viewport.height ) - screenY - static_cast<float>( viewport.y ), 0.f, 1.f );
303 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), nearPos );
310 success = Unproject( screenPos, invertedMvp, static_cast<float>( viewport.width ), static_cast<float>( viewport.height ), farPos );
316 if( XyPlaneIntersect( nearPos, farPos, local ) )
318 Vector3 size = currentSize;
319 localX = local.x + size.x * 0.5f;
320 localY = local.y + size.y * 0.5f;
331 } // unnamed namespace
333 ActorPtr Actor::New()
335 // pass a reference to actor, actor does not own its node
336 ActorPtr actor( new Actor( BASIC, *CreateNode() ) );
338 // Second-phase construction
344 const SceneGraph::Node* Actor::CreateNode()
346 // create node. Nodes are owned by the update manager
347 SceneGraph::Node* node = SceneGraph::Node::New();
348 OwnerPointer< SceneGraph::Node > transferOwnership( node );
349 Internal::ThreadLocalStorage* tls = Internal::ThreadLocalStorage::GetInternal();
351 DALI_ASSERT_ALWAYS( tls && "ThreadLocalStorage is null" );
353 AddNodeMessage( tls->GetUpdateManager(), transferOwnership );
358 void Actor::SetName( const std::string& name )
362 // ATTENTION: string for debug purposes is not thread safe.
363 DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( &GetNode() ), name );
366 uint32_t Actor::GetId() const
368 return GetNode().GetId();
371 Dali::Layer Actor::GetLayer()
375 // Short-circuit for Layer derived actors
378 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
381 // Find the immediate Layer parent
382 for( Actor* parent = mParent; !layer && parent != nullptr; parent = parent->GetParent() )
384 if( parent->IsLayer() )
386 layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
393 void Actor::Add( Actor& child )
395 DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
396 DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
400 mChildren = new ActorContainer;
403 Actor* const oldParent( child.mParent );
405 // child might already be ours
406 if( this != oldParent )
408 // if we already have parent, unparent us first
411 oldParent->Remove( child ); // This causes OnChildRemove callback & ChildRemoved signal
413 // Old parent may need to readjust to missing child
414 if( oldParent->RelayoutDependentOnChildren() )
416 oldParent->RelayoutRequest();
420 // Guard against Add() during previous OnChildRemove callback
423 // Do this first, since user callbacks from within SetParent() may need to remove child
424 mChildren->push_back( ActorPtr( &child ) );
426 // SetParent asserts that child can be added
427 child.SetParent( this );
429 // Notification for derived classes
431 EmitChildAddedSignal( child );
433 InheritLayoutDirectionRecursively( ActorPtr( &child ), mLayoutDirection );
435 // Only put in a relayout request if there is a suitable dependency
436 if( RelayoutDependentOnChildren() )
444 void Actor::Remove( Actor& child )
446 if( (this == &child) || (!mChildren) )
448 // no children or removing itself
454 // Find the child in mChildren, and unparent it
455 ActorIter end = mChildren->end();
456 for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
458 ActorPtr actor = (*iter);
460 if( actor.Get() == &child )
462 // Keep handle for OnChildRemove notification
465 // Do this first, since user callbacks from within SetParent() may need to add the child
466 mChildren->erase( iter );
468 DALI_ASSERT_DEBUG( actor->GetParent() == this );
469 actor->SetParent( nullptr );
477 // Only put in a relayout request if there is a suitable dependency
478 if( RelayoutDependentOnChildren() )
484 // Notification for derived classes
485 OnChildRemove( child );
486 EmitChildRemovedSignal( child );
489 void Actor::Unparent()
493 // Remove this actor from the parent. The remove will put a relayout request in for
494 // the parent if required
495 mParent->Remove( *this );
496 // mParent is now NULL!
500 uint32_t Actor::GetChildCount() const
502 return ( nullptr != mChildren ) ? static_cast<uint32_t>( mChildren->size() ) : 0; // only 4,294,967,295 children per actor
505 ActorPtr Actor::GetChildAt( uint32_t index ) const
507 DALI_ASSERT_ALWAYS( index < GetChildCount() );
509 return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
512 ActorPtr Actor::FindChildByName( const std::string& actorName )
514 ActorPtr child = nullptr;
515 if( actorName == mName )
521 for( const auto& actor : *mChildren )
523 child = actor->FindChildByName( actorName );
534 ActorPtr Actor::FindChildById( const uint32_t id )
536 ActorPtr child = nullptr;
543 for( const auto& actor : *mChildren )
545 child = actor->FindChildById( id );
556 void Actor::SetParentOrigin( const Vector3& origin )
558 // node is being used in a separate thread; queue a message to set the value & base value
559 SetParentOriginMessage( GetEventThreadServices(), GetNode(), origin );
561 // Cache for event-thread access
564 // not allocated, check if different from default
565 if( ParentOrigin::DEFAULT != origin )
567 mParentOrigin = new Vector3( origin );
572 // check if different from current costs more than just set
573 *mParentOrigin = origin;
577 const Vector3& Actor::GetCurrentParentOrigin() const
579 // Cached for event-thread access
580 return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
583 void Actor::SetAnchorPoint( const Vector3& anchor )
585 // node is being used in a separate thread; queue a message to set the value & base value
586 SetAnchorPointMessage( GetEventThreadServices(), GetNode(), anchor );
588 // Cache for event-thread access
591 // not allocated, check if different from default
592 if( AnchorPoint::DEFAULT != anchor )
594 mAnchorPoint = new Vector3( anchor );
599 // check if different from current costs more than just set
600 *mAnchorPoint = anchor;
604 const Vector3& Actor::GetCurrentAnchorPoint() const
606 // Cached for event-thread access
607 return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
610 void Actor::SetPosition( float x, float y )
612 SetPosition( Vector3( x, y, 0.0f ) );
615 void Actor::SetPosition( float x, float y, float z )
617 SetPosition( Vector3( x, y, z ) );
620 void Actor::SetPosition( const Vector3& position )
622 mTargetPosition = position;
624 // node is being used in a separate thread; queue a message to set the value & base value
625 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position );
628 void Actor::SetX( float x )
630 mTargetPosition.x = x;
632 // node is being used in a separate thread; queue a message to set the value & base value
633 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
636 void Actor::SetY( float y )
638 mTargetPosition.y = y;
640 // node is being used in a separate thread; queue a message to set the value & base value
641 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
644 void Actor::SetZ( float z )
646 mTargetPosition.z = z;
648 // node is being used in a separate thread; queue a message to set the value & base value
649 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
652 void Actor::TranslateBy( const Vector3& distance )
654 mTargetPosition += distance;
656 // node is being used in a separate thread; queue a message to set the value & base value
657 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance );
660 const Vector3& Actor::GetCurrentPosition() const
662 // node is being used in a separate thread; copy the value from the previous update
663 return GetNode().GetPosition(GetEventThreadServices().GetEventBufferIndex());
666 const Vector3& Actor::GetCurrentWorldPosition() const
668 // node is being used in a separate thread; copy the value from the previous update
669 return GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
672 const Vector2 Actor::GetCurrentScreenPosition() const
674 if( mScene && OnScene() )
676 Vector3 worldPosition = GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
677 Vector3 cameraPosition = mScene->GetDefaultCameraActor().GetNode().GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
678 worldPosition -= cameraPosition;
680 Vector3 actorSize = GetCurrentSize() * GetCurrentWorldScale();
681 Vector2 halfSceneSize( mScene->GetSize() * 0.5f ); // World position origin is center of scene
682 Vector3 halfActorSize( actorSize * 0.5f );
683 Vector3 anchorPointOffSet = halfActorSize - actorSize * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
685 return Vector2( halfSceneSize.width + worldPosition.x - anchorPointOffSet.x,
686 halfSceneSize.height + worldPosition.y - anchorPointOffSet.y );
689 return Vector2::ZERO;
692 void Actor::SetInheritPosition( bool inherit )
694 if( mInheritPosition != inherit )
696 // non animatable so keep local copy
697 mInheritPosition = inherit;
698 SetInheritPositionMessage( GetEventThreadServices(), GetNode(), inherit );
702 void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
704 Vector3 normalizedAxis( axis.x, axis.y, axis.z );
705 normalizedAxis.Normalize();
707 Quaternion orientation( angle, normalizedAxis );
709 SetOrientation( orientation );
712 void Actor::SetOrientation( const Quaternion& orientation )
714 mTargetOrientation = orientation;
716 // node is being used in a separate thread; queue a message to set the value & base value
717 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation );
720 void Actor::RotateBy( const Radian& angle, const Vector3& axis )
722 RotateBy( Quaternion(angle, axis) );
725 void Actor::RotateBy( const Quaternion& relativeRotation )
727 mTargetOrientation *= Quaternion( relativeRotation );
729 // node is being used in a separate thread; queue a message to set the value & base value
730 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation );
733 const Quaternion& Actor::GetCurrentOrientation() const
735 // node is being used in a separate thread; copy the value from the previous update
736 return GetNode().GetOrientation(GetEventThreadServices().GetEventBufferIndex());
739 const Quaternion& Actor::GetCurrentWorldOrientation() const
741 // node is being used in a separate thread; copy the value from the previous update
742 return GetNode().GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
745 void Actor::SetScale( float scale )
747 SetScale( Vector3( scale, scale, scale ) );
750 void Actor::SetScale( float x, float y, float z )
752 SetScale( Vector3( x, y, z ) );
755 void Actor::SetScale( const Vector3& scale )
757 mTargetScale = scale;
759 // node is being used in a separate thread; queue a message to set the value & base value
760 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale );
763 void Actor::SetScaleX( float x )
767 // node is being used in a separate thread; queue a message to set the value & base value
768 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x );
771 void Actor::SetScaleY( float y )
775 // node is being used in a separate thread; queue a message to set the value & base value
776 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y );
779 void Actor::SetScaleZ( float z )
783 // node is being used in a separate thread; queue a message to set the value & base value
784 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z );
787 void Actor::ScaleBy(const Vector3& relativeScale)
789 mTargetScale *= relativeScale;
791 // node is being used in a separate thread; queue a message to set the value & base value
792 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale );
795 const Vector3& Actor::GetCurrentScale() const
797 // node is being used in a separate thread; copy the value from the previous update
798 return GetNode().GetScale(GetEventThreadServices().GetEventBufferIndex());
801 const Vector3& Actor::GetCurrentWorldScale() const
803 // node is being used in a separate thread; copy the value from the previous update
804 return GetNode().GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
807 void Actor::SetInheritScale( bool inherit )
809 if( mInheritScale != inherit )
811 // non animatable so keep local copy
812 mInheritScale = inherit;
813 // node is being used in a separate thread; queue a message to set the value
814 SetInheritScaleMessage( GetEventThreadServices(), GetNode(), inherit );
818 Matrix Actor::GetCurrentWorldMatrix() const
820 return GetNode().GetWorldMatrix(0);
823 void Actor::SetVisible( bool visible )
825 SetVisibleInternal( visible, SendMessage::TRUE );
828 bool Actor::IsVisible() const
830 // node is being used in a separate thread; copy the value from the previous update
831 return GetNode().IsVisible( GetEventThreadServices().GetEventBufferIndex() );
834 void Actor::SetOpacity( float opacity )
836 mTargetColor.a = opacity;
838 // node is being used in a separate thread; queue a message to set the value & base value
839 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
841 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
844 float Actor::GetCurrentOpacity() const
846 // node is being used in a separate thread; copy the value from the previous update
847 return GetNode().GetOpacity(GetEventThreadServices().GetEventBufferIndex());
850 const Vector4& Actor::GetCurrentWorldColor() const
852 return GetNode().GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
855 void Actor::SetColor( const Vector4& color )
857 mTargetColor = color;
859 // node is being used in a separate thread; queue a message to set the value & base value
860 SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::Bake, color );
862 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
865 void Actor::SetColorRed( float red )
867 mTargetColor.r = red;
869 // node is being used in a separate thread; queue a message to set the value & base value
870 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeX, red );
872 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
875 void Actor::SetColorGreen( float green )
877 mTargetColor.g = green;
879 // node is being used in a separate thread; queue a message to set the value & base value
880 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeY, green );
882 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
885 void Actor::SetColorBlue( float blue )
887 mTargetColor.b = blue;
889 // node is being used in a separate thread; queue a message to set the value & base value
890 SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
892 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
895 const Vector4& Actor::GetCurrentColor() const
897 // node is being used in a separate thread; copy the value from the previous update
898 return GetNode().GetColor(GetEventThreadServices().GetEventBufferIndex());
901 void Actor::SetInheritOrientation( bool inherit )
903 if( mInheritOrientation != inherit )
905 // non animatable so keep local copy
906 mInheritOrientation = inherit;
907 // node is being used in a separate thread; queue a message to set the value
908 SetInheritOrientationMessage( GetEventThreadServices(), GetNode(), inherit );
912 void Actor::SetSizeModeFactor( const Vector3& factor )
916 mRelayoutData->sizeModeFactor = factor;
919 const Vector3& Actor::GetSizeModeFactor() const
923 return mRelayoutData->sizeModeFactor;
926 return Relayouter::DEFAULT_SIZE_MODE_FACTOR;
929 void Actor::SetColorMode( ColorMode colorMode )
931 // non animatable so keep local copy
932 mColorMode = colorMode;
933 // node is being used in a separate thread; queue a message to set the value
934 SetColorModeMessage( GetEventThreadServices(), GetNode(), colorMode );
937 void Actor::SetSize( float width, float height )
939 SetSize( Vector2( width, height ) );
942 void Actor::SetSize( float width, float height, float depth )
944 SetSize( Vector3( width, height, depth ) );
947 void Actor::SetSize( const Vector2& size )
949 SetSize( Vector3( size.width, size.height, 0.f ) );
952 void Actor::SetSizeInternal( const Vector2& size )
954 SetSizeInternal( Vector3( size.width, size.height, 0.f ) );
957 void Actor::SetSize( const Vector3& size )
959 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
961 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
962 SetPreferredSize( size.GetVectorXY() );
966 SetSizeInternal( size );
970 void Actor::SetSizeInternal( const Vector3& size )
972 // dont allow recursive loop
973 DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
974 // check that we have a node AND the new size width, height or depth is at least a little bit different from the old one
975 if( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )||
976 ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
977 ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) )
981 // node is being used in a separate thread; queue a message to set the value & base value
982 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize );
984 // Notification for derived classes
985 mInsideOnSizeSet = true;
986 OnSizeSet( mTargetSize );
987 mInsideOnSizeSet = false;
989 // Raise a relayout request if the flag is not locked
990 if( mRelayoutData && !mRelayoutData->insideRelayout )
997 void Actor::SetWidth( float width )
999 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1001 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
1002 mRelayoutData->preferredSize.width = width;
1006 mTargetSize.width = width;
1008 // node is being used in a separate thread; queue a message to set the value & base value
1009 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width );
1012 mUseAnimatedSize &= ~AnimatedSizeFlag::WIDTH;
1017 void Actor::SetHeight( float height )
1019 if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
1021 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
1022 mRelayoutData->preferredSize.height = height;
1026 mTargetSize.height = height;
1028 // node is being used in a separate thread; queue a message to set the value & base value
1029 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height );
1032 mUseAnimatedSize &= ~AnimatedSizeFlag::HEIGHT;
1037 void Actor::SetDepth( float depth )
1039 mTargetSize.depth = depth;
1041 mUseAnimatedSize &= ~AnimatedSizeFlag::DEPTH;
1043 // node is being used in a separate thread; queue a message to set the value & base value
1044 SceneGraph::NodeTransformComponentMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth );
1047 Vector3 Actor::GetTargetSize() const
1049 Vector3 size = mTargetSize;
1051 if( mUseAnimatedSize & AnimatedSizeFlag::WIDTH )
1053 // Should return animated size if size is animated
1054 size.width = mAnimatedSize.width;
1058 // Should return preferred size if size is fixed as set by SetSize
1059 if( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::FIXED )
1061 size.width = GetPreferredSize().width;
1065 if( mUseAnimatedSize & AnimatedSizeFlag::HEIGHT )
1067 size.height = mAnimatedSize.height;
1071 if( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::FIXED )
1073 size.height = GetPreferredSize().height;
1077 if( mUseAnimatedSize & AnimatedSizeFlag::DEPTH )
1079 size.depth = mAnimatedSize.depth;
1085 const Vector3& Actor::GetCurrentSize() const
1087 // node is being used in a separate thread; copy the value from the previous update
1088 return GetNode().GetSize( GetEventThreadServices().GetEventBufferIndex() );
1091 Vector3 Actor::GetNaturalSize() const
1093 // It is up to deriving classes to return the appropriate natural size
1094 return Vector3( 0.0f, 0.0f, 0.0f );
1097 void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
1099 EnsureRelayouter().SetResizePolicy(policy, dimension, mTargetSize);
1101 OnSetResizePolicy( policy, dimension );
1103 // Trigger relayout on this control
1107 ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
1109 if ( mRelayoutData )
1111 return mRelayoutData->GetResizePolicy(dimension);
1114 return ResizePolicy::DEFAULT;
1117 void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
1121 mRelayoutData->sizeSetPolicy = policy;
1123 // Trigger relayout on this control
1127 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1129 if ( mRelayoutData )
1131 return mRelayoutData->sizeSetPolicy;
1134 return Relayouter::DEFAULT_SIZE_SCALE_POLICY;
1137 void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
1139 EnsureRelayouter().SetDimensionDependency(dimension, dependency);
1142 Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
1144 if ( mRelayoutData )
1146 return mRelayoutData->GetDimensionDependency(dimension);
1149 return Dimension::ALL_DIMENSIONS; // Default
1152 void Actor::SetRelayoutEnabled( bool relayoutEnabled )
1154 // If relayout data has not been allocated yet and the client is requesting
1155 // to disable it, do nothing
1156 if( mRelayoutData || relayoutEnabled )
1160 DALI_ASSERT_DEBUG( mRelayoutData && "mRelayoutData not created" );
1162 mRelayoutData->relayoutEnabled = relayoutEnabled;
1166 bool Actor::IsRelayoutEnabled() const
1168 // Assume that if relayout data has not been allocated yet then
1169 // relayout is disabled
1170 return mRelayoutData && mRelayoutData->relayoutEnabled;
1173 void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
1175 EnsureRelayouter().SetLayoutDirty(dirty, dimension);
1178 bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
1180 return mRelayoutData && mRelayoutData->IsLayoutDirty(dimension);
1183 bool Actor::RelayoutPossible( Dimension::Type dimension ) const
1185 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
1188 bool Actor::RelayoutRequired( Dimension::Type dimension ) const
1190 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
1193 uint32_t Actor::AddRenderer( Renderer& renderer )
1197 mRenderers = new RendererContainer;
1200 if(mIsBlendEquationSet)
1202 renderer.SetBlendMode(Dali::BlendMode::ON);
1203 renderer.SetBlendEquation(static_cast<DevelBlendEquation::Type>(mBlendEquation));
1206 uint32_t index = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1207 RendererPtr rendererPtr = RendererPtr( &renderer );
1208 mRenderers->push_back( rendererPtr );
1209 AttachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1213 uint32_t Actor::GetRendererCount() const
1215 uint32_t rendererCount(0);
1218 rendererCount = static_cast<uint32_t>( mRenderers->size() ); // 4,294,967,295 renderers per actor
1221 return rendererCount;
1224 RendererPtr Actor::GetRendererAt( uint32_t index )
1226 RendererPtr renderer;
1227 if( index < GetRendererCount() )
1229 renderer = ( *mRenderers )[ index ];
1235 void Actor::RemoveRenderer( Renderer& renderer )
1239 RendererIter end = mRenderers->end();
1240 for( RendererIter iter = mRenderers->begin(); iter != end; ++iter )
1242 if( (*iter).Get() == &renderer )
1244 mRenderers->erase( iter );
1245 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject() );
1252 void Actor::RemoveRenderer( uint32_t index )
1254 if( index < GetRendererCount() )
1256 RendererPtr renderer = ( *mRenderers )[ index ];
1257 DetachRendererMessage( GetEventThreadServices(), GetNode(), renderer.Get()->GetRendererSceneObject() );
1258 mRenderers->erase( mRenderers->begin()+index );
1262 void Actor::SetBlendEquation(DevelBlendEquation::Type blendEquation)
1264 if(Dali::Capabilities::IsBlendEquationSupported(blendEquation))
1266 if(mBlendEquation != blendEquation)
1268 mBlendEquation = blendEquation;
1269 uint32_t rendererCount = GetRendererCount();
1270 for(uint32_t i = 0; i < rendererCount; ++i)
1272 RendererPtr renderer = GetRendererAt(i);
1273 renderer->SetBlendMode(Dali::BlendMode::ON);
1274 renderer->SetBlendEquation(static_cast<DevelBlendEquation::Type>(blendEquation));
1277 mIsBlendEquationSet = true;
1281 DALI_LOG_ERROR("Invalid blend equation is entered.\n");
1285 DevelBlendEquation::Type Actor::GetBlendEquation() const
1287 return mBlendEquation;
1290 void Actor::SetDrawMode( DrawMode::Type drawMode )
1292 // this flag is not animatable so keep the value
1293 mDrawMode = drawMode;
1295 // node is being used in a separate thread; queue a message to set the value
1296 SetDrawModeMessage( GetEventThreadServices(), GetNode(), drawMode );
1299 bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
1301 // only valid when on-stage
1302 if( mScene && OnScene() )
1304 const RenderTaskList& taskList = mScene->GetRenderTaskList();
1306 Vector2 converted( screenX, screenY );
1308 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1309 uint32_t taskCount = taskList.GetTaskCount();
1310 for( uint32_t i = taskCount; i > 0; --i )
1312 RenderTaskPtr task = taskList.GetTask( i - 1 );
1313 if( ScreenToLocal( *task, localX, localY, screenX, screenY ) )
1315 // found a task where this conversion was ok so return
1323 bool Actor::ScreenToLocal( const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
1325 bool retval = false;
1326 // only valid when on-stage
1329 CameraActor* camera = renderTask.GetCameraActor();
1333 renderTask.GetViewport( viewport );
1335 // need to translate coordinates to render tasks coordinate space
1336 Vector2 converted( screenX, screenY );
1337 if( renderTask.TranslateCoordinates( converted ) )
1339 retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
1346 bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
1348 return OnScene() && ScreenToLocalInternal(viewMatrix, projectionMatrix, GetNode().GetWorldMatrix(0), viewport, GetCurrentSize(), localX, localY, screenX, screenY);
1351 ActorGestureData& Actor::GetGestureData()
1353 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1354 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1355 if( nullptr == mGestureData )
1357 mGestureData = new ActorGestureData;
1359 return *mGestureData;
1362 bool Actor::IsGestureRequired( GestureType::Value type ) const
1364 return mGestureData && mGestureData->IsGestureRequired( type );
1367 bool Actor::EmitInterceptTouchEventSignal( const Dali::TouchEvent& touch )
1369 return EmitConsumingSignal( *this, mInterceptTouchedSignal, touch );
1372 bool Actor::EmitTouchEventSignal( const Dali::TouchEvent& touch )
1374 return EmitConsumingSignal( *this, mTouchedSignal, touch );
1377 bool Actor::EmitHoverEventSignal( const Dali::HoverEvent& event )
1379 return EmitConsumingSignal( *this, mHoveredSignal, event );
1382 bool Actor::EmitWheelEventSignal( const Dali::WheelEvent& event )
1384 return EmitConsumingSignal( *this, mWheelEventSignal, event );
1387 void Actor::EmitVisibilityChangedSignal( bool visible, DevelActor::VisibilityChange::Type type )
1389 EmitSignal( *this, mVisibilityChangedSignal, visible, type );
1392 void Actor::EmitLayoutDirectionChangedSignal( LayoutDirection::Type type )
1394 EmitSignal( *this, mLayoutDirectionChangedSignal, type );
1397 void Actor::EmitChildAddedSignal( Actor& child )
1399 EmitSignal( child, mChildAddedSignal );
1402 void Actor::EmitChildRemovedSignal( Actor& child )
1404 EmitSignal( child, mChildRemovedSignal );
1407 bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
1409 bool connected( true );
1410 Actor* actor = static_cast< Actor* >( object ); // TypeRegistry guarantees that this is the correct type.
1412 if( 0 == signalName.compare( SIGNAL_HOVERED ) )
1414 actor->HoveredSignal().Connect( tracker, functor );
1416 else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
1418 actor->WheelEventSignal().Connect( tracker, functor );
1420 else if( 0 == signalName.compare( SIGNAL_ON_SCENE ) )
1422 actor->OnSceneSignal().Connect( tracker, functor );
1424 else if( 0 == signalName.compare( SIGNAL_OFF_SCENE ) )
1426 actor->OffSceneSignal().Connect( tracker, functor );
1428 else if( 0 == signalName.compare( SIGNAL_ON_RELAYOUT ) )
1430 actor->OnRelayoutSignal().Connect( tracker, functor );
1432 else if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
1434 actor->TouchedSignal().Connect( tracker, functor );
1436 else if( 0 == signalName.compare( SIGNAL_VISIBILITY_CHANGED ) )
1438 actor->VisibilityChangedSignal().Connect( tracker, functor );
1440 else if( 0 == signalName.compare( SIGNAL_LAYOUT_DIRECTION_CHANGED ) )
1442 actor->LayoutDirectionChangedSignal().Connect( tracker, functor );
1444 else if( 0 == signalName.compare( SIGNAL_CHILD_ADDED ) )
1446 actor->ChildAddedSignal().Connect( tracker, functor );
1448 else if( 0 == signalName.compare( SIGNAL_CHILD_REMOVED ) )
1450 actor->ChildRemovedSignal().Connect( tracker, functor );
1454 // signalName does not match any signal
1461 Actor::Actor( DerivedType derivedType, const SceneGraph::Node& node )
1465 mChildren( nullptr ),
1466 mRenderers( nullptr ),
1467 mParentOrigin( nullptr ),
1468 mAnchorPoint( nullptr ),
1469 mRelayoutData( nullptr ),
1470 mGestureData( nullptr ),
1471 mInterceptTouchedSignal(),
1474 mWheelEventSignal(),
1477 mOnRelayoutSignal(),
1478 mVisibilityChangedSignal(),
1479 mLayoutDirectionChangedSignal(),
1480 mChildAddedSignal(),
1481 mChildRemovedSignal(),
1482 mChildOrderChangedSignal(),
1483 mTargetOrientation( Quaternion::IDENTITY ),
1484 mTargetColor( Color::WHITE ),
1485 mTargetSize( Vector3::ZERO ),
1486 mTargetPosition( Vector3::ZERO ),
1487 mTargetScale( Vector3::ONE ),
1488 mAnimatedSize( Vector3::ZERO ),
1489 mTouchArea( Vector2::ZERO ),
1493 mUseAnimatedSize( AnimatedSizeFlag::CLEAR ),
1494 mIsRoot( ROOT_LAYER == derivedType ),
1495 mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
1496 mIsOnScene( false ),
1498 mLeaveRequired( false ),
1499 mKeyboardFocusable( false ),
1500 mOnSceneSignalled( false ),
1501 mInsideOnSizeSet( false ),
1502 mInheritPosition( true ),
1503 mInheritOrientation( true ),
1504 mInheritScale( true ),
1505 mPositionUsesAnchorPoint( true ),
1507 mInheritLayoutDirection( true ),
1508 mCaptureAllTouchAfterStart( false ),
1509 mLayoutDirection( LayoutDirection::LEFT_TO_RIGHT ),
1510 mDrawMode( DrawMode::NORMAL ),
1511 mColorMode( Node::DEFAULT_COLOR_MODE ),
1512 mClippingMode( ClippingMode::DISABLED ),
1513 mBlendEquation( DevelBlendEquation::ADD ),
1514 mIsBlendEquationSet( false )
1518 void Actor::Initialize()
1522 GetEventThreadServices().RegisterObject( this );
1527 // Remove mParent pointers from children even if we're destroying core,
1528 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1531 for( const auto& actor : *mChildren )
1533 actor->SetParent( nullptr );
1539 // Guard to allow handle destruction after Core has been destroyed
1540 if( EventThreadServices::IsCoreRunning() )
1542 // Root layer will destroy its node in its own destructor
1545 DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
1547 GetEventThreadServices().UnregisterObject( this );
1551 // Cleanup optional gesture data
1552 delete mGestureData;
1554 // Cleanup optional parent origin and anchor
1555 delete mParentOrigin;
1556 delete mAnchorPoint;
1558 // Delete optional relayout data
1559 delete mRelayoutData;
1562 void Actor::ConnectToScene( uint32_t parentDepth )
1564 // This container is used instead of walking the Actor hierarchy.
1565 // It protects us when the Actor hierarchy is modified during OnSceneConnectionExternal callbacks.
1566 ActorContainer connectionList;
1570 mScene->RequestRebuildDepthTree();
1573 // This stage is atomic i.e. not interrupted by user callbacks.
1574 RecursiveConnectToScene( connectionList, parentDepth + 1 );
1576 // Notify applications about the newly connected actors.
1577 for( const auto& actor : connectionList )
1579 actor->NotifyStageConnection();
1585 void Actor::RecursiveConnectToScene( ActorContainer& connectionList, uint32_t depth )
1587 DALI_ASSERT_ALWAYS( !OnScene() );
1590 mDepth = static_cast< uint16_t >( depth ); // overflow ignored, not expected in practice
1592 ConnectToSceneGraph();
1594 // Notification for internal derived classes
1595 OnSceneConnectionInternal();
1597 // This stage is atomic; avoid emitting callbacks until all Actors are connected
1598 connectionList.push_back( ActorPtr( this ) );
1600 // Recursively connect children
1603 for( const auto& actor : *mChildren )
1605 actor->SetScene( *mScene );
1606 actor->RecursiveConnectToScene( connectionList, depth + 1 );
1612 * This method is called when the Actor is connected to the Stage.
1613 * The parent must have added its Node to the scene-graph.
1614 * The child must connect its Node to the parent's Node.
1615 * This is recursive; the child calls ConnectToScene() for its children.
1617 void Actor::ConnectToSceneGraph()
1619 DALI_ASSERT_DEBUG( mParent != NULL);
1621 // Reparent Node in next Update
1622 ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), mParent->GetNode(), GetNode() );
1624 // Request relayout on all actors that are added to the scenegraph
1627 // Notification for Object::Observers
1631 void Actor::NotifyStageConnection()
1633 // Actors can be removed (in a callback), before the on-stage stage is reported.
1634 // The actor may also have been reparented, in which case mOnSceneSignalled will be true.
1635 if( OnScene() && !mOnSceneSignalled )
1637 // Notification for external (CustomActor) derived classes
1638 OnSceneConnectionExternal( mDepth );
1640 if( !mOnSceneSignal.Empty() )
1642 Dali::Actor handle( this );
1643 mOnSceneSignal.Emit( handle );
1646 // Guard against Remove during callbacks
1649 mOnSceneSignalled = true; // signal required next time Actor is removed
1654 void Actor::DisconnectFromStage()
1656 // This container is used instead of walking the Actor hierachy.
1657 // It protects us when the Actor hierachy is modified during OnSceneDisconnectionExternal callbacks.
1658 ActorContainer disconnectionList;
1662 mScene->RequestRebuildDepthTree();
1665 // This stage is atomic i.e. not interrupted by user callbacks
1666 RecursiveDisconnectFromStage( disconnectionList );
1668 // Notify applications about the newly disconnected actors.
1669 for( const auto& actor : disconnectionList )
1671 actor->NotifyStageDisconnection();
1675 void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
1677 // need to change state first so that internals relying on IsOnScene() inside OnSceneDisconnectionInternal() get the correct value
1680 // Recursively disconnect children
1683 for( const auto& child : *mChildren )
1685 child->RecursiveDisconnectFromStage( disconnectionList );
1689 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
1690 disconnectionList.push_back( ActorPtr( this ) );
1692 // Notification for internal derived classes
1693 OnSceneDisconnectionInternal();
1695 DisconnectFromSceneGraph();
1699 * This method is called by an actor or its parent, before a node removal message is sent.
1700 * This is recursive; the child calls DisconnectFromStage() for its children.
1702 void Actor::DisconnectFromSceneGraph()
1704 // Notification for Object::Observers
1705 OnSceneObjectRemove();
1708 void Actor::NotifyStageDisconnection()
1710 // Actors can be added (in a callback), before the off-stage state is reported.
1711 // Also if the actor was added & removed before mOnSceneSignalled was set, then we don't notify here.
1712 // only do this step if there is a stage, i.e. Core is not being shut down
1713 if ( EventThreadServices::IsCoreRunning() && !OnScene() && mOnSceneSignalled )
1715 // Notification for external (CustomeActor) derived classes
1716 OnSceneDisconnectionExternal();
1718 if( !mOffSceneSignal.Empty() )
1720 Dali::Actor handle( this );
1721 mOffSceneSignal.Emit( handle );
1724 // Guard against Add during callbacks
1727 mOnSceneSignalled = false; // signal required next time Actor is added
1732 bool Actor::IsNodeConnected() const
1734 bool connected( false );
1738 if( IsRoot() || GetNode().GetParent() )
1747 // This method initiates traversal of the actor tree using depth-first
1748 // traversal to set a depth index based on traversal order. It sends a
1749 // single message to update manager to update all the actor's nodes in
1750 // this tree with the depth index. The sceneGraphNodeDepths vector's
1751 // elements are ordered by depth, and could be used to reduce sorting
1752 // in the update thread.
1753 void Actor::RebuildDepthTree()
1755 DALI_LOG_TIMER_START(depthTimer);
1757 // Vector of scene-graph nodes and their depths to send to UpdateManager
1758 // in a single message
1759 OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths( new SceneGraph::NodeDepths() );
1761 int32_t depthIndex = 1;
1762 DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
1764 SetDepthIndicesMessage( GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths );
1765 DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
1768 void Actor::DepthTraverseActorTree( OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths, int32_t& depthIndex )
1770 mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
1771 sceneGraphNodeDepths->Add( const_cast<SceneGraph::Node*>( &GetNode() ), mSortedDepth );
1773 // Create/add to children of this node
1776 for( const auto& child : *mChildren )
1778 Actor* childActor = child.Get();
1780 childActor->DepthTraverseActorTree( sceneGraphNodeDepths, depthIndex );
1785 void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
1787 PropertyHandler::SetDefaultProperty(*this, index, property);
1790 // TODO: This method needs to be removed
1791 void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
1793 PropertyHandler::SetSceneGraphProperty(index, entry, value, GetEventThreadServices(), GetNode());
1796 Property::Value Actor::GetDefaultProperty( Property::Index index ) const
1798 Property::Value value;
1800 if( ! GetCachedPropertyValue( index, value ) )
1802 // If property value is not stored in the event-side, then it must be a scene-graph only property
1803 GetCurrentPropertyValue( index, value );
1809 Property::Value Actor::GetDefaultPropertyCurrentValue( Property::Index index ) const
1811 Property::Value value;
1813 if( ! GetCurrentPropertyValue( index, value ) )
1815 // If unable to retrieve scene-graph property value, then it must be an event-side only property
1816 GetCachedPropertyValue( index, value );
1822 void Actor::OnNotifyDefaultPropertyAnimation( Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType )
1824 PropertyHandler::OnNotifyDefaultPropertyAnimation(*this, animation, index, value, animationType);
1827 const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
1829 const PropertyBase* property = PropertyHandler::GetSceneObjectAnimatableProperty(index, GetNode());
1832 // not our property, ask base
1833 property = Object::GetSceneObjectAnimatableProperty( index );
1839 const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
1841 const PropertyInputImpl* property = PropertyHandler::GetSceneObjectInputProperty(index, GetNode());
1844 // reuse animatable property getter as animatable properties are inputs as well
1845 // animatable property chains back to Object::GetSceneObjectInputProperty() so all properties get covered
1846 property = GetSceneObjectAnimatableProperty( index );
1852 int32_t Actor::GetPropertyComponentIndex( Property::Index index ) const
1854 int32_t componentIndex = PropertyHandler::GetPropertyComponentIndex(index);
1855 if( Property::INVALID_COMPONENT_INDEX == componentIndex )
1858 componentIndex = Object::GetPropertyComponentIndex( index );
1861 return componentIndex;
1864 void Actor::SetParent( Actor* parent )
1868 DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
1872 mScene = parent->mScene;
1874 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1877 // Instruct each actor to create a corresponding node in the scene graph
1878 ConnectToScene( parent->GetHierarchyDepth() );
1881 // Resolve the name and index for the child properties if any
1882 ResolveChildProperties();
1884 else // parent being set to NULL
1886 DALI_ASSERT_ALWAYS( mParent != nullptr && "Actor should have a parent" );
1890 if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1893 // Disconnect the Node & its children from the scene-graph.
1894 DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), GetNode() );
1896 // Instruct each actor to discard pointers to the scene-graph
1897 DisconnectFromStage();
1904 bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
1907 Actor* actor = dynamic_cast< Actor* >( object );
1911 if( 0 == actionName.compare( ACTION_SHOW ) )
1913 actor->SetVisible( true );
1916 else if( 0 == actionName.compare( ACTION_HIDE ) )
1918 actor->SetVisible( false );
1926 Rect<> Actor::CalculateScreenExtents( ) const
1928 auto screenPosition = GetCurrentScreenPosition();
1929 Vector3 size = GetCurrentSize() * GetCurrentWorldScale();
1930 Vector3 anchorPointOffSet = size * ( mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT );
1931 Vector2 position = Vector2( screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y );
1932 return { position.x, position.y, size.x, size.y };
1935 bool Actor::GetCachedPropertyValue( Property::Index index, Property::Value& value ) const
1937 return PropertyHandler::GetCachedPropertyValue(*this, index, value);
1940 bool Actor::GetCurrentPropertyValue( Property::Index index, Property::Value& value ) const
1942 return PropertyHandler::GetCurrentPropertyValue(*this, index, value);
1945 Actor::Relayouter& Actor::EnsureRelayouter()
1947 // Assign relayouter
1948 if( !mRelayoutData )
1950 mRelayoutData = new Relayouter();
1953 return *mRelayoutData;
1956 bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
1958 // Check if actor is dependent on parent
1959 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1961 if( ( dimension & ( 1 << i ) ) )
1963 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
1964 if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
1974 bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
1976 // Check if actor is dependent on children
1977 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
1979 if( ( dimension & ( 1 << i ) ) )
1981 const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
1982 switch( resizePolicy )
1984 case ResizePolicy::FIT_TO_CHILDREN:
1985 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
2001 bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
2003 return Actor::RelayoutDependentOnChildren( dimension );
2006 bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
2008 // Check each possible dimension and see if it is dependent on the input one
2009 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2011 if( dimension & ( 1 << i ) )
2013 return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
2020 void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
2022 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2024 if( dimension & ( 1 << i ) )
2026 mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
2031 float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
2033 // If more than one dimension is requested, just return the first one found
2034 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2036 if( ( dimension & ( 1 << i ) ) )
2038 return mRelayoutData->negotiatedDimensions[ i ];
2042 return 0.0f; // Default
2045 void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
2047 EnsureRelayouter().SetPadding( padding, dimension );
2050 Vector2 Actor::GetPadding( Dimension::Type dimension ) const
2052 if ( mRelayoutData )
2054 // If more than one dimension is requested, just return the first one found
2055 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2057 if( ( dimension & ( 1 << i ) ) )
2059 return mRelayoutData->dimensionPadding[ i ];
2064 return Relayouter::DEFAULT_DIMENSION_PADDING;
2067 void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
2069 EnsureRelayouter().SetLayoutNegotiated(negotiated, dimension);
2072 bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
2074 return mRelayoutData && mRelayoutData->IsLayoutNegotiated(dimension);
2077 float Actor::GetHeightForWidthBase( float width )
2079 float height = 0.0f;
2081 const Vector3 naturalSize = GetNaturalSize();
2082 if( naturalSize.width > 0.0f )
2084 height = naturalSize.height * width / naturalSize.width;
2086 else // we treat 0 as 1:1 aspect ratio
2094 float Actor::GetWidthForHeightBase( float height )
2098 const Vector3 naturalSize = GetNaturalSize();
2099 if( naturalSize.height > 0.0f )
2101 width = naturalSize.width * height / naturalSize.height;
2103 else // we treat 0 as 1:1 aspect ratio
2111 float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
2113 // Fill to parent, taking size mode factor into account
2114 switch( child.GetResizePolicy( dimension ) )
2116 case ResizePolicy::FILL_TO_PARENT:
2118 return GetLatestSize( dimension );
2121 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2123 return GetLatestSize( dimension ) * GetDimensionValue( child.GetProperty< Vector3 >( Dali::Actor::Property::SIZE_MODE_FACTOR ), dimension );
2126 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2128 return GetLatestSize( dimension ) + GetDimensionValue( child.GetProperty< Vector3 >( Dali::Actor::Property::SIZE_MODE_FACTOR ), dimension );
2133 return GetLatestSize( dimension );
2138 float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
2140 // Can be overridden in derived class
2141 return CalculateChildSizeBase( child, dimension );
2144 float Actor::GetHeightForWidth( float width )
2146 // Can be overridden in derived class
2147 return GetHeightForWidthBase( width );
2150 float Actor::GetWidthForHeight( float height )
2152 // Can be overridden in derived class
2153 return GetWidthForHeightBase( height );
2156 float Actor::GetLatestSize( Dimension::Type dimension ) const
2158 return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
2161 float Actor::GetRelayoutSize( Dimension::Type dimension ) const
2163 Vector2 padding = GetPadding( dimension );
2165 return GetLatestSize( dimension ) + padding.x + padding.y;
2168 float Actor::NegotiateFromParent( Dimension::Type dimension )
2170 Actor* parent = GetParent();
2173 Vector2 padding( GetPadding( dimension ) );
2174 Vector2 parentPadding( parent->GetPadding( dimension ) );
2175 return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
2181 float Actor::NegotiateFromChildren( Dimension::Type dimension )
2183 float maxDimensionPoint = 0.0f;
2185 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2187 ActorPtr child = GetChildAt( i );
2189 if( !child->RelayoutDependentOnParent( dimension ) )
2191 // Calculate the min and max points that the children range across
2192 float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
2193 float dimensionSize = child->GetRelayoutSize( dimension );
2194 maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
2198 return maxDimensionPoint;
2201 float Actor::GetSize( Dimension::Type dimension ) const
2203 return GetDimensionValue( mTargetSize, dimension );
2206 float Actor::GetNaturalSize( Dimension::Type dimension ) const
2208 return GetDimensionValue( GetNaturalSize(), dimension );
2211 float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
2213 switch( GetResizePolicy( dimension ) )
2215 case ResizePolicy::USE_NATURAL_SIZE:
2217 return GetNaturalSize( dimension );
2220 case ResizePolicy::FIXED:
2222 return GetDimensionValue( GetPreferredSize(), dimension );
2225 case ResizePolicy::USE_ASSIGNED_SIZE:
2227 return GetDimensionValue( maximumSize, dimension );
2230 case ResizePolicy::FILL_TO_PARENT:
2231 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2232 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2234 return NegotiateFromParent( dimension );
2237 case ResizePolicy::FIT_TO_CHILDREN:
2239 return NegotiateFromChildren( dimension );
2242 case ResizePolicy::DIMENSION_DEPENDENCY:
2244 const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
2247 if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
2249 return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
2252 if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
2254 return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
2266 return 0.0f; // Default
2269 void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
2271 // Check if it needs to be negotiated
2272 if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
2274 // Check that we havn't gotten into an infinite loop
2275 ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
2276 bool recursionFound = false;
2277 for( auto& element : recursionStack )
2279 if( element == searchActor )
2281 recursionFound = true;
2286 if( !recursionFound )
2288 // Record the path that we have taken
2289 recursionStack.push_back( ActorDimensionPair( this, dimension ) );
2291 // Dimension dependency check
2292 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2294 Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
2296 if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
2298 NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
2302 // Parent dependency check
2303 Actor* parent = GetParent();
2304 if( parent && RelayoutDependentOnParent( dimension ) )
2306 parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
2309 // Children dependency check
2310 if( RelayoutDependentOnChildren( dimension ) )
2312 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2314 ActorPtr child = GetChildAt( i );
2316 // Only relayout child first if it is not dependent on this actor
2317 if( !child->RelayoutDependentOnParent( dimension ) )
2319 child->NegotiateDimension( dimension, allocatedSize, recursionStack );
2324 // For deriving classes
2325 OnCalculateRelayoutSize( dimension );
2327 // All dependencies checked, calculate the size and set negotiated flag
2328 const float newSize = Relayouter::ClampDimension( *this, CalculateSize( dimension, allocatedSize ), dimension );
2330 SetNegotiatedDimension( newSize, dimension );
2331 SetLayoutNegotiated( true, dimension );
2333 // For deriving classes
2334 OnLayoutNegotiated( newSize, dimension );
2336 // This actor has been successfully processed, pop it off the recursion stack
2337 recursionStack.pop_back();
2341 // TODO: Break infinite loop
2342 SetLayoutNegotiated( true, dimension );
2347 void Actor::NegotiateDimensions( const Vector2& allocatedSize )
2349 // Negotiate all dimensions that require it
2350 ActorDimensionStack recursionStack;
2352 for( uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i )
2354 const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
2357 NegotiateDimension( dimension, allocatedSize, recursionStack );
2361 Vector2 Actor::ApplySizeSetPolicy( const Vector2& size )
2363 return mRelayoutData->ApplySizeSetPolicy(*this, size);
2366 void Actor::SetNegotiatedSize( RelayoutContainer& container )
2368 // Do the set actor size
2369 Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
2371 // Adjust for size set policy
2372 negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
2374 // Lock the flag to stop recursive relayouts on set size
2375 mRelayoutData->insideRelayout = true;
2376 SetSize( negotiatedSize );
2377 mRelayoutData->insideRelayout = false;
2379 // Clear flags for all dimensions
2380 SetLayoutDirty( false );
2382 // Give deriving classes a chance to respond
2383 OnRelayout( negotiatedSize, container );
2385 if( !mOnRelayoutSignal.Empty() )
2387 Dali::Actor handle( this );
2388 mOnRelayoutSignal.Emit( handle );
2392 void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
2394 // Force a size negotiation for actors that has assigned size during relayout
2395 // This is required as otherwise the flags that force a relayout will not
2396 // necessarilly be set. This will occur if the actor has already been laid out.
2397 // The dirty flags are then cleared. Then if the actor is added back into the
2398 // relayout container afterwards, the dirty flags would still be clear...
2399 // causing a relayout to be skipped. Here we force any actors added to the
2400 // container to be relayed out.
2401 DALI_LOG_TIMER_START( NegSizeTimer1 );
2403 if( GetUseAssignedSize(Dimension::WIDTH ) )
2405 SetLayoutNegotiated( false, Dimension::WIDTH );
2407 if( GetUseAssignedSize( Dimension::HEIGHT ) )
2409 SetLayoutNegotiated( false, Dimension::HEIGHT );
2412 // Do the negotiation
2413 NegotiateDimensions( allocatedSize );
2415 // Set the actor size
2416 SetNegotiatedSize( container );
2418 // Negotiate down to children
2419 for( uint32_t i = 0, count = GetChildCount(); i < count; ++i )
2421 ActorPtr child = GetChildAt( i );
2423 // Forces children that have already been laid out to be relayed out
2424 // if they have assigned size during relayout.
2425 if( child->GetUseAssignedSize(Dimension::WIDTH) )
2427 child->SetLayoutNegotiated(false, Dimension::WIDTH);
2428 child->SetLayoutDirty(true, Dimension::WIDTH);
2431 if( child->GetUseAssignedSize(Dimension::HEIGHT) )
2433 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
2434 child->SetLayoutDirty(true, Dimension::HEIGHT);
2437 // Only relayout if required
2438 if( child->RelayoutRequired() )
2440 container.Add( Dali::Actor( child.Get() ), mTargetSize.GetVectorXY() );
2443 DALI_LOG_TIMER_END( NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
2446 void Actor::SetUseAssignedSize( bool use, Dimension::Type dimension )
2450 mRelayoutData->SetUseAssignedSize(use, dimension);
2454 bool Actor::GetUseAssignedSize( Dimension::Type dimension ) const
2456 return mRelayoutData && mRelayoutData->GetUseAssignedSize(dimension);
2459 void Actor::RelayoutRequest( Dimension::Type dimension )
2461 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
2462 if( relayoutController )
2464 Dali::Actor self( this );
2465 relayoutController->RequestRelayout( self, dimension );
2469 void Actor::SetPreferredSize( const Vector2& size )
2473 // If valid width or height, then set the resize policy to FIXED
2474 // 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,
2475 // then change to FIXED as well
2477 if( size.width > 0.0f || GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DEFAULT )
2479 SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
2482 if( size.height > 0.0f || GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DEFAULT )
2484 SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
2487 mRelayoutData->preferredSize = size;
2489 mUseAnimatedSize = AnimatedSizeFlag::CLEAR;
2494 Vector2 Actor::GetPreferredSize() const
2496 if ( mRelayoutData )
2498 return Vector2( mRelayoutData->preferredSize );
2501 return Relayouter::DEFAULT_PREFERRED_SIZE;
2504 void Actor::SetMinimumSize( float size, Dimension::Type dimension )
2506 EnsureRelayouter().SetMinimumSize(size, dimension);
2510 float Actor::GetMinimumSize( Dimension::Type dimension ) const
2512 if ( mRelayoutData )
2514 return mRelayoutData->GetMinimumSize(dimension);
2517 return 0.0f; // Default
2520 void Actor::SetMaximumSize( float size, Dimension::Type dimension )
2522 EnsureRelayouter().SetMaximumSize(size, dimension);
2526 float Actor::GetMaximumSize( Dimension::Type dimension ) const
2528 if ( mRelayoutData )
2530 return mRelayoutData->GetMaximumSize(dimension);
2533 return FLT_MAX; // Default
2536 void Actor::SetVisibleInternal( bool visible, SendMessage::Type sendMessage )
2538 if( mVisible != visible )
2540 if( sendMessage == SendMessage::TRUE )
2542 // node is being used in a separate thread; queue a message to set the value & base value
2543 SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible );
2545 RequestRenderingMessage( GetEventThreadServices().GetUpdateManager() );
2550 // Emit the signal on this actor and all its children
2551 EmitVisibilityChangedSignalRecursively( this, visible, DevelActor::VisibilityChange::SELF );
2555 void Actor::SetSiblingOrder( uint32_t order )
2559 ActorContainer& siblings = *(mParent->mChildren);
2560 uint32_t currentOrder = GetSiblingOrder();
2562 if( order != currentOrder )
2568 else if( order < siblings.size() -1 )
2570 if( order > currentOrder )
2572 RaiseAbove( *siblings[order] );
2576 LowerBelow( *siblings[order] );
2587 uint32_t Actor::GetSiblingOrder() const
2593 ActorContainer& siblings = *(mParent->mChildren);
2594 for( std::size_t i = 0; i < siblings.size(); ++i )
2596 if( siblings[i] == this )
2598 order = static_cast<uint32_t>( i );
2607 void Actor::RequestRebuildDepthTree()
2613 mScene->RequestRebuildDepthTree();
2622 ActorContainer& siblings = *(mParent->mChildren);
2623 if( siblings.back() != this ) // If not already at end
2625 for( std::size_t i=0; i<siblings.size(); ++i )
2627 if( siblings[i] == this )
2630 ActorPtr next = siblings[i+1];
2631 siblings[i+1] = this;
2638 Dali::Actor handle( this );
2639 mParent->mChildOrderChangedSignal.Emit( handle );
2641 RequestRebuildDepthTree();
2645 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2653 ActorContainer& siblings = *(mParent->mChildren);
2654 if( siblings.front() != this ) // If not already at beginning
2656 for( std::size_t i=1; i<siblings.size(); ++i )
2658 if( siblings[i] == this )
2660 // Swap with previous
2661 ActorPtr previous = siblings[i-1];
2662 siblings[i-1] = this;
2663 siblings[i] = previous;
2669 Dali::Actor handle( this );
2670 mParent->mChildOrderChangedSignal.Emit( handle );
2672 RequestRebuildDepthTree();
2676 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2680 void Actor::RaiseToTop()
2684 ActorContainer& siblings = *(mParent->mChildren);
2685 if( siblings.back() != this ) // If not already at end
2687 auto iter = std::find( siblings.begin(), siblings.end(), this );
2688 if( iter != siblings.end() )
2690 siblings.erase(iter);
2691 siblings.push_back(ActorPtr(this));
2695 Dali::Actor handle( this );
2696 mParent->mChildOrderChangedSignal.Emit( handle );
2698 RequestRebuildDepthTree();
2702 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2706 void Actor::LowerToBottom()
2710 ActorContainer& siblings = *(mParent->mChildren);
2711 if( siblings.front() != this ) // If not already at bottom,
2713 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2715 auto iter = std::find( siblings.begin(), siblings.end(), this );
2716 if( iter != siblings.end() )
2718 siblings.erase(iter);
2719 siblings.insert(siblings.begin(), thisPtr);
2723 Dali::Actor handle( this );
2724 mParent->mChildOrderChangedSignal.Emit( handle );
2726 RequestRebuildDepthTree();
2730 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2734 void Actor::RaiseAbove( Internal::Actor& target )
2738 ActorContainer& siblings = *(mParent->mChildren);
2739 if( siblings.back() != this && target.mParent == mParent ) // If not already at top
2741 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2743 auto targetIter = std::find( siblings.begin(), siblings.end(), &target );
2744 auto thisIter = std::find( siblings.begin(), siblings.end(), this );
2745 if( thisIter < targetIter )
2747 siblings.erase(thisIter);
2748 // Erasing early invalidates the targetIter. (Conversely, inserting first may also
2749 // invalidate thisIter)
2750 targetIter = std::find( siblings.begin(), siblings.end(), &target );
2752 siblings.insert(targetIter, thisPtr);
2755 Dali::Actor handle( this );
2756 mParent->mChildOrderChangedSignal.Emit( handle );
2758 RequestRebuildDepthTree();
2763 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2767 void Actor::LowerBelow( Internal::Actor& target )
2771 ActorContainer& siblings = *(mParent->mChildren);
2772 if( siblings.front() != this && target.mParent == mParent ) // If not already at bottom
2774 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2776 auto targetIter = std::find( siblings.begin(), siblings.end(), &target );
2777 auto thisIter = std::find( siblings.begin(), siblings.end(), this );
2779 if( thisIter > targetIter )
2781 siblings.erase(thisIter); // this only invalidates iterators at or after this point.
2782 siblings.insert(targetIter, thisPtr);
2785 Dali::Actor handle( this );
2786 mParent->mChildOrderChangedSignal.Emit( handle );
2788 RequestRebuildDepthTree();
2793 DALI_LOG_WARNING( "Actor must have a parent, Sibling order not changed.\n" );
2797 void Actor::SetInheritLayoutDirection( bool inherit )
2799 if( mInheritLayoutDirection != inherit )
2801 mInheritLayoutDirection = inherit;
2803 if( inherit && mParent )
2805 InheritLayoutDirectionRecursively( this, mParent->mLayoutDirection );
2810 void Actor::InheritLayoutDirectionRecursively( ActorPtr actor, Dali::LayoutDirection::Type direction, bool set )
2812 if( actor && ( actor->mInheritLayoutDirection || set ) )
2814 if( actor->mLayoutDirection != direction )
2816 actor->mLayoutDirection = direction;
2817 actor->EmitLayoutDirectionChangedSignal( direction );
2818 actor->RelayoutRequest();
2821 if( actor->GetChildCount() > 0 )
2823 for( const auto& child : actor->GetChildrenInternal() )
2825 InheritLayoutDirectionRecursively( child, direction );
2831 void Actor::SetUpdateSizeHint( const Vector2& updateSizeHint )
2833 // node is being used in a separate thread; queue a message to set the value & base value
2834 SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), &GetNode(), &GetNode().mUpdateSizeHint, &AnimatableProperty<Vector3>::Bake, Vector3(updateSizeHint.width, updateSizeHint.height, 0.f ) );
2837 } // namespace Internal