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