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