Merge "Removed scene-graph dependency from internal actor headers" into devel/master
[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("touchArea", VECTOR2, true, false, false, Dali::DevelActor::Property::TOUCH_AREA)
150 DALI_PROPERTY("blendEquation", INTEGER, true, false, false, Dali::DevelActor::Property::BLEND_EQUATION)
151 DALI_PROPERTY_TABLE_END(DEFAULT_ACTOR_PROPERTY_START_INDEX, ActorDefaultProperties)
152
153 // Signals
154
155 static constexpr std::string_view SIGNAL_HOVERED                  = "hovered";
156 static constexpr std::string_view SIGNAL_WHEEL_EVENT              = "wheelEvent";
157 static constexpr std::string_view SIGNAL_ON_SCENE                 = "onScene";
158 static constexpr std::string_view SIGNAL_OFF_SCENE                = "offScene";
159 static constexpr std::string_view SIGNAL_ON_RELAYOUT              = "onRelayout";
160 static constexpr std::string_view SIGNAL_TOUCHED                  = "touched";
161 static constexpr std::string_view SIGNAL_VISIBILITY_CHANGED       = "visibilityChanged";
162 static constexpr std::string_view SIGNAL_LAYOUT_DIRECTION_CHANGED = "layoutDirectionChanged";
163 static constexpr std::string_view SIGNAL_CHILD_ADDED              = "childAdded";
164 static constexpr std::string_view SIGNAL_CHILD_REMOVED            = "childRemoved";
165
166 // Actions
167
168 static constexpr std::string_view ACTION_SHOW = "show";
169 static constexpr std::string_view ACTION_HIDE = "hide";
170
171 BaseHandle CreateActor()
172 {
173   return Dali::Actor::New();
174 }
175
176 TypeRegistration mType(typeid(Dali::Actor), typeid(Dali::Handle), CreateActor, ActorDefaultProperties);
177
178 SignalConnectorType signalConnector2(mType, std::string(SIGNAL_HOVERED), &Actor::DoConnectSignal);
179 SignalConnectorType signalConnector3(mType, std::string(SIGNAL_WHEEL_EVENT), &Actor::DoConnectSignal);
180 SignalConnectorType signalConnector4(mType, std::string(SIGNAL_ON_SCENE), &Actor::DoConnectSignal);
181 SignalConnectorType signalConnector5(mType, std::string(SIGNAL_OFF_SCENE), &Actor::DoConnectSignal);
182 SignalConnectorType signalConnector6(mType, std::string(SIGNAL_ON_RELAYOUT), &Actor::DoConnectSignal);
183 SignalConnectorType signalConnector7(mType, std::string(SIGNAL_TOUCHED), &Actor::DoConnectSignal);
184 SignalConnectorType signalConnector8(mType, std::string(SIGNAL_VISIBILITY_CHANGED), &Actor::DoConnectSignal);
185 SignalConnectorType signalConnector9(mType, std::string(SIGNAL_LAYOUT_DIRECTION_CHANGED), &Actor::DoConnectSignal);
186 SignalConnectorType signalConnector10(mType, std::string(SIGNAL_CHILD_ADDED), &Actor::DoConnectSignal);
187 SignalConnectorType signalConnector11(mType, std::string(SIGNAL_CHILD_REMOVED), &Actor::DoConnectSignal);
188
189 TypeAction a1(mType, std::string(ACTION_SHOW), &Actor::DoAction);
190 TypeAction a2(mType, std::string(ACTION_HIDE), &Actor::DoAction);
191
192 /**
193  * @brief Extract a given dimension from a Vector2
194  *
195  * @param[in] values The values to extract from
196  * @param[in] dimension The dimension to extract
197  * @return Return the value for the dimension
198  */
199 constexpr float GetDimensionValue(const Vector2& values, Dimension::Type dimension)
200 {
201   switch(dimension)
202   {
203     case Dimension::WIDTH:
204     {
205       return values.width;
206     }
207     case Dimension::HEIGHT:
208     {
209       return values.height;
210     }
211     default:
212     {
213       break;
214     }
215   }
216   return 0.0f;
217 }
218
219 /**
220  * @brief Extract a given dimension from a Vector3
221  *
222  * @param[in] values The values to extract from
223  * @param[in] dimension The dimension to extract
224  * @return Return the value for the dimension
225  */
226 float GetDimensionValue(const Vector3& values, Dimension::Type dimension)
227 {
228   return GetDimensionValue(values.GetVectorXY(), dimension);
229 }
230
231 /// Helper for emitting a signal
232 template<typename Signal, typename Event>
233 bool EmitConsumingSignal(Actor& actor, Signal& signal, const Event& event)
234 {
235   bool consumed = false;
236
237   if(!signal.Empty())
238   {
239     Dali::Actor handle(&actor);
240     consumed = signal.Emit(handle, event);
241   }
242
243   return consumed;
244 }
245
246 /// Helper for emitting signals with multiple parameters
247 template<typename Signal, typename... Param>
248 void EmitSignal(Actor& actor, Signal& signal, Param... params)
249 {
250   if(!signal.Empty())
251   {
252     Dali::Actor handle(&actor);
253     signal.Emit(handle, params...);
254   }
255 }
256
257 bool ScreenToLocalInternal(
258   const Matrix&   viewMatrix,
259   const Matrix&   projectionMatrix,
260   const Matrix&   worldMatrix,
261   const Viewport& viewport,
262   const Vector3&  currentSize,
263   float&          localX,
264   float&          localY,
265   float           screenX,
266   float           screenY)
267 {
268   // Get the ModelView matrix
269   Matrix modelView;
270   Matrix::Multiply(modelView, worldMatrix, viewMatrix);
271
272   // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
273   Matrix invertedMvp(false /*don't init*/);
274   Matrix::Multiply(invertedMvp, modelView, projectionMatrix);
275   bool success = invertedMvp.Invert();
276
277   // Convert to GL coordinates
278   Vector4 screenPos(screenX - static_cast<float>(viewport.x), static_cast<float>(viewport.height) - screenY - static_cast<float>(viewport.y), 0.f, 1.f);
279
280   Vector4 nearPos;
281   if(success)
282   {
283     success = Unproject(screenPos, invertedMvp, static_cast<float>(viewport.width), static_cast<float>(viewport.height), nearPos);
284   }
285
286   Vector4 farPos;
287   if(success)
288   {
289     screenPos.z = 1.0f;
290     success     = Unproject(screenPos, invertedMvp, static_cast<float>(viewport.width), static_cast<float>(viewport.height), farPos);
291   }
292
293   if(success)
294   {
295     Vector4 local;
296     if(XyPlaneIntersect(nearPos, farPos, local))
297     {
298       Vector3 size = currentSize;
299       localX       = local.x + size.x * 0.5f;
300       localY       = local.y + size.y * 0.5f;
301     }
302     else
303     {
304       success = false;
305     }
306   }
307
308   return success;
309 }
310
311 } // unnamed namespace
312
313 ActorPtr Actor::New()
314 {
315   // pass a reference to actor, actor does not own its node
316   ActorPtr actor(new Actor(BASIC, *CreateNode()));
317
318   // Second-phase construction
319   actor->Initialize();
320
321   return actor;
322 }
323
324 const SceneGraph::Node* Actor::CreateNode()
325 {
326   // create node. Nodes are owned by the update manager
327   SceneGraph::Node*              node = SceneGraph::Node::New();
328   OwnerPointer<SceneGraph::Node> transferOwnership(node);
329   Internal::ThreadLocalStorage*  tls = Internal::ThreadLocalStorage::GetInternal();
330
331   DALI_ASSERT_ALWAYS(tls && "ThreadLocalStorage is null");
332
333   AddNodeMessage(tls->GetUpdateManager(), transferOwnership);
334
335   return node;
336 }
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(), 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::SetDrawMode(DrawMode::Type drawMode)
1123 {
1124   // this flag is not animatable so keep the value
1125   mDrawMode = drawMode;
1126
1127   // node is being used in a separate thread; queue a message to set the value
1128   SetDrawModeMessage(GetEventThreadServices(), GetNode(), drawMode);
1129 }
1130
1131 bool Actor::ScreenToLocal(float& localX, float& localY, float screenX, float screenY) const
1132 {
1133   // only valid when on-stage
1134   if(mScene && OnScene())
1135   {
1136     const RenderTaskList& taskList = mScene->GetRenderTaskList();
1137
1138     Vector2 converted(screenX, screenY);
1139
1140     // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
1141     uint32_t taskCount = taskList.GetTaskCount();
1142     for(uint32_t i = taskCount; i > 0; --i)
1143     {
1144       RenderTaskPtr task = taskList.GetTask(i - 1);
1145       if(ScreenToLocal(*task, localX, localY, screenX, screenY))
1146       {
1147         // found a task where this conversion was ok so return
1148         return true;
1149       }
1150     }
1151   }
1152   return false;
1153 }
1154
1155 bool Actor::ScreenToLocal(const RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY) const
1156 {
1157   bool retval = false;
1158   // only valid when on-stage
1159   if(OnScene())
1160   {
1161     CameraActor* camera = renderTask.GetCameraActor();
1162     if(camera)
1163     {
1164       Viewport viewport;
1165       renderTask.GetViewport(viewport);
1166
1167       // need to translate coordinates to render tasks coordinate space
1168       Vector2 converted(screenX, screenY);
1169       if(renderTask.TranslateCoordinates(converted))
1170       {
1171         retval = ScreenToLocal(camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y);
1172       }
1173     }
1174   }
1175   return retval;
1176 }
1177
1178 bool Actor::ScreenToLocal(const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY) const
1179 {
1180   return OnScene() && ScreenToLocalInternal(viewMatrix, projectionMatrix, GetNode().GetWorldMatrix(0), viewport, GetCurrentSize(), localX, localY, screenX, screenY);
1181 }
1182
1183 ActorGestureData& Actor::GetGestureData()
1184 {
1185   // Likely scenario is that once gesture-data is created for this actor, the actor will require
1186   // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
1187   if(nullptr == mGestureData)
1188   {
1189     mGestureData = new ActorGestureData;
1190   }
1191   return *mGestureData;
1192 }
1193
1194 bool Actor::IsGestureRequired(GestureType::Value type) const
1195 {
1196   return mGestureData && mGestureData->IsGestureRequired(type);
1197 }
1198
1199 bool Actor::EmitInterceptTouchEventSignal(const Dali::TouchEvent& touch)
1200 {
1201   return EmitConsumingSignal(*this, mInterceptTouchedSignal, touch);
1202 }
1203
1204 bool Actor::EmitTouchEventSignal(const Dali::TouchEvent& touch)
1205 {
1206   return EmitConsumingSignal(*this, mTouchedSignal, touch);
1207 }
1208
1209 bool Actor::EmitHoverEventSignal(const Dali::HoverEvent& event)
1210 {
1211   return EmitConsumingSignal(*this, mHoveredSignal, event);
1212 }
1213
1214 bool Actor::EmitWheelEventSignal(const Dali::WheelEvent& event)
1215 {
1216   return EmitConsumingSignal(*this, mWheelEventSignal, event);
1217 }
1218
1219 void Actor::EmitVisibilityChangedSignal(bool visible, DevelActor::VisibilityChange::Type type)
1220 {
1221   EmitSignal(*this, mVisibilityChangedSignal, visible, type);
1222 }
1223
1224 void Actor::EmitLayoutDirectionChangedSignal(LayoutDirection::Type type)
1225 {
1226   EmitSignal(*this, mLayoutDirectionChangedSignal, type);
1227 }
1228
1229 DevelActor::ChildChangedSignalType& Actor::ChildAddedSignal()
1230 {
1231   return mParentImpl.ChildAddedSignal();
1232 }
1233
1234 DevelActor::ChildChangedSignalType& Actor::ChildRemovedSignal()
1235 {
1236   return mParentImpl.ChildRemovedSignal();
1237 }
1238
1239 DevelActor::ChildOrderChangedSignalType& Actor::ChildOrderChangedSignal()
1240 {
1241   return mParentImpl.ChildOrderChangedSignal();
1242 }
1243
1244 bool Actor::DoConnectSignal(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor)
1245 {
1246   bool   connected(true);
1247   Actor* actor = static_cast<Actor*>(object); // TypeRegistry guarantees that this is the correct type.
1248
1249   std::string_view name(signalName);
1250
1251   if(name == SIGNAL_HOVERED)
1252   {
1253     actor->HoveredSignal().Connect(tracker, functor);
1254   }
1255   else if(signalName == SIGNAL_WHEEL_EVENT)
1256   {
1257     actor->WheelEventSignal().Connect(tracker, functor);
1258   }
1259   else if(name == SIGNAL_ON_SCENE)
1260   {
1261     actor->OnSceneSignal().Connect(tracker, functor);
1262   }
1263   else if(name == SIGNAL_OFF_SCENE)
1264   {
1265     actor->OffSceneSignal().Connect(tracker, functor);
1266   }
1267   else if(name == SIGNAL_ON_RELAYOUT)
1268   {
1269     actor->OnRelayoutSignal().Connect(tracker, functor);
1270   }
1271   else if(name == SIGNAL_TOUCHED)
1272   {
1273     actor->TouchedSignal().Connect(tracker, functor);
1274   }
1275   else if(name == SIGNAL_VISIBILITY_CHANGED)
1276   {
1277     actor->VisibilityChangedSignal().Connect(tracker, functor);
1278   }
1279   else if(name == SIGNAL_LAYOUT_DIRECTION_CHANGED)
1280   {
1281     actor->LayoutDirectionChangedSignal().Connect(tracker, functor);
1282   }
1283   else if(name == SIGNAL_CHILD_ADDED)
1284   {
1285     actor->ChildAddedSignal().Connect(tracker, functor);
1286   }
1287   else if(name == SIGNAL_CHILD_REMOVED)
1288   {
1289     actor->ChildRemovedSignal().Connect(tracker, functor);
1290   }
1291   else
1292   {
1293     // signalName does not match any signal
1294     connected = false;
1295   }
1296
1297   return connected;
1298 }
1299
1300 Actor::Actor(DerivedType derivedType, const SceneGraph::Node& node)
1301 : Object(&node),
1302   mParentImpl(*this),
1303   mParent(nullptr),
1304   mScene(nullptr),
1305   mRenderers(nullptr),
1306   mParentOrigin(nullptr),
1307   mAnchorPoint(nullptr),
1308   mRelayoutData(nullptr),
1309   mGestureData(nullptr),
1310   mInterceptTouchedSignal(),
1311   mTouchedSignal(),
1312   mHoveredSignal(),
1313   mWheelEventSignal(),
1314   mOnSceneSignal(),
1315   mOffSceneSignal(),
1316   mOnRelayoutSignal(),
1317   mVisibilityChangedSignal(),
1318   mLayoutDirectionChangedSignal(),
1319   mTargetOrientation(Quaternion::IDENTITY),
1320   mTargetColor(Color::WHITE),
1321   mTargetSize(Vector3::ZERO),
1322   mTargetPosition(Vector3::ZERO),
1323   mTargetScale(Vector3::ONE),
1324   mAnimatedSize(Vector3::ZERO),
1325   mTouchArea(Vector2::ZERO),
1326   mName(),
1327   mSortedDepth(0u),
1328   mDepth(0u),
1329   mUseAnimatedSize(AnimatedSizeFlag::CLEAR),
1330   mIsRoot(ROOT_LAYER == derivedType),
1331   mIsLayer(LAYER == derivedType || ROOT_LAYER == derivedType),
1332   mIsOnScene(false),
1333   mSensitive(true),
1334   mLeaveRequired(false),
1335   mKeyboardFocusable(false),
1336   mOnSceneSignalled(false),
1337   mInsideOnSizeSet(false),
1338   mInheritPosition(true),
1339   mInheritOrientation(true),
1340   mInheritScale(true),
1341   mPositionUsesAnchorPoint(true),
1342   mVisible(true),
1343   mInheritLayoutDirection(true),
1344   mCaptureAllTouchAfterStart(false),
1345   mLayoutDirection(LayoutDirection::LEFT_TO_RIGHT),
1346   mDrawMode(DrawMode::NORMAL),
1347   mColorMode(Node::DEFAULT_COLOR_MODE),
1348   mClippingMode(ClippingMode::DISABLED),
1349   mBlendEquation(DevelBlendEquation::ADD),
1350   mIsBlendEquationSet(false)
1351 {
1352 }
1353
1354 void Actor::Initialize()
1355 {
1356   OnInitialize();
1357
1358   GetEventThreadServices().RegisterObject(this);
1359 }
1360
1361 Actor::~Actor()
1362 {
1363   // Remove mParent pointers from children even if we're destroying core,
1364   // to guard against GetParent() & Unparent() calls from CustomActor destructors.
1365   UnparentChildren();
1366   delete mRenderers;
1367
1368   // Guard to allow handle destruction after Core has been destroyed
1369   if(EventThreadServices::IsCoreRunning())
1370   {
1371     // Root layer will destroy its node in its own destructor
1372     if(!mIsRoot)
1373     {
1374       DestroyNodeMessage(GetEventThreadServices().GetUpdateManager(), GetNode());
1375
1376       GetEventThreadServices().UnregisterObject(this);
1377     }
1378   }
1379
1380   // Cleanup optional gesture data
1381   delete mGestureData;
1382
1383   // Cleanup optional parent origin and anchor
1384   delete mParentOrigin;
1385   delete mAnchorPoint;
1386
1387   // Delete optional relayout data
1388   delete mRelayoutData;
1389 }
1390
1391 void Actor::Add(Actor& child)
1392 {
1393   mParentImpl.Add(child);
1394 }
1395
1396 void Actor::Remove(Actor& child)
1397 {
1398   mParentImpl.Remove(child);
1399 }
1400
1401 uint32_t Actor::GetChildCount() const
1402 {
1403   return mParentImpl.GetChildCount();
1404 }
1405
1406 ActorPtr Actor::GetChildAt(uint32_t index) const
1407 {
1408   return mParentImpl.GetChildAt(index);
1409 }
1410
1411 ActorContainer& Actor::GetChildrenInternal()
1412 {
1413   return mParentImpl.GetChildrenInternal();
1414 }
1415
1416 ActorPtr Actor::FindChildByName(ConstString actorName)
1417 {
1418   return mParentImpl.FindChildByName(actorName);
1419 }
1420
1421 ActorPtr Actor::FindChildById(const uint32_t id)
1422 {
1423   return mParentImpl.FindChildById(id);
1424 }
1425
1426 void Actor::UnparentChildren()
1427 {
1428   mParentImpl.UnparentChildren();
1429 }
1430
1431 void Actor::ConnectToScene(uint32_t parentDepth)
1432 {
1433   // This container is used instead of walking the Actor hierarchy.
1434   // It protects us when the Actor hierarchy is modified during OnSceneConnectionExternal callbacks.
1435   ActorContainer connectionList;
1436
1437   if(mScene)
1438   {
1439     mScene->RequestRebuildDepthTree();
1440   }
1441
1442   // This stage is atomic i.e. not interrupted by user callbacks.
1443   RecursiveConnectToScene(connectionList, parentDepth + 1);
1444
1445   // Notify applications about the newly connected actors.
1446   for(const auto& actor : connectionList)
1447   {
1448     actor->NotifyStageConnection();
1449   }
1450
1451   RelayoutRequest();
1452 }
1453
1454 void Actor::RecursiveConnectToScene(ActorContainer& connectionList, uint32_t depth)
1455 {
1456   DALI_ASSERT_ALWAYS(!OnScene());
1457
1458   mIsOnScene = true;
1459   mDepth     = static_cast<uint16_t>(depth); // overflow ignored, not expected in practice
1460
1461   ConnectToSceneGraph();
1462
1463   // Notification for internal derived classes
1464   OnSceneConnectionInternal();
1465
1466   // This stage is atomic; avoid emitting callbacks until all Actors are connected
1467   connectionList.push_back(ActorPtr(this));
1468
1469   // Recursively connect children
1470   if(GetChildCount() > 0)
1471   {
1472     for(const auto& child : mParentImpl.GetChildrenInternal())
1473     {
1474       child->SetScene(*mScene);
1475       child->RecursiveConnectToScene(connectionList, depth + 1);
1476     }
1477   }
1478 }
1479
1480 /**
1481  * This method is called when the Actor is connected to the Stage.
1482  * The parent must have added its Node to the scene-graph.
1483  * The child must connect its Node to the parent's Node.
1484  * This is recursive; the child calls ConnectToScene() for its children.
1485  */
1486 void Actor::ConnectToSceneGraph()
1487 {
1488   DALI_ASSERT_DEBUG(mParent != NULL);
1489
1490   // Reparent Node in next Update
1491   ConnectNodeMessage(GetEventThreadServices().GetUpdateManager(), GetParent()->GetNode(), GetNode());
1492
1493   // Request relayout on all actors that are added to the scenegraph
1494   RelayoutRequest();
1495
1496   // Notification for Object::Observers
1497   OnSceneObjectAdd();
1498 }
1499
1500 void Actor::NotifyStageConnection()
1501 {
1502   // Actors can be removed (in a callback), before the on-stage stage is reported.
1503   // The actor may also have been reparented, in which case mOnSceneSignalled will be true.
1504   if(OnScene() && !mOnSceneSignalled)
1505   {
1506     // Notification for external (CustomActor) derived classes
1507     OnSceneConnectionExternal(mDepth);
1508
1509     if(!mOnSceneSignal.Empty())
1510     {
1511       Dali::Actor handle(this);
1512       mOnSceneSignal.Emit(handle);
1513     }
1514
1515     // Guard against Remove during callbacks
1516     if(OnScene())
1517     {
1518       mOnSceneSignalled = true; // signal required next time Actor is removed
1519     }
1520   }
1521 }
1522
1523 void Actor::DisconnectFromStage()
1524 {
1525   // This container is used instead of walking the Actor hierachy.
1526   // It protects us when the Actor hierachy is modified during OnSceneDisconnectionExternal callbacks.
1527   ActorContainer disconnectionList;
1528
1529   if(mScene)
1530   {
1531     mScene->RequestRebuildDepthTree();
1532   }
1533
1534   // This stage is atomic i.e. not interrupted by user callbacks
1535   RecursiveDisconnectFromStage(disconnectionList);
1536
1537   // Notify applications about the newly disconnected actors.
1538   for(const auto& actor : disconnectionList)
1539   {
1540     actor->NotifyStageDisconnection();
1541   }
1542 }
1543
1544 void Actor::RecursiveDisconnectFromStage(ActorContainer& disconnectionList)
1545 {
1546   // need to change state first so that internals relying on IsOnScene() inside OnSceneDisconnectionInternal() get the correct value
1547   mIsOnScene = false;
1548
1549   // Recursively disconnect children
1550   if(GetChildCount() > 0)
1551   {
1552     for(const auto& child : mParentImpl.GetChildrenInternal())
1553     {
1554       child->RecursiveDisconnectFromStage(disconnectionList);
1555     }
1556   }
1557
1558   // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
1559   disconnectionList.push_back(ActorPtr(this));
1560
1561   // Notification for internal derived classes
1562   OnSceneDisconnectionInternal();
1563
1564   DisconnectFromSceneGraph();
1565 }
1566
1567 /**
1568  * This method is called by an actor or its parent, before a node removal message is sent.
1569  * This is recursive; the child calls DisconnectFromStage() for its children.
1570  */
1571 void Actor::DisconnectFromSceneGraph()
1572 {
1573   // Notification for Object::Observers
1574   OnSceneObjectRemove();
1575 }
1576
1577 void Actor::NotifyStageDisconnection()
1578 {
1579   // Actors can be added (in a callback), before the off-stage state is reported.
1580   // Also if the actor was added & removed before mOnSceneSignalled was set, then we don't notify here.
1581   // only do this step if there is a stage, i.e. Core is not being shut down
1582   if(EventThreadServices::IsCoreRunning() && !OnScene() && mOnSceneSignalled)
1583   {
1584     // Notification for external (CustomeActor) derived classes
1585     OnSceneDisconnectionExternal();
1586
1587     if(!mOffSceneSignal.Empty())
1588     {
1589       Dali::Actor handle(this);
1590       mOffSceneSignal.Emit(handle);
1591     }
1592
1593     // Guard against Add during callbacks
1594     if(!OnScene())
1595     {
1596       mOnSceneSignalled = false; // signal required next time Actor is added
1597     }
1598   }
1599 }
1600
1601 bool Actor::IsNodeConnected() const
1602 {
1603   bool connected(false);
1604
1605   if(OnScene())
1606   {
1607     if(IsRoot() || GetNode().GetParent())
1608     {
1609       connected = true;
1610     }
1611   }
1612
1613   return connected;
1614 }
1615
1616 // This method initiates traversal of the actor tree using depth-first
1617 // traversal to set a depth index based on traversal order. It sends a
1618 // single message to update manager to update all the actor's nodes in
1619 // this tree with the depth index. The sceneGraphNodeDepths vector's
1620 // elements are ordered by depth, and could be used to reduce sorting
1621 // in the update thread.
1622 void Actor::RebuildDepthTree()
1623 {
1624   DALI_LOG_TIMER_START(depthTimer);
1625
1626   // Vector of scene-graph nodes and their depths to send to UpdateManager
1627   // in a single message
1628   OwnerPointer<SceneGraph::NodeDepths> sceneGraphNodeDepths(new SceneGraph::NodeDepths());
1629
1630   int32_t depthIndex = 1;
1631   DepthTraverseActorTree(sceneGraphNodeDepths, depthIndex);
1632
1633   SetDepthIndicesMessage(GetEventThreadServices().GetUpdateManager(), sceneGraphNodeDepths);
1634   DALI_LOG_TIMER_END(depthTimer, gLogFilter, Debug::Concise, "Depth tree traversal time: ");
1635 }
1636
1637 void Actor::DepthTraverseActorTree(OwnerPointer<SceneGraph::NodeDepths>& sceneGraphNodeDepths, int32_t& depthIndex)
1638 {
1639   mSortedDepth = depthIndex * DevelLayer::SIBLING_ORDER_MULTIPLIER;
1640   sceneGraphNodeDepths->Add(const_cast<SceneGraph::Node*>(&GetNode()), mSortedDepth);
1641
1642   // Create/add to children of this node
1643   if(GetChildCount() > 0)
1644   {
1645     for(const auto& child : mParentImpl.GetChildrenInternal())
1646     {
1647       Actor* childActor = child.Get();
1648       ++depthIndex;
1649       childActor->DepthTraverseActorTree(sceneGraphNodeDepths, depthIndex);
1650     }
1651   }
1652 }
1653
1654 void Actor::SetDefaultProperty(Property::Index index, const Property::Value& property)
1655 {
1656   PropertyHandler::SetDefaultProperty(*this, index, property);
1657 }
1658
1659 // TODO: This method needs to be removed
1660 void Actor::SetSceneGraphProperty(Property::Index index, const PropertyMetadata& entry, const Property::Value& value)
1661 {
1662   PropertyHandler::SetSceneGraphProperty(index, entry, value, GetEventThreadServices(), GetNode());
1663 }
1664
1665 Property::Value Actor::GetDefaultProperty(Property::Index index) const
1666 {
1667   Property::Value value;
1668
1669   if(!GetCachedPropertyValue(index, value))
1670   {
1671     // If property value is not stored in the event-side, then it must be a scene-graph only property
1672     GetCurrentPropertyValue(index, value);
1673   }
1674
1675   return value;
1676 }
1677
1678 Property::Value Actor::GetDefaultPropertyCurrentValue(Property::Index index) const
1679 {
1680   Property::Value value;
1681
1682   if(!GetCurrentPropertyValue(index, value))
1683   {
1684     // If unable to retrieve scene-graph property value, then it must be an event-side only property
1685     GetCachedPropertyValue(index, value);
1686   }
1687
1688   return value;
1689 }
1690
1691 void Actor::OnNotifyDefaultPropertyAnimation(Animation& animation, Property::Index index, const Property::Value& value, Animation::Type animationType)
1692 {
1693   PropertyHandler::OnNotifyDefaultPropertyAnimation(*this, animation, index, value, animationType);
1694 }
1695
1696 const PropertyBase* Actor::GetSceneObjectAnimatableProperty(Property::Index index) const
1697 {
1698   const PropertyBase* property = PropertyHandler::GetSceneObjectAnimatableProperty(index, GetNode());
1699   if(!property)
1700   {
1701     // not our property, ask base
1702     property = Object::GetSceneObjectAnimatableProperty(index);
1703   }
1704
1705   return property;
1706 }
1707
1708 const PropertyInputImpl* Actor::GetSceneObjectInputProperty(Property::Index index) const
1709 {
1710   const PropertyInputImpl* property = PropertyHandler::GetSceneObjectInputProperty(index, GetNode());
1711   if(!property)
1712   {
1713     // reuse animatable property getter as animatable properties are inputs as well
1714     // animatable property chains back to Object::GetSceneObjectInputProperty() so all properties get covered
1715     property = GetSceneObjectAnimatableProperty(index);
1716   }
1717
1718   return property;
1719 }
1720
1721 int32_t Actor::GetPropertyComponentIndex(Property::Index index) const
1722 {
1723   int32_t componentIndex = PropertyHandler::GetPropertyComponentIndex(index);
1724   if(Property::INVALID_COMPONENT_INDEX == componentIndex)
1725   {
1726     // ask base
1727     componentIndex = Object::GetPropertyComponentIndex(index);
1728   }
1729
1730   return componentIndex;
1731 }
1732
1733 const SceneGraph::Node& Actor::GetNode() const
1734 {
1735   return *static_cast<const SceneGraph::Node*>(mUpdateObject);
1736 }
1737
1738 void Actor::Raise()
1739 {
1740   if(mParent)
1741   {
1742     mParent->RaiseChild(*this);
1743   }
1744   else
1745   {
1746     DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
1747   }
1748 }
1749
1750 void Actor::Lower()
1751 {
1752   if(mParent)
1753   {
1754     mParent->LowerChild(*this);
1755   }
1756   else
1757   {
1758     DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
1759   }
1760 }
1761
1762 void Actor::RaiseToTop()
1763 {
1764   if(mParent)
1765   {
1766     mParent->RaiseChildToTop(*this);
1767   }
1768   else
1769   {
1770     DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
1771   }
1772 }
1773
1774 void Actor::LowerToBottom()
1775 {
1776   if(mParent)
1777   {
1778     mParent->LowerChildToBottom(*this);
1779   }
1780   else
1781   {
1782     DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
1783   }
1784 }
1785
1786 void Actor::RaiseAbove(Internal::Actor& target)
1787 {
1788   if(mParent)
1789   {
1790     mParent->RaiseChildAbove(*this, target);
1791   }
1792   else
1793   {
1794     DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
1795   }
1796 }
1797
1798 void Actor::LowerBelow(Internal::Actor& target)
1799 {
1800   if(mParent)
1801   {
1802     mParent->LowerChildBelow(*this, target);
1803   }
1804   else
1805   {
1806     DALI_LOG_WARNING("Actor must have a parent, Sibling order not changed.\n");
1807   }
1808 }
1809
1810 void Actor::SetParent(ActorParent* parent)
1811 {
1812   if(parent)
1813   {
1814     DALI_ASSERT_ALWAYS(!mParent && "Actor cannot have 2 parents");
1815
1816     mParent            = parent;
1817     Actor* parentActor = static_cast<Actor*>(parent);
1818     mScene             = parentActor->mScene;
1819
1820     if(EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1821        parentActor->OnScene())
1822     {
1823       // Instruct each actor to create a corresponding node in the scene graph
1824       ConnectToScene(parentActor->GetHierarchyDepth());
1825     }
1826
1827     // Resolve the name and index for the child properties if any
1828     ResolveChildProperties();
1829   }
1830   else // parent being set to NULL
1831   {
1832     DALI_ASSERT_ALWAYS(mParent != nullptr && "Actor should have a parent");
1833
1834     mParent = nullptr;
1835
1836     if(EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
1837        OnScene())
1838     {
1839       // Disconnect the Node & its children from the scene-graph.
1840       DisconnectNodeMessage(GetEventThreadServices().GetUpdateManager(), GetNode());
1841
1842       // Instruct each actor to discard pointers to the scene-graph
1843       DisconnectFromStage();
1844     }
1845
1846     mScene = nullptr;
1847   }
1848 }
1849
1850 bool Actor::DoAction(BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */)
1851 {
1852   bool   done  = false;
1853   Actor* actor = dynamic_cast<Actor*>(object);
1854
1855   if(actor)
1856   {
1857     std::string_view name(actionName);
1858     if(name == ACTION_SHOW)
1859     {
1860       actor->SetVisible(true);
1861       done = true;
1862     }
1863     else if(name == ACTION_HIDE)
1864     {
1865       actor->SetVisible(false);
1866       done = true;
1867     }
1868   }
1869
1870   return done;
1871 }
1872
1873 Rect<> Actor::CalculateScreenExtents() const
1874 {
1875   auto    screenPosition    = GetCurrentScreenPosition();
1876   Vector3 size              = GetCurrentSize() * GetCurrentWorldScale();
1877   Vector3 anchorPointOffSet = size * (mPositionUsesAnchorPoint ? GetCurrentAnchorPoint() : AnchorPoint::TOP_LEFT);
1878   Vector2 position          = Vector2(screenPosition.x - anchorPointOffSet.x, screenPosition.y - anchorPointOffSet.y);
1879   return {position.x, position.y, size.x, size.y};
1880 }
1881
1882 bool Actor::GetCachedPropertyValue(Property::Index index, Property::Value& value) const
1883 {
1884   return PropertyHandler::GetCachedPropertyValue(*this, index, value);
1885 }
1886
1887 bool Actor::GetCurrentPropertyValue(Property::Index index, Property::Value& value) const
1888 {
1889   return PropertyHandler::GetCurrentPropertyValue(*this, index, value);
1890 }
1891
1892 Actor::Relayouter& Actor::EnsureRelayouter()
1893 {
1894   // Assign relayouter
1895   if(!mRelayoutData)
1896   {
1897     mRelayoutData = new Relayouter();
1898   }
1899
1900   return *mRelayoutData;
1901 }
1902
1903 bool Actor::RelayoutDependentOnParent(Dimension::Type dimension)
1904 {
1905   // Check if actor is dependent on parent
1906   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
1907   {
1908     if((dimension & (1 << i)))
1909     {
1910       const ResizePolicy::Type resizePolicy = GetResizePolicy(static_cast<Dimension::Type>(1 << i));
1911       if(resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT)
1912       {
1913         return true;
1914       }
1915     }
1916   }
1917
1918   return false;
1919 }
1920
1921 bool Actor::RelayoutDependentOnChildren(Dimension::Type dimension)
1922 {
1923   // Check if actor is dependent on children
1924   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
1925   {
1926     if((dimension & (1 << i)))
1927     {
1928       const ResizePolicy::Type resizePolicy = GetResizePolicy(static_cast<Dimension::Type>(1 << i));
1929       switch(resizePolicy)
1930       {
1931         case ResizePolicy::FIT_TO_CHILDREN:
1932         case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children
1933         {
1934           return true;
1935         }
1936
1937         default:
1938         {
1939           break;
1940         }
1941       }
1942     }
1943   }
1944
1945   return false;
1946 }
1947
1948 bool Actor::RelayoutDependentOnChildrenBase(Dimension::Type dimension)
1949 {
1950   return Actor::RelayoutDependentOnChildren(dimension);
1951 }
1952
1953 bool Actor::RelayoutDependentOnDimension(Dimension::Type dimension, Dimension::Type dependentDimension)
1954 {
1955   // Check each possible dimension and see if it is dependent on the input one
1956   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
1957   {
1958     if(dimension & (1 << i))
1959     {
1960       return mRelayoutData->resizePolicies[i] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[i] == dependentDimension;
1961     }
1962   }
1963
1964   return false;
1965 }
1966
1967 void Actor::SetNegotiatedDimension(float negotiatedDimension, Dimension::Type dimension)
1968 {
1969   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
1970   {
1971     if(dimension & (1 << i))
1972     {
1973       mRelayoutData->negotiatedDimensions[i] = negotiatedDimension;
1974     }
1975   }
1976 }
1977
1978 float Actor::GetNegotiatedDimension(Dimension::Type dimension) const
1979 {
1980   // If more than one dimension is requested, just return the first one found
1981   for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
1982   {
1983     if((dimension & (1 << i)))
1984     {
1985       return mRelayoutData->negotiatedDimensions[i];
1986     }
1987   }
1988
1989   return 0.0f; // Default
1990 }
1991
1992 void Actor::SetPadding(const Vector2& padding, Dimension::Type dimension)
1993 {
1994   EnsureRelayouter().SetPadding(padding, dimension);
1995 }
1996
1997 Vector2 Actor::GetPadding(Dimension::Type dimension) const
1998 {
1999   if(mRelayoutData)
2000   {
2001     // If more than one dimension is requested, just return the first one found
2002     for(uint32_t i = 0; i < Dimension::DIMENSION_COUNT; ++i)
2003     {
2004       if((dimension & (1 << i)))
2005       {
2006         return mRelayoutData->dimensionPadding[i];
2007       }
2008     }
2009   }
2010
2011   return Relayouter::DEFAULT_DIMENSION_PADDING;
2012 }
2013
2014 void Actor::SetLayoutNegotiated(bool negotiated, Dimension::Type dimension)
2015 {
2016   EnsureRelayouter().SetLayoutNegotiated(negotiated, dimension);
2017 }
2018
2019 bool Actor::IsLayoutNegotiated(Dimension::Type dimension) const
2020 {
2021   return mRelayoutData && mRelayoutData->IsLayoutNegotiated(dimension);
2022 }
2023
2024 float Actor::GetHeightForWidthBase(float width)
2025 {
2026   float height = 0.0f;
2027
2028   const Vector3 naturalSize = GetNaturalSize();
2029   if(naturalSize.width > 0.0f)
2030   {
2031     height = naturalSize.height * width / naturalSize.width;
2032   }
2033   else // we treat 0 as 1:1 aspect ratio
2034   {
2035     height = width;
2036   }
2037
2038   return height;
2039 }
2040
2041 float Actor::GetWidthForHeightBase(float height)
2042 {
2043   float width = 0.0f;
2044
2045   const Vector3 naturalSize = GetNaturalSize();
2046   if(naturalSize.height > 0.0f)
2047   {
2048     width = naturalSize.width * height / naturalSize.height;
2049   }
2050   else // we treat 0 as 1:1 aspect ratio
2051   {
2052     width = height;
2053   }
2054
2055   return width;
2056 }
2057
2058 float Actor::CalculateChildSizeBase(const Dali::Actor& child, Dimension::Type dimension)
2059 {
2060   // Fill to parent, taking size mode factor into account
2061   switch(child.GetResizePolicy(dimension))
2062   {
2063     case ResizePolicy::FILL_TO_PARENT:
2064     {
2065       return GetLatestSize(dimension);
2066     }
2067
2068     case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2069     {
2070       return GetLatestSize(dimension) * GetDimensionValue(child.GetProperty<Vector3>(Dali::Actor::Property::SIZE_MODE_FACTOR), dimension);
2071     }
2072
2073     case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2074     {
2075       return GetLatestSize(dimension) + GetDimensionValue(child.GetProperty<Vector3>(Dali::Actor::Property::SIZE_MODE_FACTOR), dimension);
2076     }
2077
2078     default:
2079     {
2080       return GetLatestSize(dimension);
2081     }
2082   }
2083 }
2084
2085 float Actor::CalculateChildSize(const Dali::Actor& child, Dimension::Type dimension)
2086 {
2087   // Can be overridden in derived class
2088   return CalculateChildSizeBase(child, dimension);
2089 }
2090
2091 float Actor::GetHeightForWidth(float width)
2092 {
2093   // Can be overridden in derived class
2094   return GetHeightForWidthBase(width);
2095 }
2096
2097 float Actor::GetWidthForHeight(float height)
2098 {
2099   // Can be overridden in derived class
2100   return GetWidthForHeightBase(height);
2101 }
2102
2103 float Actor::GetLatestSize(Dimension::Type dimension) const
2104 {
2105   return IsLayoutNegotiated(dimension) ? GetNegotiatedDimension(dimension) : GetSize(dimension);
2106 }
2107
2108 float Actor::GetRelayoutSize(Dimension::Type dimension) const
2109 {
2110   Vector2 padding = GetPadding(dimension);
2111
2112   return GetLatestSize(dimension) + padding.x + padding.y;
2113 }
2114
2115 float Actor::NegotiateFromParent(Dimension::Type dimension)
2116 {
2117   Actor* parent = GetParent();
2118   if(parent)
2119   {
2120     Vector2 padding(GetPadding(dimension));
2121     Vector2 parentPadding(parent->GetPadding(dimension));
2122     return parent->CalculateChildSize(Dali::Actor(this), dimension) - parentPadding.x - parentPadding.y - padding.x - padding.y;
2123   }
2124
2125   return 0.0f;
2126 }
2127
2128 float Actor::NegotiateFromChildren(Dimension::Type dimension)
2129 {
2130   float maxDimensionPoint = 0.0f;
2131
2132   for(uint32_t i = 0, count = GetChildCount(); i < count; ++i)
2133   {
2134     ActorPtr child = GetChildAt(i);
2135
2136     if(!child->RelayoutDependentOnParent(dimension))
2137     {
2138       // Calculate the min and max points that the children range across
2139       float childPosition = GetDimensionValue(child->GetTargetPosition(), dimension);
2140       float dimensionSize = child->GetRelayoutSize(dimension);
2141       maxDimensionPoint   = std::max(maxDimensionPoint, childPosition + dimensionSize);
2142     }
2143   }
2144
2145   return maxDimensionPoint;
2146 }
2147
2148 float Actor::GetSize(Dimension::Type dimension) const
2149 {
2150   return GetDimensionValue(mTargetSize, dimension);
2151 }
2152
2153 float Actor::GetNaturalSize(Dimension::Type dimension) const
2154 {
2155   return GetDimensionValue(GetNaturalSize(), dimension);
2156 }
2157
2158 float Actor::CalculateSize(Dimension::Type dimension, const Vector2& maximumSize)
2159 {
2160   switch(GetResizePolicy(dimension))
2161   {
2162     case ResizePolicy::USE_NATURAL_SIZE:
2163     {
2164       return GetNaturalSize(dimension);
2165     }
2166
2167     case ResizePolicy::FIXED:
2168     {
2169       return GetDimensionValue(GetPreferredSize(), dimension);
2170     }
2171
2172     case ResizePolicy::USE_ASSIGNED_SIZE:
2173     {
2174       return GetDimensionValue(maximumSize, dimension);
2175     }
2176
2177     case ResizePolicy::FILL_TO_PARENT:
2178     case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
2179     case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
2180     {
2181       return NegotiateFromParent(dimension);
2182     }
2183
2184     case ResizePolicy::FIT_TO_CHILDREN:
2185     {
2186       return NegotiateFromChildren(dimension);
2187     }
2188
2189     case ResizePolicy::DIMENSION_DEPENDENCY:
2190     {
2191       const Dimension::Type dimensionDependency = GetDimensionDependency(dimension);
2192
2193       // Custom rules
2194       if(dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT)
2195       {
2196         return GetWidthForHeight(GetNegotiatedDimension(Dimension::HEIGHT));
2197       }
2198
2199       if(dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH)
2200       {
2201         return GetHeightForWidth(GetNegotiatedDimension(Dimension::WIDTH));
2202       }
2203
2204       break;
2205     }
2206
2207     default:
2208     {
2209       break;
2210     }
2211   }
2212
2213   return 0.0f; // Default
2214 }
2215
2216 Vector2 Actor::ApplySizeSetPolicy(const Vector2& size)
2217 {
2218   return mRelayoutData->ApplySizeSetPolicy(*this, size);
2219 }
2220
2221 void Actor::SetNegotiatedSize(RelayoutContainer& container)
2222 {
2223   // Do the set actor size
2224   Vector2 negotiatedSize(GetLatestSize(Dimension::WIDTH), GetLatestSize(Dimension::HEIGHT));
2225
2226   // Adjust for size set policy
2227   negotiatedSize = ApplySizeSetPolicy(negotiatedSize);
2228
2229   // Lock the flag to stop recursive relayouts on set size
2230   mRelayoutData->insideRelayout = true;
2231   SetSize(negotiatedSize);
2232   mRelayoutData->insideRelayout = false;
2233
2234   // Clear flags for all dimensions
2235   SetLayoutDirty(false);
2236
2237   // Give deriving classes a chance to respond
2238   OnRelayout(negotiatedSize, container);
2239
2240   if(!mOnRelayoutSignal.Empty())
2241   {
2242     Dali::Actor handle(this);
2243     mOnRelayoutSignal.Emit(handle);
2244   }
2245 }
2246
2247 void Actor::NegotiateSize(const Vector2& allocatedSize, RelayoutContainer& container)
2248 {
2249   Relayouter::NegotiateSize(*this, allocatedSize, container);
2250 }
2251
2252 void Actor::SetUseAssignedSize(bool use, Dimension::Type dimension)
2253 {
2254   if(mRelayoutData)
2255   {
2256     mRelayoutData->SetUseAssignedSize(use, dimension);
2257   }
2258 }
2259
2260 bool Actor::GetUseAssignedSize(Dimension::Type dimension) const
2261 {
2262   return mRelayoutData && mRelayoutData->GetUseAssignedSize(dimension);
2263 }
2264
2265 void Actor::RelayoutRequest(Dimension::Type dimension)
2266 {
2267   Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
2268   if(relayoutController)
2269   {
2270     Dali::Actor self(this);
2271     relayoutController->RequestRelayout(self, dimension);
2272   }
2273 }
2274
2275 void Actor::SetPreferredSize(const Vector2& size)
2276 {
2277   EnsureRelayouter().SetPreferredSize(*this, size);
2278 }
2279
2280 Vector2 Actor::GetPreferredSize() const
2281 {
2282   if(mRelayoutData)
2283   {
2284     return Vector2(mRelayoutData->preferredSize);
2285   }
2286
2287   return Relayouter::DEFAULT_PREFERRED_SIZE;
2288 }
2289
2290 void Actor::SetMinimumSize(float size, Dimension::Type dimension)
2291 {
2292   EnsureRelayouter().SetMinimumSize(size, dimension);
2293   RelayoutRequest();
2294 }
2295
2296 float Actor::GetMinimumSize(Dimension::Type dimension) const
2297 {
2298   if(mRelayoutData)
2299   {
2300     return mRelayoutData->GetMinimumSize(dimension);
2301   }
2302
2303   return 0.0f; // Default
2304 }
2305
2306 void Actor::SetMaximumSize(float size, Dimension::Type dimension)
2307 {
2308   EnsureRelayouter().SetMaximumSize(size, dimension);
2309   RelayoutRequest();
2310 }
2311
2312 float Actor::GetMaximumSize(Dimension::Type dimension) const
2313 {
2314   if(mRelayoutData)
2315   {
2316     return mRelayoutData->GetMaximumSize(dimension);
2317   }
2318
2319   return FLT_MAX; // Default
2320 }
2321
2322 void Actor::SetVisibleInternal(bool visible, SendMessage::Type sendMessage)
2323 {
2324   if(mVisible != visible)
2325   {
2326     if(sendMessage == SendMessage::TRUE)
2327     {
2328       // node is being used in a separate thread; queue a message to set the value & base value
2329       SceneGraph::NodePropertyMessage<bool>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mVisible, &AnimatableProperty<bool>::Bake, visible);
2330
2331       RequestRenderingMessage(GetEventThreadServices().GetUpdateManager());
2332     }
2333
2334     mVisible = visible;
2335
2336     // Emit the signal on this actor and all its children
2337     EmitVisibilityChangedSignalRecursively(visible, DevelActor::VisibilityChange::SELF);
2338   }
2339 }
2340
2341 void Actor::SetSiblingOrderOfChild(Actor& child, uint32_t order)
2342 {
2343   mParentImpl.SetSiblingOrderOfChild(child, order);
2344 }
2345
2346 uint32_t Actor::GetSiblingOrderOfChild(const Actor& child) const
2347 {
2348   return mParentImpl.GetSiblingOrderOfChild(child);
2349 }
2350
2351 void Actor::RaiseChild(Actor& child)
2352 {
2353   mParentImpl.RaiseChild(child);
2354 }
2355
2356 void Actor::LowerChild(Actor& child)
2357 {
2358   mParentImpl.LowerChild(child);
2359 }
2360
2361 void Actor::RaiseChildToTop(Actor& child)
2362 {
2363   mParentImpl.RaiseChildToTop(child);
2364 }
2365
2366 void Actor::LowerChildToBottom(Actor& child)
2367 {
2368   mParentImpl.LowerChildToBottom(child);
2369 }
2370
2371 void Actor::RaiseChildAbove(Actor& child, Actor& target)
2372 {
2373   mParentImpl.RaiseChildAbove(child, target);
2374 }
2375
2376 void Actor::LowerChildBelow(Actor& child, Actor& target)
2377 {
2378   mParentImpl.LowerChildBelow(child, target);
2379 }
2380
2381 void Actor::SetInheritLayoutDirection(bool inherit)
2382 {
2383   if(mInheritLayoutDirection != inherit)
2384   {
2385     mInheritLayoutDirection = inherit;
2386
2387     if(inherit && mParent)
2388     {
2389       InheritLayoutDirectionRecursively(GetParent()->mLayoutDirection);
2390     }
2391   }
2392 }
2393
2394 void Actor::InheritLayoutDirectionRecursively(Dali::LayoutDirection::Type direction, bool set)
2395 {
2396   if(mInheritLayoutDirection || set)
2397   {
2398     if(mLayoutDirection != direction)
2399     {
2400       mLayoutDirection = direction;
2401       EmitLayoutDirectionChangedSignal(direction);
2402       RelayoutRequest();
2403     }
2404
2405     if(GetChildCount() > 0)
2406     {
2407       for(const auto& child : mParentImpl.GetChildrenInternal())
2408       {
2409         child->InheritLayoutDirectionRecursively(direction);
2410       }
2411     }
2412   }
2413 }
2414
2415 void Actor::SetUpdateSizeHint(const Vector2& updateSizeHint)
2416 {
2417   // node is being used in a separate thread; queue a message to set the value & base value
2418   SceneGraph::NodePropertyMessage<Vector3>::Send(GetEventThreadServices(), &GetNode(), &GetNode().mUpdateSizeHint, &AnimatableProperty<Vector3>::Bake, Vector3(updateSizeHint.width, updateSizeHint.height, 0.f));
2419 }
2420
2421 void Actor::EmitVisibilityChangedSignalRecursively(bool                               visible,
2422                                                    DevelActor::VisibilityChange::Type type)
2423 {
2424   EmitVisibilityChangedSignal(visible, type);
2425
2426   if(GetChildCount() > 0)
2427   {
2428     for(auto& child : mParentImpl.GetChildrenInternal())
2429     {
2430       child->EmitVisibilityChangedSignalRecursively(visible, DevelActor::VisibilityChange::PARENT);
2431     }
2432   }
2433 }
2434
2435 } // namespace Internal
2436
2437 } // namespace Dali