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