2 * Copyright (c) 2023 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>
26 #include <dali/public-api/common/constants.h>
27 #include <dali/public-api/common/dali-common.h>
28 #include <dali/public-api/math/radian.h>
29 #include <dali/public-api/math/vector2.h>
30 #include <dali/public-api/math/vector3.h>
31 #include <dali/public-api/object/type-registry.h>
33 #include <dali/devel-api/actors/actor-devel.h>
34 #include <dali/devel-api/common/capabilities.h>
36 #include <dali/integration-api/debug.h>
37 #include <dali/integration-api/events/touch-integ.h>
39 #include <dali/internal/event/actors/actor-coords.h>
40 #include <dali/internal/event/actors/actor-parent.h>
41 #include <dali/internal/event/actors/actor-property-handler.h>
42 #include <dali/internal/event/actors/camera-actor-impl.h>
43 #include <dali/internal/event/common/event-thread-services.h>
44 #include <dali/internal/event/common/property-helper.h>
45 #include <dali/internal/event/common/scene-impl.h>
46 #include <dali/internal/event/common/stage-impl.h>
47 #include <dali/internal/event/common/thread-local-storage.h>
48 #include <dali/internal/event/common/type-info-impl.h>
49 #include <dali/internal/event/events/actor-gesture-data.h>
50 #include <dali/internal/event/render-tasks/render-task-impl.h>
51 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
52 #include <dali/internal/event/rendering/renderer-impl.h>
53 #include <dali/internal/update/manager/update-manager.h>
54 #include <dali/internal/update/nodes/node-messages.h>
55 #include <dali/public-api/size-negotiation/relayout-container.h>
57 using Dali::Internal::SceneGraph::AnimatableProperty;
58 using Dali::Internal::SceneGraph::Node;
59 using Dali::Internal::SceneGraph::PropertyBase;
61 #if defined(DEBUG_ENABLED)
62 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_DEPTH_TIMER");
69 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("updateAreaHint", VECTOR4, true, false, false, Dali::Actor::Property::UPDATE_AREA_HINT)
145 DALI_PROPERTY("siblingOrder", INTEGER, true, false, false, Dali::DevelActor::Property::SIBLING_ORDER)
146 DALI_PROPERTY("captureAllTouchAfterStart", BOOLEAN, true, false, false, Dali::DevelActor::Property::CAPTURE_ALL_TOUCH_AFTER_START)
147 DALI_PROPERTY("touchAreaOffset", RECTANGLE, true, false, false, Dali::DevelActor::Property::TOUCH_AREA_OFFSET)
148 DALI_PROPERTY("blendEquation", INTEGER, true, false, false, Dali::DevelActor::Property::BLEND_EQUATION)
149 DALI_PROPERTY("touchFocusable", BOOLEAN, true, false, false, Dali::DevelActor::Property::TOUCH_FOCUSABLE)
150 DALI_PROPERTY("keyboardFocusableChildren", BOOLEAN, true, false, false, Dali::DevelActor::Property::KEYBOARD_FOCUSABLE_CHILDREN)
151 DALI_PROPERTY("userInteractionEnabled", BOOLEAN, true, false, false, Dali::DevelActor::Property::USER_INTERACTION_ENABLED)
152 DALI_PROPERTY("allowOnlyOwnTouch", BOOLEAN, true, false, false, Dali::DevelActor::Property::ALLOW_ONLY_OWN_TOUCH)
153 DALI_PROPERTY("useTextureUpdateArea", BOOLEAN, true, false, false, Dali::DevelActor::Property::USE_TEXTURE_UPDATE_AREA)
154 DALI_PROPERTY_TABLE_END(DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperties)
158 static constexpr std::string_view SIGNAL_HOVERED = "hovered";
159 static constexpr std::string_view SIGNAL_WHEEL_EVENT = "wheelEvent";
160 static constexpr std::string_view SIGNAL_ON_SCENE = "onScene";
161 static constexpr std::string_view SIGNAL_OFF_SCENE = "offScene";
162 static constexpr std::string_view SIGNAL_ON_RELAYOUT = "onRelayout";
163 static constexpr std::string_view SIGNAL_TOUCHED = "touched";
164 static constexpr std::string_view SIGNAL_VISIBILITY_CHANGED = "visibilityChanged";
165 static constexpr std::string_view SIGNAL_LAYOUT_DIRECTION_CHANGED = "layoutDirectionChanged";
166 static constexpr std::string_view SIGNAL_CHILD_ADDED = "childAdded";
167 static constexpr std::string_view SIGNAL_CHILD_REMOVED = "childRemoved";
171 static constexpr std::string_view ACTION_SHOW = "show";
172 static constexpr std::string_view ACTION_HIDE = "hide";
174 BaseHandle CreateActor()
176 return Dali::Actor::New();
180 * Connects a callback function with the object's signals.
181 * @param[in] object The object providing the signal.
182 * @param[in] tracker Used to disconnect the signal.
183 * @param[in] signalName The signal to connect to.
184 * @param[in] functor A newly allocated FunctorDelegate.
185 * @return True if the signal was connected.
186 * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
188 static bool DoConnectSignal(BaseObject* object,
189 ConnectionTrackerInterface* tracker,
190 const std::string& signalName,
191 FunctorDelegate* functor)
193 bool connected(true);
194 Actor* actor = static_cast<Actor*>(object); // TypeRegistry guarantees that this is the correct type.
196 std::string_view name(signalName);
198 if(name == SIGNAL_HOVERED)
200 actor->HoveredSignal().Connect(tracker, functor);
202 else if(signalName == SIGNAL_WHEEL_EVENT)
204 actor->WheelEventSignal().Connect(tracker, functor);
206 else if(name == SIGNAL_ON_SCENE)
208 actor->OnSceneSignal().Connect(tracker, functor);
210 else if(name == SIGNAL_OFF_SCENE)
212 actor->OffSceneSignal().Connect(tracker, functor);
214 else if(name == SIGNAL_ON_RELAYOUT)
216 actor->OnRelayoutSignal().Connect(tracker, functor);
218 else if(name == SIGNAL_TOUCHED)
220 actor->TouchedSignal().Connect(tracker, functor);
222 else if(name == SIGNAL_VISIBILITY_CHANGED)
224 actor->VisibilityChangedSignal().Connect(tracker, functor);
226 else if(name == SIGNAL_LAYOUT_DIRECTION_CHANGED)
228 actor->LayoutDirectionChangedSignal().Connect(tracker, functor);
230 else if(name == SIGNAL_CHILD_ADDED)
232 actor->ChildAddedSignal().Connect(tracker, functor);
234 else if(name == SIGNAL_CHILD_REMOVED)
236 actor->ChildRemovedSignal().Connect(tracker, functor);
240 // signalName does not match any signal
248 * Performs actions as requested using the action name.
249 * @param[in] object The object on which to perform the action.
250 * @param[in] actionName The action to perform.
251 * @param[in] attributes The attributes with which to perfrom this action.
252 * @return true if the action was done.
254 bool DoAction(BaseObject* object,
255 const std::string& actionName,
256 const Property::Map& attributes)
259 Actor* actor = dynamic_cast<Actor*>(object);
263 std::string_view name(actionName);
264 if(name == ACTION_SHOW)
266 actor->SetVisible(true);
269 else if(name == ACTION_HIDE)
271 actor->SetVisible(false);
279 TypeRegistration mType(typeid(Dali::Actor), typeid(Dali::Handle), CreateActor, ActorDefaultProperties);
281 SignalConnectorType signalConnector2(mType, std::string(SIGNAL_HOVERED), &DoConnectSignal);
282 SignalConnectorType signalConnector3(mType, std::string(SIGNAL_WHEEL_EVENT), &DoConnectSignal);
283 SignalConnectorType signalConnector4(mType, std::string(SIGNAL_ON_SCENE), &DoConnectSignal);
284 SignalConnectorType signalConnector5(mType, std::string(SIGNAL_OFF_SCENE), &DoConnectSignal);
285 SignalConnectorType signalConnector6(mType, std::string(SIGNAL_ON_RELAYOUT), &DoConnectSignal);
286 SignalConnectorType signalConnector7(mType, std::string(SIGNAL_TOUCHED), &DoConnectSignal);
287 SignalConnectorType signalConnector8(mType, std::string(SIGNAL_VISIBILITY_CHANGED), &DoConnectSignal);
288 SignalConnectorType signalConnector9(mType, std::string(SIGNAL_LAYOUT_DIRECTION_CHANGED), &DoConnectSignal);
289 SignalConnectorType signalConnector10(mType, std::string(SIGNAL_CHILD_ADDED), &DoConnectSignal);
290 SignalConnectorType signalConnector11(mType, std::string(SIGNAL_CHILD_REMOVED), &DoConnectSignal);
292 TypeAction a1(mType, std::string(ACTION_SHOW), &DoAction);
293 TypeAction a2(mType, std::string(ACTION_HIDE), &DoAction);
295 /// Helper for emitting a signal
296 template<typename Signal, typename Event>
297 bool EmitConsumingSignal(Actor& actor, Signal& signal, const Event& event)
299 bool consumed = false;
303 Dali::Actor handle(&actor);
304 consumed = signal.Emit(handle, event);
310 /// Helper for emitting signals with multiple parameters
311 template<typename Signal, typename... Param>
312 void EmitSignal(Actor& actor, Signal& signal, Param... params)
316 Dali::Actor handle(&actor);
317 signal.Emit(handle, params...);
321 using ActorParentSiblingOrderMethod = void (ActorParent::*)(Actor&);
322 using ActorParentSiblingOrderMethodWithTarget = void (ActorParent::*)(Actor&, Actor&);
324 /// Helper to check and call actor sibling methods in ActorParent
325 void CheckParentAndCall(ActorParent* parent, Actor& actor, ActorParentSiblingOrderMethod memberFunction)
329 (parent->*memberFunction)(actor);
333 DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
337 /// Helper to check and call actor sibling methods with a target parameter in ActorParent
338 void CheckParentAndCall(ActorParent* parent, Actor& actor, Actor& target, ActorParentSiblingOrderMethodWithTarget memberFunction)
342 (parent->*memberFunction)(actor, target);
346 DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
350 } // unnamed namespace
352 ActorPtr Actor::New()
354 // pass a reference to actor, actor does not own its node
355 ActorPtr actor(new Actor(BASIC, *CreateNode()));
357 // Second-phase construction
363 const SceneGraph::Node* Actor::CreateNode()
365 // create node. Nodes are owned by the update manager
366 SceneGraph::Node* node = SceneGraph::Node::New();
367 OwnerPointer<SceneGraph::Node> transferOwnership(node);
368 Internal::ThreadLocalStorage* tls = Internal::ThreadLocalStorage::GetInternal();
370 DALI_ASSERT_ALWAYS(tls && "ThreadLocalStorage is null");
372 AddNodeMessage(tls->GetUpdateManager(), transferOwnership);
377 void Actor::SetName(std::string_view name)
379 mName = ConstString(name);
381 // ATTENTION: string for debug purposes is not thread safe.
382 DALI_LOG_SET_OBJECT_STRING(const_cast<SceneGraph::Node*>(&GetNode()), mName.GetCString());
385 uint32_t Actor::GetId() const
387 return GetNode().GetId();
390 Dali::Layer Actor::GetLayer()
394 // Short-circuit for Layer derived actors
397 layer = Dali::Layer(static_cast<Dali::Internal::Layer*>(this)); // static cast as we trust the flag
400 // Find the immediate Layer parent
401 for(Actor* parent = GetParent(); !layer && parent != nullptr; parent = parent->GetParent())
403 if(parent->IsLayer())
405 layer = Dali::Layer(static_cast<Dali::Internal::Layer*>(parent)); // static cast as we trust the flag
412 void Actor::Unparent()
416 // Remove this actor from the parent. The remove will put a relayout request in for
417 // the parent if required
418 mParent->Remove(*this);
419 // mParent is now NULL!
423 void Actor::SetParentOrigin(const Vector3& origin)
425 // node is being used in a separate thread; queue a message to set the value & base value
426 SetParentOriginMessage(GetEventThreadServices(), GetNode(), origin);
428 // Cache for event-thread access
431 // not allocated, check if different from default
432 if(ParentOrigin::DEFAULT != origin)
434 mParentOrigin = new Vector3(origin);
439 // check if different from current costs more than just set
440 *mParentOrigin = origin;
444 const Vector3& Actor::GetCurrentParentOrigin() const
446 // Cached for event-thread access
447 return (mParentOrigin) ? *mParentOrigin : ParentOrigin::DEFAULT;
450 void Actor::SetAnchorPoint(const Vector3& anchor)
452 // node is being used in a separate thread; queue a message to set the value & base value
453 SetAnchorPointMessage(GetEventThreadServices(), GetNode(), anchor);
455 // Cache for event-thread access
458 // not allocated, check if different from default
459 if(AnchorPoint::DEFAULT != anchor)
461 mAnchorPoint = new Vector3(anchor);
466 // check if different from current costs more than just set
467 *mAnchorPoint = anchor;
471 const Vector3& Actor::GetCurrentAnchorPoint() const
473 // Cached for event-thread access
474 return (mAnchorPoint) ? *mAnchorPoint : AnchorPoint::DEFAULT;
477 void Actor::SetPosition(float x, float y)
479 SetPosition(Vector3(x, y, 0.0f));
482 void Actor::SetPosition(float x, float y, float z)
484 SetPosition(Vector3(x, y, z));
487 void Actor::SetPosition(const Vector3& position)
489 mTargetPosition = position;
491 // node is being used in a separate thread; queue a message to set the value & base value
492 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position);
495 void Actor::SetX(float x)
497 mTargetPosition.x = x;
499 // node is being used in a separate thread; queue a message to set the value & base value
500 SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x);
503 void Actor::SetY(float y)
505 mTargetPosition.y = y;
507 // node is being used in a separate thread; queue a message to set the value & base value
508 SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y);
511 void Actor::SetZ(float z)
513 mTargetPosition.z = z;
515 // node is being used in a separate thread; queue a message to set the value & base value
516 SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z);
519 void Actor::TranslateBy(const Vector3& distance)
521 mTargetPosition += distance;
523 // node is being used in a separate thread; queue a message to set the value & base value
524 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance);
527 const Vector3& Actor::GetCurrentPosition() const
529 // node is being used in a separate thread; copy the value from the previous update
530 return GetNode().GetPosition(GetEventThreadServices().GetEventBufferIndex());
533 const Vector3& Actor::GetCurrentWorldPosition() const
535 // node is being used in a separate thread; copy the value from the previous update
536 return GetNode().GetWorldPosition(GetEventThreadServices().GetEventBufferIndex());
539 const Vector2 Actor::CalculateScreenPosition() const
543 if(mLayer3DParentsCount == 0)
545 // We can assume that this actor is under 2d layer. Use faster, but imprecise algorithm
546 return CalculateActorScreenPosition(*this);
550 return CalculateActorScreenPositionRenderTaskList(*this);
553 return Vector2::ZERO;
556 const Vector2 Actor::GetCurrentScreenPosition() const
560 BufferIndex bufferIndex = GetEventThreadServices().GetEventBufferIndex();
561 if(mLayer3DParentsCount == 0)
563 // We can assume that this actor is under 2d layer. Use faster, but imprecise algorithm
564 return CalculateCurrentActorScreenPosition(*this, bufferIndex);
568 return CalculateCurrentActorScreenPositionRenderTaskList(*this, bufferIndex);
571 return Vector2::ZERO;
574 void Actor::SetInheritPosition(bool inherit)
576 if(mInheritPosition != inherit)
578 // non animatable so keep local copy
579 mInheritPosition = inherit;
580 SetInheritPositionMessage(GetEventThreadServices(), GetNode(), inherit);
584 void Actor::SetOrientation(const Radian& angle, const Vector3& axis)
586 Vector3 normalizedAxis(axis.x, axis.y, axis.z);
587 normalizedAxis.Normalize();
589 Quaternion orientation(angle, normalizedAxis);
591 SetOrientation(orientation);
594 void Actor::SetOrientation(const Quaternion& orientation)
596 mTargetOrientation = orientation;
598 // node is being used in a separate thread; queue a message to set the value & base value
599 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation);
602 void Actor::RotateBy(const Radian& angle, const Vector3& axis)
604 RotateBy(Quaternion(angle, axis));
607 void Actor::RotateBy(const Quaternion& relativeRotation)
609 mTargetOrientation *= Quaternion(relativeRotation);
611 // node is being used in a separate thread; queue a message to set the value & base value
612 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation);
615 const Quaternion& Actor::GetCurrentOrientation() const
617 // node is being used in a separate thread; copy the value from the previous update
618 return GetNode().GetOrientation(GetEventThreadServices().GetEventBufferIndex());
621 const Quaternion& Actor::GetCurrentWorldOrientation() const
623 // node is being used in a separate thread; copy the value from the previous update
624 return GetNode().GetWorldOrientation(GetEventThreadServices().GetEventBufferIndex());
627 void Actor::SetScale(float scale)
629 SetScale(Vector3(scale, scale, scale));
632 void Actor::SetScale(float x, float y, float z)
634 SetScale(Vector3(x, y, z));
637 void Actor::SetScale(const Vector3& scale)
639 mTargetScale = scale;
641 // node is being used in a separate thread; queue a message to set the value & base value
642 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale);
645 void Actor::SetScaleX(float x)
649 // node is being used in a separate thread; queue a message to set the value & base value
650 SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x);
653 void Actor::SetScaleY(float y)
657 // node is being used in a separate thread; queue a message to set the value & base value
658 SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y);
661 void Actor::SetScaleZ(float z)
665 // node is being used in a separate thread; queue a message to set the value & base value
666 SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z);
669 void Actor::ScaleBy(const Vector3& relativeScale)
671 mTargetScale *= relativeScale;
673 // node is being used in a separate thread; queue a message to set the value & base value
674 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale);
677 const Vector3& Actor::GetCurrentScale() const
679 // node is being used in a separate thread; copy the value from the previous update
680 return GetNode().GetScale(GetEventThreadServices().GetEventBufferIndex());
683 const Vector3& Actor::GetCurrentWorldScale() const
685 // node is being used in a separate thread; copy the value from the previous update
686 return GetNode().GetWorldScale(GetEventThreadServices().GetEventBufferIndex());
689 void Actor::SetInheritScale(bool inherit)
691 if(mInheritScale != inherit)
693 // non animatable so keep local copy
694 mInheritScale = inherit;
695 // node is being used in a separate thread; queue a message to set the value
696 SetInheritScaleMessage(GetEventThreadServices(), GetNode(), inherit);
700 Matrix Actor::GetCurrentWorldMatrix() const
702 return GetNode().GetWorldMatrix(0);
705 void Actor::SetVisible(bool visible)
707 SetVisibleInternal(visible, SendMessage::TRUE);
710 bool Actor::IsVisible() const
712 // node is being used in a separate thread; copy the value from the previous update
713 return GetNode().IsVisible(GetEventThreadServices().GetEventBufferIndex());
716 void Actor::SetOpacity(float opacity)
718 mTargetColor.a = opacity;
720 // node is being used in a separate thread; queue a message to set the value & base value
721 SceneGraph::NodePropertyComponentMessage<Vector4>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeW, opacity);
723 RequestRenderingMessage(GetEventThreadServices().GetUpdateManager());
726 float Actor::GetCurrentOpacity() const
728 // node is being used in a separate thread; copy the value from the previous update
729 return GetNode().GetOpacity(GetEventThreadServices().GetEventBufferIndex());
732 const Vector4& Actor::GetCurrentWorldColor() const
734 return GetNode().GetWorldColor(GetEventThreadServices().GetEventBufferIndex());
737 void Actor::SetColor(const Vector4& color)
739 mTargetColor = color;
741 // node is being used in a separate thread; queue a message to set the value & base value
742 SceneGraph::NodePropertyMessage<Vector4>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::Bake, color);
744 RequestRenderingMessage(GetEventThreadServices().GetUpdateManager());
747 void Actor::SetColorRed(float red)
749 mTargetColor.r = red;
751 // node is being used in a separate thread; queue a message to set the value & base value
752 SceneGraph::NodePropertyComponentMessage<Vector4>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeX, red);
754 RequestRenderingMessage(GetEventThreadServices().GetUpdateManager());
757 void Actor::SetColorGreen(float green)
759 mTargetColor.g = green;
761 // node is being used in a separate thread; queue a message to set the value & base value
762 SceneGraph::NodePropertyComponentMessage<Vector4>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeY, green);
764 RequestRenderingMessage(GetEventThreadServices().GetUpdateManager());
767 void Actor::SetColorBlue(float blue)
769 mTargetColor.b = blue;
771 // node is being used in a separate thread; queue a message to set the value & base value
772 SceneGraph::NodePropertyComponentMessage<Vector4>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeZ, blue);
774 RequestRenderingMessage(GetEventThreadServices().GetUpdateManager());
777 const Vector4& Actor::GetCurrentColor() const
779 // node is being used in a separate thread; copy the value from the previous update
780 return GetNode().GetColor(GetEventThreadServices().GetEventBufferIndex());
783 void Actor::SetInheritOrientation(bool inherit)
785 if(mInheritOrientation != inherit)
787 // non animatable so keep local copy
788 mInheritOrientation = inherit;
789 // node is being used in a separate thread; queue a message to set the value
790 SetInheritOrientationMessage(GetEventThreadServices(), GetNode(), inherit);
794 void Actor::SetSizeModeFactor(const Vector3& factor)
796 mSizer.SetSizeModeFactor(factor);
799 const Vector3& Actor::GetSizeModeFactor() const
801 return mSizer.GetSizeModeFactor();
804 void Actor::SetColorMode(ColorMode colorMode)
806 // non animatable so keep local copy
807 mColorMode = colorMode;
808 // node is being used in a separate thread; queue a message to set the value
809 SetColorModeMessage(GetEventThreadServices(), GetNode(), colorMode);
812 void Actor::SetSize(float width, float height)
814 SetSize(Vector2(width, height));
817 void Actor::SetSize(float width, float height, float depth)
819 SetSize(Vector3(width, height, depth));
822 void Actor::SetSize(const Vector2& size)
824 SetSize(Vector3(size.width, size.height, 0.f));
827 void Actor::SetSize(const Vector3& size)
829 mSizer.SetSize(size);
832 void Actor::SetWidth(float width)
834 mSizer.SetWidth(width);
837 void Actor::SetHeight(float height)
839 mSizer.SetHeight(height);
842 void Actor::SetDepth(float depth)
844 mSizer.SetDepth(depth);
845 // node is being used in a separate thread; queue a message to set the value & base value
846 SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth);
849 Vector3 Actor::GetTargetSize() const
851 return mSizer.GetTargetSize();
854 const Vector3& Actor::GetCurrentSize() const
856 // node is being used in a separate thread; copy the value from the previous update
857 return GetNode().GetSize(GetEventThreadServices().GetEventBufferIndex());
860 Vector3 Actor::GetNaturalSize() const
862 // It is up to deriving classes to return the appropriate natural size
863 return Vector3(0.0f, 0.0f, 0.0f);
866 void Actor::SetResizePolicy(ResizePolicy::Type policy, Dimension::Type dimension)
868 mSizer.SetResizePolicy(policy, dimension);
871 ResizePolicy::Type Actor::GetResizePolicy(Dimension::Type dimension) const
873 return mSizer.GetResizePolicy(dimension);
876 void Actor::SetRelayoutEnabled(bool relayoutEnabled)
878 mSizer.SetRelayoutEnabled(relayoutEnabled);
881 bool Actor::IsRelayoutEnabled() const
883 return mSizer.IsRelayoutEnabled();
886 void Actor::SetLayoutDirty(bool dirty, Dimension::Type dimension)
888 mSizer.SetLayoutDirty(dirty, dimension);
891 bool Actor::IsLayoutDirty(Dimension::Type dimension) const
893 return mSizer.IsLayoutDirty(dimension);
896 bool Actor::RelayoutPossible(Dimension::Type dimension) const
898 return mSizer.RelayoutPossible(dimension);
901 bool Actor::RelayoutRequired(Dimension::Type dimension) const
903 return mSizer.RelayoutRequired(dimension);
906 uint32_t Actor::AddRenderer(Renderer& renderer)
910 mRenderers = new RendererContainer(GetEventThreadServices());
912 return mRenderers->Add(GetNode(), renderer, mIsBlendEquationSet, mBlendEquation);
915 uint32_t Actor::GetRendererCount() const
917 return mRenderers ? mRenderers->GetCount() : 0u;
920 RendererPtr Actor::GetRendererAt(uint32_t index)
922 return mRenderers ? mRenderers->GetRendererAt(index) : nullptr;
925 void Actor::RemoveRenderer(Renderer& renderer)
929 mRenderers->Remove(GetNode(), renderer);
933 void Actor::RemoveRenderer(uint32_t index)
937 mRenderers->Remove(GetNode(), index);
941 void Actor::SetBlendEquation(DevelBlendEquation::Type blendEquation)
943 if(Dali::Capabilities::IsBlendEquationSupported(blendEquation))
945 if(mBlendEquation != blendEquation)
947 mBlendEquation = blendEquation;
950 mRenderers->SetBlending(blendEquation);
953 mIsBlendEquationSet = true;
957 DALI_LOG_ERROR("Invalid blend equation is entered.\n");
961 DevelBlendEquation::Type Actor::GetBlendEquation() const
963 return mBlendEquation;
966 void Actor::SetTransparent(bool transparent)
968 SetTransparentMessage(GetEventThreadServices(), GetNode(), transparent);
971 bool Actor::IsTransparent() const
973 return GetNode().IsTransparent();
976 void Actor::SetDrawMode(DrawMode::Type drawMode)
978 // this flag is not animatable so keep the value
979 mDrawMode = drawMode;
981 // node is being used in a separate thread; queue a message to set the value
982 SetDrawModeMessage(GetEventThreadServices(), GetNode(), drawMode);
985 bool Actor::ScreenToLocal(float& localX, float& localY, float screenX, float screenY) const
987 return mScene && OnScene() && ConvertScreenToLocalRenderTaskList(mScene->GetRenderTaskList(), GetNode().GetWorldMatrix(0), GetCurrentSize(), localX, localY, screenX, screenY);
990 bool Actor::ScreenToLocal(const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY) const
992 return OnScene() && ConvertScreenToLocalRenderTask(renderTask, GetNode().GetWorldMatrix(0), GetCurrentSize(), localX, localY, screenX, screenY);
995 bool Actor::ScreenToLocal(const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY) const
997 return OnScene() && ConvertScreenToLocal(viewMatrix, projectionMatrix, GetNode().GetWorldMatrix(0), GetCurrentSize(), viewport, localX, localY, screenX, screenY);
1000 ActorGestureData& Actor::GetGestureData()
1002 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1003 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1004 if(nullptr == mGestureData)
1006 mGestureData = new ActorGestureData;
1008 return *mGestureData;
1011 bool Actor::IsGestureRequired(GestureType::Value type) const
1013 return mGestureData && mGestureData->IsGestureRequired(type);
1016 bool Actor::EmitInterceptTouchEventSignal(const Dali::TouchEvent& touch)
1018 return EmitConsumingSignal(*this, mInterceptTouchedSignal, touch);
1021 bool Actor::EmitTouchEventSignal(const Dali::TouchEvent& touch)
1023 return EmitConsumingSignal(*this, mTouchedSignal, touch);
1026 bool Actor::EmitHoverEventSignal(const Dali::HoverEvent& event)
1028 return EmitConsumingSignal(*this, mHoveredSignal, event);
1031 bool Actor::EmitWheelEventSignal(const Dali::WheelEvent& event)
1033 return EmitConsumingSignal(*this, mWheelEventSignal, event);
1036 void Actor::EmitVisibilityChangedSignal(bool visible, DevelActor::VisibilityChange::Type type)
1038 EmitSignal(*this, mVisibilityChangedSignal, visible, type);
1041 void Actor::EmitLayoutDirectionChangedSignal(LayoutDirection::Type type)
1043 EmitSignal(*this, mLayoutDirectionChangedSignal, type);
1046 bool Actor::EmitHitTestResultSignal(Integration::Point point, Vector2 hitPointLocal, uint32_t timeStamp)
1050 if(IsHitTestResultRequired())
1052 Dali::Actor handle(this);
1053 Integration::Point newPoint(point);
1054 newPoint.SetHitActor(handle);
1055 newPoint.SetLocalPosition(hitPointLocal);
1056 Dali::TouchEvent touchEvent = Dali::Integration::NewTouchEvent(timeStamp, newPoint);
1057 hit = mHitTestResultSignal.Emit(handle, touchEvent);
1062 DevelActor::ChildChangedSignalType& Actor::ChildAddedSignal()
1064 return mParentImpl.ChildAddedSignal();
1067 DevelActor::ChildChangedSignalType& Actor::ChildRemovedSignal()
1069 return mParentImpl.ChildRemovedSignal();
1072 DevelActor::ChildOrderChangedSignalType& Actor::ChildOrderChangedSignal()
1074 return mParentImpl.ChildOrderChangedSignal();
1077 Actor::Actor(DerivedType derivedType, const SceneGraph::Node& node)
1083 mRenderers(nullptr),
1084 mParentOrigin(nullptr),
1085 mAnchorPoint(nullptr),
1086 mGestureData(nullptr),
1087 mInterceptTouchedSignal(),
1090 mWheelEventSignal(),
1093 mOnRelayoutSignal(),
1094 mVisibilityChangedSignal(),
1095 mLayoutDirectionChangedSignal(),
1096 mHitTestResultSignal(),
1097 mTargetOrientation(Quaternion::IDENTITY),
1098 mTargetColor(Color::WHITE),
1099 mTargetPosition(Vector3::ZERO),
1100 mTargetScale(Vector3::ONE),
1101 mTouchAreaOffset(0, 0, 0, 0),
1105 mLayer3DParentsCount(0),
1106 mIsRoot(ROOT_LAYER == derivedType),
1107 mIsLayer(LAYER == derivedType || ROOT_LAYER == derivedType),
1110 mLeaveRequired(false),
1111 mKeyboardFocusable(false),
1112 mKeyboardFocusableChildren(true),
1113 mTouchFocusable(false),
1114 mOnSceneSignalled(false),
1115 mInheritPosition(true),
1116 mInheritOrientation(true),
1117 mInheritScale(true),
1118 mPositionUsesAnchorPoint(true),
1120 mInheritLayoutDirection(true),
1121 mCaptureAllTouchAfterStart(false),
1122 mIsBlendEquationSet(false),
1123 mNeedGesturePropagation(false),
1124 mUserInteractionEnabled(true),
1125 mAllowOnlyOwnTouch(false),
1126 mUseTextureUpdateArea(false),
1127 mLayoutDirection(LayoutDirection::LEFT_TO_RIGHT),
1128 mDrawMode(DrawMode::NORMAL),
1129 mColorMode(Node::DEFAULT_COLOR_MODE),
1130 mClippingMode(ClippingMode::DISABLED),
1131 mBlendEquation(DevelBlendEquation::ADD)
1135 void Actor::Initialize()
1139 GetEventThreadServices().RegisterObject(this);
1144 // Remove mParent pointers from children even if we're destroying core,
1145 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1148 // Guard to allow handle destruction after Core has been destroyed
1149 if(EventThreadServices::IsCoreRunning())
1153 // Detach all renderers before delete container.
1154 mRenderers->RemoveAll(GetNode());
1157 // Root layer will destroy its node in its own destructor
1160 DestroyNodeMessage(GetEventThreadServices().GetUpdateManager(), GetNode());
1162 GetEventThreadServices().UnregisterObject(this);
1165 // Cleanup renderer list
1168 // Cleanup optional gesture data
1169 delete mGestureData;
1171 // Cleanup optional parent origin and anchor
1172 delete mParentOrigin;
1173 delete mAnchorPoint;
1176 void Actor::Add(Actor& child, bool notify)
1178 mParentImpl.Add(child, notify);
1181 void Actor::Remove(Actor& child, bool notify)
1183 mParentImpl.Remove(child, notify);
1186 void Actor::SwitchParent(Actor& newParent)
1188 if(this == &newParent)
1190 DALI_LOG_ERROR("Cannot add actor to itself");
1194 if(!this->OnScene() || !newParent.OnScene())
1196 DALI_LOG_ERROR("Both of current parent and new parent must be on Scene");
1200 newParent.Add(*this, false);
1203 uint32_t Actor::GetChildCount() const
1205 return mParentImpl.GetChildCount();
1208 ActorPtr Actor::GetChildAt(uint32_t index) const
1210 return mParentImpl.GetChildAt(index);
1213 ActorContainer& Actor::GetChildrenInternal()
1215 return mParentImpl.GetChildrenInternal();
1218 ActorPtr Actor::FindChildByName(ConstString actorName)
1220 return mParentImpl.FindChildByName(actorName);
1223 ActorPtr Actor::FindChildById(const uint32_t id)
1225 return mParentImpl.FindChildById(id);
1228 void Actor::UnparentChildren()
1230 mParentImpl.UnparentChildren();
1233 void Actor::ConnectToScene(uint32_t parentDepth, uint32_t layer3DParentsCount, bool notify)
1235 // This container is used instead of walking the Actor hierarchy.
1236 // It protects us when the Actor hierarchy is modified during OnSceneConnectionExternal callbacks.
1237 ActorContainer connectionList;
1241 mScene->RequestRebuildDepthTree();
1244 // This stage is not interrupted by user callbacks.
1245 mParentImpl.RecursiveConnectToScene(connectionList, layer3DParentsCount, parentDepth + 1);
1247 // Notify applications about the newly connected actors.
1248 for(const auto& actor : connectionList)
1250 actor->NotifyStageConnection(notify);
1257 * This method is called when the Actor is connected to the Stage.
1258 * The parent must have added its Node to the scene-graph.
1259 * The child must connect its Node to the parent's Node.
1260 * This is recursive; the child calls ConnectToScene() for its children.
1262 void Actor::ConnectToSceneGraph()
1264 DALI_ASSERT_DEBUG(mParent != NULL);
1266 // Reparent Node in next Update
1267 ConnectNodeMessage(GetEventThreadServices().GetUpdateManager(), GetParent()->GetNode(), GetNode());
1269 // Request relayout on all actors that are added to the scenegraph
1272 // Notification for Object::Observers
1276 void Actor::NotifyStageConnection(bool notify)
1278 // Actors can be removed (in a callback), before the on-stage stage is reported.
1279 // The actor may also have been reparented, in which case mOnSceneSignalled will be true.
1280 if(OnScene() && !mOnSceneSignalled)
1284 // Notification for external (CustomActor) derived classes
1285 OnSceneConnectionExternal(mDepth);
1287 if(!mOnSceneSignal.Empty())
1289 Dali::Actor handle(this);
1290 mOnSceneSignal.Emit(handle);
1294 // Guard against Remove during callbacks
1297 mOnSceneSignalled = true; // signal required next time Actor is removed
1302 void Actor::DisconnectFromStage(bool notify)
1304 // This container is used instead of walking the Actor hierachy.
1305 // It protects us when the Actor hierachy is modified during OnSceneDisconnectionExternal callbacks.
1306 ActorContainer disconnectionList;
1310 mScene->RequestRebuildDepthTree();
1313 // This stage is not interrupted by user callbacks
1314 mParentImpl.RecursiveDisconnectFromScene(disconnectionList);
1316 // Notify applications about the newly disconnected actors.
1317 for(const auto& actor : disconnectionList)
1319 actor->NotifyStageDisconnection(notify);
1324 * This method is called by an actor or its parent, before a node removal message is sent.
1325 * This is recursive; the child calls DisconnectFromStage() for its children.
1327 void Actor::DisconnectFromSceneGraph()
1329 // Notification for Object::Observers
1330 OnSceneObjectRemove();
1333 void Actor::NotifyStageDisconnection(bool notify)
1335 // Actors can be added (in a callback), before the off-stage state is reported.
1336 // Also if the actor was added & removed before mOnSceneSignalled was set, then we don't notify here.
1337 // only do this step if there is a stage, i.e. Core is not being shut down
1338 if(EventThreadServices::IsCoreRunning() && !OnScene() && mOnSceneSignalled)
1342 // Notification for external (CustomeActor) derived classes
1343 OnSceneDisconnectionExternal();
1345 if(!mOffSceneSignal.Empty())
1347 Dali::Actor handle(this);
1348 mOffSceneSignal.Emit(handle);
1352 // Guard against Add during callbacks
1355 mOnSceneSignalled = false; // signal required next time Actor is added
1360 bool Actor::IsNodeConnected() const
1362 return OnScene() && (IsRoot() || GetNode().GetParent());
1365 // This method initiates traversal of the actor tree using depth-first
1366 // traversal to set a depth index based on traversal order. It sends a
1367 // single message to update manager to update all the actor's nodes in
1368 // this tree with the depth index. The sceneGraphNodeDepths vector's
1369 // elements are ordered by depth, and could be used to reduce sorting
1370 // in the update thread.
1371 void Actor::RebuildDepthTree()
1373 DALI_LOG_TIMER_START(depthTimer);
1375 // Vector of scene-graph nodes and their depths to send to UpdateManager
1376 // in a single message
1377 OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths(new SceneGraph::NodeDepths());
1379 int32_t depthIndex = 1;
1380 mParentImpl.DepthTraverseActorTree(sceneGraphNodeDepths, depthIndex);
1382 SetDepthIndicesMessage(GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths);
1383 DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
1386 void Actor::SetDefaultProperty(Property::Index index, const Property::Value& property)
1388 PropertyHandler::SetDefaultProperty(*this, index, property);
1391 // TODO: This method needs to be removed
1392 void Actor::SetSceneGraphProperty(Property::Index index, const PropertyMetadata& entry, const Property::Value& value)
1394 PropertyHandler::SetSceneGraphProperty(index, entry, value, GetEventThreadServices(), GetNode());
1397 Property::Value Actor::GetDefaultProperty(Property::Index index) const
1399 Property::Value value;
1401 if(!GetCachedPropertyValue(index, value))
1403 // If property value is not stored in the event-side, then it must be a scene-graph only property
1404 GetCurrentPropertyValue(index, value);
1410 Property::Value Actor::GetDefaultPropertyCurrentValue(Property::Index index) const
1412 Property::Value value;
1414 if(!GetCurrentPropertyValue(index, value))
1416 // If unable to retrieve scene-graph property value, then it must be an event-side only property
1417 GetCachedPropertyValue(index, value);
1423 void Actor::OnNotifyDefaultPropertyAnimation(Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType)
1425 PropertyHandler::OnNotifyDefaultPropertyAnimation(*this, animation, index, value, animationType);
1428 const PropertyBase* Actor::GetSceneObjectAnimatableProperty(Property::Index index) const
1430 const PropertyBase* property = PropertyHandler::GetSceneObjectAnimatableProperty(index, GetNode());
1433 // not our property, ask base
1434 property = Object::GetSceneObjectAnimatableProperty(index);
1440 const PropertyInputImpl* Actor::GetSceneObjectInputProperty(Property::Index index) const
1442 const PropertyInputImpl* property = PropertyHandler::GetSceneObjectInputProperty(index, GetNode());
1445 // reuse animatable property getter as animatable properties are inputs as well
1446 // animatable property chains back to Object::GetSceneObjectInputProperty() so all properties get covered
1447 property = GetSceneObjectAnimatableProperty(index);
1453 int32_t Actor::GetPropertyComponentIndex(Property::Index index) const
1455 int32_t componentIndex = PropertyHandler::GetPropertyComponentIndex(index);
1456 if(Property::INVALID_COMPONENT_INDEX == componentIndex)
1459 componentIndex = Object::GetPropertyComponentIndex(index);
1462 return componentIndex;
1465 const SceneGraph::Node& Actor::GetNode() const
1467 return *static_cast<const SceneGraph::Node*>(mUpdateObject);
1472 CheckParentAndCall(mParent, *this, &ActorParent::RaiseChild);
1477 CheckParentAndCall(mParent, *this, &ActorParent::LowerChild);
1480 void Actor::RaiseToTop()
1482 CheckParentAndCall(mParent, *this, &ActorParent::RaiseChildToTop);
1485 void Actor::LowerToBottom()
1487 CheckParentAndCall(mParent, *this, &ActorParent::LowerChildToBottom);
1490 void Actor::RaiseAbove(Internal::Actor& target)
1492 CheckParentAndCall(mParent, *this, target, &ActorParent::RaiseChildAbove);
1495 void Actor::LowerBelow(Internal::Actor& target)
1497 CheckParentAndCall(mParent, *this, target, &ActorParent::LowerChildBelow);
1500 void Actor::SetParent(ActorParent* parent, bool notify)
1504 DALI_ASSERT_ALWAYS(!mParent && "Actor cannot have 2 parents");
1507 Actor* parentActor = static_cast<Actor*>(parent);
1508 mScene = parentActor->mScene;
1510 if(!EventThreadServices::IsShuttingDown() && // Don't emit signals or send messages during Core destruction
1511 parentActor->OnScene())
1513 // Instruct each actor to create a corresponding node in the scene graph
1514 ConnectToScene(parentActor->GetHierarchyDepth(), parentActor->GetLayer3DParentCount(), notify);
1517 // Resolve the name and index for the child properties if any
1518 ResolveChildProperties();
1520 else // parent being set to NULL
1522 DALI_ASSERT_ALWAYS(mParent != nullptr && "Actor should have a parent");
1526 if(!EventThreadServices::IsShuttingDown() && // Don't emit signals or send messages during Core destruction
1529 // Disconnect the Node & its children from the scene-graph.
1530 DisconnectNodeMessage(GetEventThreadServices().GetUpdateManager(), GetNode());
1532 // Instruct each actor to discard pointers to the scene-graph
1533 DisconnectFromStage(notify);
1540 Rect<> Actor::CalculateScreenExtents() const
1542 if(mLayer3DParentsCount == 0)
1544 // We can assume that this actor is under 2d layer. Use faster, but imprecise algorithm
1545 return CalculateActorScreenExtents(*this);
1549 return CalculateActorScreenExtentsRenderTaskList(*this);
1553 Rect<> Actor::CalculateCurrentScreenExtents() const
1555 if(mLayer3DParentsCount == 0)
1557 // We can assume that this actor is under 2d layer. Use faster, but imprecise algorithm
1558 BufferIndex bufferIndex = GetEventThreadServices().GetEventBufferIndex();
1559 return CalculateCurrentActorScreenExtents(*this, bufferIndex);
1563 BufferIndex bufferIndex = GetEventThreadServices().GetEventBufferIndex();
1564 return CalculateCurrentActorScreenExtentsRenderTaskList(*this, bufferIndex);
1568 Vector3 Actor::GetAnchorPointForPosition() const
1570 return (mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT);
1573 bool Actor::GetCachedPropertyValue(Property::Index index, Property::Value& value) const
1575 return PropertyHandler::GetCachedPropertyValue(*this, index, value);
1578 bool Actor::GetCurrentPropertyValue(Property::Index index, Property::Value& value) const
1580 return PropertyHandler::GetCurrentPropertyValue(*this, index, value);
1583 bool Actor::RelayoutDependentOnParent(Dimension::Type dimension)
1585 return mSizer.RelayoutDependentOnParent(dimension);
1588 bool Actor::RelayoutDependentOnChildren(Dimension::Type dimension)
1590 return mSizer.RelayoutDependentOnChildrenBase(dimension);
1593 bool Actor::RelayoutDependentOnDimension(Dimension::Type dimension, Dimension::Type dependentDimension)
1595 return mSizer.RelayoutDependentOnDimension(dimension, dependentDimension);
1598 void Actor::SetPadding(const Vector2& padding, Dimension::Type dimension)
1600 mSizer.SetPadding(padding, dimension);
1603 Vector2 Actor::GetPadding(Dimension::Type dimension) const
1605 return mSizer.GetPadding(dimension);
1608 void Actor::SetLayoutNegotiated(bool negotiated, Dimension::Type dimension)
1610 mSizer.SetLayoutNegotiated(negotiated, dimension);
1613 bool Actor::IsLayoutNegotiated(Dimension::Type dimension) const
1615 return mSizer.IsLayoutNegotiated(dimension);
1618 float Actor::GetHeightForWidthBase(float width)
1620 // Can be overridden in derived class
1621 return mSizer.GetHeightForWidthBase(width);
1624 float Actor::GetWidthForHeightBase(float height)
1626 // Can be overridden in derived class
1627 return mSizer.GetWidthForHeightBase(height);
1630 float Actor::CalculateChildSizeBase(const Dali::Actor& child, Dimension::Type dimension)
1632 // Can be overridden in derived class
1633 return mSizer.CalculateChildSizeBase(child, dimension);
1636 bool Actor::RelayoutDependentOnChildrenBase(Dimension::Type dimension)
1638 return mSizer.RelayoutDependentOnChildrenBase(dimension);
1641 float Actor::CalculateChildSize(const Dali::Actor& child, Dimension::Type dimension)
1643 // Can be overridden in derived class
1644 return mSizer.CalculateChildSizeBase(child, dimension);
1647 float Actor::GetHeightForWidth(float width)
1649 // Can be overridden in derived class
1650 return mSizer.GetHeightForWidthBase(width);
1653 float Actor::GetWidthForHeight(float height)
1655 // Can be overridden in derived class
1656 return mSizer.GetWidthForHeightBase(height);
1659 float Actor::GetRelayoutSize(Dimension::Type dimension) const
1661 return mSizer.GetRelayoutSize(dimension);
1664 void Actor::NegotiateSize(const Vector2& allocatedSize, RelayoutContainer& container)
1666 mSizer.NegotiateSize(allocatedSize, container);
1669 void Actor::RelayoutRequest(Dimension::Type dimension)
1671 mSizer.RelayoutRequest(dimension);
1674 void Actor::SetMinimumSize(float size, Dimension::Type dimension)
1676 mSizer.SetMinimumSize(size, dimension);
1679 float Actor::GetMinimumSize(Dimension::Type dimension) const
1681 return mSizer.GetMinimumSize(dimension);
1684 void Actor::SetMaximumSize(float size, Dimension::Type dimension)
1686 mSizer.SetMaximumSize(size, dimension);
1689 float Actor::GetMaximumSize(Dimension::Type dimension) const
1691 return mSizer.GetMaximumSize(dimension);
1694 void Actor::SetVisibleInternal(bool visible, SendMessage::Type sendMessage)
1696 if(mVisible != visible)
1698 if(sendMessage == SendMessage::TRUE)
1700 // node is being used in a separate thread; queue a message to set the value & base value
1701 SceneGraph::NodePropertyMessage<bool>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible);
1703 RequestRenderingMessage(GetEventThreadServices().GetUpdateManager());
1708 // Emit the signal on this actor and all its children
1709 mParentImpl.EmitVisibilityChangedSignalRecursively(visible, DevelActor::VisibilityChange::SELF);
1713 void Actor::SetSiblingOrderOfChild(Actor& child, uint32_t order)
1715 mParentImpl.SetSiblingOrderOfChild(child, order);
1718 uint32_t Actor::GetSiblingOrderOfChild(const Actor& child) const
1720 return mParentImpl.GetSiblingOrderOfChild(child);
1723 void Actor::RaiseChild(Actor& child)
1725 mParentImpl.RaiseChild(child);
1728 void Actor::LowerChild(Actor& child)
1730 mParentImpl.LowerChild(child);
1733 void Actor::RaiseChildToTop(Actor& child)
1735 mParentImpl.RaiseChildToTop(child);
1738 void Actor::LowerChildToBottom(Actor& child)
1740 mParentImpl.LowerChildToBottom(child);
1743 void Actor::RaiseChildAbove(Actor& child, Actor& target)
1745 mParentImpl.RaiseChildAbove(child, target);
1748 void Actor::LowerChildBelow(Actor& child, Actor& target)
1750 mParentImpl.LowerChildBelow(child, target);
1753 void Actor::SetInheritLayoutDirection(bool inherit)
1755 if(mInheritLayoutDirection != inherit)
1757 mInheritLayoutDirection = inherit;
1759 if(inherit && mParent)
1761 mParentImpl.InheritLayoutDirectionRecursively(GetParent()->mLayoutDirection);
1766 void Actor::SetUpdateAreaHint(const Vector4& updateAreaHint)
1768 // node is being used in a separate thread; queue a message to set the value & base value
1769 SetUpdateAreaHintMessage(GetEventThreadServices(), GetNode(), updateAreaHint);
1772 } // namespace Internal