2 * Copyright (c) 2021 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/actor-devel.h>
28 #include <dali/devel-api/actors/layer-devel.h>
29 #include <dali/integration-api/debug.h>
30 #include <dali/internal/event/actors/actor-property-handler.h>
31 #include <dali/internal/event/actors/actor-relayouter.h>
32 #include <dali/internal/event/actors/camera-actor-impl.h>
33 #include <dali/internal/event/common/event-thread-services.h>
34 #include <dali/internal/event/common/projection.h>
35 #include <dali/internal/event/common/property-helper.h>
36 #include <dali/internal/event/common/scene-impl.h>
37 #include <dali/internal/event/common/stage-impl.h>
38 #include <dali/internal/event/common/thread-local-storage.h>
39 #include <dali/internal/event/common/type-info-impl.h>
40 #include <dali/internal/event/events/actor-gesture-data.h>
41 #include <dali/internal/event/render-tasks/render-task-impl.h>
42 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
43 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
44 #include <dali/internal/update/nodes/node-messages.h>
45 #include <dali/public-api/common/constants.h>
46 #include <dali/public-api/common/dali-common.h>
47 #include <dali/public-api/math/radian.h>
48 #include <dali/public-api/math/vector2.h>
49 #include <dali/public-api/math/vector3.h>
50 #include <dali/public-api/object/type-registry.h>
52 using Dali::Internal::SceneGraph::AnimatableProperty;
53 using Dali::Internal::SceneGraph::Node;
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");
65 namespace // unnamed namespace
70 * We want to discourage the use of property strings (minimize string comparisons),
71 * particularly for the default properties.
72 * Name Type writable animatable constraint-input enum for index-checking
74 DALI_PROPERTY_TABLE_BEGIN
75 DALI_PROPERTY("parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN)
76 DALI_PROPERTY("parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X)
77 DALI_PROPERTY("parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y)
78 DALI_PROPERTY("parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z)
79 DALI_PROPERTY("anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT)
80 DALI_PROPERTY("anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X)
81 DALI_PROPERTY("anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y)
82 DALI_PROPERTY("anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z)
83 DALI_PROPERTY("size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE)
84 DALI_PROPERTY("sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH)
85 DALI_PROPERTY("sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT)
86 DALI_PROPERTY("sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH)
87 DALI_PROPERTY("position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION)
88 DALI_PROPERTY("positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X)
89 DALI_PROPERTY("positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y)
90 DALI_PROPERTY("positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z)
91 DALI_PROPERTY("worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION)
92 DALI_PROPERTY("worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X)
93 DALI_PROPERTY("worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y)
94 DALI_PROPERTY("worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z)
95 DALI_PROPERTY("orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION)
96 DALI_PROPERTY("worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION)
97 DALI_PROPERTY("scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE)
98 DALI_PROPERTY("scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X)
99 DALI_PROPERTY("scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y)
100 DALI_PROPERTY("scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z)
101 DALI_PROPERTY("worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE)
102 DALI_PROPERTY("visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE)
103 DALI_PROPERTY("color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR)
104 DALI_PROPERTY("colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED)
105 DALI_PROPERTY("colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN)
106 DALI_PROPERTY("colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE)
107 DALI_PROPERTY("colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA)
108 DALI_PROPERTY("worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR)
109 DALI_PROPERTY("worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX)
110 DALI_PROPERTY("name", STRING, true, false, false, Dali::Actor::Property::NAME)
111 DALI_PROPERTY("sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE)
112 DALI_PROPERTY("leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED)
113 DALI_PROPERTY("inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION)
114 DALI_PROPERTY("inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE)
115 DALI_PROPERTY("colorMode", INTEGER, true, false, false, Dali::Actor::Property::COLOR_MODE)
116 DALI_PROPERTY("drawMode", INTEGER, true, false, false, Dali::Actor::Property::DRAW_MODE)
117 DALI_PROPERTY("sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR)
118 DALI_PROPERTY("widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY)
119 DALI_PROPERTY("heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY)
120 DALI_PROPERTY("sizeScalePolicy", INTEGER, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY)
121 DALI_PROPERTY("widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT)
122 DALI_PROPERTY("heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH)
123 DALI_PROPERTY("padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING)
124 DALI_PROPERTY("minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE)
125 DALI_PROPERTY("maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE)
126 DALI_PROPERTY("inheritPosition", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_POSITION)
127 DALI_PROPERTY("clippingMode", STRING, true, false, false, Dali::Actor::Property::CLIPPING_MODE)
128 DALI_PROPERTY("layoutDirection", STRING, true, false, false, Dali::Actor::Property::LAYOUT_DIRECTION)
129 DALI_PROPERTY("inheritLayoutDirection", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION)
130 DALI_PROPERTY("opacity", FLOAT, true, true, true, Dali::Actor::Property::OPACITY)
131 DALI_PROPERTY("screenPosition", VECTOR2, false, false, false, Dali::Actor::Property::SCREEN_POSITION)
132 DALI_PROPERTY("positionUsesAnchorPoint", BOOLEAN, true, false, false, Dali::Actor::Property::POSITION_USES_ANCHOR_POINT)
133 DALI_PROPERTY("culled", BOOLEAN, false, false, true, Dali::Actor::Property::CULLED)
134 DALI_PROPERTY("id", INTEGER, false, false, false, Dali::Actor::Property::ID)
135 DALI_PROPERTY("hierarchyDepth", INTEGER, false, false, false, Dali::Actor::Property::HIERARCHY_DEPTH)
136 DALI_PROPERTY("isRoot", BOOLEAN, false, false, false, Dali::Actor::Property::IS_ROOT)
137 DALI_PROPERTY("isLayer", BOOLEAN, false, false, false, Dali::Actor::Property::IS_LAYER)
138 DALI_PROPERTY("connectedToScene", BOOLEAN, false, false, false, Dali::Actor::Property::CONNECTED_TO_SCENE)
139 DALI_PROPERTY("keyboardFocusable", BOOLEAN, true, false, false, Dali::Actor::Property::KEYBOARD_FOCUSABLE)
140 DALI_PROPERTY("siblingOrder", INTEGER, true, false, false, Dali::DevelActor::Property::SIBLING_ORDER)
141 DALI_PROPERTY("updateSizeHint", VECTOR2, true, false, false, Dali::DevelActor::Property::UPDATE_SIZE_HINT)
142 DALI_PROPERTY("captureAllTouchAfterStart", BOOLEAN, true, false, false, Dali::DevelActor::Property::CAPTURE_ALL_TOUCH_AFTER_START)
143 DALI_PROPERTY("touchAreaOffset", RECTANGLE, true, false, false, Dali::DevelActor::Property::TOUCH_AREA_OFFSET)
144 DALI_PROPERTY("touchFocusable", BOOLEAN, true, false, false, Dali::DevelActor::Property::TOUCH_FOCUSABLE)
145 DALI_PROPERTY_TABLE_END(DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperties)
149 const char* const SIGNAL_HOVERED = "hovered";
150 const char* const SIGNAL_WHEEL_EVENT = "wheelEvent";
151 const char* const SIGNAL_ON_SCENE = "onScene";
152 const char* const SIGNAL_OFF_SCENE = "offScene";
153 const char* const SIGNAL_ON_RELAYOUT = "onRelayout";
154 const char* const SIGNAL_TOUCHED = "touched";
155 const char* const SIGNAL_VISIBILITY_CHANGED = "visibilityChanged";
156 const char* const SIGNAL_LAYOUT_DIRECTION_CHANGED = "layoutDirectionChanged";
157 const char* const SIGNAL_CHILD_ADDED = "childAdded";
158 const char* const SIGNAL_CHILD_REMOVED = "childRemoved";
162 const char* const ACTION_SHOW = "show";
163 const char* const ACTION_HIDE = "hide";
165 BaseHandle CreateActor()
167 return Dali::Actor::New();
170 TypeRegistration mType(typeid(Dali::Actor), typeid(Dali::Handle), CreateActor, ActorDefaultProperties);
172 SignalConnectorType signalConnector2(mType, SIGNAL_HOVERED, &Actor::DoConnectSignal);
173 SignalConnectorType signalConnector3(mType, SIGNAL_WHEEL_EVENT, &Actor::DoConnectSignal);
174 SignalConnectorType signalConnector4(mType, SIGNAL_ON_SCENE, &Actor::DoConnectSignal);
175 SignalConnectorType signalConnector5(mType, SIGNAL_OFF_SCENE, &Actor::DoConnectSignal);
176 SignalConnectorType signalConnector6(mType, SIGNAL_ON_RELAYOUT, &Actor::DoConnectSignal);
177 SignalConnectorType signalConnector7(mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal);
178 SignalConnectorType signalConnector8(mType, SIGNAL_VISIBILITY_CHANGED, &Actor::DoConnectSignal);
179 SignalConnectorType signalConnector9(mType, SIGNAL_LAYOUT_DIRECTION_CHANGED, &Actor::DoConnectSignal);
180 SignalConnectorType signalConnector10(mType, SIGNAL_CHILD_ADDED, &Actor::DoConnectSignal);
181 SignalConnectorType signalConnector11(mType, SIGNAL_CHILD_REMOVED, &Actor::DoConnectSignal);
183 TypeAction a1(mType, ACTION_SHOW, &Actor::DoAction);
184 TypeAction a2(mType, ACTION_HIDE, &Actor::DoAction);
187 * @brief Extract a given dimension from a Vector2
189 * @param[in] values The values to extract from
190 * @param[in] dimension The dimension to extract
191 * @return Return the value for the dimension
193 constexpr float GetDimensionValue(const Vector2& values, Dimension::Type dimension)
197 case Dimension::WIDTH:
201 case Dimension::HEIGHT:
203 return values.height;
214 * @brief Extract a given dimension from a Vector3
216 * @param[in] values The values to extract from
217 * @param[in] dimension The dimension to extract
218 * @return Return the value for the dimension
220 float GetDimensionValue(const Vector3& values, Dimension::Type dimension)
222 return GetDimensionValue(values.GetVectorXY(), dimension);
226 * @brief Recursively emits the visibility-changed-signal on the actor tree.
227 * @param[in] actor The actor to emit the signal on
228 * @param[in] visible The new visibility of the actor
229 * @param[in] type Whether the actor's visible property has changed or a parent's
231 void EmitVisibilityChangedSignalRecursively(ActorPtr actor, bool visible, DevelActor::VisibilityChange::Type type)
235 actor->EmitVisibilityChangedSignal(visible, type);
237 if(actor->GetChildCount() > 0)
239 for(auto& child : actor->GetChildrenInternal())
241 EmitVisibilityChangedSignalRecursively(child, visible, DevelActor::VisibilityChange::PARENT);
247 /// Helper for emitting a signal
248 template<typename Signal, typename Event>
249 bool EmitConsumingSignal(Actor& actor, Signal& signal, const Event& event)
251 bool consumed = false;
255 Dali::Actor handle(&actor);
256 consumed = signal.Emit(handle, event);
262 /// Helper for emitting signals with multiple parameters
263 template<typename Signal, typename... Param>
264 void EmitSignal(Actor& actor, Signal& signal, Param... params)
268 Dali::Actor handle(&actor);
269 signal.Emit(handle, params...);
273 bool ScreenToLocalInternal(
274 const Matrix& viewMatrix,
275 const Matrix& projectionMatrix,
276 const Matrix& worldMatrix,
277 const Viewport& viewport,
278 const Vector3& currentSize,
284 // Get the ModelView matrix
286 Matrix::Multiply(modelView, worldMatrix, viewMatrix);
288 // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
289 Matrix invertedMvp(false /*don't init*/);
290 Matrix::Multiply(invertedMvp, modelView, projectionMatrix);
291 bool success = invertedMvp.Invert();
293 // Convert to GL coordinates
294 Vector4 screenPos(screenX - static_cast<float>(viewport.x), static_cast<float>(viewport.height) - screenY - static_cast<float>(viewport.y), 0.f, 1.f);
299 success = Unproject(screenPos, invertedMvp, static_cast<float>(viewport.width), static_cast<float>(viewport.height), nearPos);
306 success = Unproject(screenPos, invertedMvp, static_cast<float>(viewport.width), static_cast<float>(viewport.height), farPos);
312 if(XyPlaneIntersect(nearPos, farPos, local))
314 Vector3 size = currentSize;
315 localX = local.x + size.x * 0.5f;
316 localY = local.y + size.y * 0.5f;
327 } // unnamed namespace
329 ActorPtr Actor::New()
331 // pass a reference to actor, actor does not own its node
332 ActorPtr actor(new Actor(BASIC, *CreateNode()));
334 // Second-phase construction
340 const SceneGraph::Node* Actor::CreateNode()
342 // create node. Nodes are owned by the update manager
343 SceneGraph::Node* node = SceneGraph::Node::New();
344 OwnerPointer<SceneGraph::Node> transferOwnership(node);
345 Internal::ThreadLocalStorage* tls = Internal::ThreadLocalStorage::GetInternal();
347 DALI_ASSERT_ALWAYS(tls && "ThreadLocalStorage is null");
349 AddNodeMessage(tls->GetUpdateManager(), transferOwnership);
354 void Actor::SetName(const std::string& name)
358 // ATTENTION: string for debug purposes is not thread safe.
359 DALI_LOG_SET_OBJECT_STRING(const_cast<SceneGraph::Node*>(&GetNode()), name);
362 uint32_t Actor::GetId() const
364 return GetNode().GetId();
367 Dali::Layer Actor::GetLayer()
371 // Short-circuit for Layer derived actors
374 layer = Dali::Layer(static_cast<Dali::Internal::Layer*>(this)); // static cast as we trust the flag
377 // Find the immediate Layer parent
378 for(Actor* parent = mParent; !layer && parent != nullptr; parent = parent->GetParent())
380 if(parent->IsLayer())
382 layer = Dali::Layer(static_cast<Dali::Internal::Layer*>(parent)); // static cast as we trust the flag
389 void Actor::Add(Actor& child)
391 DALI_ASSERT_ALWAYS(this != &child && "Cannot add actor to itself");
392 DALI_ASSERT_ALWAYS(!child.IsRoot() && "Cannot add root actor");
396 mChildren = new ActorContainer;
399 Actor* const oldParent(child.mParent);
401 // child might already be ours
402 if(this != oldParent)
404 // if we already have parent, unparent us first
407 oldParent->Remove(child); // This causes OnChildRemove callback & ChildRemoved signal
409 // Old parent may need to readjust to missing child
410 if(oldParent->RelayoutDependentOnChildren())
412 oldParent->RelayoutRequest();
416 // Guard against Add() during previous OnChildRemove callback
419 // Do this first, since user callbacks from within SetParent() may need to remove child
420 mChildren->push_back(ActorPtr(&child));
422 // SetParent asserts that child can be added
423 child.SetParent(this);
425 // Notification for derived classes
427 EmitChildAddedSignal(child);
429 InheritLayoutDirectionRecursively(ActorPtr(&child), mLayoutDirection);
431 // Only put in a relayout request if there is a suitable dependency
432 if(RelayoutDependentOnChildren())
440 void Actor::Remove(Actor& child)
442 if((this == &child) || (!mChildren))
444 // no children or removing itself
450 // Find the child in mChildren, and unparent it
451 ActorIter end = mChildren->end();
452 for(ActorIter iter = mChildren->begin(); iter != end; ++iter)
454 ActorPtr actor = (*iter);
456 if(actor.Get() == &child)
458 // Keep handle for OnChildRemove notification
461 // Do this first, since user callbacks from within SetParent() may need to add the child
462 mChildren->erase(iter);
464 DALI_ASSERT_DEBUG(actor->GetParent() == this);
465 actor->SetParent(nullptr);
473 // Only put in a relayout request if there is a suitable dependency
474 if(RelayoutDependentOnChildren())
480 // Notification for derived classes
481 OnChildRemove(child);
482 EmitChildRemovedSignal(child);
485 void Actor::Unparent()
489 // Remove this actor from the parent. The remove will put a relayout request in for
490 // the parent if required
491 mParent->Remove(*this);
492 // mParent is now NULL!
496 uint32_t Actor::GetChildCount() const
498 return (nullptr != mChildren) ? static_cast<uint32_t>(mChildren->size()) : 0; // only 4,294,967,295 children per actor
501 ActorPtr Actor::GetChildAt(uint32_t index) const
503 DALI_ASSERT_ALWAYS(index < GetChildCount());
505 return ((mChildren) ? (*mChildren)[index] : ActorPtr());
508 ActorPtr Actor::FindChildByName(const std::string& actorName)
510 ActorPtr child = nullptr;
511 if(actorName == mName)
517 for(const auto& actor : *mChildren)
519 child = actor->FindChildByName(actorName);
530 ActorPtr Actor::FindChildById(const uint32_t id)
532 ActorPtr child = nullptr;
539 for(const auto& actor : *mChildren)
541 child = actor->FindChildById(id);
552 void Actor::SetParentOrigin(const Vector3& origin)
554 // node is being used in a separate thread; queue a message to set the value & base value
555 SetParentOriginMessage(GetEventThreadServices(), GetNode(), origin);
557 // Cache for event-thread access
560 // not allocated, check if different from default
561 if(ParentOrigin::DEFAULT != origin)
563 mParentOrigin = new Vector3(origin);
568 // check if different from current costs more than just set
569 *mParentOrigin = origin;
573 const Vector3& Actor::GetCurrentParentOrigin() const
575 // Cached for event-thread access
576 return (mParentOrigin) ? *mParentOrigin : ParentOrigin::DEFAULT;
579 void Actor::SetAnchorPoint(const Vector3& anchor)
581 // node is being used in a separate thread; queue a message to set the value & base value
582 SetAnchorPointMessage(GetEventThreadServices(), GetNode(), anchor);
584 // Cache for event-thread access
587 // not allocated, check if different from default
588 if(AnchorPoint::DEFAULT != anchor)
590 mAnchorPoint = new Vector3(anchor);
595 // check if different from current costs more than just set
596 *mAnchorPoint = anchor;
600 const Vector3& Actor::GetCurrentAnchorPoint() const
602 // Cached for event-thread access
603 return (mAnchorPoint) ? *mAnchorPoint : AnchorPoint::DEFAULT;
606 void Actor::SetPosition(float x, float y)
608 SetPosition(Vector3(x, y, 0.0f));
611 void Actor::SetPosition(float x, float y, float z)
613 SetPosition(Vector3(x, y, z));
616 void Actor::SetPosition(const Vector3& position)
618 mTargetPosition = position;
620 // node is being used in a separate thread; queue a message to set the value & base value
621 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position);
624 void Actor::SetX(float x)
626 mTargetPosition.x = x;
628 // node is being used in a separate thread; queue a message to set the value & base value
629 SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x);
632 void Actor::SetY(float y)
634 mTargetPosition.y = y;
636 // node is being used in a separate thread; queue a message to set the value & base value
637 SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y);
640 void Actor::SetZ(float z)
642 mTargetPosition.z = z;
644 // node is being used in a separate thread; queue a message to set the value & base value
645 SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z);
648 void Actor::TranslateBy(const Vector3& distance)
650 mTargetPosition += distance;
652 // node is being used in a separate thread; queue a message to set the value & base value
653 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance);
656 const Vector3& Actor::GetCurrentPosition() const
658 // node is being used in a separate thread; copy the value from the previous update
659 return GetNode().GetPosition(GetEventThreadServices().GetEventBufferIndex());
662 const Vector3& Actor::GetCurrentWorldPosition() const
664 // node is being used in a separate thread; copy the value from the previous update
665 return GetNode().GetWorldPosition(GetEventThreadServices().GetEventBufferIndex());
668 const Vector2 Actor::GetCurrentScreenPosition() const
670 if(mScene && OnScene())
672 Vector3 worldPosition = GetNode().GetWorldPosition(GetEventThreadServices().GetEventBufferIndex());
673 Vector3 cameraPosition = mScene->GetDefaultCameraActor().GetNode().GetWorldPosition(GetEventThreadServices().GetEventBufferIndex());
674 worldPosition -= cameraPosition;
676 Vector3 actorSize = GetCurrentSize() * GetCurrentWorldScale();
677 Vector2 halfSceneSize(mScene->GetSize() * 0.5f); // World position origin is center of scene
678 Vector3 halfActorSize(actorSize * 0.5f);
679 Vector3 anchorPointOffSet = halfActorSize - actorSize * (mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT);
681 return Vector2(halfSceneSize.width + worldPosition.x - anchorPointOffSet.x,
682 halfSceneSize.height + worldPosition.y - anchorPointOffSet.y);
685 return Vector2::ZERO;
688 void Actor::SetInheritPosition(bool inherit)
690 if(mInheritPosition != inherit)
692 // non animatable so keep local copy
693 mInheritPosition = inherit;
694 SetInheritPositionMessage(GetEventThreadServices(), GetNode(), inherit);
698 void Actor::SetOrientation(const Radian& angle, const Vector3& axis)
700 Vector3 normalizedAxis(axis.x, axis.y, axis.z);
701 normalizedAxis.Normalize();
703 Quaternion orientation(angle, normalizedAxis);
705 SetOrientation(orientation);
708 void Actor::SetOrientation(const Quaternion& orientation)
710 mTargetOrientation = orientation;
712 // node is being used in a separate thread; queue a message to set the value & base value
713 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation);
716 void Actor::RotateBy(const Radian& angle, const Vector3& axis)
718 RotateBy(Quaternion(angle, axis));
721 void Actor::RotateBy(const Quaternion& relativeRotation)
723 mTargetOrientation *= Quaternion(relativeRotation);
725 // node is being used in a separate thread; queue a message to set the value & base value
726 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation);
729 const Quaternion& Actor::GetCurrentOrientation() const
731 // node is being used in a separate thread; copy the value from the previous update
732 return GetNode().GetOrientation(GetEventThreadServices().GetEventBufferIndex());
735 const Quaternion& Actor::GetCurrentWorldOrientation() const
737 // node is being used in a separate thread; copy the value from the previous update
738 return GetNode().GetWorldOrientation(GetEventThreadServices().GetEventBufferIndex());
741 void Actor::SetScale(float scale)
743 SetScale(Vector3(scale, scale, scale));
746 void Actor::SetScale(float x, float y, float z)
748 SetScale(Vector3(x, y, z));
751 void Actor::SetScale(const Vector3& scale)
753 mTargetScale = scale;
755 // node is being used in a separate thread; queue a message to set the value & base value
756 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale);
759 void Actor::SetScaleX(float x)
763 // node is being used in a separate thread; queue a message to set the value & base value
764 SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x);
767 void Actor::SetScaleY(float y)
771 // node is being used in a separate thread; queue a message to set the value & base value
772 SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y);
775 void Actor::SetScaleZ(float z)
779 // node is being used in a separate thread; queue a message to set the value & base value
780 SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z);
783 void Actor::ScaleBy(const Vector3& relativeScale)
785 mTargetScale *= relativeScale;
787 // node is being used in a separate thread; queue a message to set the value & base value
788 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale);
791 const Vector3& Actor::GetCurrentScale() const
793 // node is being used in a separate thread; copy the value from the previous update
794 return GetNode().GetScale(GetEventThreadServices().GetEventBufferIndex());
797 const Vector3& Actor::GetCurrentWorldScale() const
799 // node is being used in a separate thread; copy the value from the previous update
800 return GetNode().GetWorldScale(GetEventThreadServices().GetEventBufferIndex());
803 void Actor::SetInheritScale(bool inherit)
805 if(mInheritScale != inherit)
807 // non animatable so keep local copy
808 mInheritScale = inherit;
809 // node is being used in a separate thread; queue a message to set the value
810 SetInheritScaleMessage(GetEventThreadServices(), GetNode(), inherit);
814 Matrix Actor::GetCurrentWorldMatrix() const
816 return GetNode().GetWorldMatrix(0);
819 void Actor::SetVisible(bool visible)
821 SetVisibleInternal(visible, SendMessage::TRUE);
824 bool Actor::IsVisible() const
826 // node is being used in a separate thread; copy the value from the previous update
827 return GetNode().IsVisible(GetEventThreadServices().GetEventBufferIndex());
830 void Actor::SetOpacity(float opacity)
832 mTargetColor.a = opacity;
834 // node is being used in a separate thread; queue a message to set the value & base value
835 SceneGraph::NodePropertyComponentMessage<Vector4>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeW, opacity);
838 float Actor::GetCurrentOpacity() const
840 // node is being used in a separate thread; copy the value from the previous update
841 return GetNode().GetOpacity(GetEventThreadServices().GetEventBufferIndex());
844 const Vector4& Actor::GetCurrentWorldColor() const
846 return GetNode().GetWorldColor(GetEventThreadServices().GetEventBufferIndex());
849 void Actor::SetColor(const Vector4& color)
851 mTargetColor = color;
853 // node is being used in a separate thread; queue a message to set the value & base value
854 SceneGraph::NodePropertyMessage<Vector4>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::Bake, color);
857 void Actor::SetColorRed(float red)
859 mTargetColor.r = red;
861 // node is being used in a separate thread; queue a message to set the value & base value
862 SceneGraph::NodePropertyComponentMessage<Vector4>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeX, red);
865 void Actor::SetColorGreen(float green)
867 mTargetColor.g = green;
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>::BakeY, green);
873 void Actor::SetColorBlue(float blue)
875 mTargetColor.b = blue;
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>::BakeZ, blue);
881 const Vector4& Actor::GetCurrentColor() const
883 // node is being used in a separate thread; copy the value from the previous update
884 return GetNode().GetColor(GetEventThreadServices().GetEventBufferIndex());
887 void Actor::SetInheritOrientation(bool inherit)
889 if(mInheritOrientation != inherit)
891 // non animatable so keep local copy
892 mInheritOrientation = inherit;
893 // node is being used in a separate thread; queue a message to set the value
894 SetInheritOrientationMessage(GetEventThreadServices(), GetNode(), inherit);
898 void Actor::SetSizeModeFactor(const Vector3& factor)
902 mRelayoutData->sizeModeFactor = factor;
905 const Vector3& Actor::GetSizeModeFactor() const
909 return mRelayoutData->sizeModeFactor;
912 return Relayouter::DEFAULT_SIZE_MODE_FACTOR;
915 void Actor::SetColorMode(ColorMode colorMode)
917 // non animatable so keep local copy
918 mColorMode = colorMode;
919 // node is being used in a separate thread; queue a message to set the value
920 SetColorModeMessage(GetEventThreadServices(), GetNode(), colorMode);
923 void Actor::SetSize(float width, float height)
925 SetSize(Vector2(width, height));
928 void Actor::SetSize(float width, float height, float depth)
930 SetSize(Vector3(width, height, depth));
933 void Actor::SetSize(const Vector2& size)
935 SetSize(Vector3(size.width, size.height, 0.f));
938 void Actor::SetSizeInternal(const Vector2& size)
940 SetSizeInternal(Vector3(size.width, size.height, 0.f));
943 void Actor::SetSize(const Vector3& size)
945 if(IsRelayoutEnabled() && !mRelayoutData->insideRelayout)
947 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
948 SetPreferredSize(size.GetVectorXY());
952 SetSizeInternal(size);
956 void Actor::SetSizeInternal(const Vector3& size)
958 // dont allow recursive loop
959 DALI_ASSERT_ALWAYS(!mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet");
960 // 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
961 if((fabsf(mTargetSize.width - size.width) > Math::MACHINE_EPSILON_1) ||
962 (fabsf(mTargetSize.height - size.height) > Math::MACHINE_EPSILON_1) ||
963 (fabsf(mTargetSize.depth - size.depth) > Math::MACHINE_EPSILON_1))
967 // node is being used in a separate thread; queue a message to set the value & base value
968 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize);
970 // Notification for derived classes
971 mInsideOnSizeSet = true;
972 OnSizeSet(mTargetSize);
973 mInsideOnSizeSet = false;
975 // Raise a relayout request if the flag is not locked
976 if(mRelayoutData && !mRelayoutData->insideRelayout)
983 void Actor::SetWidth(float width)
985 if(IsRelayoutEnabled() && !mRelayoutData->insideRelayout)
987 SetResizePolicy(ResizePolicy::FIXED, Dimension::WIDTH);
988 mRelayoutData->preferredSize.width = width;
992 mTargetSize.width = width;
994 // node is being used in a separate thread; queue a message to set the value & base value
995 SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width);
998 mUseAnimatedSize &= ~AnimatedSizeFlag::WIDTH;
1003 void Actor::SetHeight(float height)
1005 if(IsRelayoutEnabled() && !mRelayoutData->insideRelayout)
1007 SetResizePolicy(ResizePolicy::FIXED, Dimension::HEIGHT);
1008 mRelayoutData->preferredSize.height = height;
1012 mTargetSize.height = height;
1014 // node is being used in a separate thread; queue a message to set the value & base value
1015 SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height);
1018 mUseAnimatedSize &= ~AnimatedSizeFlag::HEIGHT;
1023 void Actor::SetDepth(float depth)
1025 mTargetSize.depth = depth;
1027 mUseAnimatedSize &= ~AnimatedSizeFlag::DEPTH;
1029 // node is being used in a separate thread; queue a message to set the value & base value
1030 SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth);
1033 Vector3 Actor::GetTargetSize() const
1035 Vector3 size = mTargetSize;
1037 if(mUseAnimatedSize & AnimatedSizeFlag::WIDTH)
1039 // Should return animated size if size is animated
1040 size.width = mAnimatedSize.width;
1044 // Should return preferred size if size is fixed as set by SetSize
1045 if(GetResizePolicy(Dimension::WIDTH) == ResizePolicy::FIXED)
1047 size.width = GetPreferredSize().width;
1051 if(mUseAnimatedSize & AnimatedSizeFlag::HEIGHT)
1053 size.height = mAnimatedSize.height;
1057 if(GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::FIXED)
1059 size.height = GetPreferredSize().height;
1063 if(mUseAnimatedSize & AnimatedSizeFlag::DEPTH)
1065 size.depth = mAnimatedSize.depth;
1071 const Vector3& Actor::GetCurrentSize() const
1073 // node is being used in a separate thread; copy the value from the previous update
1074 return GetNode().GetSize(GetEventThreadServices().GetEventBufferIndex());
1077 Vector3 Actor::GetNaturalSize() const
1079 // It is up to deriving classes to return the appropriate natural size
1080 return Vector3(0.0f, 0.0f, 0.0f);
1083 void Actor::SetResizePolicy(ResizePolicy::Type policy, Dimension::Type dimension)
1085 EnsureRelayouter().SetResizePolicy(policy, dimension, mTargetSize);
1087 OnSetResizePolicy(policy, dimension);
1089 // Trigger relayout on this control
1093 ResizePolicy::Type Actor::GetResizePolicy(Dimension::Type dimension) const
1097 return mRelayoutData->GetResizePolicy(dimension);
1100 return ResizePolicy::DEFAULT;
1103 void Actor::SetSizeScalePolicy(SizeScalePolicy::Type policy)
1107 mRelayoutData->sizeSetPolicy = policy;
1109 // Trigger relayout on this control
1113 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1117 return mRelayoutData->sizeSetPolicy;
1120 return Relayouter::DEFAULT_SIZE_SCALE_POLICY;
1123 void Actor::SetDimensionDependency(Dimension::Type dimension, Dimension::Type dependency)
1125 EnsureRelayouter().SetDimensionDependency(dimension, dependency);
1128 Dimension::Type Actor::GetDimensionDependency(Dimension::Type dimension) const
1132 return mRelayoutData->GetDimensionDependency(dimension);
1135 return Dimension::ALL_DIMENSIONS; // Default
1138 void Actor::SetRelayoutEnabled(bool relayoutEnabled)
1140 // If relayout data has not been allocated yet and the client is requesting
1141 // to disable it, do nothing
1142 if(mRelayoutData || relayoutEnabled)
1146 DALI_ASSERT_DEBUG(mRelayoutData && "mRelayoutData not created");
1148 mRelayoutData->relayoutEnabled = relayoutEnabled;
1152 bool Actor::IsRelayoutEnabled() const
1154 // Assume that if relayout data has not been allocated yet then
1155 // relayout is disabled
1156 return mRelayoutData && mRelayoutData->relayoutEnabled;
1159 void Actor::SetLayoutDirty(bool dirty, Dimension::Type dimension)
1161 EnsureRelayouter().SetLayoutDirty(dirty, dimension);
1164 bool Actor::IsLayoutDirty(Dimension::Type dimension) const
1166 return mRelayoutData && mRelayoutData->IsLayoutDirty(dimension);
1169 bool Actor::RelayoutPossible(Dimension::Type dimension) const
1171 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty(dimension);
1174 bool Actor::RelayoutRequired(Dimension::Type dimension) const
1176 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty(dimension);
1179 uint32_t Actor::AddRenderer(Renderer& renderer)
1183 mRenderers = new RendererContainer;
1186 uint32_t index = static_cast<uint32_t>(mRenderers->size()); // 4,294,967,295 renderers per actor
1187 RendererPtr rendererPtr = RendererPtr(&renderer);
1188 mRenderers->push_back(rendererPtr);
1189 AttachRendererMessage(GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject());
1193 uint32_t Actor::GetRendererCount() const
1195 uint32_t rendererCount(0);
1198 rendererCount = static_cast<uint32_t>(mRenderers->size()); // 4,294,967,295 renderers per actor
1201 return rendererCount;
1204 RendererPtr Actor::GetRendererAt(uint32_t index)
1206 RendererPtr renderer;
1207 if(index < GetRendererCount())
1209 renderer = (*mRenderers)[index];
1215 void Actor::RemoveRenderer(Renderer& renderer)
1219 RendererIter end = mRenderers->end();
1220 for(RendererIter iter = mRenderers->begin(); iter != end; ++iter)
1222 if((*iter).Get() == &renderer)
1224 mRenderers->erase(iter);
1225 DetachRendererMessage(GetEventThreadServices(), GetNode(), renderer.GetRendererSceneObject());
1232 void Actor::RemoveRenderer(uint32_t index)
1234 if(index < GetRendererCount())
1236 RendererPtr renderer = (*mRenderers)[index];
1237 DetachRendererMessage(GetEventThreadServices(), GetNode(), renderer.Get()->GetRendererSceneObject());
1238 mRenderers->erase(mRenderers->begin() + index);
1242 void Actor::SetDrawMode(DrawMode::Type drawMode)
1244 // this flag is not animatable so keep the value
1245 mDrawMode = drawMode;
1247 // node is being used in a separate thread; queue a message to set the value
1248 SetDrawModeMessage(GetEventThreadServices(), GetNode(), drawMode);
1251 bool Actor::ScreenToLocal(float& localX, float& localY, float screenX, float screenY) const
1253 // only valid when on-stage
1254 if(mScene && OnScene())
1256 const RenderTaskList& taskList = mScene->GetRenderTaskList();
1258 Vector2 converted(screenX, screenY);
1260 // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1261 uint32_t taskCount = taskList.GetTaskCount();
1262 for(uint32_t i = taskCount; i > 0; --i)
1264 RenderTaskPtr task = taskList.GetTask(i - 1);
1265 if(ScreenToLocal(*task, localX, localY, screenX, screenY))
1267 // found a task where this conversion was ok so return
1275 bool Actor::ScreenToLocal(const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY) const
1277 bool retval = false;
1278 // only valid when on-stage
1281 CameraActor* camera = renderTask.GetCameraActor();
1285 renderTask.GetViewport(viewport);
1287 // need to translate coordinates to render tasks coordinate space
1288 Vector2 converted(screenX, screenY);
1289 if(renderTask.TranslateCoordinates(converted))
1291 retval = ScreenToLocal(camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y);
1298 bool Actor::ScreenToLocal(const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY) const
1300 return OnScene() && ScreenToLocalInternal(viewMatrix, projectionMatrix, GetNode().GetWorldMatrix(0), viewport, GetCurrentSize(), localX, localY, screenX, screenY);
1303 ActorGestureData& Actor::GetGestureData()
1305 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1306 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1307 if(nullptr == mGestureData)
1309 mGestureData = new ActorGestureData;
1311 return *mGestureData;
1314 bool Actor::IsGestureRequired(GestureType::Value type) const
1316 return mGestureData && mGestureData->IsGestureRequired(type);
1319 bool Actor::EmitInterceptTouchEventSignal(const Dali::TouchEvent& touch)
1321 return EmitConsumingSignal(*this, mInterceptTouchedSignal, touch);
1324 bool Actor::EmitTouchEventSignal(const Dali::TouchEvent& touch)
1326 return EmitConsumingSignal(*this, mTouchedSignal, touch);
1329 bool Actor::EmitHoverEventSignal(const Dali::HoverEvent& event)
1331 return EmitConsumingSignal(*this, mHoveredSignal, event);
1334 bool Actor::EmitWheelEventSignal(const Dali::WheelEvent& event)
1336 return EmitConsumingSignal(*this, mWheelEventSignal, event);
1339 void Actor::EmitVisibilityChangedSignal(bool visible, DevelActor::VisibilityChange::Type type)
1341 EmitSignal(*this, mVisibilityChangedSignal, visible, type);
1344 void Actor::EmitLayoutDirectionChangedSignal(LayoutDirection::Type type)
1346 EmitSignal(*this, mLayoutDirectionChangedSignal, type);
1349 void Actor::EmitChildAddedSignal(Actor& child)
1351 EmitSignal(child, mChildAddedSignal);
1354 void Actor::EmitChildRemovedSignal(Actor& child)
1356 EmitSignal(child, mChildRemovedSignal);
1359 bool Actor::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
1361 bool connected(true);
1362 Actor* actor = static_cast<Actor*>(object); // TypeRegistry guarantees that this is the correct type.
1364 if(0 == signalName.compare(SIGNAL_HOVERED))
1366 actor->HoveredSignal().Connect(tracker, functor);
1368 else if(0 == signalName.compare(SIGNAL_WHEEL_EVENT))
1370 actor->WheelEventSignal().Connect(tracker, functor);
1372 else if(0 == signalName.compare(SIGNAL_ON_SCENE))
1374 actor->OnSceneSignal().Connect(tracker, functor);
1376 else if(0 == signalName.compare(SIGNAL_OFF_SCENE))
1378 actor->OffSceneSignal().Connect(tracker, functor);
1380 else if(0 == signalName.compare(SIGNAL_ON_RELAYOUT))
1382 actor->OnRelayoutSignal().Connect(tracker, functor);
1384 else if(0 == signalName.compare(SIGNAL_TOUCHED))
1386 actor->TouchedSignal().Connect(tracker, functor);
1388 else if(0 == signalName.compare(SIGNAL_VISIBILITY_CHANGED))
1390 actor->VisibilityChangedSignal().Connect(tracker, functor);
1392 else if(0 == signalName.compare(SIGNAL_LAYOUT_DIRECTION_CHANGED))
1394 actor->LayoutDirectionChangedSignal().Connect(tracker, functor);
1396 else if(0 == signalName.compare(SIGNAL_CHILD_ADDED))
1398 actor->ChildAddedSignal().Connect(tracker, functor);
1400 else if(0 == signalName.compare(SIGNAL_CHILD_REMOVED))
1402 actor->ChildRemovedSignal().Connect(tracker, functor);
1406 // signalName does not match any signal
1413 Actor::Actor(DerivedType derivedType, const SceneGraph::Node& node)
1418 mRenderers(nullptr),
1419 mParentOrigin(nullptr),
1420 mAnchorPoint(nullptr),
1421 mRelayoutData(nullptr),
1422 mGestureData(nullptr),
1423 mInterceptTouchedSignal(),
1426 mWheelEventSignal(),
1429 mOnRelayoutSignal(),
1430 mVisibilityChangedSignal(),
1431 mLayoutDirectionChangedSignal(),
1432 mChildAddedSignal(),
1433 mChildRemovedSignal(),
1434 mChildOrderChangedSignal(),
1435 mTargetOrientation(Quaternion::IDENTITY),
1436 mTargetColor(Color::WHITE),
1437 mTargetSize(Vector3::ZERO),
1438 mTargetPosition(Vector3::ZERO),
1439 mTargetScale(Vector3::ONE),
1440 mAnimatedSize(Vector3::ZERO),
1441 mTouchAreaOffset(0, 0, 0, 0),
1445 mUseAnimatedSize(AnimatedSizeFlag::CLEAR),
1446 mIsRoot(ROOT_LAYER == derivedType),
1447 mIsLayer(LAYER == derivedType || ROOT_LAYER == derivedType),
1450 mLeaveRequired(false),
1451 mKeyboardFocusable(false),
1452 mTouchFocusable(false),
1453 mOnSceneSignalled(false),
1454 mInsideOnSizeSet(false),
1455 mInheritPosition(true),
1456 mInheritOrientation(true),
1457 mInheritScale(true),
1458 mPositionUsesAnchorPoint(true),
1460 mInheritLayoutDirection(true),
1461 mCaptureAllTouchAfterStart(false),
1462 mLayoutDirection(LayoutDirection::LEFT_TO_RIGHT),
1463 mDrawMode(DrawMode::NORMAL),
1464 mColorMode(Node::DEFAULT_COLOR_MODE),
1465 mClippingMode(ClippingMode::DISABLED)
1469 void Actor::Initialize()
1473 GetEventThreadServices().RegisterObject(this);
1478 // Remove mParent pointers from children even if we're destroying core,
1479 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1482 for(const auto& actor : *mChildren)
1484 actor->SetParent(nullptr);
1490 // Guard to allow handle destruction after Core has been destroyed
1491 if(EventThreadServices::IsCoreRunning())
1493 // Root layer will destroy its node in its own destructor
1496 DestroyNodeMessage(GetEventThreadServices().GetUpdateManager(), GetNode());
1498 GetEventThreadServices().UnregisterObject(this);
1502 // Cleanup optional gesture data
1503 delete mGestureData;
1505 // Cleanup optional parent origin and anchor
1506 delete mParentOrigin;
1507 delete mAnchorPoint;
1509 // Delete optional relayout data
1510 delete mRelayoutData;
1513 void Actor::ConnectToScene(uint32_t parentDepth)
1515 // This container is used instead of walking the Actor hierarchy.
1516 // It protects us when the Actor hierarchy is modified during OnSceneConnectionExternal callbacks.
1517 ActorContainer connectionList;
1521 mScene->RequestRebuildDepthTree();
1524 // This stage is atomic i.e. not interrupted by user callbacks.
1525 RecursiveConnectToScene(connectionList, parentDepth + 1);
1527 // Notify applications about the newly connected actors.
1528 for(const auto& actor : connectionList)
1530 actor->NotifyStageConnection();
1536 void Actor::RecursiveConnectToScene(ActorContainer& connectionList, uint32_t depth)
1538 DALI_ASSERT_ALWAYS(!OnScene());
1541 mDepth = static_cast<uint16_t>(depth); // overflow ignored, not expected in practice
1543 ConnectToSceneGraph();
1545 // Notification for internal derived classes
1546 OnSceneConnectionInternal();
1548 // This stage is atomic; avoid emitting callbacks until all Actors are connected
1549 connectionList.push_back(ActorPtr(this));
1551 // Recursively connect children
1554 for(const auto& actor : *mChildren)
1556 actor->SetScene(*mScene);
1557 actor->RecursiveConnectToScene(connectionList, depth + 1);
1563 * This method is called when the Actor is connected to the Stage.
1564 * The parent must have added its Node to the scene-graph.
1565 * The child must connect its Node to the parent's Node.
1566 * This is recursive; the child calls ConnectToScene() for its children.
1568 void Actor::ConnectToSceneGraph()
1570 DALI_ASSERT_DEBUG(mParent != NULL);
1572 // Reparent Node in next Update
1573 ConnectNodeMessage(GetEventThreadServices().GetUpdateManager(), mParent->GetNode(), GetNode());
1575 // Request relayout on all actors that are added to the scenegraph
1578 // Notification for Object::Observers
1582 void Actor::NotifyStageConnection()
1584 // Actors can be removed (in a callback), before the on-stage stage is reported.
1585 // The actor may also have been reparented, in which case mOnSceneSignalled will be true.
1586 if(OnScene() && !mOnSceneSignalled)
1588 // Notification for external (CustomActor) derived classes
1589 OnSceneConnectionExternal(mDepth);
1591 if(!mOnSceneSignal.Empty())
1593 Dali::Actor handle(this);
1594 mOnSceneSignal.Emit(handle);
1597 // Guard against Remove during callbacks
1600 mOnSceneSignalled = true; // signal required next time Actor is removed
1605 void Actor::DisconnectFromStage()
1607 // This container is used instead of walking the Actor hierachy.
1608 // It protects us when the Actor hierachy is modified during OnSceneDisconnectionExternal callbacks.
1609 ActorContainer disconnectionList;
1613 mScene->RequestRebuildDepthTree();
1616 // This stage is atomic i.e. not interrupted by user callbacks
1617 RecursiveDisconnectFromStage(disconnectionList);
1619 // Notify applications about the newly disconnected actors.
1620 for(const auto& actor : disconnectionList)
1622 actor->NotifyStageDisconnection();
1626 void Actor::RecursiveDisconnectFromStage(ActorContainer& disconnectionList)
1628 // need to change state first so that internals relying on IsOnScene() inside OnSceneDisconnectionInternal() get the correct value
1631 // Recursively disconnect children
1634 for(const auto& child : *mChildren)
1636 child->RecursiveDisconnectFromStage(disconnectionList);
1640 // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
1641 disconnectionList.push_back(ActorPtr(this));
1643 // Notification for internal derived classes
1644 OnSceneDisconnectionInternal();
1646 DisconnectFromSceneGraph();
1650 * This method is called by an actor or its parent, before a node removal message is sent.
1651 * This is recursive; the child calls DisconnectFromStage() for its children.
1653 void Actor::DisconnectFromSceneGraph()
1655 // Notification for Object::Observers
1656 OnSceneObjectRemove();
1659 void Actor::NotifyStageDisconnection()
1661 // Actors can be added (in a callback), before the off-stage state is reported.
1662 // Also if the actor was added & removed before mOnSceneSignalled was set, then we don't notify here.
1663 // only do this step if there is a stage, i.e. Core is not being shut down
1664 if(EventThreadServices::IsCoreRunning() && !OnScene() && mOnSceneSignalled)
1666 // Notification for external (CustomeActor) derived classes
1667 OnSceneDisconnectionExternal();
1669 if(!mOffSceneSignal.Empty())
1671 Dali::Actor handle(this);
1672 mOffSceneSignal.Emit(handle);
1675 // Guard against Add during callbacks
1678 mOnSceneSignalled = false; // signal required next time Actor is added
1683 bool Actor::IsNodeConnected() const
1685 bool connected(false);
1689 if(IsRoot() || GetNode().GetParent())
1698 // This method initiates traversal of the actor tree using depth-first
1699 // traversal to set a depth index based on traversal order. It sends a
1700 // single message to update manager to update all the actor's nodes in
1701 // this tree with the depth index. The sceneGraphNodeDepths vector's
1702 // elements are ordered by depth, and could be used to reduce sorting
1703 // in the update thread.
1704 void Actor::RebuildDepthTree()
1706 DALI_LOG_TIMER_START(depthTimer);
1708 // Vector of scene-graph nodes and their depths to send to UpdateManager
1709 // in a single message
1710 OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths(new SceneGraph::NodeDepths());
1712 int32_t depthIndex = 1;
1713 DepthTraverseActorTree(sceneGraphNodeDepths, depthIndex);
1715 SetDepthIndicesMessage(GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths);
1716 DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
1719 void Actor::DepthTraverseActorTree(OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths, int32_t& depthIndex)
1721 mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
1722 sceneGraphNodeDepths->Add(const_cast<SceneGraph::Node*>(&GetNode()), mSortedDepth);
1724 // Create/add to children of this node
1727 for(const auto& child : *mChildren)
1729 Actor* childActor = child.Get();
1731 childActor->DepthTraverseActorTree(sceneGraphNodeDepths, depthIndex);
1736 void Actor::SetDefaultProperty(Property::Index index, const Property::Value& property)
1738 PropertyHandler::SetDefaultProperty(*this, index, property);
1741 // TODO: This method needs to be removed
1742 void Actor::SetSceneGraphProperty(Property::Index index, const PropertyMetadata& entry, const Property::Value& value)
1744 PropertyHandler::SetSceneGraphProperty(index, entry, value, GetEventThreadServices(), GetNode());
1747 Property::Value Actor::GetDefaultProperty(Property::Index index) const
1749 Property::Value value;
1751 if(!GetCachedPropertyValue(index, value))
1753 // If property value is not stored in the event-side, then it must be a scene-graph only property
1754 GetCurrentPropertyValue(index, value);
1760 Property::Value Actor::GetDefaultPropertyCurrentValue(Property::Index index) const
1762 Property::Value value;
1764 if(!GetCurrentPropertyValue(index, value))
1766 // If unable to retrieve scene-graph property value, then it must be an event-side only property
1767 GetCachedPropertyValue(index, value);
1773 void Actor::OnNotifyDefaultPropertyAnimation(Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType)
1775 PropertyHandler::OnNotifyDefaultPropertyAnimation(*this, animation, index, value, animationType);
1778 const PropertyBase* Actor::GetSceneObjectAnimatableProperty(Property::Index index) const
1780 const PropertyBase* property = PropertyHandler::GetSceneObjectAnimatableProperty(index, GetNode());
1783 // not our property, ask base
1784 property = Object::GetSceneObjectAnimatableProperty(index);
1790 const PropertyInputImpl* Actor::GetSceneObjectInputProperty(Property::Index index) const
1792 const PropertyInputImpl* property = PropertyHandler::GetSceneObjectInputProperty(index, GetNode());
1795 // reuse animatable property getter as animatable properties are inputs as well
1796 // animatable property chains back to Object::GetSceneObjectInputProperty() so all properties get covered
1797 property = GetSceneObjectAnimatableProperty(index);
1803 int32_t Actor::GetPropertyComponentIndex(Property::Index index) const
1805 int32_t componentIndex = PropertyHandler::GetPropertyComponentIndex(index);
1806 if(Property::INVALID_COMPONENT_INDEX == componentIndex)
1809 componentIndex = Object::GetPropertyComponentIndex(index);
1812 return componentIndex;
1815 void Actor::SetParent(Actor* parent)
1819 DALI_ASSERT_ALWAYS(!mParent && "Actor cannot have 2 parents");
1823 mScene = parent->mScene;
1825 if(EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1828 // Instruct each actor to create a corresponding node in the scene graph
1829 ConnectToScene(parent->GetHierarchyDepth());
1832 // Resolve the name and index for the child properties if any
1833 ResolveChildProperties();
1835 else // parent being set to NULL
1837 DALI_ASSERT_ALWAYS(mParent != nullptr && "Actor should have a parent");
1841 if(EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1844 // Disconnect the Node & its children from the scene-graph.
1845 DisconnectNodeMessage(GetEventThreadServices().GetUpdateManager(), GetNode());
1847 // Instruct each actor to discard pointers to the scene-graph
1848 DisconnectFromStage();
1855 bool Actor::DoAction(BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */)
1858 Actor* actor = dynamic_cast<Actor*>(object);
1862 if(0 == actionName.compare(ACTION_SHOW))
1864 actor->SetVisible(true);
1867 else if(0 == actionName.compare(ACTION_HIDE))
1869 actor->SetVisible(false);
1877 Rect<> Actor::CalculateScreenExtents() const
1879 auto screenPosition = GetCurrentScreenPosition();
1880 Vector3 size = GetCurrentSize() * GetCurrentWorldScale();
1881 Vector3 anchorPointOffSet = size * (mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT);
1882 Vector2 position = Vector2(screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y);
1883 return {position.x, position.y, size.x, size.y};
1886 bool Actor::GetCachedPropertyValue(Property::Index index, Property::Value& value) const
1888 return PropertyHandler::GetCachedPropertyValue(*this, index, value);
1891 bool Actor::GetCurrentPropertyValue(Property::Index index, Property::Value& value) const
1893 return PropertyHandler::GetCurrentPropertyValue(*this, index, value);
1896 Actor::Relayouter& Actor::EnsureRelayouter()
1898 // Assign relayouter
1901 mRelayoutData = new Relayouter();
1904 return *mRelayoutData;
1907 bool Actor::RelayoutDependentOnParent(Dimension::Type dimension)
1909 // Check if actor is dependent on parent
1910 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
1912 if((dimension & (1 << i)))
1914 const ResizePolicy::Type resizePolicy = GetResizePolicy(static_cast<Dimension::Type>(1 << i));
1915 if(resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT)
1925 bool Actor::RelayoutDependentOnChildren(Dimension::Type dimension)
1927 // Check if actor is dependent on children
1928 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
1930 if((dimension & (1 << i)))
1932 const ResizePolicy::Type resizePolicy = GetResizePolicy(static_cast<Dimension::Type>(1 << i));
1933 switch(resizePolicy)
1935 case ResizePolicy::FIT_TO_CHILDREN:
1936 case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
1952 bool Actor::RelayoutDependentOnChildrenBase(Dimension::Type dimension)
1954 return Actor::RelayoutDependentOnChildren(dimension);
1957 bool Actor::RelayoutDependentOnDimension(Dimension::Type dimension, Dimension::Type dependentDimension)
1959 // Check each possible dimension and see if it is dependent on the input one
1960 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
1962 if(dimension & (1 << i))
1964 return mRelayoutData->resizePolicies[i] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[i] == dependentDimension;
1971 void Actor::SetNegotiatedDimension(float negotiatedDimension, Dimension::Type dimension)
1973 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
1975 if(dimension & (1 << i))
1977 mRelayoutData->negotiatedDimensions[i] = negotiatedDimension;
1982 float Actor::GetNegotiatedDimension(Dimension::Type dimension) const
1984 // If more than one dimension is requested, just return the first one found
1985 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
1987 if((dimension & (1 << i)))
1989 return mRelayoutData->negotiatedDimensions[i];
1993 return 0.0f; // Default
1996 void Actor::SetPadding(const Vector2& padding, Dimension::Type dimension)
1998 EnsureRelayouter().SetPadding(padding, dimension);
2001 Vector2 Actor::GetPadding(Dimension::Type dimension) const
2005 // If more than one dimension is requested, just return the first one found
2006 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
2008 if((dimension & (1 << i)))
2010 return mRelayoutData->dimensionPadding[i];
2015 return Relayouter::DEFAULT_DIMENSION_PADDING;
2018 void Actor::SetLayoutNegotiated(bool negotiated, Dimension::Type dimension)
2020 EnsureRelayouter().SetLayoutNegotiated(negotiated, dimension);
2023 bool Actor::IsLayoutNegotiated(Dimension::Type dimension) const
2025 return mRelayoutData && mRelayoutData->IsLayoutNegotiated(dimension);
2028 float Actor::GetHeightForWidthBase(float width)
2030 float height = 0.0f;
2032 const Vector3 naturalSize = GetNaturalSize();
2033 if(naturalSize.width > 0.0f)
2035 height = naturalSize.height * width / naturalSize.width;
2037 else // we treat 0 as 1:1 aspect ratio
2045 float Actor::GetWidthForHeightBase(float height)
2049 const Vector3 naturalSize = GetNaturalSize();
2050 if(naturalSize.height > 0.0f)
2052 width = naturalSize.width * height / naturalSize.height;
2054 else // we treat 0 as 1:1 aspect ratio
2062 float Actor::CalculateChildSizeBase(const Dali::Actor& child, Dimension::Type dimension)
2064 // Fill to parent, taking size mode factor into account
2065 switch(child.GetResizePolicy(dimension))
2067 case ResizePolicy::FILL_TO_PARENT:
2069 return GetLatestSize(dimension);
2072 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2074 return GetLatestSize(dimension) * GetDimensionValue(child.GetProperty<Vector3>(Dali::Actor::Property::SIZE_MODE_FACTOR), dimension);
2077 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2079 return GetLatestSize(dimension) + GetDimensionValue(child.GetProperty<Vector3>(Dali::Actor::Property::SIZE_MODE_FACTOR), dimension);
2084 return GetLatestSize(dimension);
2089 float Actor::CalculateChildSize(const Dali::Actor& child, Dimension::Type dimension)
2091 // Can be overridden in derived class
2092 return CalculateChildSizeBase(child, dimension);
2095 float Actor::GetHeightForWidth(float width)
2097 // Can be overridden in derived class
2098 return GetHeightForWidthBase(width);
2101 float Actor::GetWidthForHeight(float height)
2103 // Can be overridden in derived class
2104 return GetWidthForHeightBase(height);
2107 float Actor::GetLatestSize(Dimension::Type dimension) const
2109 return IsLayoutNegotiated(dimension) ? GetNegotiatedDimension(dimension) : GetSize(dimension);
2112 float Actor::GetRelayoutSize(Dimension::Type dimension) const
2114 Vector2 padding = GetPadding(dimension);
2116 return GetLatestSize(dimension) + padding.x + padding.y;
2119 float Actor::NegotiateFromParent(Dimension::Type dimension)
2121 Actor* parent = GetParent();
2124 Vector2 padding(GetPadding(dimension));
2125 Vector2 parentPadding(parent->GetPadding(dimension));
2126 return parent->CalculateChildSize(Dali::Actor(this), dimension) - parentPadding.x - parentPadding.y - padding.x - padding.y;
2132 float Actor::NegotiateFromChildren(Dimension::Type dimension)
2134 float maxDimensionPoint = 0.0f;
2136 for(uint32_t i = 0, count = GetChildCount(); i < count; ++i)
2138 ActorPtr child = GetChildAt(i);
2140 if(!child->RelayoutDependentOnParent(dimension))
2142 // Calculate the min and max points that the children range across
2143 float childPosition = GetDimensionValue(child->GetTargetPosition(), dimension);
2144 float dimensionSize = child->GetRelayoutSize(dimension);
2145 maxDimensionPoint = std::max(maxDimensionPoint, childPosition + dimensionSize);
2149 return maxDimensionPoint;
2152 float Actor::GetSize(Dimension::Type dimension) const
2154 return GetDimensionValue(mTargetSize, dimension);
2157 float Actor::GetNaturalSize(Dimension::Type dimension) const
2159 return GetDimensionValue(GetNaturalSize(), dimension);
2162 float Actor::CalculateSize(Dimension::Type dimension, const Vector2& maximumSize)
2164 switch(GetResizePolicy(dimension))
2166 case ResizePolicy::USE_NATURAL_SIZE:
2168 return GetNaturalSize(dimension);
2171 case ResizePolicy::FIXED:
2173 return GetDimensionValue(GetPreferredSize(), dimension);
2176 case ResizePolicy::USE_ASSIGNED_SIZE:
2178 return GetDimensionValue(maximumSize, dimension);
2181 case ResizePolicy::FILL_TO_PARENT:
2182 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2183 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2185 return NegotiateFromParent(dimension);
2188 case ResizePolicy::FIT_TO_CHILDREN:
2190 return NegotiateFromChildren(dimension);
2193 case ResizePolicy::DIMENSION_DEPENDENCY:
2195 const Dimension::Type dimensionDependency = GetDimensionDependency(dimension);
2198 if(dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT)
2200 return GetWidthForHeight(GetNegotiatedDimension(Dimension::HEIGHT));
2203 if(dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH)
2205 return GetHeightForWidth(GetNegotiatedDimension(Dimension::WIDTH));
2217 return 0.0f; // Default
2220 void Actor::NegotiateDimension(Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack)
2222 // Check if it needs to be negotiated
2223 if(IsLayoutDirty(dimension) && !IsLayoutNegotiated(dimension))
2225 // Check that we havn't gotten into an infinite loop
2226 ActorDimensionPair searchActor = ActorDimensionPair(this, dimension);
2227 bool recursionFound = false;
2228 for(auto& element : recursionStack)
2230 if(element == searchActor)
2232 recursionFound = true;
2239 // Record the path that we have taken
2240 recursionStack.push_back(ActorDimensionPair(this, dimension));
2242 // Dimension dependency check
2243 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
2245 Dimension::Type dimensionToCheck = static_cast<Dimension::Type>(1 << i);
2247 if(RelayoutDependentOnDimension(dimension, dimensionToCheck))
2249 NegotiateDimension(dimensionToCheck, allocatedSize, recursionStack);
2253 // Parent dependency check
2254 Actor* parent = GetParent();
2255 if(parent && RelayoutDependentOnParent(dimension))
2257 parent->NegotiateDimension(dimension, allocatedSize, recursionStack);
2260 // Children dependency check
2261 if(RelayoutDependentOnChildren(dimension))
2263 for(uint32_t i = 0, count = GetChildCount(); i < count; ++i)
2265 ActorPtr child = GetChildAt(i);
2267 // Only relayout child first if it is not dependent on this actor
2268 if(!child->RelayoutDependentOnParent(dimension))
2270 child->NegotiateDimension(dimension, allocatedSize, recursionStack);
2275 // For deriving classes
2276 OnCalculateRelayoutSize(dimension);
2278 // All dependencies checked, calculate the size and set negotiated flag
2279 const float newSize = Relayouter::ClampDimension(*this, CalculateSize(dimension, allocatedSize), dimension);
2281 SetNegotiatedDimension(newSize, dimension);
2282 SetLayoutNegotiated(true, dimension);
2284 // For deriving classes
2285 OnLayoutNegotiated(newSize, dimension);
2287 // This actor has been successfully processed, pop it off the recursion stack
2288 recursionStack.pop_back();
2292 // TODO: Break infinite loop
2293 SetLayoutNegotiated(true, dimension);
2298 void Actor::NegotiateDimensions(const Vector2& allocatedSize)
2300 // Negotiate all dimensions that require it
2301 ActorDimensionStack recursionStack;
2303 for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
2305 const Dimension::Type dimension = static_cast<Dimension::Type>(1 << i);
2308 NegotiateDimension(dimension, allocatedSize, recursionStack);
2312 Vector2 Actor::ApplySizeSetPolicy(const Vector2& size)
2314 return mRelayoutData->ApplySizeSetPolicy(*this, size);
2317 void Actor::SetNegotiatedSize(RelayoutContainer& container)
2319 // Do the set actor size
2320 Vector2 negotiatedSize(GetLatestSize(Dimension::WIDTH), GetLatestSize(Dimension::HEIGHT));
2322 // Adjust for size set policy
2323 negotiatedSize = ApplySizeSetPolicy(negotiatedSize);
2325 // Lock the flag to stop recursive relayouts on set size
2326 mRelayoutData->insideRelayout = true;
2327 SetSize(negotiatedSize);
2328 mRelayoutData->insideRelayout = false;
2330 // Clear flags for all dimensions
2331 SetLayoutDirty(false);
2333 // Give deriving classes a chance to respond
2334 OnRelayout(negotiatedSize, container);
2336 if(!mOnRelayoutSignal.Empty())
2338 Dali::Actor handle(this);
2339 mOnRelayoutSignal.Emit(handle);
2343 void Actor::NegotiateSize(const Vector2& allocatedSize, RelayoutContainer& container)
2345 // Force a size negotiation for actors that has assigned size during relayout
2346 // This is required as otherwise the flags that force a relayout will not
2347 // necessarilly be set. This will occur if the actor has already been laid out.
2348 // The dirty flags are then cleared. Then if the actor is added back into the
2349 // relayout container afterwards, the dirty flags would still be clear...
2350 // causing a relayout to be skipped. Here we force any actors added to the
2351 // container to be relayed out.
2352 DALI_LOG_TIMER_START(NegSizeTimer1);
2354 if(GetUseAssignedSize(Dimension::WIDTH))
2356 SetLayoutNegotiated(false, Dimension::WIDTH);
2358 if(GetUseAssignedSize(Dimension::HEIGHT))
2360 SetLayoutNegotiated(false, Dimension::HEIGHT);
2363 // Do the negotiation
2364 NegotiateDimensions(allocatedSize);
2366 // Set the actor size
2367 SetNegotiatedSize(container);
2369 // Negotiate down to children
2370 for(uint32_t i = 0, count = GetChildCount(); i < count; ++i)
2372 ActorPtr child = GetChildAt(i);
2374 // Forces children that have already been laid out to be relayed out
2375 // if they have assigned size during relayout.
2376 if(child->GetUseAssignedSize(Dimension::WIDTH))
2378 child->SetLayoutNegotiated(false, Dimension::WIDTH);
2379 child->SetLayoutDirty(true, Dimension::WIDTH);
2382 if(child->GetUseAssignedSize(Dimension::HEIGHT))
2384 child->SetLayoutNegotiated(false, Dimension::HEIGHT);
2385 child->SetLayoutDirty(true, Dimension::HEIGHT);
2388 // Only relayout if required
2389 if(child->RelayoutRequired())
2391 container.Add(Dali::Actor(child.Get()), mTargetSize.GetVectorXY());
2394 DALI_LOG_TIMER_END(NegSizeTimer1, gLogRelayoutFilter, Debug::Concise, "NegotiateSize() took: ");
2397 void Actor::SetUseAssignedSize(bool use, Dimension::Type dimension)
2401 mRelayoutData->SetUseAssignedSize(use, dimension);
2405 bool Actor::GetUseAssignedSize(Dimension::Type dimension) const
2407 return mRelayoutData && mRelayoutData->GetUseAssignedSize(dimension);
2410 void Actor::RelayoutRequest(Dimension::Type dimension)
2412 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
2413 if(relayoutController)
2415 Dali::Actor self(this);
2416 relayoutController->RequestRelayout(self, dimension);
2420 void Actor::SetPreferredSize(const Vector2& size)
2424 // If valid width or height, then set the resize policy to FIXED
2425 // 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,
2426 // then change to FIXED as well
2428 if(size.width > 0.0f || GetResizePolicy(Dimension::WIDTH) == ResizePolicy::DEFAULT)
2430 SetResizePolicy(ResizePolicy::FIXED, Dimension::WIDTH);
2433 if(size.height > 0.0f || GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::DEFAULT)
2435 SetResizePolicy(ResizePolicy::FIXED, Dimension::HEIGHT);
2438 mRelayoutData->preferredSize = size;
2440 mUseAnimatedSize = AnimatedSizeFlag::CLEAR;
2445 Vector2 Actor::GetPreferredSize() const
2449 return Vector2(mRelayoutData->preferredSize);
2452 return Relayouter::DEFAULT_PREFERRED_SIZE;
2455 void Actor::SetMinimumSize(float size, Dimension::Type dimension)
2457 EnsureRelayouter().SetMinimumSize(size, dimension);
2461 float Actor::GetMinimumSize(Dimension::Type dimension) const
2465 return mRelayoutData->GetMinimumSize(dimension);
2468 return 0.0f; // Default
2471 void Actor::SetMaximumSize(float size, Dimension::Type dimension)
2473 EnsureRelayouter().SetMaximumSize(size, dimension);
2477 float Actor::GetMaximumSize(Dimension::Type dimension) const
2481 return mRelayoutData->GetMaximumSize(dimension);
2484 return FLT_MAX; // Default
2487 void Actor::SetVisibleInternal(bool visible, SendMessage::Type sendMessage)
2489 if(mVisible != visible)
2491 if(sendMessage == SendMessage::TRUE)
2493 // node is being used in a separate thread; queue a message to set the value & base value
2494 SceneGraph::NodePropertyMessage<bool>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible);
2499 // Emit the signal on this actor and all its children
2500 EmitVisibilityChangedSignalRecursively(this, visible, DevelActor::VisibilityChange::SELF);
2504 void Actor::SetSiblingOrder(uint32_t order)
2508 ActorContainer& siblings = *(mParent->mChildren);
2509 uint32_t currentOrder = GetSiblingOrder();
2511 if(order != currentOrder)
2517 else if(order < siblings.size() - 1)
2519 if(order > currentOrder)
2521 RaiseAbove(*siblings[order]);
2525 LowerBelow(*siblings[order]);
2536 uint32_t Actor::GetSiblingOrder() const
2542 ActorContainer& siblings = *(mParent->mChildren);
2543 for(std::size_t i = 0; i < siblings.size(); ++i)
2545 if(siblings[i] == this)
2547 order = static_cast<uint32_t>(i);
2556 void Actor::RequestRebuildDepthTree()
2562 mScene->RequestRebuildDepthTree();
2571 ActorContainer& siblings = *(mParent->mChildren);
2572 if(siblings.back() != this) // If not already at end
2574 for(std::size_t i = 0; i < siblings.size(); ++i)
2576 if(siblings[i] == this)
2579 ActorPtr next = siblings[i + 1];
2580 siblings[i + 1] = this;
2587 Dali::Actor handle(this);
2588 mParent->mChildOrderChangedSignal.Emit(handle);
2590 RequestRebuildDepthTree();
2594 DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
2602 ActorContainer& siblings = *(mParent->mChildren);
2603 if(siblings.front() != this) // If not already at beginning
2605 for(std::size_t i = 1; i < siblings.size(); ++i)
2607 if(siblings[i] == this)
2609 // Swap with previous
2610 ActorPtr previous = siblings[i - 1];
2611 siblings[i - 1] = this;
2612 siblings[i] = previous;
2618 Dali::Actor handle(this);
2619 mParent->mChildOrderChangedSignal.Emit(handle);
2621 RequestRebuildDepthTree();
2625 DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
2629 void Actor::RaiseToTop()
2633 ActorContainer& siblings = *(mParent->mChildren);
2634 if(siblings.back() != this) // If not already at end
2636 auto iter = std::find(siblings.begin(), siblings.end(), this);
2637 if(iter != siblings.end())
2639 siblings.erase(iter);
2640 siblings.push_back(ActorPtr(this));
2644 Dali::Actor handle(this);
2645 mParent->mChildOrderChangedSignal.Emit(handle);
2647 RequestRebuildDepthTree();
2651 DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
2655 void Actor::LowerToBottom()
2659 ActorContainer& siblings = *(mParent->mChildren);
2660 if(siblings.front() != this) // If not already at bottom,
2662 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2664 auto iter = std::find(siblings.begin(), siblings.end(), this);
2665 if(iter != siblings.end())
2667 siblings.erase(iter);
2668 siblings.insert(siblings.begin(), thisPtr);
2672 Dali::Actor handle(this);
2673 mParent->mChildOrderChangedSignal.Emit(handle);
2675 RequestRebuildDepthTree();
2679 DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
2683 void Actor::RaiseAbove(Internal::Actor& target)
2687 ActorContainer& siblings = *(mParent->mChildren);
2688 if(siblings.back() != this && target.mParent == mParent) // If not already at top
2690 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2692 auto targetIter = std::find(siblings.begin(), siblings.end(), &target);
2693 auto thisIter = std::find(siblings.begin(), siblings.end(), this);
2694 if(thisIter < targetIter)
2696 siblings.erase(thisIter);
2697 // Erasing early invalidates the targetIter. (Conversely, inserting first may also
2698 // invalidate thisIter)
2699 targetIter = std::find(siblings.begin(), siblings.end(), &target);
2701 siblings.insert(targetIter, thisPtr);
2704 Dali::Actor handle(this);
2705 mParent->mChildOrderChangedSignal.Emit(handle);
2707 RequestRebuildDepthTree();
2712 DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
2716 void Actor::LowerBelow(Internal::Actor& target)
2720 ActorContainer& siblings = *(mParent->mChildren);
2721 if(siblings.front() != this && target.mParent == mParent) // If not already at bottom
2723 ActorPtr thisPtr(this); // ensure this actor remains referenced.
2725 auto targetIter = std::find(siblings.begin(), siblings.end(), &target);
2726 auto thisIter = std::find(siblings.begin(), siblings.end(), this);
2728 if(thisIter > targetIter)
2730 siblings.erase(thisIter); // this only invalidates iterators at or after this point.
2731 siblings.insert(targetIter, thisPtr);
2734 Dali::Actor handle(this);
2735 mParent->mChildOrderChangedSignal.Emit(handle);
2737 RequestRebuildDepthTree();
2742 DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
2746 void Actor::SetInheritLayoutDirection(bool inherit)
2748 if(mInheritLayoutDirection != inherit)
2750 mInheritLayoutDirection = inherit;
2752 if(inherit && mParent)
2754 InheritLayoutDirectionRecursively(this, mParent->mLayoutDirection);
2759 void Actor::InheritLayoutDirectionRecursively(ActorPtr actor, Dali::LayoutDirection::Type direction, bool set)
2761 if(actor && (actor->mInheritLayoutDirection || set))
2763 if(actor->mLayoutDirection != direction)
2765 actor->mLayoutDirection = direction;
2766 actor->EmitLayoutDirectionChangedSignal(direction);
2767 actor->RelayoutRequest();
2770 if(actor->GetChildCount() > 0)
2772 for(const auto& child : actor->GetChildrenInternal())
2774 InheritLayoutDirectionRecursively(child, direction);
2780 void Actor::SetUpdateSizeHint(const Vector2& updateSizeHint)
2782 // node is being used in a separate thread; queue a message to set the value & base value
2783 SceneGraph::NodePropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mUpdateSizeHint, &AnimatableProperty<Vector3>::Bake, Vector3(updateSizeHint.width, updateSizeHint.height, 0.f));
2786 } // namespace Internal