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