2 * Copyright (c) 2022 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/internal/event/actors/layer-impl.h>
24 #include <dali/public-api/actors/layer.h>
25 #include <dali/public-api/common/dali-common.h>
26 #include <dali/public-api/object/type-registry.h>
28 #include <dali/internal/event/actors/layer-list.h>
29 #include <dali/internal/event/common/event-thread-services.h>
30 #include <dali/internal/event/common/property-helper.h>
31 #include <dali/internal/event/common/scene-impl.h>
33 #include <dali/internal/update/manager/update-manager.h>
34 #include <dali/internal/update/nodes/scene-graph-layer.h>
36 using Dali::Internal::SceneGraph::UpdateManager;
42 typedef Layer::Behavior Behavior;
44 DALI_ENUM_TO_STRING_TABLE_BEGIN(BEHAVIOR)
45 DALI_ENUM_TO_STRING_WITH_SCOPE(Layer, LAYER_UI)
46 DALI_ENUM_TO_STRING_WITH_SCOPE(Layer, LAYER_3D)
47 DALI_ENUM_TO_STRING_TABLE_END(BEHAVIOR)
57 // Name Type writable animatable constraint-input enum for index-checking
58 DALI_PROPERTY_TABLE_BEGIN
59 DALI_PROPERTY("clippingEnable", BOOLEAN, true, false, true, Dali::Layer::Property::CLIPPING_ENABLE)
60 DALI_PROPERTY("clippingBox", RECTANGLE, true, false, true, Dali::Layer::Property::CLIPPING_BOX)
61 DALI_PROPERTY("behavior", INTEGER, true, false, false, Dali::Layer::Property::BEHAVIOR)
62 DALI_PROPERTY("depth", INTEGER, false, false, false, Dali::Layer::Property::DEPTH)
63 DALI_PROPERTY("depthTest", BOOLEAN, true, false, false, Dali::Layer::Property::DEPTH_TEST)
64 DALI_PROPERTY("consumesTouch", BOOLEAN, true, false, false, Dali::Layer::Property::CONSUMES_TOUCH)
65 DALI_PROPERTY("consumesHover", BOOLEAN, true, false, false, Dali::Layer::Property::CONSUMES_HOVER)
66 DALI_PROPERTY_TABLE_END(DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX, LayerDefaultProperties)
70 static constexpr std::string_view ACTION_RAISE = "raise";
71 static constexpr std::string_view ACTION_LOWER = "lower";
72 static constexpr std::string_view ACTION_RAISE_TO_TOP = "raiseToTop";
73 static constexpr std::string_view ACTION_LOWER_TO_BOTTOM = "lowerToBottom";
77 return Dali::Layer::New();
80 TypeRegistration mType(typeid(Dali::Layer), typeid(Dali::Actor), Create, LayerDefaultProperties);
82 TypeAction a1(mType, std::string(ACTION_RAISE), &Layer::DoAction);
83 TypeAction a2(mType, std::string(ACTION_LOWER), &Layer::DoAction);
84 TypeAction a3(mType, std::string(ACTION_RAISE_TO_TOP), &Layer::DoAction);
85 TypeAction a4(mType, std::string(ACTION_LOWER_TO_BOTTOM), &Layer::DoAction);
87 } // unnamed namespace
91 // create node, nodes are owned by UpdateManager
92 SceneGraph::Layer* layerNode = SceneGraph::Layer::New();
93 OwnerPointer<SceneGraph::Node> transferOwnership(layerNode);
94 AddNodeMessage(EventThreadServices::Get().GetUpdateManager(), transferOwnership);
95 LayerPtr layer(new Layer(Actor::LAYER, *layerNode));
97 // Second-phase construction
103 LayerPtr Layer::NewRoot(LayerList& layerList)
105 // create node, nodes are owned by UpdateManager
106 SceneGraph::Layer* rootLayer = SceneGraph::Layer::New();
107 OwnerPointer<SceneGraph::Layer> transferOwnership(rootLayer);
108 InstallRootMessage(EventThreadServices::Get().GetUpdateManager(), transferOwnership);
110 LayerPtr root(new Layer(Actor::ROOT_LAYER, *rootLayer));
112 // root actor is immediately considered to be on-stage
113 root->mIsOnScene = true;
115 // The root actor will not emit a stage connection signal so set the signalled flag here as well
116 root->mOnSceneSignalled = true;
118 // layer-list must be set for the root layer
119 root->mLayerList = &layerList;
120 layerList.SetRootLayer(&(*root));
121 layerList.RegisterLayer(*root);
126 Layer::Layer(Actor::DerivedType type, const SceneGraph::Layer& layer)
127 : Actor(type, layer),
129 mClippingBox(0, 0, 0, 0),
130 mSortFunction(Layer::ZValue),
131 mBehavior(Dali::Layer::LAYER_UI),
133 mDepthTestDisabled(true),
134 mTouchConsumed(false),
135 mHoverConsumed(false)
139 void Layer::OnInitialize()
147 // Guard to allow handle destruction after Core has been destroyed
148 if(EventThreadServices::IsCoreRunning())
150 UninstallRootMessage(GetEventThreadServices().GetUpdateManager(), &GetSceneGraphLayer());
152 GetEventThreadServices().UnregisterObject(this);
157 unsigned int Layer::GetDepth() const
159 return mLayerList ? mLayerList->GetDepth(this) : 0u;
166 mLayerList->RaiseLayer(*this);
174 mLayerList->LowerLayer(*this);
178 void Layer::RaiseAbove(const Internal::Layer& target)
180 // cannot raise above ourself, both have to be on the scene
181 if((this != &target) && OnScene() && target.OnScene())
183 // get parameters depth
184 const uint32_t targetDepth = target.GetDepth();
185 if(GetDepth() < targetDepth)
192 void Layer::LowerBelow(const Internal::Layer& target)
194 // cannot lower below ourself, both have to be on the scene
195 if((this != &target) && OnScene() && target.OnScene())
197 // get parameters depth
198 const uint32_t targetDepth = target.GetDepth();
199 if(GetDepth() > targetDepth)
206 void Layer::RaiseToTop()
210 mLayerList->RaiseLayerToTop(*this);
214 void Layer::LowerToBottom()
218 mLayerList->LowerLayerToBottom(*this);
222 void Layer::MoveAbove(const Internal::Layer& target)
224 // cannot raise above ourself, both have to be on the scene
225 if((this != &target) && mLayerList && target.OnScene())
227 mLayerList->MoveLayerAbove(*this, target);
231 void Layer::MoveBelow(const Internal::Layer& target)
233 // cannot lower below ourself, both have to be on the scene
234 if((this != &target) && mLayerList && target.OnScene())
236 mLayerList->MoveLayerBelow(*this, target);
240 void Layer::SetBehavior(Dali::Layer::Behavior behavior)
242 if(mBehavior != behavior)
244 mBehavior = behavior;
248 // If current layer is on scene, and it's behavior changed,
249 // Change the mLayer3DParentsCount value recursively.
250 mParentImpl.RecursiveChangeLayer3dCount(mBehavior == Dali::Layer::LAYER_3D ? 1 : -1);
253 // Notify update side object.
254 SetBehaviorMessage(GetEventThreadServices(), GetSceneGraphLayer(), behavior);
255 // By default, disable depth test for LAYER_UI, and enable for LAYER_3D.
256 SetDepthTestDisabled(mBehavior == Dali::Layer::LAYER_UI);
260 void Layer::SetClipping(bool enabled)
262 if(enabled != mIsClipping)
264 mIsClipping = enabled;
266 // layerNode is being used in a separate thread; queue a message to set the value
267 SetClippingMessage(GetEventThreadServices(), GetSceneGraphLayer(), mIsClipping);
271 void Layer::SetClippingBox(int x, int y, int width, int height)
273 if((x != mClippingBox.x) ||
274 (y != mClippingBox.y) ||
275 (width != mClippingBox.width) ||
276 (height != mClippingBox.height))
278 // Clipping box is not animatable; this is the most up-to-date value
279 mClippingBox.Set(x, y, width, height);
281 // Convert mClippingBox to GL based coordinates (from bottom-left)
282 ClippingBox clippingBox(mClippingBox);
286 clippingBox.y = static_cast<int32_t>(mScene->GetSize().height) - clippingBox.y - clippingBox.height;
288 // layerNode is being used in a separate thread; queue a message to set the value
289 SetClippingBoxMessage(GetEventThreadServices(), GetSceneGraphLayer(), clippingBox);
294 void Layer::SetDepthTestDisabled(bool disable)
296 if(disable != mDepthTestDisabled)
298 mDepthTestDisabled = disable;
301 // layerNode is being used in a separate thread; queue a message to set the value
302 SetDepthTestDisabledMessage(GetEventThreadServices(), GetSceneGraphLayer(), mDepthTestDisabled);
306 bool Layer::IsDepthTestDisabled() const
308 return mDepthTestDisabled;
311 void Layer::SetSortFunction(Dali::Layer::SortFunctionType function)
313 if(function != mSortFunction)
315 mSortFunction = function;
317 // layerNode is being used in a separate thread; queue a message to set the value
318 SetSortFunctionMessage(GetEventThreadServices(), GetSceneGraphLayer(), mSortFunction);
322 void Layer::SetTouchConsumed(bool consume)
324 mTouchConsumed = consume;
327 bool Layer::IsTouchConsumed() const
329 return mTouchConsumed;
332 void Layer::SetHoverConsumed(bool consume)
334 mHoverConsumed = consume;
337 bool Layer::IsHoverConsumed() const
339 return mHoverConsumed;
342 void Layer::OnSceneConnectionInternal()
346 DALI_ASSERT_DEBUG(NULL == mLayerList);
348 // Find the ordered layer-list
349 for(Actor* parent = GetParent(); parent != nullptr; parent = parent->GetParent())
351 if(parent->IsLayer())
353 Layer* parentLayer = static_cast<Layer*>(parent); // cheaper than dynamic_cast
354 mLayerList = parentLayer->mLayerList;
359 DALI_ASSERT_DEBUG(NULL != mLayerList);
360 mLayerList->RegisterLayer(*this);
363 void Layer::OnSceneDisconnectionInternal()
365 mLayerList->UnregisterLayer(*this);
367 // mLayerList is only valid when on-stage
368 mLayerList = nullptr;
371 const SceneGraph::Layer& Layer::GetSceneGraphLayer() const
373 return static_cast<const SceneGraph::Layer&>(GetNode()); // we know our node is a layer node
376 void Layer::SetDefaultProperty(Property::Index index, const Property::Value& propertyValue)
378 if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
380 Actor::SetDefaultProperty(index, propertyValue);
386 case Dali::Layer::Property::CLIPPING_ENABLE:
388 SetClipping(propertyValue.Get<bool>());
391 case Dali::Layer::Property::CLIPPING_BOX:
393 Rect<int32_t> clippingBox(propertyValue.Get<Rect<int32_t> >());
394 SetClippingBox(clippingBox.x, clippingBox.y, clippingBox.width, clippingBox.height);
397 case Dali::Layer::Property::BEHAVIOR:
399 Behavior behavior = mBehavior;
401 Property::Type type = propertyValue.GetType();
402 if(type == Property::STRING)
404 if(Scripting::GetEnumeration<Behavior>(propertyValue.Get<std::string>().c_str(), BEHAVIOR_TABLE, BEHAVIOR_TABLE_COUNT, behavior))
406 SetBehavior(behavior);
409 else if(type == Property::INTEGER)
411 SetBehavior(propertyValue.Get<Dali::Layer::Behavior>());
415 case Dali::Layer::Property::DEPTH_TEST:
417 SetDepthTestDisabled(!propertyValue.Get<bool>());
420 case Dali::Layer::Property::CONSUMES_TOUCH:
422 SetTouchConsumed(propertyValue.Get<bool>());
425 case Dali::Layer::Property::CONSUMES_HOVER:
427 SetHoverConsumed(propertyValue.Get<bool>());
432 DALI_LOG_WARNING("Unknown property (%d)\n", index);
440 Property::Value Layer::GetDefaultProperty(Property::Index index) const
443 if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
445 ret = Actor::GetDefaultProperty(index);
451 case Dali::Layer::Property::CLIPPING_ENABLE:
456 case Dali::Layer::Property::CLIPPING_BOX:
461 case Dali::Layer::Property::BEHAVIOR:
466 case Dali::Layer::Property::DEPTH:
468 ret = static_cast<int>(GetDepth());
471 case Dali::Layer::Property::DEPTH_TEST:
473 ret = !mDepthTestDisabled;
476 case Dali::Layer::Property::CONSUMES_TOUCH:
478 ret = mTouchConsumed;
481 case Dali::Layer::Property::CONSUMES_HOVER:
483 ret = mHoverConsumed;
488 DALI_LOG_WARNING("Unknown property (%d)\n", index);
497 Property::Value Layer::GetDefaultPropertyCurrentValue(Property::Index index) const
500 if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
502 ret = Actor::GetDefaultPropertyCurrentValue(index);
506 ret = GetDefaultProperty(index); // Layer only has event-side properties
512 bool Layer::DoAction(BaseObject* object, const std::string& actionName, const Property::Map& /*attributes*/)
515 Layer* layer = dynamic_cast<Layer*>(object);
519 std::string_view name(actionName);
521 if(name == ACTION_RAISE)
526 else if(name == ACTION_LOWER)
531 else if(name == ACTION_RAISE_TO_TOP)
536 else if(name == ACTION_LOWER_TO_BOTTOM)
538 layer->LowerToBottom();
546 } // namespace Internal