Refactored out actor render container
[platform/core/uifw/dali-core.git] / dali / internal / event / actors / actor-impl.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/event/actors/actor-impl.h>
20
21 // EXTERNAL INCLUDES
22 #include <algorithm>
23 #include <cfloat>
24 #include <cmath>
25
26 // INTERNAL INCLUDES
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>
33
34 #include <dali/devel-api/actors/actor-devel.h>
35 #include <dali/devel-api/actors/layer-devel.h>
36 #include <dali/devel-api/common/capabilities.h>
37
38 #include <dali/integration-api/debug.h>
39
40 #include <dali/internal/event/actors/actor-coords.h>
41 #include <dali/internal/event/actors/actor-parent.h>
42 #include <dali/internal/event/actors/actor-property-handler.h>
43 #include <dali/internal/event/actors/actor-relayouter.h>
44 #include <dali/internal/event/actors/camera-actor-impl.h>
45 #include <dali/internal/event/common/event-thread-services.h>
46 #include <dali/internal/event/common/property-helper.h>
47 #include <dali/internal/event/common/scene-impl.h>
48 #include <dali/internal/event/common/stage-impl.h>
49 #include <dali/internal/event/common/thread-local-storage.h>
50 #include <dali/internal/event/common/type-info-impl.h>
51 #include <dali/internal/event/events/actor-gesture-data.h>
52 #include <dali/internal/event/render-tasks/render-task-impl.h>
53 #include <dali/internal/event/render-tasks/render-task-list-impl.h>
54 #include <dali/internal/event/rendering/renderer-impl.h>
55 #include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
56 #include <dali/internal/update/manager/update-manager.h>
57 #include <dali/internal/update/nodes/node-messages.h>
58
59 using Dali::Internal::SceneGraph::AnimatableProperty;
60 using Dali::Internal::SceneGraph::Node;
61 using Dali::Internal::SceneGraph::PropertyBase;
62
63 #if defined(DEBUG_ENABLED)
64 Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_DEPTH_TIMER");
65 #endif
66
67 namespace Dali
68 {
69 namespace Internal
70 {
71 namespace // unnamed namespace
72 {
73 // Properties
74
75 /**
76  * We want to discourage the use of property strings (minimize string comparisons),
77  * particularly for the default properties.
78  *              Name                  Type   writable animatable constraint-input  enum for index-checking
79  */
80 DALI_PROPERTY_TABLE_BEGIN
81 DALI_PROPERTY("parentOrigin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN)
82 DALI_PROPERTY("parentOriginX", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X)
83 DALI_PROPERTY("parentOriginY", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y)
84 DALI_PROPERTY("parentOriginZ", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z)
85 DALI_PROPERTY("anchorPoint", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT)
86 DALI_PROPERTY("anchorPointX", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X)
87 DALI_PROPERTY("anchorPointY", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y)
88 DALI_PROPERTY("anchorPointZ", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z)
89 DALI_PROPERTY("size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE)
90 DALI_PROPERTY("sizeWidth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH)
91 DALI_PROPERTY("sizeHeight", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT)
92 DALI_PROPERTY("sizeDepth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH)
93 DALI_PROPERTY("position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION)
94 DALI_PROPERTY("positionX", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X)
95 DALI_PROPERTY("positionY", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y)
96 DALI_PROPERTY("positionZ", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z)
97 DALI_PROPERTY("worldPosition", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION)
98 DALI_PROPERTY("worldPositionX", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X)
99 DALI_PROPERTY("worldPositionY", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y)
100 DALI_PROPERTY("worldPositionZ", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z)
101 DALI_PROPERTY("orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION)
102 DALI_PROPERTY("worldOrientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION)
103 DALI_PROPERTY("scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE)
104 DALI_PROPERTY("scaleX", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X)
105 DALI_PROPERTY("scaleY", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y)
106 DALI_PROPERTY("scaleZ", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z)
107 DALI_PROPERTY("worldScale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE)
108 DALI_PROPERTY("visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE)
109 DALI_PROPERTY("color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR)
110 DALI_PROPERTY("colorRed", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED)
111 DALI_PROPERTY("colorGreen", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN)
112 DALI_PROPERTY("colorBlue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE)
113 DALI_PROPERTY("colorAlpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA)
114 DALI_PROPERTY("worldColor", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR)
115 DALI_PROPERTY("worldMatrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX)
116 DALI_PROPERTY("name", STRING, true, false, false, Dali::Actor::Property::NAME)
117 DALI_PROPERTY("sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE)
118 DALI_PROPERTY("leaveRequired", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED)
119 DALI_PROPERTY("inheritOrientation", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION)
120 DALI_PROPERTY("inheritScale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE)
121 DALI_PROPERTY("colorMode", INTEGER, true, false, false, Dali::Actor::Property::COLOR_MODE)
122 DALI_PROPERTY("drawMode", INTEGER, true, false, false, Dali::Actor::Property::DRAW_MODE)
123 DALI_PROPERTY("sizeModeFactor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR)
124 DALI_PROPERTY("widthResizePolicy", STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY)
125 DALI_PROPERTY("heightResizePolicy", STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY)
126 DALI_PROPERTY("sizeScalePolicy", INTEGER, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY)
127 DALI_PROPERTY("widthForHeight", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT)
128 DALI_PROPERTY("heightForWidth", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH)
129 DALI_PROPERTY("padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING)
130 DALI_PROPERTY("minimumSize", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE)
131 DALI_PROPERTY("maximumSize", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE)
132 DALI_PROPERTY("inheritPosition", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_POSITION)
133 DALI_PROPERTY("clippingMode", STRING, true, false, false, Dali::Actor::Property::CLIPPING_MODE)
134 DALI_PROPERTY("layoutDirection", STRING, true, false, false, Dali::Actor::Property::LAYOUT_DIRECTION)
135 DALI_PROPERTY("inheritLayoutDirection", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_LAYOUT_DIRECTION)
136 DALI_PROPERTY("opacity", FLOAT, true, true, true, Dali::Actor::Property::OPACITY)
137 DALI_PROPERTY("screenPosition", VECTOR2, false, false, false, Dali::Actor::Property::SCREEN_POSITION)
138 DALI_PROPERTY("positionUsesAnchorPoint", BOOLEAN, true, false, false, Dali::Actor::Property::POSITION_USES_ANCHOR_POINT)
139 DALI_PROPERTY("culled", BOOLEAN, false, false, true, Dali::Actor::Property::CULLED)
140 DALI_PROPERTY("id", INTEGER, false, false, false, Dali::Actor::Property::ID)
141 DALI_PROPERTY("hierarchyDepth", INTEGER, false, false, false, Dali::Actor::Property::HIERARCHY_DEPTH)
142 DALI_PROPERTY("isRoot", BOOLEAN, false, false, false, Dali::Actor::Property::IS_ROOT)
143 DALI_PROPERTY("isLayer", BOOLEAN, false, false, false, Dali::Actor::Property::IS_LAYER)
144 DALI_PROPERTY("connectedToScene", BOOLEAN, false, false, false, Dali::Actor::Property::CONNECTED_TO_SCENE)
145 DALI_PROPERTY("keyboardFocusable", BOOLEAN, true, false, false, Dali::Actor::Property::KEYBOARD_FOCUSABLE)
146 DALI_PROPERTY("siblingOrder", INTEGER, true, false, false, Dali::DevelActor::Property::SIBLING_ORDER)
147 DALI_PROPERTY("updateSizeHint", VECTOR2, true, false, false, Dali::DevelActor::Property::UPDATE_SIZE_HINT)
148 DALI_PROPERTY("captureAllTouchAfterStart", BOOLEAN, true, false, false, Dali::DevelActor::Property::CAPTURE_ALL_TOUCH_AFTER_START)
149 DALI_PROPERTY("touchAreaOffset", RECTANGLE, true, false, false, Dali::DevelActor::Property::TOUCH_AREA_OFFSET)
150 DALI_PROPERTY("blendEquation", INTEGER, true, false, false, Dali::DevelActor::Property::BLEND_EQUATION)
151 DALI_PROPERTY("touchFocusable", BOOLEAN, true, false, false, Dali::DevelActor::Property::TOUCH_FOCUSABLE)
152 DALI_PROPERTY("keyboardFocusableChildren", BOOLEAN, true, false, false, Dali::DevelActor::Property::KEYBOARD_FOCUSABLE_CHILDREN)
153 DALI_PROPERTY_TABLE_END(DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperties)
154
155 // Signals
156
157 static constexpr std::string_view SIGNAL_HOVERED                  = "hovered";
158 static constexpr std::string_view SIGNAL_WHEEL_EVENT              = "wheelEvent";
159 static constexpr std::string_view SIGNAL_ON_SCENE                 = "onScene";
160 static constexpr std::string_view SIGNAL_OFF_SCENE                = "offScene";
161 static constexpr std::string_view SIGNAL_ON_RELAYOUT              = "onRelayout";
162 static constexpr std::string_view SIGNAL_TOUCHED                  = "touched";
163 static constexpr std::string_view SIGNAL_VISIBILITY_CHANGED       = "visibilityChanged";
164 static constexpr std::string_view SIGNAL_LAYOUT_DIRECTION_CHANGED = "layoutDirectionChanged";
165 static constexpr std::string_view SIGNAL_CHILD_ADDED              = "childAdded";
166 static constexpr std::string_view SIGNAL_CHILD_REMOVED            = "childRemoved";
167
168 // Actions
169
170 static constexpr std::string_view ACTION_SHOW = "show";
171 static constexpr std::string_view ACTION_HIDE = "hide";
172
173 BaseHandle CreateActor()
174 {
175   return Dali::Actor::New();
176 }
177
178 TypeRegistration mType(typeid(Dali::Actor), typeid(Dali::Handle), CreateActor, ActorDefaultProperties);
179
180 SignalConnectorType signalConnector2(mType, std::string(SIGNAL_HOVERED), &Actor::DoConnectSignal);
181 SignalConnectorType signalConnector3(mType, std::string(SIGNAL_WHEEL_EVENT), &Actor::DoConnectSignal);
182 SignalConnectorType signalConnector4(mType, std::string(SIGNAL_ON_SCENE), &Actor::DoConnectSignal);
183 SignalConnectorType signalConnector5(mType, std::string(SIGNAL_OFF_SCENE), &Actor::DoConnectSignal);
184 SignalConnectorType signalConnector6(mType, std::string(SIGNAL_ON_RELAYOUT), &Actor::DoConnectSignal);
185 SignalConnectorType signalConnector7(mType, std::string(SIGNAL_TOUCHED), &Actor::DoConnectSignal);
186 SignalConnectorType signalConnector8(mType, std::string(SIGNAL_VISIBILITY_CHANGED), &Actor::DoConnectSignal);
187 SignalConnectorType signalConnector9(mType, std::string(SIGNAL_LAYOUT_DIRECTION_CHANGED), &Actor::DoConnectSignal);
188 SignalConnectorType signalConnector10(mType, std::string(SIGNAL_CHILD_ADDED), &Actor::DoConnectSignal);
189 SignalConnectorType signalConnector11(mType, std::string(SIGNAL_CHILD_REMOVED), &Actor::DoConnectSignal);
190
191 TypeAction a1(mType, std::string(ACTION_SHOW), &Actor::DoAction);
192 TypeAction a2(mType, std::string(ACTION_HIDE), &Actor::DoAction);
193
194 /**
195  * @brief Extract a given dimension from a Vector2
196  *
197  * @param[in] values The values to extract from
198  * @param[in] dimension The dimension to extract
199  * @return Return the value for the dimension
200  */
201 constexpr float GetDimensionValue(const Vector2& values, Dimension::Type dimension)
202 {
203   switch(dimension)
204   {
205     case Dimension::WIDTH:
206     {
207       return values.width;
208     }
209     case Dimension::HEIGHT:
210     {
211       return values.height;
212     }
213     default:
214     {
215       break;
216     }
217   }
218   return 0.0f;
219 }
220
221 /**
222  * @brief Extract a given dimension from a Vector3
223  *
224  * @param[in] values The values to extract from
225  * @param[in] dimension The dimension to extract
226  * @return Return the value for the dimension
227  */
228 float GetDimensionValue(const Vector3& values, Dimension::Type dimension)
229 {
230   return GetDimensionValue(values.GetVectorXY(), dimension);
231 }
232
233 /// Helper for emitting a signal
234 template<typename Signal, typename Event>
235 bool EmitConsumingSignal(Actor& actor, Signal& signal, const Event& event)
236 {
237   bool consumed = false;
238
239   if(!signal.Empty())
240   {
241     Dali::Actor handle(&actor);
242     consumed = signal.Emit(handle, event);
243   }
244
245   return consumed;
246 }
247
248 /// Helper for emitting signals with multiple parameters
249 template<typename Signal, typename... Param>
250 void EmitSignal(Actor& actor, Signal& signal, Param... params)
251 {
252   if(!signal.Empty())
253   {
254     Dali::Actor handle(&actor);
255     signal.Emit(handle, params...);
256   }
257 }
258
259 } // unnamed namespace
260
261 ActorPtr Actor::New()
262 {
263   // pass a reference to actor, actor does not own its node
264   ActorPtr actor(new Actor(BASIC, *CreateNode()));
265
266   // Second-phase construction
267   actor->Initialize();
268
269   return actor;
270 }
271
272 const SceneGraph::Node* Actor::CreateNode()
273 {
274   // create node. Nodes are owned by the update manager
275   SceneGraph::Node*              node = SceneGraph::Node::New();
276   OwnerPointer<SceneGraph::Node> transferOwnership(node);
277   Internal::ThreadLocalStorage*  tls = Internal::ThreadLocalStorage::GetInternal();
278
279   DALI_ASSERT_ALWAYS(tls && "ThreadLocalStorage is null");
280
281   AddNodeMessage(tls->GetUpdateManager(), transferOwnership);
282
283   return node;
284 }
285
286 void Actor::SetName(std::string_view name)
287 {
288   mName = ConstString(name);
289
290   // ATTENTION: string for debug purposes is not thread safe.
291   DALI_LOG_SET_OBJECT_STRING(const_cast<SceneGraph::Node*>(&GetNode()), mName.GetCString());
292 }
293
294 uint32_t Actor::GetId() const
295 {
296   return GetNode().GetId();
297 }
298
299 Dali::Layer Actor::GetLayer()
300 {
301   Dali::Layer layer;
302
303   // Short-circuit for Layer derived actors
304   if(mIsLayer)
305   {
306     layer = Dali::Layer(static_cast<Dali::Internal::Layer*>(this)); // static cast as we trust the flag
307   }
308
309   // Find the immediate Layer parent
310   for(Actor* parent = GetParent(); !layer && parent != nullptr; parent = parent->GetParent())
311   {
312     if(parent->IsLayer())
313     {
314       layer = Dali::Layer(static_cast<Dali::Internal::Layer*>(parent)); // static cast as we trust the flag
315     }
316   }
317
318   return layer;
319 }
320
321 void Actor::Unparent()
322 {
323   if(mParent)
324   {
325     // Remove this actor from the parent. The remove will put a relayout request in for
326     // the parent if required
327     mParent->Remove(*this);
328     // mParent is now NULL!
329   }
330 }
331
332 void Actor::SetParentOrigin(const Vector3& origin)
333 {
334   // node is being used in a separate thread; queue a message to set the value & base value
335   SetParentOriginMessage(GetEventThreadServices(), GetNode(), origin);
336
337   // Cache for event-thread access
338   if(!mParentOrigin)
339   {
340     // not allocated, check if different from default
341     if(ParentOrigin::DEFAULT != origin)
342     {
343       mParentOrigin = new Vector3(origin);
344     }
345   }
346   else
347   {
348     // check if different from current costs more than just set
349     *mParentOrigin = origin;
350   }
351 }
352
353 const Vector3& Actor::GetCurrentParentOrigin() const
354 {
355   // Cached for event-thread access
356   return (mParentOrigin) ? *mParentOrigin : ParentOrigin::DEFAULT;
357 }
358
359 void Actor::SetAnchorPoint(const Vector3& anchor)
360 {
361   // node is being used in a separate thread; queue a message to set the value & base value
362   SetAnchorPointMessage(GetEventThreadServices(), GetNode(), anchor);
363
364   // Cache for event-thread access
365   if(!mAnchorPoint)
366   {
367     // not allocated, check if different from default
368     if(AnchorPoint::DEFAULT != anchor)
369     {
370       mAnchorPoint = new Vector3(anchor);
371     }
372   }
373   else
374   {
375     // check if different from current costs more than just set
376     *mAnchorPoint = anchor;
377   }
378 }
379
380 const Vector3& Actor::GetCurrentAnchorPoint() const
381 {
382   // Cached for event-thread access
383   return (mAnchorPoint) ? *mAnchorPoint : AnchorPoint::DEFAULT;
384 }
385
386 void Actor::SetPosition(float x, float y)
387 {
388   SetPosition(Vector3(x, y, 0.0f));
389 }
390
391 void Actor::SetPosition(float x, float y, float z)
392 {
393   SetPosition(Vector3(x, y, z));
394 }
395
396 void Actor::SetPosition(const Vector3& position)
397 {
398   mTargetPosition = position;
399
400   // node is being used in a separate thread; queue a message to set the value & base value
401   SceneGraph::NodeTransformPropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, position);
402 }
403
404 void Actor::SetX(float x)
405 {
406   mTargetPosition.x = x;
407
408   // node is being used in a separate thread; queue a message to set the value & base value
409   SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x);
410 }
411
412 void Actor::SetY(float y)
413 {
414   mTargetPosition.y = y;
415
416   // node is being used in a separate thread; queue a message to set the value & base value
417   SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y);
418 }
419
420 void Actor::SetZ(float z)
421 {
422   mTargetPosition.z = z;
423
424   // node is being used in a separate thread; queue a message to set the value & base value
425   SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z);
426 }
427
428 void Actor::TranslateBy(const Vector3& distance)
429 {
430   mTargetPosition += distance;
431
432   // node is being used in a separate thread; queue a message to set the value & base value
433   SceneGraph::NodeTransformPropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mPosition, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelative, distance);
434 }
435
436 const Vector3& Actor::GetCurrentPosition() const
437 {
438   // node is being used in a separate thread; copy the value from the previous update
439   return GetNode().GetPosition(GetEventThreadServices().GetEventBufferIndex());
440 }
441
442 const Vector3& Actor::GetCurrentWorldPosition() const
443 {
444   // node is being used in a separate thread; copy the value from the previous update
445   return GetNode().GetWorldPosition(GetEventThreadServices().GetEventBufferIndex());
446 }
447
448 const Vector2 Actor::GetCurrentScreenPosition() const
449 {
450   if(mScene && OnScene())
451   {
452     Vector3 worldPosition  = GetNode().GetWorldPosition(GetEventThreadServices().GetEventBufferIndex());
453     Vector3 cameraPosition = mScene->GetDefaultCameraActor().GetNode().GetWorldPosition(GetEventThreadServices().GetEventBufferIndex());
454     worldPosition -= cameraPosition;
455
456     Vector3 actorSize = GetCurrentSize() * GetCurrentWorldScale();
457     Vector2 halfSceneSize(mScene->GetSize() * 0.5f); // World position origin is center of scene
458     Vector3 halfActorSize(actorSize * 0.5f);
459     Vector3 anchorPointOffSet = halfActorSize - actorSize * (mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT);
460
461     return Vector2(halfSceneSize.width + worldPosition.x - anchorPointOffSet.x,
462                    halfSceneSize.height + worldPosition.y - anchorPointOffSet.y);
463   }
464
465   return Vector2::ZERO;
466 }
467
468 void Actor::SetInheritPosition(bool inherit)
469 {
470   if(mInheritPosition != inherit)
471   {
472     // non animatable so keep local copy
473     mInheritPosition = inherit;
474     SetInheritPositionMessage(GetEventThreadServices(), GetNode(), inherit);
475   }
476 }
477
478 void Actor::SetOrientation(const Radian& angle, const Vector3& axis)
479 {
480   Vector3 normalizedAxis(axis.x, axis.y, axis.z);
481   normalizedAxis.Normalize();
482
483   Quaternion orientation(angle, normalizedAxis);
484
485   SetOrientation(orientation);
486 }
487
488 void Actor::SetOrientation(const Quaternion& orientation)
489 {
490   mTargetOrientation = orientation;
491
492   // node is being used in a separate thread; queue a message to set the value & base value
493   SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::Bake, orientation);
494 }
495
496 void Actor::RotateBy(const Radian& angle, const Vector3& axis)
497 {
498   RotateBy(Quaternion(angle, axis));
499 }
500
501 void Actor::RotateBy(const Quaternion& relativeRotation)
502 {
503   mTargetOrientation *= Quaternion(relativeRotation);
504
505   // node is being used in a separate thread; queue a message to set the value & base value
506   SceneGraph::NodeTransformPropertyMessage<Quaternion>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mOrientation, &SceneGraph::TransformManagerPropertyHandler<Quaternion>::BakeRelative, relativeRotation);
507 }
508
509 const Quaternion& Actor::GetCurrentOrientation() const
510 {
511   // node is being used in a separate thread; copy the value from the previous update
512   return GetNode().GetOrientation(GetEventThreadServices().GetEventBufferIndex());
513 }
514
515 const Quaternion& Actor::GetCurrentWorldOrientation() const
516 {
517   // node is being used in a separate thread; copy the value from the previous update
518   return GetNode().GetWorldOrientation(GetEventThreadServices().GetEventBufferIndex());
519 }
520
521 void Actor::SetScale(float scale)
522 {
523   SetScale(Vector3(scale, scale, scale));
524 }
525
526 void Actor::SetScale(float x, float y, float z)
527 {
528   SetScale(Vector3(x, y, z));
529 }
530
531 void Actor::SetScale(const Vector3& scale)
532 {
533   mTargetScale = scale;
534
535   // node is being used in a separate thread; queue a message to set the value & base value
536   SceneGraph::NodeTransformPropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, scale);
537 }
538
539 void Actor::SetScaleX(float x)
540 {
541   mTargetScale.x = x;
542
543   // node is being used in a separate thread; queue a message to set the value & base value
544   SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, x);
545 }
546
547 void Actor::SetScaleY(float y)
548 {
549   mTargetScale.y = y;
550
551   // node is being used in a separate thread; queue a message to set the value & base value
552   SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, y);
553 }
554
555 void Actor::SetScaleZ(float z)
556 {
557   mTargetScale.z = z;
558
559   // node is being used in a separate thread; queue a message to set the value & base value
560   SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, z);
561 }
562
563 void Actor::ScaleBy(const Vector3& relativeScale)
564 {
565   mTargetScale *= relativeScale;
566
567   // node is being used in a separate thread; queue a message to set the value & base value
568   SceneGraph::NodeTransformPropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mScale, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeRelativeMultiply, relativeScale);
569 }
570
571 const Vector3& Actor::GetCurrentScale() const
572 {
573   // node is being used in a separate thread; copy the value from the previous update
574   return GetNode().GetScale(GetEventThreadServices().GetEventBufferIndex());
575 }
576
577 const Vector3& Actor::GetCurrentWorldScale() const
578 {
579   // node is being used in a separate thread; copy the value from the previous update
580   return GetNode().GetWorldScale(GetEventThreadServices().GetEventBufferIndex());
581 }
582
583 void Actor::SetInheritScale(bool inherit)
584 {
585   if(mInheritScale != inherit)
586   {
587     // non animatable so keep local copy
588     mInheritScale = inherit;
589     // node is being used in a separate thread; queue a message to set the value
590     SetInheritScaleMessage(GetEventThreadServices(), GetNode(), inherit);
591   }
592 }
593
594 Matrix Actor::GetCurrentWorldMatrix() const
595 {
596   return GetNode().GetWorldMatrix(0);
597 }
598
599 void Actor::SetVisible(bool visible)
600 {
601   SetVisibleInternal(visible, SendMessage::TRUE);
602 }
603
604 bool Actor::IsVisible() const
605 {
606   // node is being used in a separate thread; copy the value from the previous update
607   return GetNode().IsVisible(GetEventThreadServices().GetEventBufferIndex());
608 }
609
610 void Actor::SetOpacity(float opacity)
611 {
612   mTargetColor.a = opacity;
613
614   // node is being used in a separate thread; queue a message to set the value & base value
615   SceneGraph::NodePropertyComponentMessage<Vector4>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeW, opacity);
616
617   RequestRenderingMessage(GetEventThreadServices().GetUpdateManager());
618 }
619
620 float Actor::GetCurrentOpacity() const
621 {
622   // node is being used in a separate thread; copy the value from the previous update
623   return GetNode().GetOpacity(GetEventThreadServices().GetEventBufferIndex());
624 }
625
626 const Vector4& Actor::GetCurrentWorldColor() const
627 {
628   return GetNode().GetWorldColor(GetEventThreadServices().GetEventBufferIndex());
629 }
630
631 void Actor::SetColor(const Vector4& color)
632 {
633   mTargetColor = color;
634
635   // node is being used in a separate thread; queue a message to set the value & base value
636   SceneGraph::NodePropertyMessage<Vector4>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::Bake, color);
637
638   RequestRenderingMessage(GetEventThreadServices().GetUpdateManager());
639 }
640
641 void Actor::SetColorRed(float red)
642 {
643   mTargetColor.r = red;
644
645   // node is being used in a separate thread; queue a message to set the value & base value
646   SceneGraph::NodePropertyComponentMessage<Vector4>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeX, red);
647
648   RequestRenderingMessage(GetEventThreadServices().GetUpdateManager());
649 }
650
651 void Actor::SetColorGreen(float green)
652 {
653   mTargetColor.g = green;
654
655   // node is being used in a separate thread; queue a message to set the value & base value
656   SceneGraph::NodePropertyComponentMessage<Vector4>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeY, green);
657
658   RequestRenderingMessage(GetEventThreadServices().GetUpdateManager());
659 }
660
661 void Actor::SetColorBlue(float blue)
662 {
663   mTargetColor.b = blue;
664
665   // node is being used in a separate thread; queue a message to set the value & base value
666   SceneGraph::NodePropertyComponentMessage<Vector4>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mColor, &AnimatableProperty<Vector4>::BakeZ, blue);
667
668   RequestRenderingMessage(GetEventThreadServices().GetUpdateManager());
669 }
670
671 const Vector4& Actor::GetCurrentColor() const
672 {
673   // node is being used in a separate thread; copy the value from the previous update
674   return GetNode().GetColor(GetEventThreadServices().GetEventBufferIndex());
675 }
676
677 void Actor::SetInheritOrientation(bool inherit)
678 {
679   if(mInheritOrientation != inherit)
680   {
681     // non animatable so keep local copy
682     mInheritOrientation = inherit;
683     // node is being used in a separate thread; queue a message to set the value
684     SetInheritOrientationMessage(GetEventThreadServices(), GetNode(), inherit);
685   }
686 }
687
688 void Actor::SetSizeModeFactor(const Vector3& factor)
689 {
690   EnsureRelayouter();
691
692   mRelayoutData->sizeModeFactor = factor;
693 }
694
695 const Vector3& Actor::GetSizeModeFactor() const
696 {
697   if(mRelayoutData)
698   {
699     return mRelayoutData->sizeModeFactor;
700   }
701
702   return Relayouter::DEFAULT_SIZE_MODE_FACTOR;
703 }
704
705 void Actor::SetColorMode(ColorMode colorMode)
706 {
707   // non animatable so keep local copy
708   mColorMode = colorMode;
709   // node is being used in a separate thread; queue a message to set the value
710   SetColorModeMessage(GetEventThreadServices(), GetNode(), colorMode);
711 }
712
713 void Actor::SetSize(float width, float height)
714 {
715   SetSize(Vector2(width, height));
716 }
717
718 void Actor::SetSize(float width, float height, float depth)
719 {
720   SetSize(Vector3(width, height, depth));
721 }
722
723 void Actor::SetSize(const Vector2& size)
724 {
725   SetSize(Vector3(size.width, size.height, 0.f));
726 }
727
728 void Actor::SetSizeInternal(const Vector2& size)
729 {
730   SetSizeInternal(Vector3(size.width, size.height, 0.f));
731 }
732
733 void Actor::SetSize(const Vector3& size)
734 {
735   if(IsRelayoutEnabled() && !mRelayoutData->insideRelayout)
736   {
737     // TODO we cannot just ignore the given Z but that means rewrite the size negotiation!!
738     SetPreferredSize(size.GetVectorXY());
739   }
740   else
741   {
742     SetSizeInternal(size);
743   }
744 }
745
746 void Actor::SetSizeInternal(const Vector3& size)
747 {
748   // dont allow recursive loop
749   DALI_ASSERT_ALWAYS(!mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet");
750   // 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
751   Vector3 currentSize = GetCurrentSize();
752
753   if((fabsf(mTargetSize.width - size.width) > Math::MACHINE_EPSILON_1) ||
754      (fabsf(mTargetSize.height - size.height) > Math::MACHINE_EPSILON_1) ||
755      (fabsf(mTargetSize.depth - size.depth) > Math::MACHINE_EPSILON_1) ||
756      (fabsf(mTargetSize.width - currentSize.width) > Math::MACHINE_EPSILON_1) ||
757      (fabsf(mTargetSize.height - currentSize.height) > Math::MACHINE_EPSILON_1) ||
758      (fabsf(mTargetSize.depth - currentSize.depth) > Math::MACHINE_EPSILON_1))
759   {
760     mTargetSize = size;
761
762     // node is being used in a separate thread; queue a message to set the value & base value
763     SceneGraph::NodeTransformPropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize);
764
765     // Notification for derived classes
766     mInsideOnSizeSet = true;
767     OnSizeSet(mTargetSize);
768     mInsideOnSizeSet = false;
769
770     // Raise a relayout request if the flag is not locked
771     if(mRelayoutData && !mRelayoutData->insideRelayout)
772     {
773       RelayoutRequest();
774     }
775   }
776 }
777
778 void Actor::SetWidth(float width)
779 {
780   if(IsRelayoutEnabled() && !mRelayoutData->insideRelayout)
781   {
782     SetResizePolicy(ResizePolicy::FIXED, Dimension::WIDTH);
783     mRelayoutData->preferredSize.width = width;
784   }
785   else
786   {
787     mTargetSize.width = width;
788
789     // node is being used in a separate thread; queue a message to set the value & base value
790     SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width);
791   }
792
793   mUseAnimatedSize &= ~AnimatedSizeFlag::WIDTH;
794
795   RelayoutRequest();
796 }
797
798 void Actor::SetHeight(float height)
799 {
800   if(IsRelayoutEnabled() && !mRelayoutData->insideRelayout)
801   {
802     SetResizePolicy(ResizePolicy::FIXED, Dimension::HEIGHT);
803     mRelayoutData->preferredSize.height = height;
804   }
805   else
806   {
807     mTargetSize.height = height;
808
809     // node is being used in a separate thread; queue a message to set the value & base value
810     SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height);
811   }
812
813   mUseAnimatedSize &= ~AnimatedSizeFlag::HEIGHT;
814
815   RelayoutRequest();
816 }
817
818 void Actor::SetDepth(float depth)
819 {
820   mTargetSize.depth = depth;
821
822   mUseAnimatedSize &= ~AnimatedSizeFlag::DEPTH;
823
824   // node is being used in a separate thread; queue a message to set the value & base value
825   SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth);
826 }
827
828 Vector3 Actor::GetTargetSize() const
829 {
830   Vector3 size = mTargetSize;
831
832   if(mUseAnimatedSize & AnimatedSizeFlag::WIDTH)
833   {
834     // Should return animated size if size is animated
835     size.width = mAnimatedSize.width;
836   }
837   else
838   {
839     // Should return preferred size if size is fixed as set by SetSize
840     if(GetResizePolicy(Dimension::WIDTH) == ResizePolicy::FIXED)
841     {
842       size.width = GetPreferredSize().width;
843     }
844   }
845
846   if(mUseAnimatedSize & AnimatedSizeFlag::HEIGHT)
847   {
848     size.height = mAnimatedSize.height;
849   }
850   else
851   {
852     if(GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::FIXED)
853     {
854       size.height = GetPreferredSize().height;
855     }
856   }
857
858   if(mUseAnimatedSize & AnimatedSizeFlag::DEPTH)
859   {
860     size.depth = mAnimatedSize.depth;
861   }
862
863   return size;
864 }
865
866 const Vector3& Actor::GetCurrentSize() const
867 {
868   // node is being used in a separate thread; copy the value from the previous update
869   return GetNode().GetSize(GetEventThreadServices().GetEventBufferIndex());
870 }
871
872 Vector3 Actor::GetNaturalSize() const
873 {
874   // It is up to deriving classes to return the appropriate natural size
875   return Vector3(0.0f, 0.0f, 0.0f);
876 }
877
878 void Actor::SetResizePolicy(ResizePolicy::Type policy, Dimension::Type dimension)
879 {
880   EnsureRelayouter().SetResizePolicy(policy, dimension, mTargetSize);
881
882   OnSetResizePolicy(policy, dimension);
883
884   // Trigger relayout on this control
885   RelayoutRequest();
886 }
887
888 ResizePolicy::Type Actor::GetResizePolicy(Dimension::Type dimension) const
889 {
890   if(mRelayoutData)
891   {
892     return mRelayoutData->GetResizePolicy(dimension);
893   }
894
895   return ResizePolicy::DEFAULT;
896 }
897
898 void Actor::SetSizeScalePolicy(SizeScalePolicy::Type policy)
899 {
900   EnsureRelayouter();
901
902   mRelayoutData->sizeSetPolicy = policy;
903
904   // Trigger relayout on this control
905   RelayoutRequest();
906 }
907
908 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
909 {
910   if(mRelayoutData)
911   {
912     return mRelayoutData->sizeSetPolicy;
913   }
914
915   return Relayouter::DEFAULT_SIZE_SCALE_POLICY;
916 }
917
918 void Actor::SetDimensionDependency(Dimension::Type dimension, Dimension::Type dependency)
919 {
920   EnsureRelayouter().SetDimensionDependency(dimension, dependency);
921 }
922
923 Dimension::Type Actor::GetDimensionDependency(Dimension::Type dimension) const
924 {
925   if(mRelayoutData)
926   {
927     return mRelayoutData->GetDimensionDependency(dimension);
928   }
929
930   return Dimension::ALL_DIMENSIONS; // Default
931 }
932
933 void Actor::SetRelayoutEnabled(bool relayoutEnabled)
934 {
935   // If relayout data has not been allocated yet and the client is requesting
936   // to disable it, do nothing
937   if(mRelayoutData || relayoutEnabled)
938   {
939     EnsureRelayouter();
940
941     DALI_ASSERT_DEBUG(mRelayoutData && "mRelayoutData not created");
942
943     mRelayoutData->relayoutEnabled = relayoutEnabled;
944   }
945 }
946
947 bool Actor::IsRelayoutEnabled() const
948 {
949   // Assume that if relayout data has not been allocated yet then
950   // relayout is disabled
951   return mRelayoutData && mRelayoutData->relayoutEnabled;
952 }
953
954 void Actor::SetLayoutDirty(bool dirty, Dimension::Type dimension)
955 {
956   EnsureRelayouter().SetLayoutDirty(dirty, dimension);
957 }
958
959 bool Actor::IsLayoutDirty(Dimension::Type dimension) const
960 {
961   return mRelayoutData && mRelayoutData->IsLayoutDirty(dimension);
962 }
963
964 bool Actor::RelayoutPossible(Dimension::Type dimension) const
965 {
966   return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty(dimension);
967 }
968
969 bool Actor::RelayoutRequired(Dimension::Type dimension) const
970 {
971   return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty(dimension);
972 }
973
974 uint32_t Actor::AddRenderer(Renderer& renderer)
975 {
976   if(!mRenderers)
977   {
978     mRenderers = new RendererContainer(GetEventThreadServices());
979   }
980   return mRenderers->Add(GetNode(), renderer, mIsBlendEquationSet, mBlendEquation);
981 }
982
983 uint32_t Actor::GetRendererCount() const
984 {
985   return mRenderers ? mRenderers->GetCount() : 0u;
986 }
987
988 RendererPtr Actor::GetRendererAt(uint32_t index)
989 {
990   return mRenderers ? mRenderers->GetRendererAt(index) : nullptr;
991 }
992
993 void Actor::RemoveRenderer(Renderer& renderer)
994 {
995   if(mRenderers)
996   {
997     mRenderers->Remove(GetNode(), renderer);
998   }
999 }
1000
1001 void Actor::RemoveRenderer(uint32_t index)
1002 {
1003   if(mRenderers)
1004   {
1005     mRenderers->Remove(GetNode(), index);
1006   }
1007 }
1008
1009 void Actor::SetBlendEquation(DevelBlendEquation::Type blendEquation)
1010 {
1011   if(Dali::Capabilities::IsBlendEquationSupported(blendEquation))
1012   {
1013     if(mBlendEquation != blendEquation)
1014     {
1015       mBlendEquation = blendEquation;
1016       if(mRenderers)
1017       {
1018         mRenderers->SetBlending(blendEquation);
1019       }
1020     }
1021     mIsBlendEquationSet = true;
1022   }
1023   else
1024   {
1025     DALI_LOG_ERROR("Invalid blend equation is entered.\n");
1026   }
1027 }
1028
1029 DevelBlendEquation::Type Actor::GetBlendEquation() const
1030 {
1031   return mBlendEquation;
1032 }
1033
1034 void Actor::SetTransparent(bool transparent)
1035 {
1036   SetTransparentMessage(GetEventThreadServices(), GetNode(), transparent);
1037 }
1038
1039 bool Actor::IsTransparent() const
1040 {
1041   return GetNode().IsTransparent();
1042 }
1043
1044 void Actor::SetDrawMode(DrawMode::Type drawMode)
1045 {
1046   // this flag is not animatable so keep the value
1047   mDrawMode = drawMode;
1048
1049   // node is being used in a separate thread; queue a message to set the value
1050   SetDrawModeMessage(GetEventThreadServices(), GetNode(), drawMode);
1051 }
1052
1053 bool Actor::ScreenToLocal(float& localX, float& localY, float screenX, float screenY) const
1054 {
1055   return mScene && OnScene() && ConvertScreenToLocalRenderTaskList(mScene->GetRenderTaskList(), GetNode().GetWorldMatrix(0), GetCurrentSize(), localX, localY, screenX, screenY);
1056 }
1057
1058 bool Actor::ScreenToLocal(const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY) const
1059 {
1060   return OnScene() && ConvertScreenToLocalRenderTask(renderTask, GetNode().GetWorldMatrix(0), GetCurrentSize(), localX, localY, screenX, screenY);
1061 }
1062
1063 bool Actor::ScreenToLocal(const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY) const
1064 {
1065   return OnScene() && ConvertScreenToLocal(viewMatrix, projectionMatrix, GetNode().GetWorldMatrix(0), GetCurrentSize(), viewport, localX, localY, screenX, screenY);
1066 }
1067
1068 ActorGestureData& Actor::GetGestureData()
1069 {
1070   // Likely scenario is that once gesture-data is created for this actor, the actor will require
1071   // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1072   if(nullptr == mGestureData)
1073   {
1074     mGestureData = new ActorGestureData;
1075   }
1076   return *mGestureData;
1077 }
1078
1079 bool Actor::IsGestureRequired(GestureType::Value type) const
1080 {
1081   return mGestureData && mGestureData->IsGestureRequired(type);
1082 }
1083
1084 bool Actor::EmitInterceptTouchEventSignal(const Dali::TouchEvent& touch)
1085 {
1086   return EmitConsumingSignal(*this, mInterceptTouchedSignal, touch);
1087 }
1088
1089 bool Actor::EmitTouchEventSignal(const Dali::TouchEvent& touch)
1090 {
1091   return EmitConsumingSignal(*this, mTouchedSignal, touch);
1092 }
1093
1094 bool Actor::EmitHoverEventSignal(const Dali::HoverEvent& event)
1095 {
1096   return EmitConsumingSignal(*this, mHoveredSignal, event);
1097 }
1098
1099 bool Actor::EmitWheelEventSignal(const Dali::WheelEvent& event)
1100 {
1101   return EmitConsumingSignal(*this, mWheelEventSignal, event);
1102 }
1103
1104 void Actor::EmitVisibilityChangedSignal(bool visible, DevelActor::VisibilityChange::Type type)
1105 {
1106   EmitSignal(*this, mVisibilityChangedSignal, visible, type);
1107 }
1108
1109 void Actor::EmitLayoutDirectionChangedSignal(LayoutDirection::Type type)
1110 {
1111   EmitSignal(*this, mLayoutDirectionChangedSignal, type);
1112 }
1113
1114 DevelActor::ChildChangedSignalType& Actor::ChildAddedSignal()
1115 {
1116   return mParentImpl.ChildAddedSignal();
1117 }
1118
1119 DevelActor::ChildChangedSignalType& Actor::ChildRemovedSignal()
1120 {
1121   return mParentImpl.ChildRemovedSignal();
1122 }
1123
1124 DevelActor::ChildOrderChangedSignalType& Actor::ChildOrderChangedSignal()
1125 {
1126   return mParentImpl.ChildOrderChangedSignal();
1127 }
1128
1129 bool Actor::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
1130 {
1131   bool   connected(true);
1132   Actor* actor = static_cast<Actor*>(object); // TypeRegistry guarantees that this is the correct type.
1133
1134   std::string_view name(signalName);
1135
1136   if(name == SIGNAL_HOVERED)
1137   {
1138     actor->HoveredSignal().Connect(tracker, functor);
1139   }
1140   else if(signalName == SIGNAL_WHEEL_EVENT)
1141   {
1142     actor->WheelEventSignal().Connect(tracker, functor);
1143   }
1144   else if(name == SIGNAL_ON_SCENE)
1145   {
1146     actor->OnSceneSignal().Connect(tracker, functor);
1147   }
1148   else if(name == SIGNAL_OFF_SCENE)
1149   {
1150     actor->OffSceneSignal().Connect(tracker, functor);
1151   }
1152   else if(name == SIGNAL_ON_RELAYOUT)
1153   {
1154     actor->OnRelayoutSignal().Connect(tracker, functor);
1155   }
1156   else if(name == SIGNAL_TOUCHED)
1157   {
1158     actor->TouchedSignal().Connect(tracker, functor);
1159   }
1160   else if(name == SIGNAL_VISIBILITY_CHANGED)
1161   {
1162     actor->VisibilityChangedSignal().Connect(tracker, functor);
1163   }
1164   else if(name == SIGNAL_LAYOUT_DIRECTION_CHANGED)
1165   {
1166     actor->LayoutDirectionChangedSignal().Connect(tracker, functor);
1167   }
1168   else if(name == SIGNAL_CHILD_ADDED)
1169   {
1170     actor->ChildAddedSignal().Connect(tracker, functor);
1171   }
1172   else if(name == SIGNAL_CHILD_REMOVED)
1173   {
1174     actor->ChildRemovedSignal().Connect(tracker, functor);
1175   }
1176   else
1177   {
1178     // signalName does not match any signal
1179     connected = false;
1180   }
1181
1182   return connected;
1183 }
1184
1185 Actor::Actor(DerivedType derivedType, const SceneGraph::Node& node)
1186 : Object(&node),
1187   mParentImpl(*this),
1188   mParent(nullptr),
1189   mScene(nullptr),
1190   mRenderers(nullptr),
1191   mParentOrigin(nullptr),
1192   mAnchorPoint(nullptr),
1193   mRelayoutData(nullptr),
1194   mGestureData(nullptr),
1195   mInterceptTouchedSignal(),
1196   mTouchedSignal(),
1197   mHoveredSignal(),
1198   mWheelEventSignal(),
1199   mOnSceneSignal(),
1200   mOffSceneSignal(),
1201   mOnRelayoutSignal(),
1202   mVisibilityChangedSignal(),
1203   mLayoutDirectionChangedSignal(),
1204   mTargetOrientation(Quaternion::IDENTITY),
1205   mTargetColor(Color::WHITE),
1206   mTargetSize(Vector3::ZERO),
1207   mTargetPosition(Vector3::ZERO),
1208   mTargetScale(Vector3::ONE),
1209   mAnimatedSize(Vector3::ZERO),
1210   mTouchAreaOffset(0, 0, 0, 0),
1211   mName(),
1212   mSortedDepth(0u),
1213   mDepth(0u),
1214   mUseAnimatedSize(AnimatedSizeFlag::CLEAR),
1215   mIsRoot(ROOT_LAYER == derivedType),
1216   mIsLayer(LAYER == derivedType || ROOT_LAYER == derivedType),
1217   mIsOnScene(false),
1218   mSensitive(true),
1219   mLeaveRequired(false),
1220   mKeyboardFocusable(false),
1221   mKeyboardFocusableChildren(true),
1222   mTouchFocusable(false),
1223   mOnSceneSignalled(false),
1224   mInsideOnSizeSet(false),
1225   mInheritPosition(true),
1226   mInheritOrientation(true),
1227   mInheritScale(true),
1228   mPositionUsesAnchorPoint(true),
1229   mVisible(true),
1230   mInheritLayoutDirection(true),
1231   mCaptureAllTouchAfterStart(false),
1232   mIsBlendEquationSet(false),
1233   mNeedGesturePropagation(false),
1234   mLayoutDirection(LayoutDirection::LEFT_TO_RIGHT),
1235   mDrawMode(DrawMode::NORMAL),
1236   mColorMode(Node::DEFAULT_COLOR_MODE),
1237   mClippingMode(ClippingMode::DISABLED),
1238   mBlendEquation(DevelBlendEquation::ADD)
1239 {
1240 }
1241
1242 void Actor::Initialize()
1243 {
1244   OnInitialize();
1245
1246   GetEventThreadServices().RegisterObject(this);
1247 }
1248
1249 Actor::~Actor()
1250 {
1251   // Remove mParent pointers from children even if we're destroying core,
1252   // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1253   UnparentChildren();
1254   delete mRenderers;
1255
1256   // Guard to allow handle destruction after Core has been destroyed
1257   if(EventThreadServices::IsCoreRunning())
1258   {
1259     // Root layer will destroy its node in its own destructor
1260     if(!mIsRoot)
1261     {
1262       DestroyNodeMessage(GetEventThreadServices().GetUpdateManager(), GetNode());
1263
1264       GetEventThreadServices().UnregisterObject(this);
1265     }
1266   }
1267
1268   // Cleanup optional gesture data
1269   delete mGestureData;
1270
1271   // Cleanup optional parent origin and anchor
1272   delete mParentOrigin;
1273   delete mAnchorPoint;
1274
1275   // Delete optional relayout data
1276   delete mRelayoutData;
1277 }
1278
1279 void Actor::Add(Actor& child, bool notify)
1280 {
1281   mParentImpl.Add(child, notify);
1282 }
1283
1284 void Actor::Remove(Actor& child, bool notify)
1285 {
1286   mParentImpl.Remove(child, notify);
1287 }
1288
1289 void Actor::SwitchParent(Actor& newParent)
1290 {
1291   if(this == &newParent)
1292   {
1293     DALI_LOG_ERROR("Cannot add actor to itself");
1294     return;
1295   }
1296
1297   if(!this->OnScene() || !newParent.OnScene())
1298   {
1299     DALI_LOG_ERROR("Both of current parent and new parent must be on Scene");
1300     return;
1301   }
1302
1303   newParent.Add(*this, false);
1304 }
1305
1306 uint32_t Actor::GetChildCount() const
1307 {
1308   return mParentImpl.GetChildCount();
1309 }
1310
1311 ActorPtr Actor::GetChildAt(uint32_t index) const
1312 {
1313   return mParentImpl.GetChildAt(index);
1314 }
1315
1316 ActorContainer& Actor::GetChildrenInternal()
1317 {
1318   return mParentImpl.GetChildrenInternal();
1319 }
1320
1321 ActorPtr Actor::FindChildByName(ConstString actorName)
1322 {
1323   return mParentImpl.FindChildByName(actorName);
1324 }
1325
1326 ActorPtr Actor::FindChildById(const uint32_t id)
1327 {
1328   return mParentImpl.FindChildById(id);
1329 }
1330
1331 void Actor::UnparentChildren()
1332 {
1333   mParentImpl.UnparentChildren();
1334 }
1335
1336 void Actor::ConnectToScene(uint32_t parentDepth, bool notify)
1337 {
1338   // This container is used instead of walking the Actor hierarchy.
1339   // It protects us when the Actor hierarchy is modified during OnSceneConnectionExternal callbacks.
1340   ActorContainer connectionList;
1341
1342   if(mScene)
1343   {
1344     mScene->RequestRebuildDepthTree();
1345   }
1346
1347   // This stage is atomic i.e. not interrupted by user callbacks.
1348   RecursiveConnectToScene(connectionList, parentDepth + 1);
1349
1350   // Notify applications about the newly connected actors.
1351   for(const auto& actor : connectionList)
1352   {
1353     actor->NotifyStageConnection(notify);
1354   }
1355
1356   RelayoutRequest();
1357 }
1358
1359 void Actor::RecursiveConnectToScene(ActorContainer& connectionList, uint32_t depth)
1360 {
1361   DALI_ASSERT_ALWAYS(!OnScene());
1362
1363   mIsOnScene = true;
1364   mDepth     = static_cast<uint16_t>(depth); // overflow ignored, not expected in practice
1365
1366   ConnectToSceneGraph();
1367
1368   // Notification for internal derived classes
1369   OnSceneConnectionInternal();
1370
1371   // This stage is atomic; avoid emitting callbacks until all Actors are connected
1372   connectionList.push_back(ActorPtr(this));
1373
1374   // Recursively connect children
1375   if(GetChildCount() > 0)
1376   {
1377     for(const auto& child : mParentImpl.GetChildrenInternal())
1378     {
1379       child->SetScene(*mScene);
1380       child->RecursiveConnectToScene(connectionList, depth + 1);
1381     }
1382   }
1383 }
1384
1385 /**
1386  * This method is called when the Actor is connected to the Stage.
1387  * The parent must have added its Node to the scene-graph.
1388  * The child must connect its Node to the parent's Node.
1389  * This is recursive; the child calls ConnectToScene() for its children.
1390  */
1391 void Actor::ConnectToSceneGraph()
1392 {
1393   DALI_ASSERT_DEBUG(mParent != NULL);
1394
1395   // Reparent Node in next Update
1396   ConnectNodeMessage(GetEventThreadServices().GetUpdateManager(), GetParent()->GetNode(), GetNode());
1397
1398   // Request relayout on all actors that are added to the scenegraph
1399   RelayoutRequest();
1400
1401   // Notification for Object::Observers
1402   OnSceneObjectAdd();
1403 }
1404
1405 void Actor::NotifyStageConnection(bool notify)
1406 {
1407   // Actors can be removed (in a callback), before the on-stage stage is reported.
1408   // The actor may also have been reparented, in which case mOnSceneSignalled will be true.
1409   if(OnScene() && !mOnSceneSignalled)
1410   {
1411     if(notify)
1412     {
1413       // Notification for external (CustomActor) derived classes
1414       OnSceneConnectionExternal(mDepth);
1415
1416       if(!mOnSceneSignal.Empty())
1417       {
1418         Dali::Actor handle(this);
1419         mOnSceneSignal.Emit(handle);
1420       }
1421     }
1422
1423     // Guard against Remove during callbacks
1424     if(OnScene())
1425     {
1426       mOnSceneSignalled = true; // signal required next time Actor is removed
1427     }
1428   }
1429 }
1430
1431 void Actor::DisconnectFromStage(bool notify)
1432 {
1433   // This container is used instead of walking the Actor hierachy.
1434   // It protects us when the Actor hierachy is modified during OnSceneDisconnectionExternal callbacks.
1435   ActorContainer disconnectionList;
1436
1437   if(mScene)
1438   {
1439     mScene->RequestRebuildDepthTree();
1440   }
1441
1442   // This stage is atomic i.e. not interrupted by user callbacks
1443   RecursiveDisconnectFromStage(disconnectionList);
1444
1445   // Notify applications about the newly disconnected actors.
1446   for(const auto& actor : disconnectionList)
1447   {
1448     actor->NotifyStageDisconnection(notify);
1449   }
1450 }
1451
1452 void Actor::RecursiveDisconnectFromStage(ActorContainer& disconnectionList)
1453 {
1454   // need to change state first so that internals relying on IsOnScene() inside OnSceneDisconnectionInternal() get the correct value
1455   mIsOnScene = false;
1456
1457   // Recursively disconnect children
1458   if(GetChildCount() > 0)
1459   {
1460     for(const auto& child : mParentImpl.GetChildrenInternal())
1461     {
1462       child->RecursiveDisconnectFromStage(disconnectionList);
1463     }
1464   }
1465
1466   // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
1467   disconnectionList.push_back(ActorPtr(this));
1468
1469   // Notification for internal derived classes
1470   OnSceneDisconnectionInternal();
1471
1472   DisconnectFromSceneGraph();
1473 }
1474
1475 /**
1476  * This method is called by an actor or its parent, before a node removal message is sent.
1477  * This is recursive; the child calls DisconnectFromStage() for its children.
1478  */
1479 void Actor::DisconnectFromSceneGraph()
1480 {
1481   // Notification for Object::Observers
1482   OnSceneObjectRemove();
1483 }
1484
1485 void Actor::NotifyStageDisconnection(bool notify)
1486 {
1487   // Actors can be added (in a callback), before the off-stage state is reported.
1488   // Also if the actor was added & removed before mOnSceneSignalled was set, then we don't notify here.
1489   // only do this step if there is a stage, i.e. Core is not being shut down
1490   if(EventThreadServices::IsCoreRunning() && !OnScene() && mOnSceneSignalled)
1491   {
1492     if(notify)
1493     {
1494       // Notification for external (CustomeActor) derived classes
1495       OnSceneDisconnectionExternal();
1496
1497       if(!mOffSceneSignal.Empty())
1498       {
1499         Dali::Actor handle(this);
1500         mOffSceneSignal.Emit(handle);
1501       }
1502     }
1503
1504     // Guard against Add during callbacks
1505     if(!OnScene())
1506     {
1507       mOnSceneSignalled = false; // signal required next time Actor is added
1508     }
1509   }
1510 }
1511
1512 bool Actor::IsNodeConnected() const
1513 {
1514   bool connected(false);
1515
1516   if(OnScene())
1517   {
1518     if(IsRoot() || GetNode().GetParent())
1519     {
1520       connected = true;
1521     }
1522   }
1523
1524   return connected;
1525 }
1526
1527 // This method initiates traversal of the actor tree using depth-first
1528 // traversal to set a depth index based on traversal order. It sends a
1529 // single message to update manager to update all the actor's nodes in
1530 // this tree with the depth index. The sceneGraphNodeDepths vector's
1531 // elements are ordered by depth, and could be used to reduce sorting
1532 // in the update thread.
1533 void Actor::RebuildDepthTree()
1534 {
1535   DALI_LOG_TIMER_START(depthTimer);
1536
1537   // Vector of scene-graph nodes and their depths to send to UpdateManager
1538   // in a single message
1539   OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths(new SceneGraph::NodeDepths());
1540
1541   int32_t depthIndex = 1;
1542   DepthTraverseActorTree(sceneGraphNodeDepths, depthIndex);
1543
1544   SetDepthIndicesMessage(GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths);
1545   DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
1546 }
1547
1548 void Actor::DepthTraverseActorTree(OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths, int32_t& depthIndex)
1549 {
1550   mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
1551   sceneGraphNodeDepths->Add(const_cast<SceneGraph::Node*>(&GetNode()), mSortedDepth);
1552
1553   // Create/add to children of this node
1554   if(GetChildCount() > 0)
1555   {
1556     for(const auto& child : mParentImpl.GetChildrenInternal())
1557     {
1558       Actor* childActor = child.Get();
1559       ++depthIndex;
1560       childActor->DepthTraverseActorTree(sceneGraphNodeDepths, depthIndex);
1561     }
1562   }
1563 }
1564
1565 void Actor::SetDefaultProperty(Property::Index index, const Property::Value& property)
1566 {
1567   PropertyHandler::SetDefaultProperty(*this, index, property);
1568 }
1569
1570 // TODO: This method needs to be removed
1571 void Actor::SetSceneGraphProperty(Property::Index index, const PropertyMetadata& entry, const Property::Value& value)
1572 {
1573   PropertyHandler::SetSceneGraphProperty(index, entry, value, GetEventThreadServices(), GetNode());
1574 }
1575
1576 Property::Value Actor::GetDefaultProperty(Property::Index index) const
1577 {
1578   Property::Value value;
1579
1580   if(!GetCachedPropertyValue(index, value))
1581   {
1582     // If property value is not stored in the event-side, then it must be a scene-graph only property
1583     GetCurrentPropertyValue(index, value);
1584   }
1585
1586   return value;
1587 }
1588
1589 Property::Value Actor::GetDefaultPropertyCurrentValue(Property::Index index) const
1590 {
1591   Property::Value value;
1592
1593   if(!GetCurrentPropertyValue(index, value))
1594   {
1595     // If unable to retrieve scene-graph property value, then it must be an event-side only property
1596     GetCachedPropertyValue(index, value);
1597   }
1598
1599   return value;
1600 }
1601
1602 void Actor::OnNotifyDefaultPropertyAnimation(Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType)
1603 {
1604   PropertyHandler::OnNotifyDefaultPropertyAnimation(*this, animation, index, value, animationType);
1605 }
1606
1607 const PropertyBase* Actor::GetSceneObjectAnimatableProperty(Property::Index index) const
1608 {
1609   const PropertyBase* property = PropertyHandler::GetSceneObjectAnimatableProperty(index, GetNode());
1610   if(!property)
1611   {
1612     // not our property, ask base
1613     property = Object::GetSceneObjectAnimatableProperty(index);
1614   }
1615
1616   return property;
1617 }
1618
1619 const PropertyInputImpl* Actor::GetSceneObjectInputProperty(Property::Index index) const
1620 {
1621   const PropertyInputImpl* property = PropertyHandler::GetSceneObjectInputProperty(index, GetNode());
1622   if(!property)
1623   {
1624     // reuse animatable property getter as animatable properties are inputs as well
1625     // animatable property chains back to Object::GetSceneObjectInputProperty() so all properties get covered
1626     property = GetSceneObjectAnimatableProperty(index);
1627   }
1628
1629   return property;
1630 }
1631
1632 int32_t Actor::GetPropertyComponentIndex(Property::Index index) const
1633 {
1634   int32_t componentIndex = PropertyHandler::GetPropertyComponentIndex(index);
1635   if(Property::INVALID_COMPONENT_INDEX == componentIndex)
1636   {
1637     // ask base
1638     componentIndex = Object::GetPropertyComponentIndex(index);
1639   }
1640
1641   return componentIndex;
1642 }
1643
1644 const SceneGraph::Node& Actor::GetNode() const
1645 {
1646   return *static_cast<const SceneGraph::Node*>(mUpdateObject);
1647 }
1648
1649 void Actor::Raise()
1650 {
1651   if(mParent)
1652   {
1653     mParent->RaiseChild(*this);
1654   }
1655   else
1656   {
1657     DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
1658   }
1659 }
1660
1661 void Actor::Lower()
1662 {
1663   if(mParent)
1664   {
1665     mParent->LowerChild(*this);
1666   }
1667   else
1668   {
1669     DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
1670   }
1671 }
1672
1673 void Actor::RaiseToTop()
1674 {
1675   if(mParent)
1676   {
1677     mParent->RaiseChildToTop(*this);
1678   }
1679   else
1680   {
1681     DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
1682   }
1683 }
1684
1685 void Actor::LowerToBottom()
1686 {
1687   if(mParent)
1688   {
1689     mParent->LowerChildToBottom(*this);
1690   }
1691   else
1692   {
1693     DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
1694   }
1695 }
1696
1697 void Actor::RaiseAbove(Internal::Actor& target)
1698 {
1699   if(mParent)
1700   {
1701     mParent->RaiseChildAbove(*this, target);
1702   }
1703   else
1704   {
1705     DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
1706   }
1707 }
1708
1709 void Actor::LowerBelow(Internal::Actor& target)
1710 {
1711   if(mParent)
1712   {
1713     mParent->LowerChildBelow(*this, target);
1714   }
1715   else
1716   {
1717     DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
1718   }
1719 }
1720
1721 void Actor::SetParent(ActorParent* parent, bool notify)
1722 {
1723   if(parent)
1724   {
1725     DALI_ASSERT_ALWAYS(!mParent && "Actor cannot have 2 parents");
1726
1727     mParent            = parent;
1728     Actor* parentActor = static_cast<Actor*>(parent);
1729     mScene             = parentActor->mScene;
1730
1731     if(EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1732        parentActor->OnScene())
1733     {
1734       // Instruct each actor to create a corresponding node in the scene graph
1735       ConnectToScene(parentActor->GetHierarchyDepth(), notify);
1736     }
1737
1738     // Resolve the name and index for the child properties if any
1739     ResolveChildProperties();
1740   }
1741   else // parent being set to NULL
1742   {
1743     DALI_ASSERT_ALWAYS(mParent != nullptr && "Actor should have a parent");
1744
1745     mParent = nullptr;
1746
1747     if(EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1748        OnScene())
1749     {
1750       // Disconnect the Node & its children from the scene-graph.
1751       DisconnectNodeMessage(GetEventThreadServices().GetUpdateManager(), GetNode());
1752
1753       // Instruct each actor to discard pointers to the scene-graph
1754       DisconnectFromStage(notify);
1755     }
1756
1757     mScene = nullptr;
1758   }
1759 }
1760
1761 bool Actor::DoAction(BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */)
1762 {
1763   bool   done  = false;
1764   Actor* actor = dynamic_cast<Actor*>(object);
1765
1766   if(actor)
1767   {
1768     std::string_view name(actionName);
1769     if(name == ACTION_SHOW)
1770     {
1771       actor->SetVisible(true);
1772       done = true;
1773     }
1774     else if(name == ACTION_HIDE)
1775     {
1776       actor->SetVisible(false);
1777       done = true;
1778     }
1779   }
1780
1781   return done;
1782 }
1783
1784 Rect<> Actor::CalculateScreenExtents() const
1785 {
1786   auto    screenPosition    = GetCurrentScreenPosition();
1787   Vector3 size              = GetCurrentSize() * GetCurrentWorldScale();
1788   Vector3 anchorPointOffSet = size * (mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT);
1789   Vector2 position          = Vector2(screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y);
1790   return {position.x, position.y, size.x, size.y};
1791 }
1792
1793 void Actor::SetNeedGesturePropagation(bool propagation)
1794 {
1795   mNeedGesturePropagation = propagation;
1796 }
1797
1798 bool Actor::NeedGesturePropagation()
1799 {
1800   return mNeedGesturePropagation;
1801 }
1802
1803 bool Actor::GetCachedPropertyValue(Property::Index index, Property::Value& value) const
1804 {
1805   return PropertyHandler::GetCachedPropertyValue(*this, index, value);
1806 }
1807
1808 bool Actor::GetCurrentPropertyValue(Property::Index index, Property::Value& value) const
1809 {
1810   return PropertyHandler::GetCurrentPropertyValue(*this, index, value);
1811 }
1812
1813 Actor::Relayouter& Actor::EnsureRelayouter()
1814 {
1815   // Assign relayouter
1816   if(!mRelayoutData)
1817   {
1818     mRelayoutData = new Relayouter();
1819   }
1820
1821   return *mRelayoutData;
1822 }
1823
1824 bool Actor::RelayoutDependentOnParent(Dimension::Type dimension)
1825 {
1826   // Check if actor is dependent on parent
1827   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
1828   {
1829     if((dimension & (1 << i)))
1830     {
1831       const ResizePolicy::Type resizePolicy = GetResizePolicy(static_cast<Dimension::Type>(1 << i));
1832       if(resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT)
1833       {
1834         return true;
1835       }
1836     }
1837   }
1838
1839   return false;
1840 }
1841
1842 bool Actor::RelayoutDependentOnChildren(Dimension::Type dimension)
1843 {
1844   // Check if actor is dependent on children
1845   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
1846   {
1847     if((dimension & (1 << i)))
1848     {
1849       const ResizePolicy::Type resizePolicy = GetResizePolicy(static_cast<Dimension::Type>(1 << i));
1850       switch(resizePolicy)
1851       {
1852         case ResizePolicy::FIT_TO_CHILDREN:
1853         case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
1854         {
1855           return true;
1856         }
1857
1858         default:
1859         {
1860           break;
1861         }
1862       }
1863     }
1864   }
1865
1866   return false;
1867 }
1868
1869 bool Actor::RelayoutDependentOnChildrenBase(Dimension::Type dimension)
1870 {
1871   return Actor::RelayoutDependentOnChildren(dimension);
1872 }
1873
1874 bool Actor::RelayoutDependentOnDimension(Dimension::Type dimension, Dimension::Type dependentDimension)
1875 {
1876   // Check each possible dimension and see if it is dependent on the input one
1877   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
1878   {
1879     if(dimension & (1 << i))
1880     {
1881       return mRelayoutData->resizePolicies[i] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[i] == dependentDimension;
1882     }
1883   }
1884
1885   return false;
1886 }
1887
1888 void Actor::SetNegotiatedDimension(float negotiatedDimension, Dimension::Type dimension)
1889 {
1890   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
1891   {
1892     if(dimension & (1 << i))
1893     {
1894       mRelayoutData->negotiatedDimensions[i] = negotiatedDimension;
1895     }
1896   }
1897 }
1898
1899 float Actor::GetNegotiatedDimension(Dimension::Type dimension) const
1900 {
1901   // If more than one dimension is requested, just return the first one found
1902   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
1903   {
1904     if((dimension & (1 << i)))
1905     {
1906       return mRelayoutData->negotiatedDimensions[i];
1907     }
1908   }
1909
1910   return 0.0f; // Default
1911 }
1912
1913 void Actor::SetPadding(const Vector2& padding, Dimension::Type dimension)
1914 {
1915   EnsureRelayouter().SetPadding(padding, dimension);
1916 }
1917
1918 Vector2 Actor::GetPadding(Dimension::Type dimension) const
1919 {
1920   if(mRelayoutData)
1921   {
1922     // If more than one dimension is requested, just return the first one found
1923     for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
1924     {
1925       if((dimension & (1 << i)))
1926       {
1927         return mRelayoutData->dimensionPadding[i];
1928       }
1929     }
1930   }
1931
1932   return Relayouter::DEFAULT_DIMENSION_PADDING;
1933 }
1934
1935 void Actor::SetLayoutNegotiated(bool negotiated, Dimension::Type dimension)
1936 {
1937   EnsureRelayouter().SetLayoutNegotiated(negotiated, dimension);
1938 }
1939
1940 bool Actor::IsLayoutNegotiated(Dimension::Type dimension) const
1941 {
1942   return mRelayoutData && mRelayoutData->IsLayoutNegotiated(dimension);
1943 }
1944
1945 float Actor::GetHeightForWidthBase(float width)
1946 {
1947   float height = 0.0f;
1948
1949   const Vector3 naturalSize = GetNaturalSize();
1950   if(naturalSize.width > 0.0f)
1951   {
1952     height = naturalSize.height * width / naturalSize.width;
1953   }
1954   else // we treat 0 as 1:1 aspect ratio
1955   {
1956     height = width;
1957   }
1958
1959   return height;
1960 }
1961
1962 float Actor::GetWidthForHeightBase(float height)
1963 {
1964   float width = 0.0f;
1965
1966   const Vector3 naturalSize = GetNaturalSize();
1967   if(naturalSize.height > 0.0f)
1968   {
1969     width = naturalSize.width * height / naturalSize.height;
1970   }
1971   else // we treat 0 as 1:1 aspect ratio
1972   {
1973     width = height;
1974   }
1975
1976   return width;
1977 }
1978
1979 float Actor::CalculateChildSizeBase(const Dali::Actor& child, Dimension::Type dimension)
1980 {
1981   // Fill to parent, taking size mode factor into account
1982   switch(child.GetResizePolicy(dimension))
1983   {
1984     case ResizePolicy::FILL_TO_PARENT:
1985     {
1986       return GetLatestSize(dimension);
1987     }
1988
1989     case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
1990     {
1991       return GetLatestSize(dimension) * GetDimensionValue(child.GetProperty<Vector3>(Dali::Actor::Property::SIZE_MODE_FACTOR), dimension);
1992     }
1993
1994     case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
1995     {
1996       return GetLatestSize(dimension) + GetDimensionValue(child.GetProperty<Vector3>(Dali::Actor::Property::SIZE_MODE_FACTOR), dimension);
1997     }
1998
1999     default:
2000     {
2001       return GetLatestSize(dimension);
2002     }
2003   }
2004 }
2005
2006 float Actor::CalculateChildSize(const Dali::Actor& child, Dimension::Type dimension)
2007 {
2008   // Can be overridden in derived class
2009   return CalculateChildSizeBase(child, dimension);
2010 }
2011
2012 float Actor::GetHeightForWidth(float width)
2013 {
2014   // Can be overridden in derived class
2015   return GetHeightForWidthBase(width);
2016 }
2017
2018 float Actor::GetWidthForHeight(float height)
2019 {
2020   // Can be overridden in derived class
2021   return GetWidthForHeightBase(height);
2022 }
2023
2024 float Actor::GetLatestSize(Dimension::Type dimension) const
2025 {
2026   return IsLayoutNegotiated(dimension) ? GetNegotiatedDimension(dimension) : GetSize(dimension);
2027 }
2028
2029 float Actor::GetRelayoutSize(Dimension::Type dimension) const
2030 {
2031   Vector2 padding = GetPadding(dimension);
2032
2033   return GetLatestSize(dimension) + padding.x + padding.y;
2034 }
2035
2036 float Actor::NegotiateFromParent(Dimension::Type dimension)
2037 {
2038   Actor* parent = GetParent();
2039   if(parent)
2040   {
2041     Vector2 padding(GetPadding(dimension));
2042     Vector2 parentPadding(parent->GetPadding(dimension));
2043     return parent->CalculateChildSize(Dali::Actor(this), dimension) - parentPadding.x - parentPadding.y - padding.x - padding.y;
2044   }
2045
2046   return 0.0f;
2047 }
2048
2049 float Actor::NegotiateFromChildren(Dimension::Type dimension)
2050 {
2051   float maxDimensionPoint = 0.0f;
2052
2053   for(uint32_t i = 0, count = GetChildCount(); i < count; ++i)
2054   {
2055     ActorPtr child = GetChildAt(i);
2056
2057     if(!child->RelayoutDependentOnParent(dimension))
2058     {
2059       // Calculate the min and max points that the children range across
2060       float childPosition = GetDimensionValue(child->GetTargetPosition(), dimension);
2061       float dimensionSize = child->GetRelayoutSize(dimension);
2062       maxDimensionPoint   = std::max(maxDimensionPoint, childPosition + dimensionSize);
2063     }
2064   }
2065
2066   return maxDimensionPoint;
2067 }
2068
2069 float Actor::GetSize(Dimension::Type dimension) const
2070 {
2071   return GetDimensionValue(mTargetSize, dimension);
2072 }
2073
2074 float Actor::GetNaturalSize(Dimension::Type dimension) const
2075 {
2076   return GetDimensionValue(GetNaturalSize(), dimension);
2077 }
2078
2079 float Actor::CalculateSize(Dimension::Type dimension, const Vector2& maximumSize)
2080 {
2081   switch(GetResizePolicy(dimension))
2082   {
2083     case ResizePolicy::USE_NATURAL_SIZE:
2084     {
2085       return GetNaturalSize(dimension);
2086     }
2087
2088     case ResizePolicy::FIXED:
2089     {
2090       return GetDimensionValue(GetPreferredSize(), dimension);
2091     }
2092
2093     case ResizePolicy::USE_ASSIGNED_SIZE:
2094     {
2095       return GetDimensionValue(maximumSize, dimension);
2096     }
2097
2098     case ResizePolicy::FILL_TO_PARENT:
2099     case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2100     case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2101     {
2102       return NegotiateFromParent(dimension);
2103     }
2104
2105     case ResizePolicy::FIT_TO_CHILDREN:
2106     {
2107       return NegotiateFromChildren(dimension);
2108     }
2109
2110     case ResizePolicy::DIMENSION_DEPENDENCY:
2111     {
2112       const Dimension::Type dimensionDependency = GetDimensionDependency(dimension);
2113
2114       // Custom rules
2115       if(dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT)
2116       {
2117         return GetWidthForHeight(GetNegotiatedDimension(Dimension::HEIGHT));
2118       }
2119
2120       if(dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH)
2121       {
2122         return GetHeightForWidth(GetNegotiatedDimension(Dimension::WIDTH));
2123       }
2124
2125       break;
2126     }
2127
2128     default:
2129     {
2130       break;
2131     }
2132   }
2133
2134   return 0.0f; // Default
2135 }
2136
2137 Vector2 Actor::ApplySizeSetPolicy(const Vector2& size)
2138 {
2139   return mRelayoutData->ApplySizeSetPolicy(*this, size);
2140 }
2141
2142 void Actor::SetNegotiatedSize(RelayoutContainer& container)
2143 {
2144   // Do the set actor size
2145   Vector2 negotiatedSize(GetLatestSize(Dimension::WIDTH), GetLatestSize(Dimension::HEIGHT));
2146
2147   // Adjust for size set policy
2148   negotiatedSize = ApplySizeSetPolicy(negotiatedSize);
2149
2150   // Lock the flag to stop recursive relayouts on set size
2151   mRelayoutData->insideRelayout = true;
2152   SetSize(negotiatedSize);
2153   mRelayoutData->insideRelayout = false;
2154
2155   // Clear flags for all dimensions
2156   SetLayoutDirty(false);
2157
2158   // Give deriving classes a chance to respond
2159   OnRelayout(negotiatedSize, container);
2160
2161   if(!mOnRelayoutSignal.Empty())
2162   {
2163     Dali::Actor handle(this);
2164     mOnRelayoutSignal.Emit(handle);
2165   }
2166 }
2167
2168 void Actor::NegotiateSize(const Vector2& allocatedSize, RelayoutContainer& container)
2169 {
2170   Relayouter::NegotiateSize(*this, allocatedSize, container);
2171 }
2172
2173 void Actor::SetUseAssignedSize(bool use, Dimension::Type dimension)
2174 {
2175   if(mRelayoutData)
2176   {
2177     mRelayoutData->SetUseAssignedSize(use, dimension);
2178   }
2179 }
2180
2181 bool Actor::GetUseAssignedSize(Dimension::Type dimension) const
2182 {
2183   return mRelayoutData && mRelayoutData->GetUseAssignedSize(dimension);
2184 }
2185
2186 void Actor::RelayoutRequest(Dimension::Type dimension)
2187 {
2188   Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
2189   if(relayoutController)
2190   {
2191     Dali::Actor self(this);
2192     relayoutController->RequestRelayout(self, dimension);
2193   }
2194 }
2195
2196 void Actor::SetPreferredSize(const Vector2& size)
2197 {
2198   EnsureRelayouter().SetPreferredSize(*this, size);
2199 }
2200
2201 Vector2 Actor::GetPreferredSize() const
2202 {
2203   if(mRelayoutData)
2204   {
2205     return Vector2(mRelayoutData->preferredSize);
2206   }
2207
2208   return Relayouter::DEFAULT_PREFERRED_SIZE;
2209 }
2210
2211 void Actor::SetMinimumSize(float size, Dimension::Type dimension)
2212 {
2213   EnsureRelayouter().SetMinimumSize(size, dimension);
2214   RelayoutRequest();
2215 }
2216
2217 float Actor::GetMinimumSize(Dimension::Type dimension) const
2218 {
2219   if(mRelayoutData)
2220   {
2221     return mRelayoutData->GetMinimumSize(dimension);
2222   }
2223
2224   return 0.0f; // Default
2225 }
2226
2227 void Actor::SetMaximumSize(float size, Dimension::Type dimension)
2228 {
2229   EnsureRelayouter().SetMaximumSize(size, dimension);
2230   RelayoutRequest();
2231 }
2232
2233 float Actor::GetMaximumSize(Dimension::Type dimension) const
2234 {
2235   if(mRelayoutData)
2236   {
2237     return mRelayoutData->GetMaximumSize(dimension);
2238   }
2239
2240   return FLT_MAX; // Default
2241 }
2242
2243 void Actor::SetVisibleInternal(bool visible, SendMessage::Type sendMessage)
2244 {
2245   if(mVisible != visible)
2246   {
2247     if(sendMessage == SendMessage::TRUE)
2248     {
2249       // node is being used in a separate thread; queue a message to set the value & base value
2250       SceneGraph::NodePropertyMessage<bool>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible);
2251
2252       RequestRenderingMessage(GetEventThreadServices().GetUpdateManager());
2253     }
2254
2255     mVisible = visible;
2256
2257     // Emit the signal on this actor and all its children
2258     EmitVisibilityChangedSignalRecursively(visible, DevelActor::VisibilityChange::SELF);
2259   }
2260 }
2261
2262 void Actor::SetSiblingOrderOfChild(Actor& child, uint32_t order)
2263 {
2264   mParentImpl.SetSiblingOrderOfChild(child, order);
2265 }
2266
2267 uint32_t Actor::GetSiblingOrderOfChild(const Actor& child) const
2268 {
2269   return mParentImpl.GetSiblingOrderOfChild(child);
2270 }
2271
2272 void Actor::RaiseChild(Actor& child)
2273 {
2274   mParentImpl.RaiseChild(child);
2275 }
2276
2277 void Actor::LowerChild(Actor& child)
2278 {
2279   mParentImpl.LowerChild(child);
2280 }
2281
2282 void Actor::RaiseChildToTop(Actor& child)
2283 {
2284   mParentImpl.RaiseChildToTop(child);
2285 }
2286
2287 void Actor::LowerChildToBottom(Actor& child)
2288 {
2289   mParentImpl.LowerChildToBottom(child);
2290 }
2291
2292 void Actor::RaiseChildAbove(Actor& child, Actor& target)
2293 {
2294   mParentImpl.RaiseChildAbove(child, target);
2295 }
2296
2297 void Actor::LowerChildBelow(Actor& child, Actor& target)
2298 {
2299   mParentImpl.LowerChildBelow(child, target);
2300 }
2301
2302 void Actor::SetInheritLayoutDirection(bool inherit)
2303 {
2304   if(mInheritLayoutDirection != inherit)
2305   {
2306     mInheritLayoutDirection = inherit;
2307
2308     if(inherit && mParent)
2309     {
2310       InheritLayoutDirectionRecursively(GetParent()->mLayoutDirection);
2311     }
2312   }
2313 }
2314
2315 void Actor::InheritLayoutDirectionRecursively(Dali::LayoutDirection::Type direction, bool set)
2316 {
2317   if(mInheritLayoutDirection || set)
2318   {
2319     if(mLayoutDirection != direction)
2320     {
2321       mLayoutDirection = direction;
2322       EmitLayoutDirectionChangedSignal(direction);
2323       RelayoutRequest();
2324     }
2325
2326     if(GetChildCount() > 0)
2327     {
2328       for(const auto& child : mParentImpl.GetChildrenInternal())
2329       {
2330         child->InheritLayoutDirectionRecursively(direction);
2331       }
2332     }
2333   }
2334 }
2335
2336 void Actor::SetUpdateSizeHint(const Vector2& updateSizeHint)
2337 {
2338   // node is being used in a separate thread; queue a message to set the value & base value
2339   SceneGraph::NodePropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mUpdateSizeHint, &AnimatableProperty<Vector3>::Bake, Vector3(updateSizeHint.width, updateSizeHint.height, 0.f));
2340 }
2341
2342 void Actor::EmitVisibilityChangedSignalRecursively(bool                               visible,
2343                                                    DevelActor::VisibilityChange::Type type)
2344 {
2345   EmitVisibilityChangedSignal(visible, type);
2346
2347   if(GetChildCount() > 0)
2348   {
2349     for(auto& child : mParentImpl.GetChildrenInternal())
2350     {
2351       child->EmitVisibilityChangedSignalRecursively(visible, DevelActor::VisibilityChange::PARENT);
2352     }
2353   }
2354 }
2355
2356 } // namespace Internal
2357
2358 } // namespace Dali