X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fevent%2Fevents%2Fhit-test-algorithm-impl.cpp;h=587df4de6e1b13e5b3af4786caba79185938ecc4;hb=ac791d290a2050dc0166f6ad5bfe4158f889c60d;hp=59bb3d07a3734653488c8f3645f618ab69db91dc;hpb=0ba3f763e7369e7b52a12cf759560dc329e14f2e;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/internal/event/events/hit-test-algorithm-impl.cpp b/dali/internal/event/events/hit-test-algorithm-impl.cpp index 59bb3d0..587df4d 100644 --- a/dali/internal/event/events/hit-test-algorithm-impl.cpp +++ b/dali/internal/event/events/hit-test-algorithm-impl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. + * Copyright (c) 2020 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,9 +27,8 @@ #include #include #include -#include #include -#include +#include #include #include @@ -48,7 +47,7 @@ namespace struct HitActor { HitActor() - : actor( NULL ), + : actor( nullptr ), distance( std::numeric_limits::max() ), depth( std::numeric_limits::min() ) { @@ -75,17 +74,17 @@ struct HitTestFunctionWrapper : public HitTestInterface { } - virtual bool IsActorHittable( Actor* actor ) + bool IsActorHittable( Actor* actor ) override { return mFunc( Dali::Actor( actor ), Dali::HitTestAlgorithm::CHECK_ACTOR ); } - virtual bool DescendActorHierarchy( Actor* actor ) + bool DescendActorHierarchy( Actor* actor ) override { return mFunc( Dali::Actor( actor ), Dali::HitTestAlgorithm::DESCEND_ACTOR_TREE ); } - virtual bool DoesLayerConsumeHit( Layer* layer ) + bool DoesLayerConsumeHit( Layer* layer ) override { // Layer::IsTouchConsumed() focuses on touch only. Here we are a wrapper for the public-api // where the caller may want to check for something completely different. @@ -102,19 +101,19 @@ struct HitTestFunctionWrapper : public HitTestInterface */ struct ActorTouchableCheck : public HitTestInterface { - virtual bool IsActorHittable( Actor* actor ) + bool IsActorHittable( Actor* actor ) override { return actor->GetTouchRequired() && // Does the Application or derived actor type require a touch event? actor->IsHittable(); // Is actor sensitive, visible and on the scene? } - virtual bool DescendActorHierarchy( Actor* actor ) + bool DescendActorHierarchy( Actor* actor ) override { return actor->IsVisible() && // Actor is visible, if not visible then none of its children are visible. actor->IsSensitive(); // Actor is sensitive, if insensitive none of its children should be hittable either. } - virtual bool DoesLayerConsumeHit( Layer* layer ) + bool DoesLayerConsumeHit( Layer* layer ) override { return layer->IsTouchConsumed(); } @@ -125,14 +124,14 @@ struct ActorTouchableCheck : public HitTestInterface */ bool IsActorExclusiveToAnotherRenderTask( const Actor& actor, const RenderTask& renderTask, - const Vector< RenderTaskList::Exclusive >& exclusives ) + const RenderTaskList::ExclusivesContainer& exclusives ) { - if( exclusives.Size() ) + if( exclusives.size() ) { - for( Vector< RenderTaskList::Exclusive >::Iterator exclusiveIt = exclusives.Begin(); exclusives.End() != exclusiveIt; ++exclusiveIt ) + for( const auto& exclusive : exclusives ) { - if( ( exclusiveIt->renderTaskPtr != &renderTask ) && ( exclusiveIt->actorPtr == &actor ) ) + if( ( exclusive.renderTaskPtr != &renderTask ) && ( exclusive.actor.GetActor() == &actor ) ) { return true; } @@ -152,7 +151,7 @@ bool IsActorExclusiveToAnotherRenderTask( const Actor& actor, */ HitActor HitTestWithinLayer( Actor& actor, const RenderTask& renderTask, - const Vector< RenderTaskList::Exclusive >& exclusives, + const RenderTaskList::ExclusivesContainer& exclusives, const Vector4& rayOrigin, const Vector4& rayDir, float& nearClippingPlane, @@ -161,7 +160,8 @@ HitActor HitTestWithinLayer( Actor& actor, bool& overlayHit, bool layerIs3d, uint32_t clippingDepth, - uint32_t clippingBitPlaneMask ) + uint32_t clippingBitPlaneMask, + const RayTest& rayTest ) { HitActor hit; @@ -188,13 +188,13 @@ HitActor HitTestWithinLayer( Actor& actor, // Ensure the actor has a valid size. // If so, perform a quick ray sphere test to see if our ray is close to the actor. - if( size.x > 0.0f && size.y > 0.0f && actor.RaySphereTest( rayOrigin, rayDir ) ) + if( size.x > 0.0f && size.y > 0.0f && rayTest.SphereTest( actor, rayOrigin, rayDir ) ) { Vector2 hitPointLocal; float distance; // Finally, perform a more accurate ray test to see if our ray actually hits the actor. - if( actor.RayActorTest( rayOrigin, rayDir, hitPointLocal, distance ) ) + if( rayTest.ActorTest( actor, rayOrigin, rayDir, hitPointLocal, distance ) ) { if( distance >= nearClippingPlane && distance <= farClippingPlane ) { @@ -298,7 +298,8 @@ HitActor HitTestWithinLayer( Actor& actor, overlayHit, layerIs3d, newClippingDepth, - clippingBitPlaneMask ) ); + clippingBitPlaneMask, + rayTest ) ); bool updateChildHit = false; if( currentHit.distance >= 0.0f ) @@ -402,13 +403,14 @@ void GetCameraClippingPlane( RenderTask& renderTask, float& nearClippingPlane, f /** * Hit test a RenderTask */ -bool HitTestRenderTask( const Vector< RenderTaskList::Exclusive >& exclusives, - Stage& stage, +bool HitTestRenderTask( const RenderTaskList::ExclusivesContainer& exclusives, + const Vector2& sceneSize, LayerList& layers, RenderTask& renderTask, Vector2 screenCoordinates, Results& results, - HitTestInterface& hitCheck ) + HitTestInterface& hitCheck, + const RayTest& rayTest ) { if ( renderTask.IsHittable( screenCoordinates ) ) { @@ -433,7 +435,7 @@ bool HitTestRenderTask( const Vector< RenderTaskList::Exclusive >& exclusives, Dali::Layer layer( sourceActor->GetLayer() ); if( layer ) { - const uint32_t sourceActorDepth( layer.GetDepth() ); + const uint32_t sourceActorDepth( layer.GetProperty< bool >( Dali::Layer::Property::DEPTH ) ); CameraActor* cameraActor = renderTask.GetCameraActor(); bool pickingPossible = cameraActor->BuildPickingRay( @@ -450,7 +452,6 @@ bool HitTestRenderTask( const Vector< RenderTaskList::Exclusive >& exclusives, HitActor hit; bool overlayHit = false; bool layerConsumesHit = false; - const Vector2& stageSize = stage.GetSize(); for( int32_t i = layers.GetLayerCount() - 1; i >= 0 && !( hit.actor ); --i ) { @@ -458,7 +459,7 @@ bool HitTestRenderTask( const Vector< RenderTaskList::Exclusive >& exclusives, overlayHit = false; // Ensure layer is touchable (also checks whether ancestors are also touchable) - if( IsActuallyHittable( *layer, screenCoordinates, stageSize, hitCheck ) ) + if( IsActuallyHittable( *layer, screenCoordinates, sceneSize, hitCheck ) ) { // Always hit-test the source actor; otherwise test whether the layer is below the source actor in the hierarchy if( sourceActorDepth == static_cast( i ) ) @@ -475,7 +476,8 @@ bool HitTestRenderTask( const Vector< RenderTaskList::Exclusive >& exclusives, overlayHit, layer->GetBehavior() == Dali::Layer::LAYER_3D, 0u, - 0u ); + 0u, + rayTest ); } else if( IsWithinSourceActors( *sourceActor, *layer ) ) { @@ -491,7 +493,8 @@ bool HitTestRenderTask( const Vector< RenderTaskList::Exclusive >& exclusives, overlayHit, layer->GetBehavior() == Dali::Layer::LAYER_3D, 0u, - 0u ); + 0u, + rayTest ); } // If this layer is set to consume the hit, then do not check any layers behind it @@ -525,7 +528,7 @@ bool HitTestRenderTask( const Vector< RenderTaskList::Exclusive >& exclusives, /** * Iterate through the RenderTaskList and perform hit testing. * - * @param[in] stage The stage the tests will be performed in + * @param[in] sceneSize The scene size the tests will be performed in * @param[in] layers The list of layers to test * @param[in] taskList The list of render tasks * @param[out] results Ray information calculated by the camera @@ -533,7 +536,7 @@ bool HitTestRenderTask( const Vector< RenderTaskList::Exclusive >& exclusives, * @param[in] onScreen True to test on-screen, false to test off-screen * @return True if we have a hit, false otherwise */ -bool HitTestRenderTaskList( Stage& stage, +bool HitTestRenderTaskList( const Vector2& sceneSize, LayerList& layers, RenderTaskList& taskList, const Vector2& screenCoordinates, @@ -543,19 +546,20 @@ bool HitTestRenderTaskList( Stage& stage, { RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks(); RenderTaskList::RenderTaskContainer::reverse_iterator endIter = tasks.rend(); - const Vector< RenderTaskList::Exclusive >& exclusives = taskList.GetExclusivesList(); + const auto& exclusives = taskList.GetExclusivesList(); + RayTest rayTest; for( RenderTaskList::RenderTaskContainer::reverse_iterator iter = tasks.rbegin(); endIter != iter; ++iter ) { RenderTask& renderTask = *iter->Get(); - bool isOffscreenRenderTask = ( renderTask.GetTargetFrameBuffer() || renderTask.GetFrameBuffer() ); + const bool isOffscreenRenderTask = renderTask.GetFrameBuffer(); if( (onScreen && isOffscreenRenderTask) || (!onScreen && !isOffscreenRenderTask) ) { // Skip to next task continue; } - if( HitTestRenderTask( exclusives, stage, layers, renderTask, screenCoordinates, results, hitCheck ) ) + if( HitTestRenderTask( exclusives, sceneSize, layers, renderTask, screenCoordinates, results, hitCheck, rayTest ) ) { // Return true when an actor is hit (or layer in our render-task consumes the hit) return true; // don't bother checking off screen tasks @@ -568,7 +572,7 @@ bool HitTestRenderTaskList( Stage& stage, /** * Iterate through the RenderTaskList and perform hit testing for both on-screen and off-screen. * - * @param[in] stage The stage the tests will be performed in + * @param[in] sceneSize The scene size the tests will be performed in * @param[in] layers The list of layers to test * @param[in] taskList The list of render tasks * @param[out] results Ray information calculated by the camera @@ -576,7 +580,7 @@ bool HitTestRenderTaskList( Stage& stage, * @param[in] onScreen True to test on-screen, false to test off-screen * @return True if we have a hit, false otherwise */ -bool HitTestForEachRenderTask( Stage& stage, +bool HitTestForEachRenderTask( const Vector2& sceneSize, LayerList& layers, RenderTaskList& taskList, const Vector2& screenCoordinates, @@ -587,8 +591,8 @@ bool HitTestForEachRenderTask( Stage& stage, // Check on-screen tasks before off-screen ones. // Hit test order should be reverse of draw order (see ProcessRenderTasks() where off-screen tasks are drawn first). - if( HitTestRenderTaskList( stage, layers, taskList, screenCoordinates, results, hitCheck, true ) || - HitTestRenderTaskList( stage, layers, taskList, screenCoordinates, results, hitCheck, false ) ) + if( HitTestRenderTaskList( sceneSize, layers, taskList, screenCoordinates, results, hitCheck, true ) || + HitTestRenderTaskList( sceneSize, layers, taskList, screenCoordinates, results, hitCheck, false ) ) { // Found hit. result = true; @@ -603,16 +607,13 @@ HitTestInterface::~HitTestInterface() { } -bool HitTest( Stage& stage, const Vector2& screenCoordinates, Dali::HitTestAlgorithm::Results& results, Dali::HitTestAlgorithm::HitTestFunction func ) +bool HitTest( const Vector2& sceneSize, RenderTaskList& taskList, LayerList& layerList, const Vector2& screenCoordinates, Dali::HitTestAlgorithm::Results& results, Dali::HitTestAlgorithm::HitTestFunction func ) { bool wasHit( false ); - // Hit-test the regular on-stage actors - RenderTaskList& taskList = stage.GetRenderTaskList(); - LayerList& layerList = stage.GetLayerList(); - + // Hit-test the regular on-scene actors Results hitTestResults; HitTestFunctionWrapper hitTestFunctionWrapper( func ); - if( HitTestForEachRenderTask( stage, layerList, taskList, screenCoordinates, hitTestResults, hitTestFunctionWrapper ) ) + if( HitTestForEachRenderTask( sceneSize, layerList, taskList, screenCoordinates, hitTestResults, hitTestFunctionWrapper ) ) { results.actor = hitTestResults.actor; results.actorCoordinates = hitTestResults.actorCoordinates; @@ -621,45 +622,24 @@ bool HitTest( Stage& stage, const Vector2& screenCoordinates, Dali::HitTestAlgor return wasHit; } -bool HitTest( Stage& stage, const Vector2& screenCoordinates, Results& results, HitTestInterface& hitTestInterface ) +bool HitTest( const Vector2& sceneSize, RenderTaskList& renderTaskList, LayerList& layerList, const Vector2& screenCoordinates, Results& results, HitTestInterface& hitTestInterface ) { bool wasHit( false ); - // Hit-test the regular on-stage actors + // Hit-test the regular on-scene actors if( !wasHit ) { - RenderTaskList& taskList = stage.GetRenderTaskList(); - LayerList& layerList = stage.GetLayerList(); - - wasHit = HitTestForEachRenderTask( stage, layerList, taskList, screenCoordinates, results, hitTestInterface ); + wasHit = HitTestForEachRenderTask( sceneSize, layerList, renderTaskList, screenCoordinates, results, hitTestInterface ); } return wasHit; } -bool HitTest( Stage& stage, const Vector2& screenCoordinates, Results& results ) +bool HitTest( const Vector2& sceneSize, RenderTaskList& renderTaskList, LayerList& layerList, const Vector2& screenCoordinates, Results& results ) { ActorTouchableCheck actorTouchableCheck; - return HitTest( stage, screenCoordinates, results, actorTouchableCheck ); -} - -bool HitTest( Stage& stage, RenderTask& renderTask, const Vector2& screenCoordinates, - Dali::HitTestAlgorithm::Results& results, Dali::HitTestAlgorithm::HitTestFunction func ) -{ - bool wasHit( false ); - Results hitTestResults; - - const Vector< RenderTaskList::Exclusive >& exclusives = stage.GetRenderTaskList().GetExclusivesList(); - HitTestFunctionWrapper hitTestFunctionWrapper( func ); - if( HitTestRenderTask( exclusives, stage, stage.GetLayerList(), renderTask, screenCoordinates, hitTestResults, hitTestFunctionWrapper ) ) - { - results.actor = hitTestResults.actor; - results.actorCoordinates = hitTestResults.actorCoordinates; - wasHit = true; - } - return wasHit; + return HitTest( sceneSize, renderTaskList, layerList, screenCoordinates, results, actorTouchableCheck ); } - } // namespace HitTestAlgorithm } // namespace Internal