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