Merge "Add Gesture Propagation" into devel/master
[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   mIsBlendEquationSet(false),
1345   mNeedGesturePropagation(false),
1346   mLayoutDirection(LayoutDirection::LEFT_TO_RIGHT),
1347   mDrawMode(DrawMode::NORMAL),
1348   mColorMode(Node::DEFAULT_COLOR_MODE),
1349   mClippingMode(ClippingMode::DISABLED),
1350   mBlendEquation(DevelBlendEquation::ADD)
1351 {
1352 }
1353
1354 void Actor::Initialize()
1355 {
1356   OnInitialize();
1357
1358   GetEventThreadServices().RegisterObject(this);
1359 }
1360
1361 Actor::~Actor()
1362 {
1363   // Remove mParent pointers from children even if we're destroying core,
1364   // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1365   UnparentChildren();
1366   delete mRenderers;
1367
1368   // Guard to allow handle destruction after Core has been destroyed
1369   if(EventThreadServices::IsCoreRunning())
1370   {
1371     // Root layer will destroy its node in its own destructor
1372     if(!mIsRoot)
1373     {
1374       DestroyNodeMessage(GetEventThreadServices().GetUpdateManager(), GetNode());
1375
1376       GetEventThreadServices().UnregisterObject(this);
1377     }
1378   }
1379
1380   // Cleanup optional gesture data
1381   delete mGestureData;
1382
1383   // Cleanup optional parent origin and anchor
1384   delete mParentOrigin;
1385   delete mAnchorPoint;
1386
1387   // Delete optional relayout data
1388   delete mRelayoutData;
1389 }
1390
1391 void Actor::Add(Actor& child)
1392 {
1393   mParentImpl.Add(child);
1394 }
1395
1396 void Actor::Remove(Actor& child)
1397 {
1398   mParentImpl.Remove(child);
1399 }
1400
1401 uint32_t Actor::GetChildCount() const
1402 {
1403   return mParentImpl.GetChildCount();
1404 }
1405
1406 ActorPtr Actor::GetChildAt(uint32_t index) const
1407 {
1408   return mParentImpl.GetChildAt(index);
1409 }
1410
1411 ActorContainer& Actor::GetChildrenInternal()
1412 {
1413   return mParentImpl.GetChildrenInternal();
1414 }
1415
1416 ActorPtr Actor::FindChildByName(ConstString actorName)
1417 {
1418   return mParentImpl.FindChildByName(actorName);
1419 }
1420
1421 ActorPtr Actor::FindChildById(const uint32_t id)
1422 {
1423   return mParentImpl.FindChildById(id);
1424 }
1425
1426 void Actor::UnparentChildren()
1427 {
1428   mParentImpl.UnparentChildren();
1429 }
1430
1431 void Actor::ConnectToScene(uint32_t parentDepth)
1432 {
1433   // This container is used instead of walking the Actor hierarchy.
1434   // It protects us when the Actor hierarchy is modified during OnSceneConnectionExternal callbacks.
1435   ActorContainer connectionList;
1436
1437   if(mScene)
1438   {
1439     mScene->RequestRebuildDepthTree();
1440   }
1441
1442   // This stage is atomic i.e. not interrupted by user callbacks.
1443   RecursiveConnectToScene(connectionList, parentDepth + 1);
1444
1445   // Notify applications about the newly connected actors.
1446   for(const auto& actor : connectionList)
1447   {
1448     actor->NotifyStageConnection();
1449   }
1450
1451   RelayoutRequest();
1452 }
1453
1454 void Actor::RecursiveConnectToScene(ActorContainer& connectionList, uint32_t depth)
1455 {
1456   DALI_ASSERT_ALWAYS(!OnScene());
1457
1458   mIsOnScene = true;
1459   mDepth     = static_cast<uint16_t>(depth); // overflow ignored, not expected in practice
1460
1461   ConnectToSceneGraph();
1462
1463   // Notification for internal derived classes
1464   OnSceneConnectionInternal();
1465
1466   // This stage is atomic; avoid emitting callbacks until all Actors are connected
1467   connectionList.push_back(ActorPtr(this));
1468
1469   // Recursively connect children
1470   if(GetChildCount() > 0)
1471   {
1472     for(const auto& child : mParentImpl.GetChildrenInternal())
1473     {
1474       child->SetScene(*mScene);
1475       child->RecursiveConnectToScene(connectionList, depth + 1);
1476     }
1477   }
1478 }
1479
1480 /**
1481  * This method is called when the Actor is connected to the Stage.
1482  * The parent must have added its Node to the scene-graph.
1483  * The child must connect its Node to the parent's Node.
1484  * This is recursive; the child calls ConnectToScene() for its children.
1485  */
1486 void Actor::ConnectToSceneGraph()
1487 {
1488   DALI_ASSERT_DEBUG(mParent != NULL);
1489
1490   // Reparent Node in next Update
1491   ConnectNodeMessage(GetEventThreadServices().GetUpdateManager(), GetParent()->GetNode(), GetNode());
1492
1493   // Request relayout on all actors that are added to the scenegraph
1494   RelayoutRequest();
1495
1496   // Notification for Object::Observers
1497   OnSceneObjectAdd();
1498 }
1499
1500 void Actor::NotifyStageConnection()
1501 {
1502   // Actors can be removed (in a callback), before the on-stage stage is reported.
1503   // The actor may also have been reparented, in which case mOnSceneSignalled will be true.
1504   if(OnScene() && !mOnSceneSignalled)
1505   {
1506     // Notification for external (CustomActor) derived classes
1507     OnSceneConnectionExternal(mDepth);
1508
1509     if(!mOnSceneSignal.Empty())
1510     {
1511       Dali::Actor handle(this);
1512       mOnSceneSignal.Emit(handle);
1513     }
1514
1515     // Guard against Remove during callbacks
1516     if(OnScene())
1517     {
1518       mOnSceneSignalled = true; // signal required next time Actor is removed
1519     }
1520   }
1521 }
1522
1523 void Actor::DisconnectFromStage()
1524 {
1525   // This container is used instead of walking the Actor hierachy.
1526   // It protects us when the Actor hierachy is modified during OnSceneDisconnectionExternal callbacks.
1527   ActorContainer disconnectionList;
1528
1529   if(mScene)
1530   {
1531     mScene->RequestRebuildDepthTree();
1532   }
1533
1534   // This stage is atomic i.e. not interrupted by user callbacks
1535   RecursiveDisconnectFromStage(disconnectionList);
1536
1537   // Notify applications about the newly disconnected actors.
1538   for(const auto& actor : disconnectionList)
1539   {
1540     actor->NotifyStageDisconnection();
1541   }
1542 }
1543
1544 void Actor::RecursiveDisconnectFromStage(ActorContainer& disconnectionList)
1545 {
1546   // need to change state first so that internals relying on IsOnScene() inside OnSceneDisconnectionInternal() get the correct value
1547   mIsOnScene = false;
1548
1549   // Recursively disconnect children
1550   if(GetChildCount() > 0)
1551   {
1552     for(const auto& child : mParentImpl.GetChildrenInternal())
1553     {
1554       child->RecursiveDisconnectFromStage(disconnectionList);
1555     }
1556   }
1557
1558   // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
1559   disconnectionList.push_back(ActorPtr(this));
1560
1561   // Notification for internal derived classes
1562   OnSceneDisconnectionInternal();
1563
1564   DisconnectFromSceneGraph();
1565 }
1566
1567 /**
1568  * This method is called by an actor or its parent, before a node removal message is sent.
1569  * This is recursive; the child calls DisconnectFromStage() for its children.
1570  */
1571 void Actor::DisconnectFromSceneGraph()
1572 {
1573   // Notification for Object::Observers
1574   OnSceneObjectRemove();
1575 }
1576
1577 void Actor::NotifyStageDisconnection()
1578 {
1579   // Actors can be added (in a callback), before the off-stage state is reported.
1580   // Also if the actor was added & removed before mOnSceneSignalled was set, then we don't notify here.
1581   // only do this step if there is a stage, i.e. Core is not being shut down
1582   if(EventThreadServices::IsCoreRunning() && !OnScene() && mOnSceneSignalled)
1583   {
1584     // Notification for external (CustomeActor) derived classes
1585     OnSceneDisconnectionExternal();
1586
1587     if(!mOffSceneSignal.Empty())
1588     {
1589       Dali::Actor handle(this);
1590       mOffSceneSignal.Emit(handle);
1591     }
1592
1593     // Guard against Add during callbacks
1594     if(!OnScene())
1595     {
1596       mOnSceneSignalled = false; // signal required next time Actor is added
1597     }
1598   }
1599 }
1600
1601 bool Actor::IsNodeConnected() const
1602 {
1603   bool connected(false);
1604
1605   if(OnScene())
1606   {
1607     if(IsRoot() || GetNode().GetParent())
1608     {
1609       connected = true;
1610     }
1611   }
1612
1613   return connected;
1614 }
1615
1616 // This method initiates traversal of the actor tree using depth-first
1617 // traversal to set a depth index based on traversal order. It sends a
1618 // single message to update manager to update all the actor's nodes in
1619 // this tree with the depth index. The sceneGraphNodeDepths vector's
1620 // elements are ordered by depth, and could be used to reduce sorting
1621 // in the update thread.
1622 void Actor::RebuildDepthTree()
1623 {
1624   DALI_LOG_TIMER_START(depthTimer);
1625
1626   // Vector of scene-graph nodes and their depths to send to UpdateManager
1627   // in a single message
1628   OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths(new SceneGraph::NodeDepths());
1629
1630   int32_t depthIndex = 1;
1631   DepthTraverseActorTree(sceneGraphNodeDepths, depthIndex);
1632
1633   SetDepthIndicesMessage(GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths);
1634   DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
1635 }
1636
1637 void Actor::DepthTraverseActorTree(OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths, int32_t& depthIndex)
1638 {
1639   mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
1640   sceneGraphNodeDepths->Add(const_cast<SceneGraph::Node*>(&GetNode()), mSortedDepth);
1641
1642   // Create/add to children of this node
1643   if(GetChildCount() > 0)
1644   {
1645     for(const auto& child : mParentImpl.GetChildrenInternal())
1646     {
1647       Actor* childActor = child.Get();
1648       ++depthIndex;
1649       childActor->DepthTraverseActorTree(sceneGraphNodeDepths, depthIndex);
1650     }
1651   }
1652 }
1653
1654 void Actor::SetDefaultProperty(Property::Index index, const Property::Value& property)
1655 {
1656   PropertyHandler::SetDefaultProperty(*this, index, property);
1657 }
1658
1659 // TODO: This method needs to be removed
1660 void Actor::SetSceneGraphProperty(Property::Index index, const PropertyMetadata& entry, const Property::Value& value)
1661 {
1662   PropertyHandler::SetSceneGraphProperty(index, entry, value, GetEventThreadServices(), GetNode());
1663 }
1664
1665 Property::Value Actor::GetDefaultProperty(Property::Index index) const
1666 {
1667   Property::Value value;
1668
1669   if(!GetCachedPropertyValue(index, value))
1670   {
1671     // If property value is not stored in the event-side, then it must be a scene-graph only property
1672     GetCurrentPropertyValue(index, value);
1673   }
1674
1675   return value;
1676 }
1677
1678 Property::Value Actor::GetDefaultPropertyCurrentValue(Property::Index index) const
1679 {
1680   Property::Value value;
1681
1682   if(!GetCurrentPropertyValue(index, value))
1683   {
1684     // If unable to retrieve scene-graph property value, then it must be an event-side only property
1685     GetCachedPropertyValue(index, value);
1686   }
1687
1688   return value;
1689 }
1690
1691 void Actor::OnNotifyDefaultPropertyAnimation(Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType)
1692 {
1693   PropertyHandler::OnNotifyDefaultPropertyAnimation(*this, animation, index, value, animationType);
1694 }
1695
1696 const PropertyBase* Actor::GetSceneObjectAnimatableProperty(Property::Index index) const
1697 {
1698   const PropertyBase* property = PropertyHandler::GetSceneObjectAnimatableProperty(index, GetNode());
1699   if(!property)
1700   {
1701     // not our property, ask base
1702     property = Object::GetSceneObjectAnimatableProperty(index);
1703   }
1704
1705   return property;
1706 }
1707
1708 const PropertyInputImpl* Actor::GetSceneObjectInputProperty(Property::Index index) const
1709 {
1710   const PropertyInputImpl* property = PropertyHandler::GetSceneObjectInputProperty(index, GetNode());
1711   if(!property)
1712   {
1713     // reuse animatable property getter as animatable properties are inputs as well
1714     // animatable property chains back to Object::GetSceneObjectInputProperty() so all properties get covered
1715     property = GetSceneObjectAnimatableProperty(index);
1716   }
1717
1718   return property;
1719 }
1720
1721 int32_t Actor::GetPropertyComponentIndex(Property::Index index) const
1722 {
1723   int32_t componentIndex = PropertyHandler::GetPropertyComponentIndex(index);
1724   if(Property::INVALID_COMPONENT_INDEX == componentIndex)
1725   {
1726     // ask base
1727     componentIndex = Object::GetPropertyComponentIndex(index);
1728   }
1729
1730   return componentIndex;
1731 }
1732
1733 const SceneGraph::Node& Actor::GetNode() const
1734 {
1735   return *static_cast<const SceneGraph::Node*>(mUpdateObject);
1736 }
1737
1738 void Actor::Raise()
1739 {
1740   if(mParent)
1741   {
1742     mParent->RaiseChild(*this);
1743   }
1744   else
1745   {
1746     DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
1747   }
1748 }
1749
1750 void Actor::Lower()
1751 {
1752   if(mParent)
1753   {
1754     mParent->LowerChild(*this);
1755   }
1756   else
1757   {
1758     DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
1759   }
1760 }
1761
1762 void Actor::RaiseToTop()
1763 {
1764   if(mParent)
1765   {
1766     mParent->RaiseChildToTop(*this);
1767   }
1768   else
1769   {
1770     DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
1771   }
1772 }
1773
1774 void Actor::LowerToBottom()
1775 {
1776   if(mParent)
1777   {
1778     mParent->LowerChildToBottom(*this);
1779   }
1780   else
1781   {
1782     DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
1783   }
1784 }
1785
1786 void Actor::RaiseAbove(Internal::Actor& target)
1787 {
1788   if(mParent)
1789   {
1790     mParent->RaiseChildAbove(*this, target);
1791   }
1792   else
1793   {
1794     DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
1795   }
1796 }
1797
1798 void Actor::LowerBelow(Internal::Actor& target)
1799 {
1800   if(mParent)
1801   {
1802     mParent->LowerChildBelow(*this, target);
1803   }
1804   else
1805   {
1806     DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
1807   }
1808 }
1809
1810 void Actor::SetParent(ActorParent* parent)
1811 {
1812   if(parent)
1813   {
1814     DALI_ASSERT_ALWAYS(!mParent && "Actor cannot have 2 parents");
1815
1816     mParent            = parent;
1817     Actor* parentActor = static_cast<Actor*>(parent);
1818     mScene             = parentActor->mScene;
1819
1820     if(EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1821        parentActor->OnScene())
1822     {
1823       // Instruct each actor to create a corresponding node in the scene graph
1824       ConnectToScene(parentActor->GetHierarchyDepth());
1825     }
1826
1827     // Resolve the name and index for the child properties if any
1828     ResolveChildProperties();
1829   }
1830   else // parent being set to NULL
1831   {
1832     DALI_ASSERT_ALWAYS(mParent != nullptr && "Actor should have a parent");
1833
1834     mParent = nullptr;
1835
1836     if(EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1837        OnScene())
1838     {
1839       // Disconnect the Node & its children from the scene-graph.
1840       DisconnectNodeMessage(GetEventThreadServices().GetUpdateManager(), GetNode());
1841
1842       // Instruct each actor to discard pointers to the scene-graph
1843       DisconnectFromStage();
1844     }
1845
1846     mScene = nullptr;
1847   }
1848 }
1849
1850 bool Actor::DoAction(BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */)
1851 {
1852   bool   done  = false;
1853   Actor* actor = dynamic_cast<Actor*>(object);
1854
1855   if(actor)
1856   {
1857     std::string_view name(actionName);
1858     if(name == ACTION_SHOW)
1859     {
1860       actor->SetVisible(true);
1861       done = true;
1862     }
1863     else if(name == ACTION_HIDE)
1864     {
1865       actor->SetVisible(false);
1866       done = true;
1867     }
1868   }
1869
1870   return done;
1871 }
1872
1873 Rect<> Actor::CalculateScreenExtents() const
1874 {
1875   auto    screenPosition    = GetCurrentScreenPosition();
1876   Vector3 size              = GetCurrentSize() * GetCurrentWorldScale();
1877   Vector3 anchorPointOffSet = size * (mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT);
1878   Vector2 position          = Vector2(screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y);
1879   return {position.x, position.y, size.x, size.y};
1880 }
1881
1882 void Actor::SetNeedGesturePropagation(bool propagation)
1883 {
1884   mNeedGesturePropagation = propagation;
1885 }
1886
1887 bool Actor::NeedGesturePropagation()
1888 {
1889   return mNeedGesturePropagation;
1890 }
1891
1892 bool Actor::GetCachedPropertyValue(Property::Index index, Property::Value& value) const
1893 {
1894   return PropertyHandler::GetCachedPropertyValue(*this, index, value);
1895 }
1896
1897 bool Actor::GetCurrentPropertyValue(Property::Index index, Property::Value& value) const
1898 {
1899   return PropertyHandler::GetCurrentPropertyValue(*this, index, value);
1900 }
1901
1902 Actor::Relayouter& Actor::EnsureRelayouter()
1903 {
1904   // Assign relayouter
1905   if(!mRelayoutData)
1906   {
1907     mRelayoutData = new Relayouter();
1908   }
1909
1910   return *mRelayoutData;
1911 }
1912
1913 bool Actor::RelayoutDependentOnParent(Dimension::Type dimension)
1914 {
1915   // Check if actor is dependent on parent
1916   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
1917   {
1918     if((dimension & (1 << i)))
1919     {
1920       const ResizePolicy::Type resizePolicy = GetResizePolicy(static_cast<Dimension::Type>(1 << i));
1921       if(resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT)
1922       {
1923         return true;
1924       }
1925     }
1926   }
1927
1928   return false;
1929 }
1930
1931 bool Actor::RelayoutDependentOnChildren(Dimension::Type dimension)
1932 {
1933   // Check if actor is dependent on children
1934   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
1935   {
1936     if((dimension & (1 << i)))
1937     {
1938       const ResizePolicy::Type resizePolicy = GetResizePolicy(static_cast<Dimension::Type>(1 << i));
1939       switch(resizePolicy)
1940       {
1941         case ResizePolicy::FIT_TO_CHILDREN:
1942         case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
1943         {
1944           return true;
1945         }
1946
1947         default:
1948         {
1949           break;
1950         }
1951       }
1952     }
1953   }
1954
1955   return false;
1956 }
1957
1958 bool Actor::RelayoutDependentOnChildrenBase(Dimension::Type dimension)
1959 {
1960   return Actor::RelayoutDependentOnChildren(dimension);
1961 }
1962
1963 bool Actor::RelayoutDependentOnDimension(Dimension::Type dimension, Dimension::Type dependentDimension)
1964 {
1965   // Check each possible dimension and see if it is dependent on the input one
1966   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
1967   {
1968     if(dimension & (1 << i))
1969     {
1970       return mRelayoutData->resizePolicies[i] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[i] == dependentDimension;
1971     }
1972   }
1973
1974   return false;
1975 }
1976
1977 void Actor::SetNegotiatedDimension(float negotiatedDimension, Dimension::Type dimension)
1978 {
1979   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
1980   {
1981     if(dimension & (1 << i))
1982     {
1983       mRelayoutData->negotiatedDimensions[i] = negotiatedDimension;
1984     }
1985   }
1986 }
1987
1988 float Actor::GetNegotiatedDimension(Dimension::Type dimension) const
1989 {
1990   // If more than one dimension is requested, just return the first one found
1991   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
1992   {
1993     if((dimension & (1 << i)))
1994     {
1995       return mRelayoutData->negotiatedDimensions[i];
1996     }
1997   }
1998
1999   return 0.0f; // Default
2000 }
2001
2002 void Actor::SetPadding(const Vector2& padding, Dimension::Type dimension)
2003 {
2004   EnsureRelayouter().SetPadding(padding, dimension);
2005 }
2006
2007 Vector2 Actor::GetPadding(Dimension::Type dimension) const
2008 {
2009   if(mRelayoutData)
2010   {
2011     // If more than one dimension is requested, just return the first one found
2012     for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
2013     {
2014       if((dimension & (1 << i)))
2015       {
2016         return mRelayoutData->dimensionPadding[i];
2017       }
2018     }
2019   }
2020
2021   return Relayouter::DEFAULT_DIMENSION_PADDING;
2022 }
2023
2024 void Actor::SetLayoutNegotiated(bool negotiated, Dimension::Type dimension)
2025 {
2026   EnsureRelayouter().SetLayoutNegotiated(negotiated, dimension);
2027 }
2028
2029 bool Actor::IsLayoutNegotiated(Dimension::Type dimension) const
2030 {
2031   return mRelayoutData && mRelayoutData->IsLayoutNegotiated(dimension);
2032 }
2033
2034 float Actor::GetHeightForWidthBase(float width)
2035 {
2036   float height = 0.0f;
2037
2038   const Vector3 naturalSize = GetNaturalSize();
2039   if(naturalSize.width > 0.0f)
2040   {
2041     height = naturalSize.height * width / naturalSize.width;
2042   }
2043   else // we treat 0 as 1:1 aspect ratio
2044   {
2045     height = width;
2046   }
2047
2048   return height;
2049 }
2050
2051 float Actor::GetWidthForHeightBase(float height)
2052 {
2053   float width = 0.0f;
2054
2055   const Vector3 naturalSize = GetNaturalSize();
2056   if(naturalSize.height > 0.0f)
2057   {
2058     width = naturalSize.width * height / naturalSize.height;
2059   }
2060   else // we treat 0 as 1:1 aspect ratio
2061   {
2062     width = height;
2063   }
2064
2065   return width;
2066 }
2067
2068 float Actor::CalculateChildSizeBase(const Dali::Actor& child, Dimension::Type dimension)
2069 {
2070   // Fill to parent, taking size mode factor into account
2071   switch(child.GetResizePolicy(dimension))
2072   {
2073     case ResizePolicy::FILL_TO_PARENT:
2074     {
2075       return GetLatestSize(dimension);
2076     }
2077
2078     case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2079     {
2080       return GetLatestSize(dimension) * GetDimensionValue(child.GetProperty<Vector3>(Dali::Actor::Property::SIZE_MODE_FACTOR), dimension);
2081     }
2082
2083     case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2084     {
2085       return GetLatestSize(dimension) + GetDimensionValue(child.GetProperty<Vector3>(Dali::Actor::Property::SIZE_MODE_FACTOR), dimension);
2086     }
2087
2088     default:
2089     {
2090       return GetLatestSize(dimension);
2091     }
2092   }
2093 }
2094
2095 float Actor::CalculateChildSize(const Dali::Actor& child, Dimension::Type dimension)
2096 {
2097   // Can be overridden in derived class
2098   return CalculateChildSizeBase(child, dimension);
2099 }
2100
2101 float Actor::GetHeightForWidth(float width)
2102 {
2103   // Can be overridden in derived class
2104   return GetHeightForWidthBase(width);
2105 }
2106
2107 float Actor::GetWidthForHeight(float height)
2108 {
2109   // Can be overridden in derived class
2110   return GetWidthForHeightBase(height);
2111 }
2112
2113 float Actor::GetLatestSize(Dimension::Type dimension) const
2114 {
2115   return IsLayoutNegotiated(dimension) ? GetNegotiatedDimension(dimension) : GetSize(dimension);
2116 }
2117
2118 float Actor::GetRelayoutSize(Dimension::Type dimension) const
2119 {
2120   Vector2 padding = GetPadding(dimension);
2121
2122   return GetLatestSize(dimension) + padding.x + padding.y;
2123 }
2124
2125 float Actor::NegotiateFromParent(Dimension::Type dimension)
2126 {
2127   Actor* parent = GetParent();
2128   if(parent)
2129   {
2130     Vector2 padding(GetPadding(dimension));
2131     Vector2 parentPadding(parent->GetPadding(dimension));
2132     return parent->CalculateChildSize(Dali::Actor(this), dimension) - parentPadding.x - parentPadding.y - padding.x - padding.y;
2133   }
2134
2135   return 0.0f;
2136 }
2137
2138 float Actor::NegotiateFromChildren(Dimension::Type dimension)
2139 {
2140   float maxDimensionPoint = 0.0f;
2141
2142   for(uint32_t i = 0, count = GetChildCount(); i < count; ++i)
2143   {
2144     ActorPtr child = GetChildAt(i);
2145
2146     if(!child->RelayoutDependentOnParent(dimension))
2147     {
2148       // Calculate the min and max points that the children range across
2149       float childPosition = GetDimensionValue(child->GetTargetPosition(), dimension);
2150       float dimensionSize = child->GetRelayoutSize(dimension);
2151       maxDimensionPoint   = std::max(maxDimensionPoint, childPosition + dimensionSize);
2152     }
2153   }
2154
2155   return maxDimensionPoint;
2156 }
2157
2158 float Actor::GetSize(Dimension::Type dimension) const
2159 {
2160   return GetDimensionValue(mTargetSize, dimension);
2161 }
2162
2163 float Actor::GetNaturalSize(Dimension::Type dimension) const
2164 {
2165   return GetDimensionValue(GetNaturalSize(), dimension);
2166 }
2167
2168 float Actor::CalculateSize(Dimension::Type dimension, const Vector2& maximumSize)
2169 {
2170   switch(GetResizePolicy(dimension))
2171   {
2172     case ResizePolicy::USE_NATURAL_SIZE:
2173     {
2174       return GetNaturalSize(dimension);
2175     }
2176
2177     case ResizePolicy::FIXED:
2178     {
2179       return GetDimensionValue(GetPreferredSize(), dimension);
2180     }
2181
2182     case ResizePolicy::USE_ASSIGNED_SIZE:
2183     {
2184       return GetDimensionValue(maximumSize, dimension);
2185     }
2186
2187     case ResizePolicy::FILL_TO_PARENT:
2188     case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2189     case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2190     {
2191       return NegotiateFromParent(dimension);
2192     }
2193
2194     case ResizePolicy::FIT_TO_CHILDREN:
2195     {
2196       return NegotiateFromChildren(dimension);
2197     }
2198
2199     case ResizePolicy::DIMENSION_DEPENDENCY:
2200     {
2201       const Dimension::Type dimensionDependency = GetDimensionDependency(dimension);
2202
2203       // Custom rules
2204       if(dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT)
2205       {
2206         return GetWidthForHeight(GetNegotiatedDimension(Dimension::HEIGHT));
2207       }
2208
2209       if(dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH)
2210       {
2211         return GetHeightForWidth(GetNegotiatedDimension(Dimension::WIDTH));
2212       }
2213
2214       break;
2215     }
2216
2217     default:
2218     {
2219       break;
2220     }
2221   }
2222
2223   return 0.0f; // Default
2224 }
2225
2226 Vector2 Actor::ApplySizeSetPolicy(const Vector2& size)
2227 {
2228   return mRelayoutData->ApplySizeSetPolicy(*this, size);
2229 }
2230
2231 void Actor::SetNegotiatedSize(RelayoutContainer& container)
2232 {
2233   // Do the set actor size
2234   Vector2 negotiatedSize(GetLatestSize(Dimension::WIDTH), GetLatestSize(Dimension::HEIGHT));
2235
2236   // Adjust for size set policy
2237   negotiatedSize = ApplySizeSetPolicy(negotiatedSize);
2238
2239   // Lock the flag to stop recursive relayouts on set size
2240   mRelayoutData->insideRelayout = true;
2241   SetSize(negotiatedSize);
2242   mRelayoutData->insideRelayout = false;
2243
2244   // Clear flags for all dimensions
2245   SetLayoutDirty(false);
2246
2247   // Give deriving classes a chance to respond
2248   OnRelayout(negotiatedSize, container);
2249
2250   if(!mOnRelayoutSignal.Empty())
2251   {
2252     Dali::Actor handle(this);
2253     mOnRelayoutSignal.Emit(handle);
2254   }
2255 }
2256
2257 void Actor::NegotiateSize(const Vector2& allocatedSize, RelayoutContainer& container)
2258 {
2259   Relayouter::NegotiateSize(*this, allocatedSize, container);
2260 }
2261
2262 void Actor::SetUseAssignedSize(bool use, Dimension::Type dimension)
2263 {
2264   if(mRelayoutData)
2265   {
2266     mRelayoutData->SetUseAssignedSize(use, dimension);
2267   }
2268 }
2269
2270 bool Actor::GetUseAssignedSize(Dimension::Type dimension) const
2271 {
2272   return mRelayoutData && mRelayoutData->GetUseAssignedSize(dimension);
2273 }
2274
2275 void Actor::RelayoutRequest(Dimension::Type dimension)
2276 {
2277   Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
2278   if(relayoutController)
2279   {
2280     Dali::Actor self(this);
2281     relayoutController->RequestRelayout(self, dimension);
2282   }
2283 }
2284
2285 void Actor::SetPreferredSize(const Vector2& size)
2286 {
2287   EnsureRelayouter().SetPreferredSize(*this, size);
2288 }
2289
2290 Vector2 Actor::GetPreferredSize() const
2291 {
2292   if(mRelayoutData)
2293   {
2294     return Vector2(mRelayoutData->preferredSize);
2295   }
2296
2297   return Relayouter::DEFAULT_PREFERRED_SIZE;
2298 }
2299
2300 void Actor::SetMinimumSize(float size, Dimension::Type dimension)
2301 {
2302   EnsureRelayouter().SetMinimumSize(size, dimension);
2303   RelayoutRequest();
2304 }
2305
2306 float Actor::GetMinimumSize(Dimension::Type dimension) const
2307 {
2308   if(mRelayoutData)
2309   {
2310     return mRelayoutData->GetMinimumSize(dimension);
2311   }
2312
2313   return 0.0f; // Default
2314 }
2315
2316 void Actor::SetMaximumSize(float size, Dimension::Type dimension)
2317 {
2318   EnsureRelayouter().SetMaximumSize(size, dimension);
2319   RelayoutRequest();
2320 }
2321
2322 float Actor::GetMaximumSize(Dimension::Type dimension) const
2323 {
2324   if(mRelayoutData)
2325   {
2326     return mRelayoutData->GetMaximumSize(dimension);
2327   }
2328
2329   return FLT_MAX; // Default
2330 }
2331
2332 void Actor::SetVisibleInternal(bool visible, SendMessage::Type sendMessage)
2333 {
2334   if(mVisible != visible)
2335   {
2336     if(sendMessage == SendMessage::TRUE)
2337     {
2338       // node is being used in a separate thread; queue a message to set the value & base value
2339       SceneGraph::NodePropertyMessage<bool>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible);
2340
2341       RequestRenderingMessage(GetEventThreadServices().GetUpdateManager());
2342     }
2343
2344     mVisible = visible;
2345
2346     // Emit the signal on this actor and all its children
2347     EmitVisibilityChangedSignalRecursively(visible, DevelActor::VisibilityChange::SELF);
2348   }
2349 }
2350
2351 void Actor::SetSiblingOrderOfChild(Actor& child, uint32_t order)
2352 {
2353   mParentImpl.SetSiblingOrderOfChild(child, order);
2354 }
2355
2356 uint32_t Actor::GetSiblingOrderOfChild(const Actor& child) const
2357 {
2358   return mParentImpl.GetSiblingOrderOfChild(child);
2359 }
2360
2361 void Actor::RaiseChild(Actor& child)
2362 {
2363   mParentImpl.RaiseChild(child);
2364 }
2365
2366 void Actor::LowerChild(Actor& child)
2367 {
2368   mParentImpl.LowerChild(child);
2369 }
2370
2371 void Actor::RaiseChildToTop(Actor& child)
2372 {
2373   mParentImpl.RaiseChildToTop(child);
2374 }
2375
2376 void Actor::LowerChildToBottom(Actor& child)
2377 {
2378   mParentImpl.LowerChildToBottom(child);
2379 }
2380
2381 void Actor::RaiseChildAbove(Actor& child, Actor& target)
2382 {
2383   mParentImpl.RaiseChildAbove(child, target);
2384 }
2385
2386 void Actor::LowerChildBelow(Actor& child, Actor& target)
2387 {
2388   mParentImpl.LowerChildBelow(child, target);
2389 }
2390
2391 void Actor::SetInheritLayoutDirection(bool inherit)
2392 {
2393   if(mInheritLayoutDirection != inherit)
2394   {
2395     mInheritLayoutDirection = inherit;
2396
2397     if(inherit && mParent)
2398     {
2399       InheritLayoutDirectionRecursively(GetParent()->mLayoutDirection);
2400     }
2401   }
2402 }
2403
2404 void Actor::InheritLayoutDirectionRecursively(Dali::LayoutDirection::Type direction, bool set)
2405 {
2406   if(mInheritLayoutDirection || set)
2407   {
2408     if(mLayoutDirection != direction)
2409     {
2410       mLayoutDirection = direction;
2411       EmitLayoutDirectionChangedSignal(direction);
2412       RelayoutRequest();
2413     }
2414
2415     if(GetChildCount() > 0)
2416     {
2417       for(const auto& child : mParentImpl.GetChildrenInternal())
2418       {
2419         child->InheritLayoutDirectionRecursively(direction);
2420       }
2421     }
2422   }
2423 }
2424
2425 void Actor::SetUpdateSizeHint(const Vector2& updateSizeHint)
2426 {
2427   // node is being used in a separate thread; queue a message to set the value & base value
2428   SceneGraph::NodePropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mUpdateSizeHint, &AnimatableProperty<Vector3>::Bake, Vector3(updateSizeHint.width, updateSizeHint.height, 0.f));
2429 }
2430
2431 void Actor::EmitVisibilityChangedSignalRecursively(bool                               visible,
2432                                                    DevelActor::VisibilityChange::Type type)
2433 {
2434   EmitVisibilityChangedSignal(visible, type);
2435
2436   if(GetChildCount() > 0)
2437   {
2438     for(auto& child : mParentImpl.GetChildrenInternal())
2439     {
2440       child->EmitVisibilityChangedSignalRecursively(visible, DevelActor::VisibilityChange::PARENT);
2441     }
2442   }
2443 }
2444
2445 } // namespace Internal
2446
2447 } // namespace Dali