X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fevent%2Fevents%2Fhit-test-algorithm-impl.cpp;h=f6858379e505356f1d82cb039747cdb938547b43;hb=c1df908470fc3dd242fef202248e56009727bca4;hp=5026b95536d68b9328e5f5fddbe428b3b1de27e1;hpb=d753679093d22b5023eff4b58b9d0d2c2f045a85;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 5026b95..f685837 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) 2016 Samsung Electronics Co., Ltd. + * Copyright (c) 2019 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. @@ -19,18 +19,14 @@ #include // INTERNAL INCLUDES -#include #include #include #include #include #include #include -#include #include #include -#include -#include #include #include #include @@ -57,10 +53,10 @@ struct HitActor { } - Actor *actor; ///< The actor hit (if actor is hit, then this is initialised). - Vector2 hitPosition; ///< Position of hit (only valid if actor valid). - float distance; ///< Distance from ray origin to hit actor. - int depth; ///< Depth index of this actor. + Actor *actor; ///< The actor hit (if actor is hit, then this is initialised). + Vector2 hitPosition; ///< Position of hit (only valid if actor valid). + float distance; ///< Distance from ray origin to hit actor. + int32_t depth; ///< Depth index of this actor. }; /** @@ -128,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; } @@ -155,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, @@ -163,8 +159,8 @@ HitActor HitTestWithinLayer( Actor& actor, HitTestInterface& hitCheck, bool& overlayHit, bool layerIs3d, - unsigned int clippingDepth, - unsigned int clippingBitPlaneMask ) + uint32_t clippingDepth, + uint32_t clippingBitPlaneMask ) { HitActor hit; @@ -177,7 +173,7 @@ HitActor HitTestWithinLayer( Actor& actor, // we increase the clipping depth if we have hit a clipping actor. // This is used later to ensure all nested clipped children have hit // all clipping actors also for them to be counted as hit. - unsigned int newClippingDepth = clippingDepth; + uint32_t newClippingDepth = clippingDepth; bool clippingActor = actor.GetClippingMode() != ClippingMode::DISABLED; if( clippingActor ) { @@ -234,7 +230,8 @@ HitActor HitTestWithinLayer( Actor& actor, // Here we calculate a comparison mask by setting all the bits up to the current depth value. // EG. a depth of 4 (10000 binary) = a mask of 1111 binary. // This allows us a fast way of comparing all bits are set up to this depth. - unsigned int clippingDepthMask = ( 1u << clippingDepth ) - 1u; + // Note: If the current Actor has clipping, that is included in the depth mask too. + uint32_t clippingDepthMask = ( 1u << newClippingDepth ) - 1u; // The two masks must be equal to be a hit, as we are already assuming a hit // (for non-clipping mode) then they must be not-equal to disqualify the hit. @@ -249,13 +246,13 @@ HitActor HitTestWithinLayer( Actor& actor, hit.actor = &actor; hit.hitPosition = hitPointLocal; hit.distance = distance; - hit.depth = actor.GetHierarchyDepth() * Dali::Layer::TREE_DEPTH_MULTIPLIER; + hit.depth = actor.GetSortingDepth() ; if( actor.GetRendererCount() > 0 ) { //Get renderer with maximum depth int rendererMaxDepth(actor.GetRendererAt( 0 ).Get()->GetDepthIndex()); - for( unsigned int i(1); i < actor.GetRendererCount(); ++i ) + for( uint32_t i(1); i < actor.GetRendererCount(); ++i ) { int depth = actor.GetRendererAt( i ).Get()->GetDepthIndex(); if( depth > rendererMaxDepth ) @@ -277,7 +274,7 @@ HitActor HitTestWithinLayer( Actor& actor, if( actor.GetChildCount() > 0 ) { childHit.distance = std::numeric_limits::max(); - childHit.depth = std::numeric_limits::min(); + childHit.depth = std::numeric_limits::min(); ActorContainer& children = actor.GetChildrenInternal(); // Hit test ALL children and calculate their distance. @@ -362,10 +359,10 @@ inline bool IsActuallyHittable( Layer& layer, const Vector2& screenCoordinates, { ClippingBox box = layer.GetClippingBox(); - if( screenCoordinates.x < box.x || - screenCoordinates.x > box.x + box.width || - screenCoordinates.y < stageSize.y - (box.y + box.height) || - screenCoordinates.y > stageSize.y - box.y) + if( screenCoordinates.x < static_cast( box.x )|| + screenCoordinates.x > static_cast( box.x + box.width )|| + screenCoordinates.y < stageSize.y - static_cast( box.y + box.height ) || + screenCoordinates.y > stageSize.y - static_cast( box.y ) ) { // Not touchable if clipping is enabled in the layer and the screen coordinate is outside the clip region. hittable = false; @@ -404,8 +401,8 @@ 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, @@ -416,10 +413,10 @@ bool HitTestRenderTask( const Vector< RenderTaskList::Exclusive >& exclusives, { Viewport viewport; renderTask.GetViewport( viewport ); - if( screenCoordinates.x < viewport.x || - screenCoordinates.x > viewport.x + viewport.width || - screenCoordinates.y < viewport.y || - screenCoordinates.y > viewport.y + viewport.height ) + if( screenCoordinates.x < static_cast( viewport.x ) || + screenCoordinates.x > static_cast( viewport.x + viewport.width ) || + screenCoordinates.y < static_cast( viewport.y ) || + screenCoordinates.y > static_cast( viewport.y + viewport.height ) ) { // The screen coordinate is outside the viewport of render task. The viewport clips all layers. return false; @@ -435,7 +432,7 @@ bool HitTestRenderTask( const Vector< RenderTaskList::Exclusive >& exclusives, Dali::Layer layer( sourceActor->GetLayer() ); if( layer ) { - const unsigned int sourceActorDepth( layer.GetDepth() ); + const uint32_t sourceActorDepth( layer.GetDepth() ); CameraActor* cameraActor = renderTask.GetCameraActor(); bool pickingPossible = cameraActor->BuildPickingRay( @@ -452,18 +449,17 @@ bool HitTestRenderTask( const Vector< RenderTaskList::Exclusive >& exclusives, HitActor hit; bool overlayHit = false; bool layerConsumesHit = false; - const Vector2& stageSize = stage.GetSize(); - for( int i = layers.GetLayerCount() - 1; i >= 0 && !( hit.actor ); --i ) + for( int32_t i = layers.GetLayerCount() - 1; i >= 0 && !( hit.actor ); --i ) { Layer* layer( layers.GetLayer( i ) ); 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 ) ) + if( sourceActorDepth == static_cast( i ) ) { // Recursively hit test the source actor & children, without crossing into other layers. hit = HitTestWithinLayer( *sourceActor, @@ -507,7 +503,7 @@ bool HitTestRenderTask( const Vector< RenderTaskList::Exclusive >& exclusives, if( hit.actor ) { - results.renderTask = Dali::RenderTask( &renderTask ); + results.renderTask = RenderTaskPtr( &renderTask ); results.actor = Dali::Actor( hit.actor ); results.actorCoordinates = hit.hitPosition; @@ -527,7 +523,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 @@ -535,7 +531,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, @@ -545,27 +541,19 @@ 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(); for( RenderTaskList::RenderTaskContainer::reverse_iterator iter = tasks.rbegin(); endIter != iter; ++iter ) { - RenderTask& renderTask = GetImplementation( *iter ); - Dali::FrameBufferImage frameBufferImage = renderTask.GetTargetFrameBuffer(); - - // Note that if frameBufferImage is NULL we are using the default (on screen) render target - if( frameBufferImage ) + RenderTask& renderTask = *iter->Get(); + bool isOffscreenRenderTask = ( renderTask.GetTargetFrameBuffer() || renderTask.GetFrameBuffer() ); + if( (onScreen && isOffscreenRenderTask) || (!onScreen && !isOffscreenRenderTask) ) { - ResourceId id = GetImplementation( frameBufferImage ).GetResourceId(); - - // Change comparison depending on if on-screen or off-screen. - if( onScreen ? ( 0 != id ) : ( 0 == id ) ) - { - // Skip to next task - continue; - } + // Skip to next task + continue; } - if( HitTestRenderTask( exclusives, stage, layers, renderTask, screenCoordinates, results, hitCheck ) ) + if( HitTestRenderTask( exclusives, sceneSize, layers, renderTask, screenCoordinates, results, hitCheck ) ) { // 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 @@ -578,7 +566,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 @@ -586,7 +574,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, @@ -597,8 +585,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; @@ -609,16 +597,17 @@ bool HitTestForEachRenderTask( Stage& stage, } // unnamed namespace -bool HitTest( Stage& stage, const Vector2& screenCoordinates, Dali::HitTestAlgorithm::Results& results, Dali::HitTestAlgorithm::HitTestFunction func ) +HitTestInterface::~HitTestInterface() { - bool wasHit( false ); - // Hit-test the regular on-stage actors - RenderTaskList& taskList = stage.GetRenderTaskList(); - LayerList& layerList = stage.GetLayerList(); +} +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-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; @@ -627,56 +616,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 system-overlay actors first - SystemOverlay* systemOverlay = stage.GetSystemOverlayInternal(); - - if( systemOverlay ) - { - RenderTaskList& overlayTaskList = systemOverlay->GetOverlayRenderTasks(); - LayerList& overlayLayerList = systemOverlay->GetLayerList(); - - wasHit = HitTestForEachRenderTask( stage, overlayLayerList, overlayTaskList, screenCoordinates, results, hitTestInterface ); - } - - // 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 ); + return HitTest( sceneSize, renderTaskList, layerList, 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; -} - - } // namespace HitTestAlgorithm } // namespace Internal