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