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