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