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