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