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/public-api/common/constants.h>
28 #include <dali/public-api/common/dali-common.h>
29 #include <dali/public-api/math/radian.h>
30 #include <dali/public-api/math/vector2.h>
31 #include <dali/public-api/math/vector3.h>
32 #include <dali/public-api/object/type-registry.h>
34 #include <dali/devel-api/actors/actor-devel.h>
35 #include <dali/devel-api/common/capabilities.h>
37 #include <dali/integration-api/debug.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/actor-relayouter.h>
43 #include <dali/internal/event/actors/camera-actor-impl.h>
44 #include <dali/internal/event/common/event-thread-services.h>
45 #include <dali/internal/event/common/property-helper.h>
46 #include <dali/internal/event/common/scene-impl.h>
47 #include <dali/internal/event/common/stage-impl.h>
48 #include <dali/internal/event/common/thread-local-storage.h>
49 #include <dali/internal/event/common/type-info-impl.h>
50 #include <dali/internal/event/events/actor-gesture-data.h>
51 #include <dali/internal/event/render-tasks/render-task-impl.h>
52 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
53 #include <dali/internal/event/rendering/renderer-impl.h>
54 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
55 #include <dali/internal/update/manager/update-manager.h>
56 #include <dali/internal/update/nodes/node-messages.h>
58 using Dali::Internal::SceneGraph::AnimatableProperty;
59 using Dali::Internal::SceneGraph::Node;
60 using Dali::Internal::SceneGraph::PropertyBase;
62 #if defined(DEBUG_ENABLED)
63 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_DEPTH_TIMER");
70 namespace // unnamed namespace
75 * We want to discourage the use of property strings (minimize string comparisons),
76 * particularly for the default properties.
77 * Name Type writable animatable constraint-input enum for index-checking
79 DALI_PROPERTY_TABLE_BEGIN
80 DALI_PROPERTY("parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN)
81 DALI_PROPERTY("parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X)
82 DALI_PROPERTY("parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y)
83 DALI_PROPERTY("parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z)
84 DALI_PROPERTY("anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT)
85 DALI_PROPERTY("anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X)
86 DALI_PROPERTY("anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y)
87 DALI_PROPERTY("anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z)
88 DALI_PROPERTY("size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE)
89 DALI_PROPERTY("sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH)
90 DALI_PROPERTY("sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT)
91 DALI_PROPERTY("sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH)
92 DALI_PROPERTY("position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION)
93 DALI_PROPERTY("positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X)
94 DALI_PROPERTY("positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y)
95 DALI_PROPERTY("positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z)
96 DALI_PROPERTY("worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION)
97 DALI_PROPERTY("worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X)
98 DALI_PROPERTY("worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y)
99 DALI_PROPERTY("worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z)
100 DALI_PROPERTY("orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION)
101 DALI_PROPERTY("worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION)
102 DALI_PROPERTY("scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE)
103 DALI_PROPERTY("scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X)
104 DALI_PROPERTY("scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y)
105 DALI_PROPERTY("scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z)
106 DALI_PROPERTY("worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE)
107 DALI_PROPERTY("visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE)
108 DALI_PROPERTY("color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR)
109 DALI_PROPERTY("colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED)
110 DALI_PROPERTY("colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN)
111 DALI_PROPERTY("colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE)
112 DALI_PROPERTY("colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA)
113 DALI_PROPERTY("worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR)
114 DALI_PROPERTY("worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX)
115 DALI_PROPERTY("name", STRING, true, false, false, Dali::Actor::Property::NAME)
116 DALI_PROPERTY("sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE)
117 DALI_PROPERTY("leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED)
118 DALI_PROPERTY("inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION)
119 DALI_PROPERTY("inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE)
120 DALI_PROPERTY("colorMode", INTEGER, true, false, false, Dali::Actor::Property::COLOR_MODE)
121 DALI_PROPERTY("drawMode", INTEGER, true, false, false, Dali::Actor::Property::DRAW_MODE)
122 DALI_PROPERTY("sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR)
123 DALI_PROPERTY("widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY)
124 DALI_PROPERTY("heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY)
125 DALI_PROPERTY("sizeScalePolicy", INTEGER, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY)
126 DALI_PROPERTY("widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT)
127 DALI_PROPERTY("heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH)
128 DALI_PROPERTY("padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING)
129 DALI_PROPERTY("minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE)
130 DALI_PROPERTY("maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE)
131 DALI_PROPERTY("inheritPosition", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_POSITION)
132 DALI_PROPERTY("clippingMode", STRING, true, false, false, Dali::Actor::Property::CLIPPING_MODE)
133 DALI_PROPERTY("layoutDirection", STRING, true, false, false, Dali::Actor::Property::LAYOUT_DIRECTION)
134 DALI_PROPERTY("inheritLayoutDirection", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION)
135 DALI_PROPERTY("opacity", FLOAT, true, true, true, Dali::Actor::Property::OPACITY)
136 DALI_PROPERTY("screenPosition", VECTOR2, false, false, false, Dali::Actor::Property::SCREEN_POSITION)
137 DALI_PROPERTY("positionUsesAnchorPoint", BOOLEAN, true, false, false, Dali::Actor::Property::POSITION_USES_ANCHOR_POINT)
138 DALI_PROPERTY("culled", BOOLEAN, false, false, true, Dali::Actor::Property::CULLED)
139 DALI_PROPERTY("id", INTEGER, false, false, false, Dali::Actor::Property::ID)
140 DALI_PROPERTY("hierarchyDepth", INTEGER, false, false, false, Dali::Actor::Property::HIERARCHY_DEPTH)
141 DALI_PROPERTY("isRoot", BOOLEAN, false, false, false, Dali::Actor::Property::IS_ROOT)
142 DALI_PROPERTY("isLayer", BOOLEAN, false, false, false, Dali::Actor::Property::IS_LAYER)
143 DALI_PROPERTY("connectedToScene", BOOLEAN, false, false, false, Dali::Actor::Property::CONNECTED_TO_SCENE)
144 DALI_PROPERTY("keyboardFocusable", BOOLEAN, true, false, false, Dali::Actor::Property::KEYBOARD_FOCUSABLE)
145 DALI_PROPERTY("siblingOrder", INTEGER, true, false, false, Dali::DevelActor::Property::SIBLING_ORDER)
146 DALI_PROPERTY("updateSizeHint", VECTOR2, true, false, false, Dali::DevelActor::Property::UPDATE_SIZE_HINT)
147 DALI_PROPERTY("captureAllTouchAfterStart", BOOLEAN, true, false, false, Dali::DevelActor::Property::CAPTURE_ALL_TOUCH_AFTER_START)
148 DALI_PROPERTY("touchAreaOffset", RECTANGLE, true, false, false, Dali::DevelActor::Property::TOUCH_AREA_OFFSET)
149 DALI_PROPERTY("blendEquation", INTEGER, true, false, false, Dali::DevelActor::Property::BLEND_EQUATION)
150 DALI_PROPERTY("touchFocusable", BOOLEAN, true, false, false, Dali::DevelActor::Property::TOUCH_FOCUSABLE)
151 DALI_PROPERTY("keyboardFocusableChildren", BOOLEAN, true, false, false, Dali::DevelActor::Property::KEYBOARD_FOCUSABLE_CHILDREN)
152 DALI_PROPERTY_TABLE_END(DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperties)
156 static constexpr std::string_view SIGNAL_HOVERED = "hovered";
157 static constexpr std::string_view SIGNAL_WHEEL_EVENT = "wheelEvent";
158 static constexpr std::string_view SIGNAL_ON_SCENE = "onScene";
159 static constexpr std::string_view SIGNAL_OFF_SCENE = "offScene";
160 static constexpr std::string_view SIGNAL_ON_RELAYOUT = "onRelayout";
161 static constexpr std::string_view SIGNAL_TOUCHED = "touched";
162 static constexpr std::string_view SIGNAL_VISIBILITY_CHANGED = "visibilityChanged";
163 static constexpr std::string_view SIGNAL_LAYOUT_DIRECTION_CHANGED = "layoutDirectionChanged";
164 static constexpr std::string_view SIGNAL_CHILD_ADDED = "childAdded";
165 static constexpr std::string_view SIGNAL_CHILD_REMOVED = "childRemoved";
169 static constexpr std::string_view ACTION_SHOW = "show";
170 static constexpr std::string_view ACTION_HIDE = "hide";
172 BaseHandle CreateActor()
174 return Dali::Actor::New();
178 * Connects a callback function with the object's signals.
179 * @param[in] object The object providing the signal.
180 * @param[in] tracker Used to disconnect the signal.
181 * @param[in] signalName The signal to connect to.
182 * @param[in] functor A newly allocated FunctorDelegate.
183 * @return True if the signal was connected.
184 * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
186 static bool DoConnectSignal(BaseObject* object,
187 ConnectionTrackerInterface* tracker,
188 const std::string& signalName,
189 FunctorDelegate* functor)
191 bool connected(true);
192 Actor* actor = static_cast<Actor*>(object); // TypeRegistry guarantees that this is the correct type.
194 std::string_view name(signalName);
196 if(name == SIGNAL_HOVERED)
198 actor->HoveredSignal().Connect(tracker, functor);
200 else if(signalName == SIGNAL_WHEEL_EVENT)
202 actor->WheelEventSignal().Connect(tracker, functor);
204 else if(name == SIGNAL_ON_SCENE)
206 actor->OnSceneSignal().Connect(tracker, functor);
208 else if(name == SIGNAL_OFF_SCENE)
210 actor->OffSceneSignal().Connect(tracker, functor);
212 else if(name == SIGNAL_ON_RELAYOUT)
214 actor->OnRelayoutSignal().Connect(tracker, functor);
216 else if(name == SIGNAL_TOUCHED)
218 actor->TouchedSignal().Connect(tracker, functor);
220 else if(name == SIGNAL_VISIBILITY_CHANGED)
222 actor->VisibilityChangedSignal().Connect(tracker, functor);
224 else if(name == SIGNAL_LAYOUT_DIRECTION_CHANGED)
226 actor->LayoutDirectionChangedSignal().Connect(tracker, functor);
228 else if(name == SIGNAL_CHILD_ADDED)
230 actor->ChildAddedSignal().Connect(tracker, functor);
232 else if(name == SIGNAL_CHILD_REMOVED)
234 actor->ChildRemovedSignal().Connect(tracker, functor);
238 // signalName does not match any signal
246 * Performs actions as requested using the action name.
247 * @param[in] object The object on which to perform the action.
248 * @param[in] actionName The action to perform.
249 * @param[in] attributes The attributes with which to perfrom this action.
250 * @return true if the action was done.
252 bool DoAction(BaseObject* object,
253 const std::string& actionName,
254 const Property::Map& attributes)
257 Actor* actor = dynamic_cast<Actor*>(object);
261 std::string_view name(actionName);
262 if(name == ACTION_SHOW)
264 actor->SetVisible(true);
267 else if(name == ACTION_HIDE)
269 actor->SetVisible(false);
277 TypeRegistration mType(typeid(Dali::Actor), typeid(Dali::Handle), CreateActor, ActorDefaultProperties);
279 SignalConnectorType signalConnector2(mType, std::string(SIGNAL_HOVERED), &DoConnectSignal);
280 SignalConnectorType signalConnector3(mType, std::string(SIGNAL_WHEEL_EVENT), &DoConnectSignal);
281 SignalConnectorType signalConnector4(mType, std::string(SIGNAL_ON_SCENE), &DoConnectSignal);
282 SignalConnectorType signalConnector5(mType, std::string(SIGNAL_OFF_SCENE), &DoConnectSignal);
283 SignalConnectorType signalConnector6(mType, std::string(SIGNAL_ON_RELAYOUT), &DoConnectSignal);
284 SignalConnectorType signalConnector7(mType, std::string(SIGNAL_TOUCHED), &DoConnectSignal);
285 SignalConnectorType signalConnector8(mType, std::string(SIGNAL_VISIBILITY_CHANGED), &DoConnectSignal);
286 SignalConnectorType signalConnector9(mType, std::string(SIGNAL_LAYOUT_DIRECTION_CHANGED), &DoConnectSignal);
287 SignalConnectorType signalConnector10(mType, std::string(SIGNAL_CHILD_ADDED), &DoConnectSignal);
288 SignalConnectorType signalConnector11(mType, std::string(SIGNAL_CHILD_REMOVED), &DoConnectSignal);
290 TypeAction a1(mType, std::string(ACTION_SHOW), &DoAction);
291 TypeAction a2(mType, std::string(ACTION_HIDE), &DoAction);
294 * @brief Extract a given dimension from a Vector2
296 * @param[in] values The values to extract from
297 * @param[in] dimension The dimension to extract
298 * @return Return the value for the dimension
300 constexpr float GetDimensionValue(const Vector2& values, Dimension::Type dimension)
304 case Dimension::WIDTH:
308 case Dimension::HEIGHT:
310 return values.height;
321 * @brief Extract a given dimension from a Vector3
323 * @param[in] values The values to extract from
324 * @param[in] dimension The dimension to extract
325 * @return Return the value for the dimension
327 float GetDimensionValue(const Vector3& values, Dimension::Type dimension)
329 return GetDimensionValue(values.GetVectorXY(), dimension);
332 /// Helper for emitting a signal
333 template<typename Signal, typename Event>
334 bool EmitConsumingSignal(Actor& actor, Signal& signal, const Event& event)
336 bool consumed = false;
340 Dali::Actor handle(&actor);
341 consumed = signal.Emit(handle, event);
347 /// Helper for emitting signals with multiple parameters
348 template<typename Signal, typename... Param>
349 void EmitSignal(Actor& actor, Signal& signal, Param... params)
353 Dali::Actor handle(&actor);
354 signal.Emit(handle, params...);
358 using ActorParentSiblingOrderMethod = void (ActorParent::*)(Actor&);
359 using ActorParentSiblingOrderMethodWithTarget = void (ActorParent::*)(Actor&, Actor&);
361 /// Helper to check and call actor sibling methods in ActorParent
362 void CheckParentAndCall(ActorParent* parent, Actor& actor, ActorParentSiblingOrderMethod memberFunction)
366 (parent->*memberFunction)(actor);
370 DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
374 /// Helper to check and call actor sibling methods with a target parameter in ActorParent
375 void CheckParentAndCall(ActorParent* parent, Actor& actor, Actor& target, ActorParentSiblingOrderMethodWithTarget memberFunction)
379 (parent->*memberFunction)(actor, target);
383 DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
387 } // unnamed namespace
389 ActorPtr Actor::New()
391 // pass a reference to actor, actor does not own its node
392 ActorPtr actor(new Actor(BASIC, *CreateNode()));
394 // Second-phase construction
400 const SceneGraph::Node* Actor::CreateNode()
402 // create node. Nodes are owned by the update manager
403 SceneGraph::Node* node = SceneGraph::Node::New();
404 OwnerPointer<SceneGraph::Node> transferOwnership(node);
405 Internal::ThreadLocalStorage* tls = Internal::ThreadLocalStorage::GetInternal();
407 DALI_ASSERT_ALWAYS(tls && "ThreadLocalStorage is null");
409 AddNodeMessage(tls->GetUpdateManager(), transferOwnership);
414 void Actor::SetName(std::string_view name)
416 mName = ConstString(name);
418 // ATTENTION: string for debug purposes is not thread safe.
419 DALI_LOG_SET_OBJECT_STRING(const_cast<SceneGraph::Node*>(&GetNode()), mName.GetCString());
422 uint32_t Actor::GetId() const
424 return GetNode().GetId();
427 Dali::Layer Actor::GetLayer()
431 // Short-circuit for Layer derived actors
434 layer = Dali::Layer(static_cast<Dali::Internal::Layer*>(this)); // static cast as we trust the flag
437 // Find the immediate Layer parent
438 for(Actor* parent = GetParent(); !layer && parent != nullptr; parent = parent->GetParent())
440 if(parent->IsLayer())
442 layer = Dali::Layer(static_cast<Dali::Internal::Layer*>(parent)); // static cast as we trust the flag
449 void Actor::Unparent()
453 // Remove this actor from the parent. The remove will put a relayout request in for
454 // the parent if required
455 mParent->Remove(*this);
456 // mParent is now NULL!
460 void Actor::SetParentOrigin(const Vector3& origin)
462 // node is being used in a separate thread; queue a message to set the value & base value
463 SetParentOriginMessage(GetEventThreadServices(), GetNode(), origin);
465 // Cache for event-thread access
468 // not allocated, check if different from default
469 if(ParentOrigin::DEFAULT != origin)
471 mParentOrigin = new Vector3(origin);
476 // check if different from current costs more than just set
477 *mParentOrigin = origin;
481 const Vector3& Actor::GetCurrentParentOrigin() const
483 // Cached for event-thread access
484 return (mParentOrigin) ? *mParentOrigin : ParentOrigin::DEFAULT;
487 void Actor::SetAnchorPoint(const Vector3& anchor)
489 // node is being used in a separate thread; queue a message to set the value & base value
490 SetAnchorPointMessage(GetEventThreadServices(), GetNode(), anchor);
492 // Cache for event-thread access
495 // not allocated, check if different from default
496 if(AnchorPoint::DEFAULT != anchor)
498 mAnchorPoint = new Vector3(anchor);
503 // check if different from current costs more than just set
504 *mAnchorPoint = anchor;
508 const Vector3& Actor::GetCurrentAnchorPoint() const
510 // Cached for event-thread access
511 return (mAnchorPoint) ? *mAnchorPoint : AnchorPoint::DEFAULT;
514 void Actor::SetPosition(float x, float y)
516 SetPosition(Vector3(x, y, 0.0f));
519 void Actor::SetPosition(float x, float y, float z)
521 SetPosition(Vector3(x, y, z));
524 void Actor::SetPosition(const Vector3& position)
526 mTargetPosition = position;
528 // node is being used in a separate thread; queue a message to set the value & base value
529 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position);
532 void Actor::SetX(float x)
534 mTargetPosition.x = x;
536 // node is being used in a separate thread; queue a message to set the value & base value
537 SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x);
540 void Actor::SetY(float y)
542 mTargetPosition.y = y;
544 // node is being used in a separate thread; queue a message to set the value & base value
545 SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y);
548 void Actor::SetZ(float z)
550 mTargetPosition.z = z;
552 // node is being used in a separate thread; queue a message to set the value & base value
553 SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z);
556 void Actor::TranslateBy(const Vector3& distance)
558 mTargetPosition += distance;
560 // node is being used in a separate thread; queue a message to set the value & base value
561 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance);
564 const Vector3& Actor::GetCurrentPosition() const
566 // node is being used in a separate thread; copy the value from the previous update
567 return GetNode().GetPosition(GetEventThreadServices().GetEventBufferIndex());
570 const Vector3& Actor::GetCurrentWorldPosition() const
572 // node is being used in a separate thread; copy the value from the previous update
573 return GetNode().GetWorldPosition(GetEventThreadServices().GetEventBufferIndex());
576 const Vector2 Actor::GetCurrentScreenPosition() const
578 if(mScene && OnScene())
580 Vector3 worldPosition = GetNode().GetWorldPosition(GetEventThreadServices().GetEventBufferIndex());
581 Vector3 cameraPosition = mScene->GetDefaultCameraActor().GetNode().GetWorldPosition(GetEventThreadServices().GetEventBufferIndex());
582 worldPosition -= cameraPosition;
584 Vector3 actorSize = GetCurrentSize() * GetCurrentWorldScale();
585 Vector2 halfSceneSize(mScene->GetSize() * 0.5f); // World position origin is center of scene
586 Vector3 halfActorSize(actorSize * 0.5f);
587 Vector3 anchorPointOffSet = halfActorSize - actorSize * (mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT);
589 return Vector2(halfSceneSize.width + worldPosition.x - anchorPointOffSet.x,
590 halfSceneSize.height + worldPosition.y - anchorPointOffSet.y);
593 return Vector2::ZERO;
596 void Actor::SetInheritPosition(bool inherit)
598 if(mInheritPosition != inherit)
600 // non animatable so keep local copy
601 mInheritPosition = inherit;
602 SetInheritPositionMessage(GetEventThreadServices(), GetNode(), inherit);
606 void Actor::SetOrientation(const Radian& angle, const Vector3& axis)
608 Vector3 normalizedAxis(axis.x, axis.y, axis.z);
609 normalizedAxis.Normalize();
611 Quaternion orientation(angle, normalizedAxis);
613 SetOrientation(orientation);
616 void Actor::SetOrientation(const Quaternion& orientation)
618 mTargetOrientation = orientation;
620 // node is being used in a separate thread; queue a message to set the value & base value
621 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation);
624 void Actor::RotateBy(const Radian& angle, const Vector3& axis)
626 RotateBy(Quaternion(angle, axis));
629 void Actor::RotateBy(const Quaternion& relativeRotation)
631 mTargetOrientation *= Quaternion(relativeRotation);
633 // node is being used in a separate thread; queue a message to set the value & base value
634 SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation);
637 const Quaternion& Actor::GetCurrentOrientation() const
639 // node is being used in a separate thread; copy the value from the previous update
640 return GetNode().GetOrientation(GetEventThreadServices().GetEventBufferIndex());
643 const Quaternion& Actor::GetCurrentWorldOrientation() const
645 // node is being used in a separate thread; copy the value from the previous update
646 return GetNode().GetWorldOrientation(GetEventThreadServices().GetEventBufferIndex());
649 void Actor::SetScale(float scale)
651 SetScale(Vector3(scale, scale, scale));
654 void Actor::SetScale(float x, float y, float z)
656 SetScale(Vector3(x, y, z));
659 void Actor::SetScale(const Vector3& scale)
661 mTargetScale = scale;
663 // node is being used in a separate thread; queue a message to set the value & base value
664 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale);
667 void Actor::SetScaleX(float x)
671 // node is being used in a separate thread; queue a message to set the value & base value
672 SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x);
675 void Actor::SetScaleY(float y)
679 // node is being used in a separate thread; queue a message to set the value & base value
680 SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y);
683 void Actor::SetScaleZ(float z)
687 // node is being used in a separate thread; queue a message to set the value & base value
688 SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z);
691 void Actor::ScaleBy(const Vector3& relativeScale)
693 mTargetScale *= relativeScale;
695 // node is being used in a separate thread; queue a message to set the value & base value
696 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale);
699 const Vector3& Actor::GetCurrentScale() const
701 // node is being used in a separate thread; copy the value from the previous update
702 return GetNode().GetScale(GetEventThreadServices().GetEventBufferIndex());
705 const Vector3& Actor::GetCurrentWorldScale() const
707 // node is being used in a separate thread; copy the value from the previous update
708 return GetNode().GetWorldScale(GetEventThreadServices().GetEventBufferIndex());
711 void Actor::SetInheritScale(bool inherit)
713 if(mInheritScale != inherit)
715 // non animatable so keep local copy
716 mInheritScale = inherit;
717 // node is being used in a separate thread; queue a message to set the value
718 SetInheritScaleMessage(GetEventThreadServices(), GetNode(), inherit);
722 Matrix Actor::GetCurrentWorldMatrix() const
724 return GetNode().GetWorldMatrix(0);
727 void Actor::SetVisible(bool visible)
729 SetVisibleInternal(visible, SendMessage::TRUE);
732 bool Actor::IsVisible() const
734 // node is being used in a separate thread; copy the value from the previous update
735 return GetNode().IsVisible(GetEventThreadServices().GetEventBufferIndex());
738 void Actor::SetOpacity(float opacity)
740 mTargetColor.a = opacity;
742 // node is being used in a separate thread; queue a message to set the value & base value
743 SceneGraph::NodePropertyComponentMessage<Vector4>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeW, opacity);
745 RequestRenderingMessage(GetEventThreadServices().GetUpdateManager());
748 float Actor::GetCurrentOpacity() const
750 // node is being used in a separate thread; copy the value from the previous update
751 return GetNode().GetOpacity(GetEventThreadServices().GetEventBufferIndex());
754 const Vector4& Actor::GetCurrentWorldColor() const
756 return GetNode().GetWorldColor(GetEventThreadServices().GetEventBufferIndex());
759 void Actor::SetColor(const Vector4& color)
761 mTargetColor = color;
763 // node is being used in a separate thread; queue a message to set the value & base value
764 SceneGraph::NodePropertyMessage<Vector4>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::Bake, color);
766 RequestRenderingMessage(GetEventThreadServices().GetUpdateManager());
769 void Actor::SetColorRed(float red)
771 mTargetColor.r = red;
773 // node is being used in a separate thread; queue a message to set the value & base value
774 SceneGraph::NodePropertyComponentMessage<Vector4>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeX, red);
776 RequestRenderingMessage(GetEventThreadServices().GetUpdateManager());
779 void Actor::SetColorGreen(float green)
781 mTargetColor.g = green;
783 // node is being used in a separate thread; queue a message to set the value & base value
784 SceneGraph::NodePropertyComponentMessage<Vector4>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeY, green);
786 RequestRenderingMessage(GetEventThreadServices().GetUpdateManager());
789 void Actor::SetColorBlue(float blue)
791 mTargetColor.b = blue;
793 // node is being used in a separate thread; queue a message to set the value & base value
794 SceneGraph::NodePropertyComponentMessage<Vector4>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeZ, blue);
796 RequestRenderingMessage(GetEventThreadServices().GetUpdateManager());
799 const Vector4& Actor::GetCurrentColor() const
801 // node is being used in a separate thread; copy the value from the previous update
802 return GetNode().GetColor(GetEventThreadServices().GetEventBufferIndex());
805 void Actor::SetInheritOrientation(bool inherit)
807 if(mInheritOrientation != inherit)
809 // non animatable so keep local copy
810 mInheritOrientation = inherit;
811 // node is being used in a separate thread; queue a message to set the value
812 SetInheritOrientationMessage(GetEventThreadServices(), GetNode(), inherit);
816 void Actor::SetSizeModeFactor(const Vector3& factor)
820 mRelayoutData->sizeModeFactor = factor;
823 const Vector3& Actor::GetSizeModeFactor() const
825 return mRelayoutData ? mRelayoutData->sizeModeFactor : Relayouter::DEFAULT_SIZE_MODE_FACTOR;
828 void Actor::SetColorMode(ColorMode colorMode)
830 // non animatable so keep local copy
831 mColorMode = colorMode;
832 // node is being used in a separate thread; queue a message to set the value
833 SetColorModeMessage(GetEventThreadServices(), GetNode(), colorMode);
836 void Actor::SetSize(float width, float height)
838 SetSize(Vector2(width, height));
841 void Actor::SetSize(float width, float height, float depth)
843 SetSize(Vector3(width, height, depth));
846 void Actor::SetSize(const Vector2& size)
848 SetSize(Vector3(size.width, size.height, 0.f));
851 void Actor::SetSizeInternal(const Vector2& size)
853 SetSizeInternal(Vector3(size.width, size.height, 0.f));
856 void Actor::SetSize(const Vector3& size)
858 if(IsRelayoutEnabled() && !mRelayoutData->insideRelayout)
860 // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
861 SetPreferredSize(size.GetVectorXY());
865 SetSizeInternal(size);
869 void Actor::SetSizeInternal(const Vector3& size)
871 // dont allow recursive loop
872 DALI_ASSERT_ALWAYS(!mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet");
873 // 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
874 Vector3 currentSize = GetCurrentSize();
876 if((fabsf(mTargetSize.width - size.width) > Math::MACHINE_EPSILON_1) ||
877 (fabsf(mTargetSize.height - size.height) > Math::MACHINE_EPSILON_1) ||
878 (fabsf(mTargetSize.depth - size.depth) > Math::MACHINE_EPSILON_1) ||
879 (fabsf(mTargetSize.width - currentSize.width) > Math::MACHINE_EPSILON_1) ||
880 (fabsf(mTargetSize.height - currentSize.height) > Math::MACHINE_EPSILON_1) ||
881 (fabsf(mTargetSize.depth - currentSize.depth) > Math::MACHINE_EPSILON_1))
885 // Update the preferred size after relayoutting
886 // It should be used in the next relayoutting
887 if(mUseAnimatedSize & AnimatedSizeFlag::WIDTH && mRelayoutData)
889 mRelayoutData->preferredSize.width = mAnimatedSize.width;
892 if(mUseAnimatedSize & AnimatedSizeFlag::HEIGHT && mRelayoutData)
894 mRelayoutData->preferredSize.height = mAnimatedSize.height;
897 // node is being used in a separate thread; queue a message to set the value & base value
898 SceneGraph::NodeTransformPropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize);
900 // Notification for derived classes
901 mInsideOnSizeSet = true;
902 OnSizeSet(mTargetSize);
903 mInsideOnSizeSet = false;
905 // Raise a relayout request if the flag is not locked
906 if(mRelayoutData && !mRelayoutData->insideRelayout)
913 void Actor::SetWidth(float width)
915 if(IsRelayoutEnabled() && !mRelayoutData->insideRelayout)
917 SetResizePolicy(ResizePolicy::FIXED, Dimension::WIDTH);
918 mRelayoutData->preferredSize.width = width;
922 mTargetSize.width = width;
924 // node is being used in a separate thread; queue a message to set the value & base value
925 SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width);
928 mUseAnimatedSize &= ~AnimatedSizeFlag::WIDTH;
933 void Actor::SetHeight(float height)
935 if(IsRelayoutEnabled() && !mRelayoutData->insideRelayout)
937 SetResizePolicy(ResizePolicy::FIXED, Dimension::HEIGHT);
938 mRelayoutData->preferredSize.height = height;
942 mTargetSize.height = height;
944 // node is being used in a separate thread; queue a message to set the value & base value
945 SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height);
948 mUseAnimatedSize &= ~AnimatedSizeFlag::HEIGHT;
953 void Actor::SetDepth(float depth)
955 mTargetSize.depth = depth;
957 mUseAnimatedSize &= ~AnimatedSizeFlag::DEPTH;
959 // node is being used in a separate thread; queue a message to set the value & base value
960 SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth);
963 Vector3 Actor::GetTargetSize() const
965 Vector3 size = mTargetSize;
967 if(mUseAnimatedSize & AnimatedSizeFlag::WIDTH)
969 // Should return animated size if size is animated
970 size.width = mAnimatedSize.width;
974 // Should return preferred size if size is fixed as set by SetSize
975 if(GetResizePolicy(Dimension::WIDTH) == ResizePolicy::FIXED)
977 size.width = GetPreferredSize().width;
981 if(mUseAnimatedSize & AnimatedSizeFlag::HEIGHT)
983 size.height = mAnimatedSize.height;
987 if(GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::FIXED)
989 size.height = GetPreferredSize().height;
993 if(mUseAnimatedSize & AnimatedSizeFlag::DEPTH)
995 size.depth = mAnimatedSize.depth;
1001 const Vector3& Actor::GetCurrentSize() const
1003 // node is being used in a separate thread; copy the value from the previous update
1004 return GetNode().GetSize(GetEventThreadServices().GetEventBufferIndex());
1007 Vector3 Actor::GetNaturalSize() const
1009 // It is up to deriving classes to return the appropriate natural size
1010 return Vector3(0.0f, 0.0f, 0.0f);
1013 void Actor::SetResizePolicy(ResizePolicy::Type policy, Dimension::Type dimension)
1015 EnsureRelayouter().SetResizePolicy(policy, dimension, mTargetSize);
1017 OnSetResizePolicy(policy, dimension);
1019 // Trigger relayout on this control
1023 ResizePolicy::Type Actor::GetResizePolicy(Dimension::Type dimension) const
1025 return mRelayoutData ? mRelayoutData->GetResizePolicy(dimension) : ResizePolicy::DEFAULT;
1028 void Actor::SetSizeScalePolicy(SizeScalePolicy::Type policy)
1032 mRelayoutData->sizeSetPolicy = policy;
1034 // Trigger relayout on this control
1038 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
1040 return mRelayoutData ? mRelayoutData->sizeSetPolicy : Relayouter::DEFAULT_SIZE_SCALE_POLICY;
1043 void Actor::SetDimensionDependency(Dimension::Type dimension, Dimension::Type dependency)
1045 EnsureRelayouter().SetDimensionDependency(dimension, dependency);
1048 Dimension::Type Actor::GetDimensionDependency(Dimension::Type dimension) const
1050 return mRelayoutData ? mRelayoutData->GetDimensionDependency(dimension) : Dimension::ALL_DIMENSIONS;
1053 void Actor::SetRelayoutEnabled(bool relayoutEnabled)
1055 // If relayout data has not been allocated yet and the client is requesting
1056 // to disable it, do nothing
1057 if(mRelayoutData || relayoutEnabled)
1061 DALI_ASSERT_DEBUG(mRelayoutData && "mRelayoutData not created");
1063 mRelayoutData->relayoutEnabled = relayoutEnabled;
1067 bool Actor::IsRelayoutEnabled() const
1069 // Assume that if relayout data has not been allocated yet then
1070 // relayout is disabled
1071 return mRelayoutData && mRelayoutData->relayoutEnabled;
1074 void Actor::SetLayoutDirty(bool dirty, Dimension::Type dimension)
1076 EnsureRelayouter().SetLayoutDirty(dirty, dimension);
1079 bool Actor::IsLayoutDirty(Dimension::Type dimension) const
1081 return mRelayoutData && mRelayoutData->IsLayoutDirty(dimension);
1084 bool Actor::RelayoutPossible(Dimension::Type dimension) const
1086 return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty(dimension);
1089 bool Actor::RelayoutRequired(Dimension::Type dimension) const
1091 return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty(dimension);
1094 uint32_t Actor::AddRenderer(Renderer& renderer)
1098 mRenderers = new RendererContainer(GetEventThreadServices());
1100 return mRenderers->Add(GetNode(), renderer, mIsBlendEquationSet, mBlendEquation);
1103 uint32_t Actor::GetRendererCount() const
1105 return mRenderers ? mRenderers->GetCount() : 0u;
1108 RendererPtr Actor::GetRendererAt(uint32_t index)
1110 return mRenderers ? mRenderers->GetRendererAt(index) : nullptr;
1113 void Actor::RemoveRenderer(Renderer& renderer)
1117 mRenderers->Remove(GetNode(), renderer);
1121 void Actor::RemoveRenderer(uint32_t index)
1125 mRenderers->Remove(GetNode(), index);
1129 void Actor::SetBlendEquation(DevelBlendEquation::Type blendEquation)
1131 if(Dali::Capabilities::IsBlendEquationSupported(blendEquation))
1133 if(mBlendEquation != blendEquation)
1135 mBlendEquation = blendEquation;
1138 mRenderers->SetBlending(blendEquation);
1141 mIsBlendEquationSet = true;
1145 DALI_LOG_ERROR("Invalid blend equation is entered.\n");
1149 DevelBlendEquation::Type Actor::GetBlendEquation() const
1151 return mBlendEquation;
1154 void Actor::SetTransparent(bool transparent)
1156 SetTransparentMessage(GetEventThreadServices(), GetNode(), transparent);
1159 bool Actor::IsTransparent() const
1161 return GetNode().IsTransparent();
1164 void Actor::SetDrawMode(DrawMode::Type drawMode)
1166 // this flag is not animatable so keep the value
1167 mDrawMode = drawMode;
1169 // node is being used in a separate thread; queue a message to set the value
1170 SetDrawModeMessage(GetEventThreadServices(), GetNode(), drawMode);
1173 bool Actor::ScreenToLocal(float& localX, float& localY, float screenX, float screenY) const
1175 return mScene && OnScene() && ConvertScreenToLocalRenderTaskList(mScene->GetRenderTaskList(), GetNode().GetWorldMatrix(0), GetCurrentSize(), localX, localY, screenX, screenY);
1178 bool Actor::ScreenToLocal(const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY) const
1180 return OnScene() && ConvertScreenToLocalRenderTask(renderTask, GetNode().GetWorldMatrix(0), GetCurrentSize(), localX, localY, screenX, screenY);
1183 bool Actor::ScreenToLocal(const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY) const
1185 return OnScene() && ConvertScreenToLocal(viewMatrix, projectionMatrix, GetNode().GetWorldMatrix(0), GetCurrentSize(), viewport, localX, localY, screenX, screenY);
1188 ActorGestureData& Actor::GetGestureData()
1190 // Likely scenario is that once gesture-data is created for this actor, the actor will require
1191 // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1192 if(nullptr == mGestureData)
1194 mGestureData = new ActorGestureData;
1196 return *mGestureData;
1199 bool Actor::IsGestureRequired(GestureType::Value type) const
1201 return mGestureData && mGestureData->IsGestureRequired(type);
1204 bool Actor::EmitInterceptTouchEventSignal(const Dali::TouchEvent& touch)
1206 return EmitConsumingSignal(*this, mInterceptTouchedSignal, touch);
1209 bool Actor::EmitTouchEventSignal(const Dali::TouchEvent& touch)
1211 return EmitConsumingSignal(*this, mTouchedSignal, touch);
1214 bool Actor::EmitHoverEventSignal(const Dali::HoverEvent& event)
1216 return EmitConsumingSignal(*this, mHoveredSignal, event);
1219 bool Actor::EmitWheelEventSignal(const Dali::WheelEvent& event)
1221 return EmitConsumingSignal(*this, mWheelEventSignal, event);
1224 void Actor::EmitVisibilityChangedSignal(bool visible, DevelActor::VisibilityChange::Type type)
1226 EmitSignal(*this, mVisibilityChangedSignal, visible, type);
1229 void Actor::EmitLayoutDirectionChangedSignal(LayoutDirection::Type type)
1231 EmitSignal(*this, mLayoutDirectionChangedSignal, type);
1234 DevelActor::ChildChangedSignalType& Actor::ChildAddedSignal()
1236 return mParentImpl.ChildAddedSignal();
1239 DevelActor::ChildChangedSignalType& Actor::ChildRemovedSignal()
1241 return mParentImpl.ChildRemovedSignal();
1244 DevelActor::ChildOrderChangedSignalType& Actor::ChildOrderChangedSignal()
1246 return mParentImpl.ChildOrderChangedSignal();
1249 Actor::Actor(DerivedType derivedType, const SceneGraph::Node& node)
1254 mRenderers(nullptr),
1255 mParentOrigin(nullptr),
1256 mAnchorPoint(nullptr),
1257 mRelayoutData(nullptr),
1258 mGestureData(nullptr),
1259 mInterceptTouchedSignal(),
1262 mWheelEventSignal(),
1265 mOnRelayoutSignal(),
1266 mVisibilityChangedSignal(),
1267 mLayoutDirectionChangedSignal(),
1268 mTargetOrientation(Quaternion::IDENTITY),
1269 mTargetColor(Color::WHITE),
1270 mTargetSize(Vector3::ZERO),
1271 mTargetPosition(Vector3::ZERO),
1272 mTargetScale(Vector3::ONE),
1273 mAnimatedSize(Vector3::ZERO),
1274 mTouchAreaOffset(0, 0, 0, 0),
1278 mUseAnimatedSize(AnimatedSizeFlag::CLEAR),
1279 mIsRoot(ROOT_LAYER == derivedType),
1280 mIsLayer(LAYER == derivedType || ROOT_LAYER == derivedType),
1283 mLeaveRequired(false),
1284 mKeyboardFocusable(false),
1285 mKeyboardFocusableChildren(true),
1286 mTouchFocusable(false),
1287 mOnSceneSignalled(false),
1288 mInsideOnSizeSet(false),
1289 mInheritPosition(true),
1290 mInheritOrientation(true),
1291 mInheritScale(true),
1292 mPositionUsesAnchorPoint(true),
1294 mInheritLayoutDirection(true),
1295 mCaptureAllTouchAfterStart(false),
1296 mIsBlendEquationSet(false),
1297 mNeedGesturePropagation(false),
1298 mLayoutDirection(LayoutDirection::LEFT_TO_RIGHT),
1299 mDrawMode(DrawMode::NORMAL),
1300 mColorMode(Node::DEFAULT_COLOR_MODE),
1301 mClippingMode(ClippingMode::DISABLED),
1302 mBlendEquation(DevelBlendEquation::ADD)
1306 void Actor::Initialize()
1310 GetEventThreadServices().RegisterObject(this);
1315 // Remove mParent pointers from children even if we're destroying core,
1316 // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1320 // Guard to allow handle destruction after Core has been destroyed
1321 if(EventThreadServices::IsCoreRunning())
1323 // Root layer will destroy its node in its own destructor
1326 DestroyNodeMessage(GetEventThreadServices().GetUpdateManager(), GetNode());
1328 GetEventThreadServices().UnregisterObject(this);
1332 // Cleanup optional gesture data
1333 delete mGestureData;
1335 // Cleanup optional parent origin and anchor
1336 delete mParentOrigin;
1337 delete mAnchorPoint;
1339 // Delete optional relayout data
1340 delete mRelayoutData;
1343 void Actor::Add(Actor& child, bool notify)
1345 mParentImpl.Add(child, notify);
1348 void Actor::Remove(Actor& child, bool notify)
1350 mParentImpl.Remove(child, notify);
1353 void Actor::SwitchParent(Actor& newParent)
1355 if(this == &newParent)
1357 DALI_LOG_ERROR("Cannot add actor to itself");
1361 if(!this->OnScene() || !newParent.OnScene())
1363 DALI_LOG_ERROR("Both of current parent and new parent must be on Scene");
1367 newParent.Add(*this, false);
1370 uint32_t Actor::GetChildCount() const
1372 return mParentImpl.GetChildCount();
1375 ActorPtr Actor::GetChildAt(uint32_t index) const
1377 return mParentImpl.GetChildAt(index);
1380 ActorContainer& Actor::GetChildrenInternal()
1382 return mParentImpl.GetChildrenInternal();
1385 ActorPtr Actor::FindChildByName(ConstString actorName)
1387 return mParentImpl.FindChildByName(actorName);
1390 ActorPtr Actor::FindChildById(const uint32_t id)
1392 return mParentImpl.FindChildById(id);
1395 void Actor::UnparentChildren()
1397 mParentImpl.UnparentChildren();
1400 void Actor::ConnectToScene(uint32_t parentDepth, bool notify)
1402 // This container is used instead of walking the Actor hierarchy.
1403 // It protects us when the Actor hierarchy is modified during OnSceneConnectionExternal callbacks.
1404 ActorContainer connectionList;
1408 mScene->RequestRebuildDepthTree();
1411 // This stage is not interrupted by user callbacks.
1412 mParentImpl.RecursiveConnectToScene(connectionList, parentDepth + 1);
1414 // Notify applications about the newly connected actors.
1415 for(const auto& actor : connectionList)
1417 actor->NotifyStageConnection(notify);
1424 * This method is called when the Actor is connected to the Stage.
1425 * The parent must have added its Node to the scene-graph.
1426 * The child must connect its Node to the parent's Node.
1427 * This is recursive; the child calls ConnectToScene() for its children.
1429 void Actor::ConnectToSceneGraph()
1431 DALI_ASSERT_DEBUG(mParent != NULL);
1433 // Reparent Node in next Update
1434 ConnectNodeMessage(GetEventThreadServices().GetUpdateManager(), GetParent()->GetNode(), GetNode());
1436 // Request relayout on all actors that are added to the scenegraph
1439 // Notification for Object::Observers
1443 void Actor::NotifyStageConnection(bool notify)
1445 // Actors can be removed (in a callback), before the on-stage stage is reported.
1446 // The actor may also have been reparented, in which case mOnSceneSignalled will be true.
1447 if(OnScene() && !mOnSceneSignalled)
1451 // Notification for external (CustomActor) derived classes
1452 OnSceneConnectionExternal(mDepth);
1454 if(!mOnSceneSignal.Empty())
1456 Dali::Actor handle(this);
1457 mOnSceneSignal.Emit(handle);
1461 // Guard against Remove during callbacks
1464 mOnSceneSignalled = true; // signal required next time Actor is removed
1469 void Actor::DisconnectFromStage(bool notify)
1471 // This container is used instead of walking the Actor hierachy.
1472 // It protects us when the Actor hierachy is modified during OnSceneDisconnectionExternal callbacks.
1473 ActorContainer disconnectionList;
1477 mScene->RequestRebuildDepthTree();
1480 // This stage is not interrupted by user callbacks
1481 mParentImpl.RecursiveDisconnectFromScene(disconnectionList);
1483 // Notify applications about the newly disconnected actors.
1484 for(const auto& actor : disconnectionList)
1486 actor->NotifyStageDisconnection(notify);
1491 * This method is called by an actor or its parent, before a node removal message is sent.
1492 * This is recursive; the child calls DisconnectFromStage() for its children.
1494 void Actor::DisconnectFromSceneGraph()
1496 // Notification for Object::Observers
1497 OnSceneObjectRemove();
1500 void Actor::NotifyStageDisconnection(bool notify)
1502 // Actors can be added (in a callback), before the off-stage state is reported.
1503 // Also if the actor was added & removed before mOnSceneSignalled was set, then we don't notify here.
1504 // only do this step if there is a stage, i.e. Core is not being shut down
1505 if(EventThreadServices::IsCoreRunning() && !OnScene() && mOnSceneSignalled)
1509 // Notification for external (CustomeActor) derived classes
1510 OnSceneDisconnectionExternal();
1512 if(!mOffSceneSignal.Empty())
1514 Dali::Actor handle(this);
1515 mOffSceneSignal.Emit(handle);
1519 // Guard against Add during callbacks
1522 mOnSceneSignalled = false; // signal required next time Actor is added
1527 bool Actor::IsNodeConnected() const
1529 return OnScene() && (IsRoot() || GetNode().GetParent());
1532 // This method initiates traversal of the actor tree using depth-first
1533 // traversal to set a depth index based on traversal order. It sends a
1534 // single message to update manager to update all the actor's nodes in
1535 // this tree with the depth index. The sceneGraphNodeDepths vector's
1536 // elements are ordered by depth, and could be used to reduce sorting
1537 // in the update thread.
1538 void Actor::RebuildDepthTree()
1540 DALI_LOG_TIMER_START(depthTimer);
1542 // Vector of scene-graph nodes and their depths to send to UpdateManager
1543 // in a single message
1544 OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths(new SceneGraph::NodeDepths());
1546 int32_t depthIndex = 1;
1547 mParentImpl.DepthTraverseActorTree(sceneGraphNodeDepths, depthIndex);
1549 SetDepthIndicesMessage(GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths);
1550 DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
1553 void Actor::SetDefaultProperty(Property::Index index, const Property::Value& property)
1555 PropertyHandler::SetDefaultProperty(*this, index, property);
1558 // TODO: This method needs to be removed
1559 void Actor::SetSceneGraphProperty(Property::Index index, const PropertyMetadata& entry, const Property::Value& value)
1561 PropertyHandler::SetSceneGraphProperty(index, entry, value, GetEventThreadServices(), GetNode());
1564 Property::Value Actor::GetDefaultProperty(Property::Index index) const
1566 Property::Value value;
1568 if(!GetCachedPropertyValue(index, value))
1570 // If property value is not stored in the event-side, then it must be a scene-graph only property
1571 GetCurrentPropertyValue(index, value);
1577 Property::Value Actor::GetDefaultPropertyCurrentValue(Property::Index index) const
1579 Property::Value value;
1581 if(!GetCurrentPropertyValue(index, value))
1583 // If unable to retrieve scene-graph property value, then it must be an event-side only property
1584 GetCachedPropertyValue(index, value);
1590 void Actor::OnNotifyDefaultPropertyAnimation(Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType)
1592 PropertyHandler::OnNotifyDefaultPropertyAnimation(*this, animation, index, value, animationType);
1595 const PropertyBase* Actor::GetSceneObjectAnimatableProperty(Property::Index index) const
1597 const PropertyBase* property = PropertyHandler::GetSceneObjectAnimatableProperty(index, GetNode());
1600 // not our property, ask base
1601 property = Object::GetSceneObjectAnimatableProperty(index);
1607 const PropertyInputImpl* Actor::GetSceneObjectInputProperty(Property::Index index) const
1609 const PropertyInputImpl* property = PropertyHandler::GetSceneObjectInputProperty(index, GetNode());
1612 // reuse animatable property getter as animatable properties are inputs as well
1613 // animatable property chains back to Object::GetSceneObjectInputProperty() so all properties get covered
1614 property = GetSceneObjectAnimatableProperty(index);
1620 int32_t Actor::GetPropertyComponentIndex(Property::Index index) const
1622 int32_t componentIndex = PropertyHandler::GetPropertyComponentIndex(index);
1623 if(Property::INVALID_COMPONENT_INDEX == componentIndex)
1626 componentIndex = Object::GetPropertyComponentIndex(index);
1629 return componentIndex;
1632 const SceneGraph::Node& Actor::GetNode() const
1634 return *static_cast<const SceneGraph::Node*>(mUpdateObject);
1639 CheckParentAndCall(mParent, *this, &ActorParent::RaiseChild);
1644 CheckParentAndCall(mParent, *this, &ActorParent::LowerChild);
1647 void Actor::RaiseToTop()
1649 CheckParentAndCall(mParent, *this, &ActorParent::RaiseChildToTop);
1652 void Actor::LowerToBottom()
1654 CheckParentAndCall(mParent, *this, &ActorParent::LowerChildToBottom);
1657 void Actor::RaiseAbove(Internal::Actor& target)
1659 CheckParentAndCall(mParent, *this, target, &ActorParent::RaiseChildAbove);
1662 void Actor::LowerBelow(Internal::Actor& target)
1664 CheckParentAndCall(mParent, *this, target, &ActorParent::LowerChildBelow);
1667 void Actor::SetParent(ActorParent* parent, bool notify)
1671 DALI_ASSERT_ALWAYS(!mParent && "Actor cannot have 2 parents");
1674 Actor* parentActor = static_cast<Actor*>(parent);
1675 mScene = parentActor->mScene;
1677 if(EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1678 parentActor->OnScene())
1680 // Instruct each actor to create a corresponding node in the scene graph
1681 ConnectToScene(parentActor->GetHierarchyDepth(), notify);
1684 // Resolve the name and index for the child properties if any
1685 ResolveChildProperties();
1687 else // parent being set to NULL
1689 DALI_ASSERT_ALWAYS(mParent != nullptr && "Actor should have a parent");
1693 if(EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1696 // Disconnect the Node & its children from the scene-graph.
1697 DisconnectNodeMessage(GetEventThreadServices().GetUpdateManager(), GetNode());
1699 // Instruct each actor to discard pointers to the scene-graph
1700 DisconnectFromStage(notify);
1707 Rect<> Actor::CalculateScreenExtents() const
1709 auto screenPosition = GetCurrentScreenPosition();
1710 Vector3 size = GetCurrentSize() * GetCurrentWorldScale();
1711 Vector3 anchorPointOffSet = size * (mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT);
1712 Vector2 position = Vector2(screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y);
1713 return {position.x, position.y, size.x, size.y};
1716 bool Actor::GetCachedPropertyValue(Property::Index index, Property::Value& value) const
1718 return PropertyHandler::GetCachedPropertyValue(*this, index, value);
1721 bool Actor::GetCurrentPropertyValue(Property::Index index, Property::Value& value) const
1723 return PropertyHandler::GetCurrentPropertyValue(*this, index, value);
1726 Actor::Relayouter& Actor::EnsureRelayouter()
1728 // Assign relayouter
1731 mRelayoutData = new Relayouter();
1734 return *mRelayoutData;
1737 bool Actor::RelayoutDependentOnParent(Dimension::Type dimension)
1739 return mRelayoutData && mRelayoutData->GetRelayoutDependentOnParent(dimension);
1742 bool Actor::RelayoutDependentOnChildren(Dimension::Type dimension)
1744 return mRelayoutData && mRelayoutData->GetRelayoutDependentOnChildren(dimension);
1747 bool Actor::RelayoutDependentOnChildrenBase(Dimension::Type dimension)
1749 return Actor::RelayoutDependentOnChildren(dimension);
1752 bool Actor::RelayoutDependentOnDimension(Dimension::Type dimension, Dimension::Type dependentDimension)
1754 return mRelayoutData && mRelayoutData->GetRelayoutDependentOnDimension(dimension, dependentDimension);
1757 void Actor::SetNegotiatedDimension(float negotiatedDimension, Dimension::Type dimension)
1761 mRelayoutData->SetNegotiatedDimension(negotiatedDimension, dimension);
1765 float Actor::GetNegotiatedDimension(Dimension::Type dimension) const
1767 return mRelayoutData ? mRelayoutData->GetNegotiatedDimension(dimension) : 0.0f;
1770 void Actor::SetPadding(const Vector2& padding, Dimension::Type dimension)
1772 EnsureRelayouter().SetPadding(padding, dimension);
1775 Vector2 Actor::GetPadding(Dimension::Type dimension) const
1777 return mRelayoutData ? mRelayoutData->GetPadding(dimension) : Relayouter::DEFAULT_DIMENSION_PADDING;
1780 void Actor::SetLayoutNegotiated(bool negotiated, Dimension::Type dimension)
1782 EnsureRelayouter().SetLayoutNegotiated(negotiated, dimension);
1785 bool Actor::IsLayoutNegotiated(Dimension::Type dimension) const
1787 return mRelayoutData && mRelayoutData->IsLayoutNegotiated(dimension);
1790 float Actor::GetHeightForWidthBase(float width)
1792 const Vector3 naturalSize = GetNaturalSize();
1793 return naturalSize.width > 0.0f ? naturalSize.height * width / naturalSize.width : width;
1796 float Actor::GetWidthForHeightBase(float height)
1798 const Vector3 naturalSize = GetNaturalSize();
1799 return naturalSize.height > 0.0f ? naturalSize.width * height / naturalSize.height : height;
1802 float Actor::CalculateChildSizeBase(const Dali::Actor& child, Dimension::Type dimension)
1804 // Fill to parent, taking size mode factor into account
1805 switch(child.GetResizePolicy(dimension))
1807 case ResizePolicy::FILL_TO_PARENT:
1809 return GetLatestSize(dimension);
1812 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
1814 return GetLatestSize(dimension) * GetDimensionValue(child.GetProperty<Vector3>(Dali::Actor::Property::SIZE_MODE_FACTOR), dimension);
1817 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
1819 return GetLatestSize(dimension) + GetDimensionValue(child.GetProperty<Vector3>(Dali::Actor::Property::SIZE_MODE_FACTOR), dimension);
1824 return GetLatestSize(dimension);
1829 float Actor::CalculateChildSize(const Dali::Actor& child, Dimension::Type dimension)
1831 // Can be overridden in derived class
1832 return CalculateChildSizeBase(child, dimension);
1835 float Actor::GetHeightForWidth(float width)
1837 // Can be overridden in derived class
1838 return GetHeightForWidthBase(width);
1841 float Actor::GetWidthForHeight(float height)
1843 // Can be overridden in derived class
1844 return GetWidthForHeightBase(height);
1847 float Actor::GetLatestSize(Dimension::Type dimension) const
1849 return IsLayoutNegotiated(dimension) ? GetNegotiatedDimension(dimension) : GetSize(dimension);
1852 float Actor::GetRelayoutSize(Dimension::Type dimension) const
1854 Vector2 padding = GetPadding(dimension);
1856 return GetLatestSize(dimension) + padding.x + padding.y;
1859 float Actor::NegotiateFromParent(Dimension::Type dimension)
1861 Actor* parent = GetParent();
1864 Vector2 padding(GetPadding(dimension));
1865 Vector2 parentPadding(parent->GetPadding(dimension));
1866 return parent->CalculateChildSize(Dali::Actor(this), dimension) - parentPadding.x - parentPadding.y - padding.x - padding.y;
1872 float Actor::NegotiateFromChildren(Dimension::Type dimension)
1874 float maxDimensionPoint = 0.0f;
1876 for(uint32_t i = 0, count = GetChildCount(); i < count; ++i)
1878 ActorPtr child = GetChildAt(i);
1880 if(!child->RelayoutDependentOnParent(dimension))
1882 // Calculate the min and max points that the children range across
1883 float childPosition = GetDimensionValue(child->GetTargetPosition(), dimension);
1884 float dimensionSize = child->GetRelayoutSize(dimension);
1885 maxDimensionPoint = std::max(maxDimensionPoint, childPosition + dimensionSize);
1889 return maxDimensionPoint;
1892 float Actor::GetSize(Dimension::Type dimension) const
1894 return GetDimensionValue(mTargetSize, dimension);
1897 float Actor::GetNaturalSize(Dimension::Type dimension) const
1899 return GetDimensionValue(GetNaturalSize(), dimension);
1902 float Actor::CalculateSize(Dimension::Type dimension, const Vector2& maximumSize)
1904 switch(GetResizePolicy(dimension))
1906 case ResizePolicy::USE_NATURAL_SIZE:
1908 return GetNaturalSize(dimension);
1911 case ResizePolicy::FIXED:
1913 return GetDimensionValue(GetPreferredSize(), dimension);
1916 case ResizePolicy::USE_ASSIGNED_SIZE:
1918 return GetDimensionValue(maximumSize, dimension);
1921 case ResizePolicy::FILL_TO_PARENT:
1922 case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
1923 case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
1925 return NegotiateFromParent(dimension);
1928 case ResizePolicy::FIT_TO_CHILDREN:
1930 return NegotiateFromChildren(dimension);
1933 case ResizePolicy::DIMENSION_DEPENDENCY:
1935 const Dimension::Type dimensionDependency = GetDimensionDependency(dimension);
1938 if(dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT)
1940 return GetWidthForHeight(GetNegotiatedDimension(Dimension::HEIGHT));
1943 if(dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH)
1945 return GetHeightForWidth(GetNegotiatedDimension(Dimension::WIDTH));
1957 return 0.0f; // Default
1960 Vector2 Actor::ApplySizeSetPolicy(const Vector2& size)
1962 return mRelayoutData->ApplySizeSetPolicy(*this, size);
1965 void Actor::SetNegotiatedSize(RelayoutContainer& container)
1967 // Do the set actor size
1968 Vector2 negotiatedSize(GetLatestSize(Dimension::WIDTH), GetLatestSize(Dimension::HEIGHT));
1970 // Adjust for size set policy
1971 negotiatedSize = ApplySizeSetPolicy(negotiatedSize);
1973 // Lock the flag to stop recursive relayouts on set size
1974 mRelayoutData->insideRelayout = true;
1975 SetSize(negotiatedSize);
1976 mRelayoutData->insideRelayout = false;
1978 // Clear flags for all dimensions
1979 SetLayoutDirty(false);
1981 // Give deriving classes a chance to respond
1982 OnRelayout(negotiatedSize, container);
1984 if(!mOnRelayoutSignal.Empty())
1986 Dali::Actor handle(this);
1987 mOnRelayoutSignal.Emit(handle);
1990 mRelayoutData->relayoutRequested = false;
1993 void Actor::NegotiateSize(const Vector2& allocatedSize, RelayoutContainer& container)
1995 Relayouter::NegotiateSize(*this, allocatedSize, container);
1998 void Actor::SetUseAssignedSize(bool use, Dimension::Type dimension)
2002 mRelayoutData->SetUseAssignedSize(use, dimension);
2006 bool Actor::GetUseAssignedSize(Dimension::Type dimension) const
2008 return mRelayoutData && mRelayoutData->GetUseAssignedSize(dimension);
2011 void Actor::RelayoutRequest(Dimension::Type dimension)
2013 Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
2014 if(relayoutController)
2016 Dali::Actor self(this);
2017 relayoutController->RequestRelayout(self, dimension);
2021 mRelayoutData->relayoutRequested = true;
2026 void Actor::SetPreferredSize(const Vector2& size)
2028 EnsureRelayouter().SetPreferredSize(*this, size);
2031 Vector2 Actor::GetPreferredSize() const
2033 return mRelayoutData ? Vector2(mRelayoutData->preferredSize) : Relayouter::DEFAULT_PREFERRED_SIZE;
2036 void Actor::SetMinimumSize(float size, Dimension::Type dimension)
2038 EnsureRelayouter().SetMinimumSize(size, dimension);
2042 float Actor::GetMinimumSize(Dimension::Type dimension) const
2044 return mRelayoutData ? mRelayoutData->GetMinimumSize(dimension) : 0.0f;
2047 void Actor::SetMaximumSize(float size, Dimension::Type dimension)
2049 EnsureRelayouter().SetMaximumSize(size, dimension);
2053 float Actor::GetMaximumSize(Dimension::Type dimension) const
2055 return mRelayoutData ? mRelayoutData->GetMaximumSize(dimension) : FLT_MAX;
2058 void Actor::SetVisibleInternal(bool visible, SendMessage::Type sendMessage)
2060 if(mVisible != visible)
2062 if(sendMessage == SendMessage::TRUE)
2064 // node is being used in a separate thread; queue a message to set the value & base value
2065 SceneGraph::NodePropertyMessage<bool>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible);
2067 RequestRenderingMessage(GetEventThreadServices().GetUpdateManager());
2072 // Emit the signal on this actor and all its children
2073 mParentImpl.EmitVisibilityChangedSignalRecursively(visible, DevelActor::VisibilityChange::SELF);
2077 void Actor::SetSiblingOrderOfChild(Actor& child, uint32_t order)
2079 mParentImpl.SetSiblingOrderOfChild(child, order);
2082 uint32_t Actor::GetSiblingOrderOfChild(const Actor& child) const
2084 return mParentImpl.GetSiblingOrderOfChild(child);
2087 void Actor::RaiseChild(Actor& child)
2089 mParentImpl.RaiseChild(child);
2092 void Actor::LowerChild(Actor& child)
2094 mParentImpl.LowerChild(child);
2097 void Actor::RaiseChildToTop(Actor& child)
2099 mParentImpl.RaiseChildToTop(child);
2102 void Actor::LowerChildToBottom(Actor& child)
2104 mParentImpl.LowerChildToBottom(child);
2107 void Actor::RaiseChildAbove(Actor& child, Actor& target)
2109 mParentImpl.RaiseChildAbove(child, target);
2112 void Actor::LowerChildBelow(Actor& child, Actor& target)
2114 mParentImpl.LowerChildBelow(child, target);
2117 void Actor::SetInheritLayoutDirection(bool inherit)
2119 if(mInheritLayoutDirection != inherit)
2121 mInheritLayoutDirection = inherit;
2123 if(inherit && mParent)
2125 mParentImpl.InheritLayoutDirectionRecursively(GetParent()->mLayoutDirection);
2130 void Actor::SetUpdateSizeHint(const Vector2& updateSizeHint)
2132 // node is being used in a separate thread; queue a message to set the value & base value
2133 SceneGraph::NodePropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mUpdateSizeHint, &AnimatableProperty<Vector3>::Bake, Vector3(updateSizeHint.width, updateSizeHint.height, 0.f));
2136 } // namespace Internal