Update the preferred size after relayoutting
[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     // Update the preferred size after relayoutting
762     // It should be used in the next relayoutting
763     if(mUseAnimatedSize & AnimatedSizeFlag::WIDTH && mRelayoutData)
764     {
765       mRelayoutData->preferredSize.width = mAnimatedSize.width;
766     }
767
768     if(mUseAnimatedSize & AnimatedSizeFlag::HEIGHT && mRelayoutData)
769     {
770       mRelayoutData->preferredSize.height = mAnimatedSize.height;
771     }
772
773     // node is being used in a separate thread; queue a message to set the value & base value
774     SceneGraph::NodeTransformPropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::Bake, mTargetSize);
775
776     // Notification for derived classes
777     mInsideOnSizeSet = true;
778     OnSizeSet(mTargetSize);
779     mInsideOnSizeSet = false;
780
781     // Raise a relayout request if the flag is not locked
782     if(mRelayoutData && !mRelayoutData->insideRelayout)
783     {
784       RelayoutRequest();
785     }
786   }
787 }
788
789 void Actor::SetWidth(float width)
790 {
791   if(IsRelayoutEnabled() && !mRelayoutData->insideRelayout)
792   {
793     SetResizePolicy(ResizePolicy::FIXED, Dimension::WIDTH);
794     mRelayoutData->preferredSize.width = width;
795   }
796   else
797   {
798     mTargetSize.width = width;
799
800     // node is being used in a separate thread; queue a message to set the value & base value
801     SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeX, width);
802   }
803
804   mUseAnimatedSize &= ~AnimatedSizeFlag::WIDTH;
805
806   RelayoutRequest();
807 }
808
809 void Actor::SetHeight(float height)
810 {
811   if(IsRelayoutEnabled() && !mRelayoutData->insideRelayout)
812   {
813     SetResizePolicy(ResizePolicy::FIXED, Dimension::HEIGHT);
814     mRelayoutData->preferredSize.height = height;
815   }
816   else
817   {
818     mTargetSize.height = height;
819
820     // node is being used in a separate thread; queue a message to set the value & base value
821     SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeY, height);
822   }
823
824   mUseAnimatedSize &= ~AnimatedSizeFlag::HEIGHT;
825
826   RelayoutRequest();
827 }
828
829 void Actor::SetDepth(float depth)
830 {
831   mTargetSize.depth = depth;
832
833   mUseAnimatedSize &= ~AnimatedSizeFlag::DEPTH;
834
835   // node is being used in a separate thread; queue a message to set the value & base value
836   SceneGraph::NodeTransformComponentMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mSize, &SceneGraph::TransformManagerPropertyHandler<Vector3>::BakeZ, depth);
837 }
838
839 Vector3 Actor::GetTargetSize() const
840 {
841   Vector3 size = mTargetSize;
842
843   if(mUseAnimatedSize & AnimatedSizeFlag::WIDTH)
844   {
845     // Should return animated size if size is animated
846     size.width = mAnimatedSize.width;
847   }
848   else
849   {
850     // Should return preferred size if size is fixed as set by SetSize
851     if(GetResizePolicy(Dimension::WIDTH) == ResizePolicy::FIXED)
852     {
853       size.width = GetPreferredSize().width;
854     }
855   }
856
857   if(mUseAnimatedSize & AnimatedSizeFlag::HEIGHT)
858   {
859     size.height = mAnimatedSize.height;
860   }
861   else
862   {
863     if(GetResizePolicy(Dimension::HEIGHT) == ResizePolicy::FIXED)
864     {
865       size.height = GetPreferredSize().height;
866     }
867   }
868
869   if(mUseAnimatedSize & AnimatedSizeFlag::DEPTH)
870   {
871     size.depth = mAnimatedSize.depth;
872   }
873
874   return size;
875 }
876
877 const Vector3& Actor::GetCurrentSize() const
878 {
879   // node is being used in a separate thread; copy the value from the previous update
880   return GetNode().GetSize(GetEventThreadServices().GetEventBufferIndex());
881 }
882
883 Vector3 Actor::GetNaturalSize() const
884 {
885   // It is up to deriving classes to return the appropriate natural size
886   return Vector3(0.0f, 0.0f, 0.0f);
887 }
888
889 void Actor::SetResizePolicy(ResizePolicy::Type policy, Dimension::Type dimension)
890 {
891   EnsureRelayouter().SetResizePolicy(policy, dimension, mTargetSize);
892
893   OnSetResizePolicy(policy, dimension);
894
895   // Trigger relayout on this control
896   RelayoutRequest();
897 }
898
899 ResizePolicy::Type Actor::GetResizePolicy(Dimension::Type dimension) const
900 {
901   if(mRelayoutData)
902   {
903     return mRelayoutData->GetResizePolicy(dimension);
904   }
905
906   return ResizePolicy::DEFAULT;
907 }
908
909 void Actor::SetSizeScalePolicy(SizeScalePolicy::Type policy)
910 {
911   EnsureRelayouter();
912
913   mRelayoutData->sizeSetPolicy = policy;
914
915   // Trigger relayout on this control
916   RelayoutRequest();
917 }
918
919 SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
920 {
921   if(mRelayoutData)
922   {
923     return mRelayoutData->sizeSetPolicy;
924   }
925
926   return Relayouter::DEFAULT_SIZE_SCALE_POLICY;
927 }
928
929 void Actor::SetDimensionDependency(Dimension::Type dimension, Dimension::Type dependency)
930 {
931   EnsureRelayouter().SetDimensionDependency(dimension, dependency);
932 }
933
934 Dimension::Type Actor::GetDimensionDependency(Dimension::Type dimension) const
935 {
936   if(mRelayoutData)
937   {
938     return mRelayoutData->GetDimensionDependency(dimension);
939   }
940
941   return Dimension::ALL_DIMENSIONS; // Default
942 }
943
944 void Actor::SetRelayoutEnabled(bool relayoutEnabled)
945 {
946   // If relayout data has not been allocated yet and the client is requesting
947   // to disable it, do nothing
948   if(mRelayoutData || relayoutEnabled)
949   {
950     EnsureRelayouter();
951
952     DALI_ASSERT_DEBUG(mRelayoutData && "mRelayoutData not created");
953
954     mRelayoutData->relayoutEnabled = relayoutEnabled;
955   }
956 }
957
958 bool Actor::IsRelayoutEnabled() const
959 {
960   // Assume that if relayout data has not been allocated yet then
961   // relayout is disabled
962   return mRelayoutData && mRelayoutData->relayoutEnabled;
963 }
964
965 void Actor::SetLayoutDirty(bool dirty, Dimension::Type dimension)
966 {
967   EnsureRelayouter().SetLayoutDirty(dirty, dimension);
968 }
969
970 bool Actor::IsLayoutDirty(Dimension::Type dimension) const
971 {
972   return mRelayoutData && mRelayoutData->IsLayoutDirty(dimension);
973 }
974
975 bool Actor::RelayoutPossible(Dimension::Type dimension) const
976 {
977   return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty(dimension);
978 }
979
980 bool Actor::RelayoutRequired(Dimension::Type dimension) const
981 {
982   return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty(dimension);
983 }
984
985 uint32_t Actor::AddRenderer(Renderer& renderer)
986 {
987   if(!mRenderers)
988   {
989     mRenderers = new RendererContainer(GetEventThreadServices());
990   }
991   return mRenderers->Add(GetNode(), renderer, mIsBlendEquationSet, mBlendEquation);
992 }
993
994 uint32_t Actor::GetRendererCount() const
995 {
996   return mRenderers ? mRenderers->GetCount() : 0u;
997 }
998
999 RendererPtr Actor::GetRendererAt(uint32_t index)
1000 {
1001   return mRenderers ? mRenderers->GetRendererAt(index) : nullptr;
1002 }
1003
1004 void Actor::RemoveRenderer(Renderer& renderer)
1005 {
1006   if(mRenderers)
1007   {
1008     mRenderers->Remove(GetNode(), renderer);
1009   }
1010 }
1011
1012 void Actor::RemoveRenderer(uint32_t index)
1013 {
1014   if(mRenderers)
1015   {
1016     mRenderers->Remove(GetNode(), index);
1017   }
1018 }
1019
1020 void Actor::SetBlendEquation(DevelBlendEquation::Type blendEquation)
1021 {
1022   if(Dali::Capabilities::IsBlendEquationSupported(blendEquation))
1023   {
1024     if(mBlendEquation != blendEquation)
1025     {
1026       mBlendEquation = blendEquation;
1027       if(mRenderers)
1028       {
1029         mRenderers->SetBlending(blendEquation);
1030       }
1031     }
1032     mIsBlendEquationSet = true;
1033   }
1034   else
1035   {
1036     DALI_LOG_ERROR("Invalid blend equation is entered.\n");
1037   }
1038 }
1039
1040 DevelBlendEquation::Type Actor::GetBlendEquation() const
1041 {
1042   return mBlendEquation;
1043 }
1044
1045 void Actor::SetTransparent(bool transparent)
1046 {
1047   SetTransparentMessage(GetEventThreadServices(), GetNode(), transparent);
1048 }
1049
1050 bool Actor::IsTransparent() const
1051 {
1052   return GetNode().IsTransparent();
1053 }
1054
1055 void Actor::SetDrawMode(DrawMode::Type drawMode)
1056 {
1057   // this flag is not animatable so keep the value
1058   mDrawMode = drawMode;
1059
1060   // node is being used in a separate thread; queue a message to set the value
1061   SetDrawModeMessage(GetEventThreadServices(), GetNode(), drawMode);
1062 }
1063
1064 bool Actor::ScreenToLocal(float& localX, float& localY, float screenX, float screenY) const
1065 {
1066   return mScene && OnScene() && ConvertScreenToLocalRenderTaskList(mScene->GetRenderTaskList(), GetNode().GetWorldMatrix(0), GetCurrentSize(), localX, localY, screenX, screenY);
1067 }
1068
1069 bool Actor::ScreenToLocal(const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY) const
1070 {
1071   return OnScene() && ConvertScreenToLocalRenderTask(renderTask, GetNode().GetWorldMatrix(0), GetCurrentSize(), localX, localY, screenX, screenY);
1072 }
1073
1074 bool Actor::ScreenToLocal(const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY) const
1075 {
1076   return OnScene() && ConvertScreenToLocal(viewMatrix, projectionMatrix, GetNode().GetWorldMatrix(0), GetCurrentSize(), viewport, localX, localY, screenX, screenY);
1077 }
1078
1079 ActorGestureData& Actor::GetGestureData()
1080 {
1081   // Likely scenario is that once gesture-data is created for this actor, the actor will require
1082   // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1083   if(nullptr == mGestureData)
1084   {
1085     mGestureData = new ActorGestureData;
1086   }
1087   return *mGestureData;
1088 }
1089
1090 bool Actor::IsGestureRequired(GestureType::Value type) const
1091 {
1092   return mGestureData && mGestureData->IsGestureRequired(type);
1093 }
1094
1095 bool Actor::EmitInterceptTouchEventSignal(const Dali::TouchEvent& touch)
1096 {
1097   return EmitConsumingSignal(*this, mInterceptTouchedSignal, touch);
1098 }
1099
1100 bool Actor::EmitTouchEventSignal(const Dali::TouchEvent& touch)
1101 {
1102   return EmitConsumingSignal(*this, mTouchedSignal, touch);
1103 }
1104
1105 bool Actor::EmitHoverEventSignal(const Dali::HoverEvent& event)
1106 {
1107   return EmitConsumingSignal(*this, mHoveredSignal, event);
1108 }
1109
1110 bool Actor::EmitWheelEventSignal(const Dali::WheelEvent& event)
1111 {
1112   return EmitConsumingSignal(*this, mWheelEventSignal, event);
1113 }
1114
1115 void Actor::EmitVisibilityChangedSignal(bool visible, DevelActor::VisibilityChange::Type type)
1116 {
1117   EmitSignal(*this, mVisibilityChangedSignal, visible, type);
1118 }
1119
1120 void Actor::EmitLayoutDirectionChangedSignal(LayoutDirection::Type type)
1121 {
1122   EmitSignal(*this, mLayoutDirectionChangedSignal, type);
1123 }
1124
1125 DevelActor::ChildChangedSignalType& Actor::ChildAddedSignal()
1126 {
1127   return mParentImpl.ChildAddedSignal();
1128 }
1129
1130 DevelActor::ChildChangedSignalType& Actor::ChildRemovedSignal()
1131 {
1132   return mParentImpl.ChildRemovedSignal();
1133 }
1134
1135 DevelActor::ChildOrderChangedSignalType& Actor::ChildOrderChangedSignal()
1136 {
1137   return mParentImpl.ChildOrderChangedSignal();
1138 }
1139
1140 bool Actor::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
1141 {
1142   bool   connected(true);
1143   Actor* actor = static_cast<Actor*>(object); // TypeRegistry guarantees that this is the correct type.
1144
1145   std::string_view name(signalName);
1146
1147   if(name == SIGNAL_HOVERED)
1148   {
1149     actor->HoveredSignal().Connect(tracker, functor);
1150   }
1151   else if(signalName == SIGNAL_WHEEL_EVENT)
1152   {
1153     actor->WheelEventSignal().Connect(tracker, functor);
1154   }
1155   else if(name == SIGNAL_ON_SCENE)
1156   {
1157     actor->OnSceneSignal().Connect(tracker, functor);
1158   }
1159   else if(name == SIGNAL_OFF_SCENE)
1160   {
1161     actor->OffSceneSignal().Connect(tracker, functor);
1162   }
1163   else if(name == SIGNAL_ON_RELAYOUT)
1164   {
1165     actor->OnRelayoutSignal().Connect(tracker, functor);
1166   }
1167   else if(name == SIGNAL_TOUCHED)
1168   {
1169     actor->TouchedSignal().Connect(tracker, functor);
1170   }
1171   else if(name == SIGNAL_VISIBILITY_CHANGED)
1172   {
1173     actor->VisibilityChangedSignal().Connect(tracker, functor);
1174   }
1175   else if(name == SIGNAL_LAYOUT_DIRECTION_CHANGED)
1176   {
1177     actor->LayoutDirectionChangedSignal().Connect(tracker, functor);
1178   }
1179   else if(name == SIGNAL_CHILD_ADDED)
1180   {
1181     actor->ChildAddedSignal().Connect(tracker, functor);
1182   }
1183   else if(name == SIGNAL_CHILD_REMOVED)
1184   {
1185     actor->ChildRemovedSignal().Connect(tracker, functor);
1186   }
1187   else
1188   {
1189     // signalName does not match any signal
1190     connected = false;
1191   }
1192
1193   return connected;
1194 }
1195
1196 Actor::Actor(DerivedType derivedType, const SceneGraph::Node& node)
1197 : Object(&node),
1198   mParentImpl(*this),
1199   mParent(nullptr),
1200   mScene(nullptr),
1201   mRenderers(nullptr),
1202   mParentOrigin(nullptr),
1203   mAnchorPoint(nullptr),
1204   mRelayoutData(nullptr),
1205   mGestureData(nullptr),
1206   mInterceptTouchedSignal(),
1207   mTouchedSignal(),
1208   mHoveredSignal(),
1209   mWheelEventSignal(),
1210   mOnSceneSignal(),
1211   mOffSceneSignal(),
1212   mOnRelayoutSignal(),
1213   mVisibilityChangedSignal(),
1214   mLayoutDirectionChangedSignal(),
1215   mTargetOrientation(Quaternion::IDENTITY),
1216   mTargetColor(Color::WHITE),
1217   mTargetSize(Vector3::ZERO),
1218   mTargetPosition(Vector3::ZERO),
1219   mTargetScale(Vector3::ONE),
1220   mAnimatedSize(Vector3::ZERO),
1221   mTouchAreaOffset(0, 0, 0, 0),
1222   mName(),
1223   mSortedDepth(0u),
1224   mDepth(0u),
1225   mUseAnimatedSize(AnimatedSizeFlag::CLEAR),
1226   mIsRoot(ROOT_LAYER == derivedType),
1227   mIsLayer(LAYER == derivedType || ROOT_LAYER == derivedType),
1228   mIsOnScene(false),
1229   mSensitive(true),
1230   mLeaveRequired(false),
1231   mKeyboardFocusable(false),
1232   mKeyboardFocusableChildren(true),
1233   mTouchFocusable(false),
1234   mOnSceneSignalled(false),
1235   mInsideOnSizeSet(false),
1236   mInheritPosition(true),
1237   mInheritOrientation(true),
1238   mInheritScale(true),
1239   mPositionUsesAnchorPoint(true),
1240   mVisible(true),
1241   mInheritLayoutDirection(true),
1242   mCaptureAllTouchAfterStart(false),
1243   mIsBlendEquationSet(false),
1244   mNeedGesturePropagation(false),
1245   mLayoutDirection(LayoutDirection::LEFT_TO_RIGHT),
1246   mDrawMode(DrawMode::NORMAL),
1247   mColorMode(Node::DEFAULT_COLOR_MODE),
1248   mClippingMode(ClippingMode::DISABLED),
1249   mBlendEquation(DevelBlendEquation::ADD)
1250 {
1251 }
1252
1253 void Actor::Initialize()
1254 {
1255   OnInitialize();
1256
1257   GetEventThreadServices().RegisterObject(this);
1258 }
1259
1260 Actor::~Actor()
1261 {
1262   // Remove mParent pointers from children even if we're destroying core,
1263   // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1264   UnparentChildren();
1265   delete mRenderers;
1266
1267   // Guard to allow handle destruction after Core has been destroyed
1268   if(EventThreadServices::IsCoreRunning())
1269   {
1270     // Root layer will destroy its node in its own destructor
1271     if(!mIsRoot)
1272     {
1273       DestroyNodeMessage(GetEventThreadServices().GetUpdateManager(), GetNode());
1274
1275       GetEventThreadServices().UnregisterObject(this);
1276     }
1277   }
1278
1279   // Cleanup optional gesture data
1280   delete mGestureData;
1281
1282   // Cleanup optional parent origin and anchor
1283   delete mParentOrigin;
1284   delete mAnchorPoint;
1285
1286   // Delete optional relayout data
1287   delete mRelayoutData;
1288 }
1289
1290 void Actor::Add(Actor& child, bool notify)
1291 {
1292   mParentImpl.Add(child, notify);
1293 }
1294
1295 void Actor::Remove(Actor& child, bool notify)
1296 {
1297   mParentImpl.Remove(child, notify);
1298 }
1299
1300 void Actor::SwitchParent(Actor& newParent)
1301 {
1302   if(this == &newParent)
1303   {
1304     DALI_LOG_ERROR("Cannot add actor to itself");
1305     return;
1306   }
1307
1308   if(!this->OnScene() || !newParent.OnScene())
1309   {
1310     DALI_LOG_ERROR("Both of current parent and new parent must be on Scene");
1311     return;
1312   }
1313
1314   newParent.Add(*this, false);
1315 }
1316
1317 uint32_t Actor::GetChildCount() const
1318 {
1319   return mParentImpl.GetChildCount();
1320 }
1321
1322 ActorPtr Actor::GetChildAt(uint32_t index) const
1323 {
1324   return mParentImpl.GetChildAt(index);
1325 }
1326
1327 ActorContainer& Actor::GetChildrenInternal()
1328 {
1329   return mParentImpl.GetChildrenInternal();
1330 }
1331
1332 ActorPtr Actor::FindChildByName(ConstString actorName)
1333 {
1334   return mParentImpl.FindChildByName(actorName);
1335 }
1336
1337 ActorPtr Actor::FindChildById(const uint32_t id)
1338 {
1339   return mParentImpl.FindChildById(id);
1340 }
1341
1342 void Actor::UnparentChildren()
1343 {
1344   mParentImpl.UnparentChildren();
1345 }
1346
1347 void Actor::ConnectToScene(uint32_t parentDepth, bool notify)
1348 {
1349   // This container is used instead of walking the Actor hierarchy.
1350   // It protects us when the Actor hierarchy is modified during OnSceneConnectionExternal callbacks.
1351   ActorContainer connectionList;
1352
1353   if(mScene)
1354   {
1355     mScene->RequestRebuildDepthTree();
1356   }
1357
1358   // This stage is not interrupted by user callbacks.
1359   mParentImpl.RecursiveConnectToScene(connectionList, parentDepth + 1);
1360
1361   // Notify applications about the newly connected actors.
1362   for(const auto& actor : connectionList)
1363   {
1364     actor->NotifyStageConnection(notify);
1365   }
1366
1367   RelayoutRequest();
1368 }
1369
1370 /**
1371  * This method is called when the Actor is connected to the Stage.
1372  * The parent must have added its Node to the scene-graph.
1373  * The child must connect its Node to the parent's Node.
1374  * This is recursive; the child calls ConnectToScene() for its children.
1375  */
1376 void Actor::ConnectToSceneGraph()
1377 {
1378   DALI_ASSERT_DEBUG(mParent != NULL);
1379
1380   // Reparent Node in next Update
1381   ConnectNodeMessage(GetEventThreadServices().GetUpdateManager(), GetParent()->GetNode(), GetNode());
1382
1383   // Request relayout on all actors that are added to the scenegraph
1384   RelayoutRequest();
1385
1386   // Notification for Object::Observers
1387   OnSceneObjectAdd();
1388 }
1389
1390 void Actor::NotifyStageConnection(bool notify)
1391 {
1392   // Actors can be removed (in a callback), before the on-stage stage is reported.
1393   // The actor may also have been reparented, in which case mOnSceneSignalled will be true.
1394   if(OnScene() && !mOnSceneSignalled)
1395   {
1396     if(notify)
1397     {
1398       // Notification for external (CustomActor) derived classes
1399       OnSceneConnectionExternal(mDepth);
1400
1401       if(!mOnSceneSignal.Empty())
1402       {
1403         Dali::Actor handle(this);
1404         mOnSceneSignal.Emit(handle);
1405       }
1406     }
1407
1408     // Guard against Remove during callbacks
1409     if(OnScene())
1410     {
1411       mOnSceneSignalled = true; // signal required next time Actor is removed
1412     }
1413   }
1414 }
1415
1416 void Actor::DisconnectFromStage(bool notify)
1417 {
1418   // This container is used instead of walking the Actor hierachy.
1419   // It protects us when the Actor hierachy is modified during OnSceneDisconnectionExternal callbacks.
1420   ActorContainer disconnectionList;
1421
1422   if(mScene)
1423   {
1424     mScene->RequestRebuildDepthTree();
1425   }
1426
1427   // This stage is not interrupted by user callbacks
1428   mParentImpl.RecursiveDisconnectFromScene(disconnectionList);
1429
1430   // Notify applications about the newly disconnected actors.
1431   for(const auto& actor : disconnectionList)
1432   {
1433     actor->NotifyStageDisconnection(notify);
1434   }
1435 }
1436
1437 /**
1438  * This method is called by an actor or its parent, before a node removal message is sent.
1439  * This is recursive; the child calls DisconnectFromStage() for its children.
1440  */
1441 void Actor::DisconnectFromSceneGraph()
1442 {
1443   // Notification for Object::Observers
1444   OnSceneObjectRemove();
1445 }
1446
1447 void Actor::NotifyStageDisconnection(bool notify)
1448 {
1449   // Actors can be added (in a callback), before the off-stage state is reported.
1450   // Also if the actor was added & removed before mOnSceneSignalled was set, then we don't notify here.
1451   // only do this step if there is a stage, i.e. Core is not being shut down
1452   if(EventThreadServices::IsCoreRunning() && !OnScene() && mOnSceneSignalled)
1453   {
1454     if(notify)
1455     {
1456       // Notification for external (CustomeActor) derived classes
1457       OnSceneDisconnectionExternal();
1458
1459       if(!mOffSceneSignal.Empty())
1460       {
1461         Dali::Actor handle(this);
1462         mOffSceneSignal.Emit(handle);
1463       }
1464     }
1465
1466     // Guard against Add during callbacks
1467     if(!OnScene())
1468     {
1469       mOnSceneSignalled = false; // signal required next time Actor is added
1470     }
1471   }
1472 }
1473
1474 bool Actor::IsNodeConnected() const
1475 {
1476   return OnScene() && (IsRoot() || GetNode().GetParent());
1477 }
1478
1479 // This method initiates traversal of the actor tree using depth-first
1480 // traversal to set a depth index based on traversal order. It sends a
1481 // single message to update manager to update all the actor's nodes in
1482 // this tree with the depth index. The sceneGraphNodeDepths vector's
1483 // elements are ordered by depth, and could be used to reduce sorting
1484 // in the update thread.
1485 void Actor::RebuildDepthTree()
1486 {
1487   DALI_LOG_TIMER_START(depthTimer);
1488
1489   // Vector of scene-graph nodes and their depths to send to UpdateManager
1490   // in a single message
1491   OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths(new SceneGraph::NodeDepths());
1492
1493   int32_t depthIndex = 1;
1494   mParentImpl.DepthTraverseActorTree(sceneGraphNodeDepths, depthIndex);
1495
1496   SetDepthIndicesMessage(GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths);
1497   DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
1498 }
1499
1500 void Actor::SetDefaultProperty(Property::Index index, const Property::Value& property)
1501 {
1502   PropertyHandler::SetDefaultProperty(*this, index, property);
1503 }
1504
1505 // TODO: This method needs to be removed
1506 void Actor::SetSceneGraphProperty(Property::Index index, const PropertyMetadata& entry, const Property::Value& value)
1507 {
1508   PropertyHandler::SetSceneGraphProperty(index, entry, value, GetEventThreadServices(), GetNode());
1509 }
1510
1511 Property::Value Actor::GetDefaultProperty(Property::Index index) const
1512 {
1513   Property::Value value;
1514
1515   if(!GetCachedPropertyValue(index, value))
1516   {
1517     // If property value is not stored in the event-side, then it must be a scene-graph only property
1518     GetCurrentPropertyValue(index, value);
1519   }
1520
1521   return value;
1522 }
1523
1524 Property::Value Actor::GetDefaultPropertyCurrentValue(Property::Index index) const
1525 {
1526   Property::Value value;
1527
1528   if(!GetCurrentPropertyValue(index, value))
1529   {
1530     // If unable to retrieve scene-graph property value, then it must be an event-side only property
1531     GetCachedPropertyValue(index, value);
1532   }
1533
1534   return value;
1535 }
1536
1537 void Actor::OnNotifyDefaultPropertyAnimation(Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType)
1538 {
1539   PropertyHandler::OnNotifyDefaultPropertyAnimation(*this, animation, index, value, animationType);
1540 }
1541
1542 const PropertyBase* Actor::GetSceneObjectAnimatableProperty(Property::Index index) const
1543 {
1544   const PropertyBase* property = PropertyHandler::GetSceneObjectAnimatableProperty(index, GetNode());
1545   if(!property)
1546   {
1547     // not our property, ask base
1548     property = Object::GetSceneObjectAnimatableProperty(index);
1549   }
1550
1551   return property;
1552 }
1553
1554 const PropertyInputImpl* Actor::GetSceneObjectInputProperty(Property::Index index) const
1555 {
1556   const PropertyInputImpl* property = PropertyHandler::GetSceneObjectInputProperty(index, GetNode());
1557   if(!property)
1558   {
1559     // reuse animatable property getter as animatable properties are inputs as well
1560     // animatable property chains back to Object::GetSceneObjectInputProperty() so all properties get covered
1561     property = GetSceneObjectAnimatableProperty(index);
1562   }
1563
1564   return property;
1565 }
1566
1567 int32_t Actor::GetPropertyComponentIndex(Property::Index index) const
1568 {
1569   int32_t componentIndex = PropertyHandler::GetPropertyComponentIndex(index);
1570   if(Property::INVALID_COMPONENT_INDEX == componentIndex)
1571   {
1572     // ask base
1573     componentIndex = Object::GetPropertyComponentIndex(index);
1574   }
1575
1576   return componentIndex;
1577 }
1578
1579 const SceneGraph::Node& Actor::GetNode() const
1580 {
1581   return *static_cast<const SceneGraph::Node*>(mUpdateObject);
1582 }
1583
1584 void Actor::Raise()
1585 {
1586   if(mParent)
1587   {
1588     mParent->RaiseChild(*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::Lower()
1597 {
1598   if(mParent)
1599   {
1600     mParent->LowerChild(*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::RaiseToTop()
1609 {
1610   if(mParent)
1611   {
1612     mParent->RaiseChildToTop(*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::LowerToBottom()
1621 {
1622   if(mParent)
1623   {
1624     mParent->LowerChildToBottom(*this);
1625   }
1626   else
1627   {
1628     DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
1629   }
1630 }
1631
1632 void Actor::RaiseAbove(Internal::Actor& target)
1633 {
1634   if(mParent)
1635   {
1636     mParent->RaiseChildAbove(*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::LowerBelow(Internal::Actor& target)
1645 {
1646   if(mParent)
1647   {
1648     mParent->LowerChildBelow(*this, target);
1649   }
1650   else
1651   {
1652     DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
1653   }
1654 }
1655
1656 void Actor::SetParent(ActorParent* parent, bool notify)
1657 {
1658   if(parent)
1659   {
1660     DALI_ASSERT_ALWAYS(!mParent && "Actor cannot have 2 parents");
1661
1662     mParent            = parent;
1663     Actor* parentActor = static_cast<Actor*>(parent);
1664     mScene             = parentActor->mScene;
1665
1666     if(EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1667        parentActor->OnScene())
1668     {
1669       // Instruct each actor to create a corresponding node in the scene graph
1670       ConnectToScene(parentActor->GetHierarchyDepth(), notify);
1671     }
1672
1673     // Resolve the name and index for the child properties if any
1674     ResolveChildProperties();
1675   }
1676   else // parent being set to NULL
1677   {
1678     DALI_ASSERT_ALWAYS(mParent != nullptr && "Actor should have a parent");
1679
1680     mParent = nullptr;
1681
1682     if(EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1683        OnScene())
1684     {
1685       // Disconnect the Node & its children from the scene-graph.
1686       DisconnectNodeMessage(GetEventThreadServices().GetUpdateManager(), GetNode());
1687
1688       // Instruct each actor to discard pointers to the scene-graph
1689       DisconnectFromStage(notify);
1690     }
1691
1692     mScene = nullptr;
1693   }
1694 }
1695
1696 bool Actor::DoAction(BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */)
1697 {
1698   bool   done  = false;
1699   Actor* actor = dynamic_cast<Actor*>(object);
1700
1701   if(actor)
1702   {
1703     std::string_view name(actionName);
1704     if(name == ACTION_SHOW)
1705     {
1706       actor->SetVisible(true);
1707       done = true;
1708     }
1709     else if(name == ACTION_HIDE)
1710     {
1711       actor->SetVisible(false);
1712       done = true;
1713     }
1714   }
1715
1716   return done;
1717 }
1718
1719 Rect<> Actor::CalculateScreenExtents() const
1720 {
1721   auto    screenPosition    = GetCurrentScreenPosition();
1722   Vector3 size              = GetCurrentSize() * GetCurrentWorldScale();
1723   Vector3 anchorPointOffSet = size * (mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT);
1724   Vector2 position          = Vector2(screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y);
1725   return {position.x, position.y, size.x, size.y};
1726 }
1727
1728 void Actor::SetNeedGesturePropagation(bool propagation)
1729 {
1730   mNeedGesturePropagation = propagation;
1731 }
1732
1733 bool Actor::NeedGesturePropagation()
1734 {
1735   return mNeedGesturePropagation;
1736 }
1737
1738 bool Actor::GetCachedPropertyValue(Property::Index index, Property::Value& value) const
1739 {
1740   return PropertyHandler::GetCachedPropertyValue(*this, index, value);
1741 }
1742
1743 bool Actor::GetCurrentPropertyValue(Property::Index index, Property::Value& value) const
1744 {
1745   return PropertyHandler::GetCurrentPropertyValue(*this, index, value);
1746 }
1747
1748 Actor::Relayouter& Actor::EnsureRelayouter()
1749 {
1750   // Assign relayouter
1751   if(!mRelayoutData)
1752   {
1753     mRelayoutData = new Relayouter();
1754   }
1755
1756   return *mRelayoutData;
1757 }
1758
1759 bool Actor::RelayoutDependentOnParent(Dimension::Type dimension)
1760 {
1761   // Check if actor is dependent on parent
1762   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
1763   {
1764     if((dimension & (1 << i)))
1765     {
1766       const ResizePolicy::Type resizePolicy = GetResizePolicy(static_cast<Dimension::Type>(1 << i));
1767       if(resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT)
1768       {
1769         return true;
1770       }
1771     }
1772   }
1773
1774   return false;
1775 }
1776
1777 bool Actor::RelayoutDependentOnChildren(Dimension::Type dimension)
1778 {
1779   // Check if actor is dependent on children
1780   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
1781   {
1782     if((dimension & (1 << i)))
1783     {
1784       const ResizePolicy::Type resizePolicy = GetResizePolicy(static_cast<Dimension::Type>(1 << i));
1785       switch(resizePolicy)
1786       {
1787         case ResizePolicy::FIT_TO_CHILDREN:
1788         case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
1789         {
1790           return true;
1791         }
1792
1793         default:
1794         {
1795           break;
1796         }
1797       }
1798     }
1799   }
1800
1801   return false;
1802 }
1803
1804 bool Actor::RelayoutDependentOnChildrenBase(Dimension::Type dimension)
1805 {
1806   return Actor::RelayoutDependentOnChildren(dimension);
1807 }
1808
1809 bool Actor::RelayoutDependentOnDimension(Dimension::Type dimension, Dimension::Type dependentDimension)
1810 {
1811   // Check each possible dimension and see if it is dependent on the input one
1812   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
1813   {
1814     if(dimension & (1 << i))
1815     {
1816       return mRelayoutData->resizePolicies[i] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[i] == dependentDimension;
1817     }
1818   }
1819
1820   return false;
1821 }
1822
1823 void Actor::SetNegotiatedDimension(float negotiatedDimension, Dimension::Type dimension)
1824 {
1825   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
1826   {
1827     if(dimension & (1 << i))
1828     {
1829       mRelayoutData->negotiatedDimensions[i] = negotiatedDimension;
1830     }
1831   }
1832 }
1833
1834 float Actor::GetNegotiatedDimension(Dimension::Type dimension) const
1835 {
1836   // If more than one dimension is requested, just return the first one found
1837   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
1838   {
1839     if((dimension & (1 << i)))
1840     {
1841       return mRelayoutData->negotiatedDimensions[i];
1842     }
1843   }
1844
1845   return 0.0f; // Default
1846 }
1847
1848 void Actor::SetPadding(const Vector2& padding, Dimension::Type dimension)
1849 {
1850   EnsureRelayouter().SetPadding(padding, dimension);
1851 }
1852
1853 Vector2 Actor::GetPadding(Dimension::Type dimension) const
1854 {
1855   if(mRelayoutData)
1856   {
1857     // If more than one dimension is requested, just return the first one found
1858     for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
1859     {
1860       if((dimension & (1 << i)))
1861       {
1862         return mRelayoutData->dimensionPadding[i];
1863       }
1864     }
1865   }
1866
1867   return Relayouter::DEFAULT_DIMENSION_PADDING;
1868 }
1869
1870 void Actor::SetLayoutNegotiated(bool negotiated, Dimension::Type dimension)
1871 {
1872   EnsureRelayouter().SetLayoutNegotiated(negotiated, dimension);
1873 }
1874
1875 bool Actor::IsLayoutNegotiated(Dimension::Type dimension) const
1876 {
1877   return mRelayoutData && mRelayoutData->IsLayoutNegotiated(dimension);
1878 }
1879
1880 float Actor::GetHeightForWidthBase(float width)
1881 {
1882   const Vector3 naturalSize = GetNaturalSize();
1883   return naturalSize.width > 0.0f ? naturalSize.height * width / naturalSize.width : width;
1884 }
1885
1886 float Actor::GetWidthForHeightBase(float height)
1887 {
1888   const Vector3 naturalSize = GetNaturalSize();
1889   return naturalSize.height > 0.0f ? naturalSize.width * height / naturalSize.height : height;
1890 }
1891
1892 float Actor::CalculateChildSizeBase(const Dali::Actor& child, Dimension::Type dimension)
1893 {
1894   // Fill to parent, taking size mode factor into account
1895   switch(child.GetResizePolicy(dimension))
1896   {
1897     case ResizePolicy::FILL_TO_PARENT:
1898     {
1899       return GetLatestSize(dimension);
1900     }
1901
1902     case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
1903     {
1904       return GetLatestSize(dimension) * GetDimensionValue(child.GetProperty<Vector3>(Dali::Actor::Property::SIZE_MODE_FACTOR), dimension);
1905     }
1906
1907     case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
1908     {
1909       return GetLatestSize(dimension) + GetDimensionValue(child.GetProperty<Vector3>(Dali::Actor::Property::SIZE_MODE_FACTOR), dimension);
1910     }
1911
1912     default:
1913     {
1914       return GetLatestSize(dimension);
1915     }
1916   }
1917 }
1918
1919 float Actor::CalculateChildSize(const Dali::Actor& child, Dimension::Type dimension)
1920 {
1921   // Can be overridden in derived class
1922   return CalculateChildSizeBase(child, dimension);
1923 }
1924
1925 float Actor::GetHeightForWidth(float width)
1926 {
1927   // Can be overridden in derived class
1928   return GetHeightForWidthBase(width);
1929 }
1930
1931 float Actor::GetWidthForHeight(float height)
1932 {
1933   // Can be overridden in derived class
1934   return GetWidthForHeightBase(height);
1935 }
1936
1937 float Actor::GetLatestSize(Dimension::Type dimension) const
1938 {
1939   return IsLayoutNegotiated(dimension) ? GetNegotiatedDimension(dimension) : GetSize(dimension);
1940 }
1941
1942 float Actor::GetRelayoutSize(Dimension::Type dimension) const
1943 {
1944   Vector2 padding = GetPadding(dimension);
1945
1946   return GetLatestSize(dimension) + padding.x + padding.y;
1947 }
1948
1949 float Actor::NegotiateFromParent(Dimension::Type dimension)
1950 {
1951   Actor* parent = GetParent();
1952   if(parent)
1953   {
1954     Vector2 padding(GetPadding(dimension));
1955     Vector2 parentPadding(parent->GetPadding(dimension));
1956     return parent->CalculateChildSize(Dali::Actor(this), dimension) - parentPadding.x - parentPadding.y - padding.x - padding.y;
1957   }
1958
1959   return 0.0f;
1960 }
1961
1962 float Actor::NegotiateFromChildren(Dimension::Type dimension)
1963 {
1964   float maxDimensionPoint = 0.0f;
1965
1966   for(uint32_t i = 0, count = GetChildCount(); i < count; ++i)
1967   {
1968     ActorPtr child = GetChildAt(i);
1969
1970     if(!child->RelayoutDependentOnParent(dimension))
1971     {
1972       // Calculate the min and max points that the children range across
1973       float childPosition = GetDimensionValue(child->GetTargetPosition(), dimension);
1974       float dimensionSize = child->GetRelayoutSize(dimension);
1975       maxDimensionPoint   = std::max(maxDimensionPoint, childPosition + dimensionSize);
1976     }
1977   }
1978
1979   return maxDimensionPoint;
1980 }
1981
1982 float Actor::GetSize(Dimension::Type dimension) const
1983 {
1984   return GetDimensionValue(mTargetSize, dimension);
1985 }
1986
1987 float Actor::GetNaturalSize(Dimension::Type dimension) const
1988 {
1989   return GetDimensionValue(GetNaturalSize(), dimension);
1990 }
1991
1992 float Actor::CalculateSize(Dimension::Type dimension, const Vector2& maximumSize)
1993 {
1994   switch(GetResizePolicy(dimension))
1995   {
1996     case ResizePolicy::USE_NATURAL_SIZE:
1997     {
1998       return GetNaturalSize(dimension);
1999     }
2000
2001     case ResizePolicy::FIXED:
2002     {
2003       return GetDimensionValue(GetPreferredSize(), dimension);
2004     }
2005
2006     case ResizePolicy::USE_ASSIGNED_SIZE:
2007     {
2008       return GetDimensionValue(maximumSize, dimension);
2009     }
2010
2011     case ResizePolicy::FILL_TO_PARENT:
2012     case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2013     case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2014     {
2015       return NegotiateFromParent(dimension);
2016     }
2017
2018     case ResizePolicy::FIT_TO_CHILDREN:
2019     {
2020       return NegotiateFromChildren(dimension);
2021     }
2022
2023     case ResizePolicy::DIMENSION_DEPENDENCY:
2024     {
2025       const Dimension::Type dimensionDependency = GetDimensionDependency(dimension);
2026
2027       // Custom rules
2028       if(dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT)
2029       {
2030         return GetWidthForHeight(GetNegotiatedDimension(Dimension::HEIGHT));
2031       }
2032
2033       if(dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH)
2034       {
2035         return GetHeightForWidth(GetNegotiatedDimension(Dimension::WIDTH));
2036       }
2037
2038       break;
2039     }
2040
2041     default:
2042     {
2043       break;
2044     }
2045   }
2046
2047   return 0.0f; // Default
2048 }
2049
2050 Vector2 Actor::ApplySizeSetPolicy(const Vector2& size)
2051 {
2052   return mRelayoutData->ApplySizeSetPolicy(*this, size);
2053 }
2054
2055 void Actor::SetNegotiatedSize(RelayoutContainer& container)
2056 {
2057   // Do the set actor size
2058   Vector2 negotiatedSize(GetLatestSize(Dimension::WIDTH), GetLatestSize(Dimension::HEIGHT));
2059
2060   // Adjust for size set policy
2061   negotiatedSize = ApplySizeSetPolicy(negotiatedSize);
2062
2063   // Lock the flag to stop recursive relayouts on set size
2064   mRelayoutData->insideRelayout = true;
2065   SetSize(negotiatedSize);
2066   mRelayoutData->insideRelayout = false;
2067
2068   // Clear flags for all dimensions
2069   SetLayoutDirty(false);
2070
2071   // Give deriving classes a chance to respond
2072   OnRelayout(negotiatedSize, container);
2073
2074   if(!mOnRelayoutSignal.Empty())
2075   {
2076     Dali::Actor handle(this);
2077     mOnRelayoutSignal.Emit(handle);
2078   }
2079
2080   mRelayoutData->relayoutRequested = false;
2081 }
2082
2083 void Actor::NegotiateSize(const Vector2& allocatedSize, RelayoutContainer& container)
2084 {
2085   Relayouter::NegotiateSize(*this, allocatedSize, container);
2086 }
2087
2088 void Actor::SetUseAssignedSize(bool use, Dimension::Type dimension)
2089 {
2090   if(mRelayoutData)
2091   {
2092     mRelayoutData->SetUseAssignedSize(use, dimension);
2093   }
2094 }
2095
2096 bool Actor::GetUseAssignedSize(Dimension::Type dimension) const
2097 {
2098   return mRelayoutData && mRelayoutData->GetUseAssignedSize(dimension);
2099 }
2100
2101 void Actor::RelayoutRequest(Dimension::Type dimension)
2102 {
2103   Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
2104   if(relayoutController)
2105   {
2106     Dali::Actor self(this);
2107     relayoutController->RequestRelayout(self, dimension);
2108
2109     if(mRelayoutData)
2110     {
2111       mRelayoutData->relayoutRequested = true;
2112     }
2113   }
2114 }
2115
2116 void Actor::SetPreferredSize(const Vector2& size)
2117 {
2118   EnsureRelayouter().SetPreferredSize(*this, size);
2119 }
2120
2121 Vector2 Actor::GetPreferredSize() const
2122 {
2123   return mRelayoutData ? Vector2(mRelayoutData->preferredSize) : Relayouter::DEFAULT_PREFERRED_SIZE;
2124 }
2125
2126 void Actor::SetMinimumSize(float size, Dimension::Type dimension)
2127 {
2128   EnsureRelayouter().SetMinimumSize(size, dimension);
2129   RelayoutRequest();
2130 }
2131
2132 float Actor::GetMinimumSize(Dimension::Type dimension) const
2133 {
2134   return mRelayoutData ? mRelayoutData->GetMinimumSize(dimension) : 0.0f;
2135 }
2136
2137 void Actor::SetMaximumSize(float size, Dimension::Type dimension)
2138 {
2139   EnsureRelayouter().SetMaximumSize(size, dimension);
2140   RelayoutRequest();
2141 }
2142
2143 float Actor::GetMaximumSize(Dimension::Type dimension) const
2144 {
2145   return mRelayoutData ? mRelayoutData->GetMaximumSize(dimension) : FLT_MAX;
2146 }
2147
2148 void Actor::SetVisibleInternal(bool visible, SendMessage::Type sendMessage)
2149 {
2150   if(mVisible != visible)
2151   {
2152     if(sendMessage == SendMessage::TRUE)
2153     {
2154       // node is being used in a separate thread; queue a message to set the value & base value
2155       SceneGraph::NodePropertyMessage<bool>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible);
2156
2157       RequestRenderingMessage(GetEventThreadServices().GetUpdateManager());
2158     }
2159
2160     mVisible = visible;
2161
2162     // Emit the signal on this actor and all its children
2163     mParentImpl.EmitVisibilityChangedSignalRecursively(visible, DevelActor::VisibilityChange::SELF);
2164   }
2165 }
2166
2167 void Actor::SetSiblingOrderOfChild(Actor& child, uint32_t order)
2168 {
2169   mParentImpl.SetSiblingOrderOfChild(child, order);
2170 }
2171
2172 uint32_t Actor::GetSiblingOrderOfChild(const Actor& child) const
2173 {
2174   return mParentImpl.GetSiblingOrderOfChild(child);
2175 }
2176
2177 void Actor::RaiseChild(Actor& child)
2178 {
2179   mParentImpl.RaiseChild(child);
2180 }
2181
2182 void Actor::LowerChild(Actor& child)
2183 {
2184   mParentImpl.LowerChild(child);
2185 }
2186
2187 void Actor::RaiseChildToTop(Actor& child)
2188 {
2189   mParentImpl.RaiseChildToTop(child);
2190 }
2191
2192 void Actor::LowerChildToBottom(Actor& child)
2193 {
2194   mParentImpl.LowerChildToBottom(child);
2195 }
2196
2197 void Actor::RaiseChildAbove(Actor& child, Actor& target)
2198 {
2199   mParentImpl.RaiseChildAbove(child, target);
2200 }
2201
2202 void Actor::LowerChildBelow(Actor& child, Actor& target)
2203 {
2204   mParentImpl.LowerChildBelow(child, target);
2205 }
2206
2207 void Actor::SetInheritLayoutDirection(bool inherit)
2208 {
2209   if(mInheritLayoutDirection != inherit)
2210   {
2211     mInheritLayoutDirection = inherit;
2212
2213     if(inherit && mParent)
2214     {
2215       mParentImpl.InheritLayoutDirectionRecursively(GetParent()->mLayoutDirection);
2216     }
2217   }
2218 }
2219
2220 void Actor::SetUpdateSizeHint(const Vector2& updateSizeHint)
2221 {
2222   // node is being used in a separate thread; queue a message to set the value & base value
2223   SceneGraph::NodePropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mUpdateSizeHint, &AnimatableProperty<Vector3>::Bake, Vector3(updateSizeHint.width, updateSizeHint.height, 0.f));
2224 }
2225
2226 } // namespace Internal
2227
2228 } // namespace Dali