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