2 * Copyright (c) 2020 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>
27 #include <dali/internal/event/actors/layer-list.h>
28 #include <dali/internal/event/common/property-helper.h>
29 #include <dali/internal/event/common/scene-impl.h>
30 #include <dali/internal/event/common/event-thread-services.h>
32 using Dali::Internal::SceneGraph::UpdateManager;
40 typedef Layer::Behavior Behavior;
42 DALI_ENUM_TO_STRING_TABLE_BEGIN( BEHAVIOR )
43 DALI_ENUM_TO_STRING_WITH_SCOPE( Layer, LAYER_UI )
44 DALI_ENUM_TO_STRING_WITH_SCOPE( Layer, LAYER_3D )
45 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
92 // create node, nodes are owned by UpdateManager
93 SceneGraph::Layer* layerNode = SceneGraph::Layer::New();
94 OwnerPointer< SceneGraph::Node > transferOwnership( layerNode );
95 AddNodeMessage( EventThreadServices::Get().GetUpdateManager(), transferOwnership );
96 LayerPtr layer( new Layer( Actor::LAYER, *layerNode ) );
98 // Second-phase construction
104 LayerPtr Layer::NewRoot( LayerList& layerList )
106 // create node, nodes are owned by UpdateManager
107 SceneGraph::Layer* rootLayer = SceneGraph::Layer::New();
108 OwnerPointer< SceneGraph::Layer > transferOwnership( rootLayer );
109 InstallRootMessage( EventThreadServices::Get().GetUpdateManager(), transferOwnership );
111 LayerPtr root( new Layer( Actor::ROOT_LAYER, *rootLayer ) );
113 // root actor is immediately considered to be on-stage
114 root->mIsOnScene = true;
116 // The root actor will not emit a stage connection signal so set the signalled flag here as well
117 root->mOnSceneSignalled = true;
119 // layer-list must be set for the root layer
120 root->mLayerList = &layerList;
121 layerList.SetRootLayer( &(*root) );
122 layerList.RegisterLayer( *root );
127 Layer::Layer( Actor::DerivedType type, const SceneGraph::Layer& layer )
128 : Actor( type, layer ),
129 mLayerList( nullptr ),
130 mClippingBox( 0, 0, 0, 0 ),
131 mSortFunction( Layer::ZValue ),
132 mBehavior( Dali::Layer::LAYER_UI ),
133 mIsClipping( false ),
134 mDepthTestDisabled( true ),
135 mTouchConsumed( false ),
136 mHoverConsumed( false )
140 void Layer::OnInitialize()
148 // Guard to allow handle destruction after Core has been destroyed
149 if( EventThreadServices::IsCoreRunning() )
151 UninstallRootMessage( GetEventThreadServices().GetUpdateManager(), &GetSceneGraphLayer() );
153 GetEventThreadServices().UnregisterObject( this );
158 unsigned int Layer::GetDepth() const
160 return mLayerList ? mLayerList->GetDepth( this ) : 0u;
167 mLayerList->RaiseLayer(*this);
175 mLayerList->LowerLayer(*this);
179 void Layer::RaiseAbove( const Internal::Layer& target )
181 // cannot raise above ourself, both have to be on the scene
182 if( ( this != &target ) && OnScene() && target.OnScene() )
184 // get parameters depth
185 const uint32_t targetDepth = target.GetDepth();
186 if( GetDepth() < targetDepth )
193 void Layer::LowerBelow( const Internal::Layer& target )
195 // cannot lower below ourself, both have to be on the scene
196 if( ( this != &target ) && OnScene() && target.OnScene() )
198 // get parameters depth
199 const uint32_t targetDepth = target.GetDepth();
200 if( GetDepth() > targetDepth )
207 void Layer::RaiseToTop()
211 mLayerList->RaiseLayerToTop(*this);
215 void Layer::LowerToBottom()
219 mLayerList->LowerLayerToBottom(*this);
223 void Layer::MoveAbove( const Internal::Layer& target )
225 // cannot raise above ourself, both have to be on the scene
226 if( ( this != &target ) && mLayerList && target.OnScene() )
228 mLayerList->MoveLayerAbove(*this, target );
232 void Layer::MoveBelow( const Internal::Layer& target )
234 // cannot lower below ourself, both have to be on the scene
235 if( ( this != &target ) && mLayerList && target.OnScene() )
237 mLayerList->MoveLayerBelow(*this, target );
241 void Layer::SetBehavior( Dali::Layer::Behavior behavior )
243 mBehavior = behavior;
245 // Notify update side object.
246 SetBehaviorMessage( GetEventThreadServices(), GetSceneGraphLayer(), behavior );
247 // By default, disable depth test for LAYER_UI, and enable for LAYER_3D.
248 SetDepthTestDisabled( mBehavior == Dali::Layer::LAYER_UI );
251 void Layer::SetClipping(bool enabled)
253 if (enabled != mIsClipping)
255 mIsClipping = enabled;
257 // layerNode is being used in a separate thread; queue a message to set the value
258 SetClippingMessage( GetEventThreadServices(), GetSceneGraphLayer(), mIsClipping );
262 void Layer::SetClippingBox(int x, int y, int width, int height)
264 if( ( x != mClippingBox.x ) ||
265 ( y != mClippingBox.y ) ||
266 ( width != mClippingBox.width ) ||
267 ( height != mClippingBox.height ) )
269 // Clipping box is not animatable; this is the most up-to-date value
270 mClippingBox.Set(x, y, width, height);
272 // Convert mClippingBox to GL based coordinates (from bottom-left)
273 ClippingBox clippingBox( mClippingBox );
277 clippingBox.y = static_cast<int32_t>( mScene->GetSize().height ) - clippingBox.y - clippingBox.height;
279 // layerNode is being used in a separate thread; queue a message to set the value
280 SetClippingBoxMessage( GetEventThreadServices(), GetSceneGraphLayer(), clippingBox );
285 void Layer::SetDepthTestDisabled( bool disable )
287 if( disable != mDepthTestDisabled )
289 mDepthTestDisabled = disable;
292 // layerNode is being used in a separate thread; queue a message to set the value
293 SetDepthTestDisabledMessage( GetEventThreadServices(), GetSceneGraphLayer(), mDepthTestDisabled );
297 bool Layer::IsDepthTestDisabled() const
299 return mDepthTestDisabled;
302 void Layer::SetSortFunction(Dali::Layer::SortFunctionType function)
304 if( function != mSortFunction )
306 mSortFunction = function;
308 // layerNode is being used in a separate thread; queue a message to set the value
309 SetSortFunctionMessage( GetEventThreadServices(), GetSceneGraphLayer(), mSortFunction );
313 void Layer::SetTouchConsumed( bool consume )
315 mTouchConsumed = consume;
318 bool Layer::IsTouchConsumed() const
320 return mTouchConsumed;
323 void Layer::SetHoverConsumed( bool consume )
325 mHoverConsumed = consume;
328 bool Layer::IsHoverConsumed() const
330 return mHoverConsumed;
333 void Layer::OnSceneConnectionInternal()
337 DALI_ASSERT_DEBUG( NULL == mLayerList );
339 // Find the ordered layer-list
340 for ( Actor* parent = mParent; parent != nullptr; parent = parent->GetParent() )
342 if( parent->IsLayer() )
344 Layer* parentLayer = static_cast< Layer* >( parent ); // cheaper than dynamic_cast
345 mLayerList = parentLayer->mLayerList;
350 DALI_ASSERT_DEBUG( NULL != mLayerList );
351 mLayerList->RegisterLayer( *this );
354 void Layer::OnSceneDisconnectionInternal()
356 mLayerList->UnregisterLayer(*this);
358 // mLayerList is only valid when on-stage
359 mLayerList = nullptr;
362 const SceneGraph::Layer& Layer::GetSceneGraphLayer() const
364 return static_cast< const SceneGraph::Layer& >( GetNode() ); // we know our node is a layer node
367 void Layer::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue )
369 if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
371 Actor::SetDefaultProperty( index, propertyValue );
377 case Dali::Layer::Property::CLIPPING_ENABLE:
379 SetClipping( propertyValue.Get<bool>() );
382 case Dali::Layer::Property::CLIPPING_BOX:
384 Rect<int32_t> clippingBox( propertyValue.Get<Rect<int32_t> >() );
385 SetClippingBox( clippingBox.x, clippingBox.y, clippingBox.width, clippingBox.height );
388 case Dali::Layer::Property::BEHAVIOR:
390 Behavior behavior = mBehavior;
392 Property::Type type = propertyValue.GetType();
393 if( type == Property::STRING )
395 if( Scripting::GetEnumeration< Behavior >( propertyValue.Get< std::string >().c_str(), BEHAVIOR_TABLE, BEHAVIOR_TABLE_COUNT, behavior ) )
397 SetBehavior( behavior );
400 else if ( type == Property::INTEGER )
402 SetBehavior( propertyValue.Get< Dali::Layer::Behavior >() );
406 case Dali::Layer::Property::DEPTH_TEST:
408 SetDepthTestDisabled( !propertyValue.Get<bool>() );
411 case Dali::Layer::Property::CONSUMES_TOUCH:
413 SetTouchConsumed( propertyValue.Get<bool>() );
416 case Dali::Layer::Property::CONSUMES_HOVER:
418 SetHoverConsumed( propertyValue.Get<bool>() );
423 DALI_LOG_WARNING( "Unknown property (%d)\n", index );
431 Property::Value Layer::GetDefaultProperty( Property::Index index ) const
434 if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
436 ret = Actor::GetDefaultProperty( index );
442 case Dali::Layer::Property::CLIPPING_ENABLE:
447 case Dali::Layer::Property::CLIPPING_BOX:
452 case Dali::Layer::Property::BEHAVIOR:
457 case Dali::Layer::Property::DEPTH:
459 ret = static_cast<int>( GetDepth() );
462 case Dali::Layer::Property::DEPTH_TEST:
464 ret = !mDepthTestDisabled;
467 case Dali::Layer::Property::CONSUMES_TOUCH:
469 ret = mTouchConsumed;
472 case Dali::Layer::Property::CONSUMES_HOVER:
474 ret = mHoverConsumed;
479 DALI_LOG_WARNING( "Unknown property (%d)\n", index );
488 Property::Value Layer::GetDefaultPropertyCurrentValue( Property::Index index ) const
491 if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
493 ret = Actor::GetDefaultPropertyCurrentValue( index );
497 ret = GetDefaultProperty( index ); // Layer only has event-side properties
503 bool Layer::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /*attributes*/ )
506 Layer* layer = dynamic_cast<Layer*>( object );
510 std::string_view name(actionName);
512 if(name == ACTION_RAISE)
517 else if(name == ACTION_LOWER)
522 else if(name == ACTION_RAISE_TO_TOP)
527 else if(name == ACTION_LOWER_TO_BOTTOM)
529 layer->LowerToBottom();
537 } // namespace Internal