return mFunc( Dali::Actor( actor ), Dali::HitTestAlgorithm::DESCEND_ACTOR_TREE );
}
+ virtual bool DoesLayerConsumeHit( Layer* layer )
+ {
+ // 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.
+ // TODO: Should provide a means to let caller decide. For now do not allow layers to consume
+ return false;
+ }
+
Dali::HitTestAlgorithm::HitTestFunction mFunc;
};
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 )
+ {
+ return layer->IsTouchConsumed();
+ }
};
/**
}
}
- // If there is a stencil on this layer and we've also registered a hit, then don't both searching any children
- if ( stencilHit && hit.actor )
+ // If we are a stencil (or a child of a stencil) and we have already ascertained that the stencil has been hit then there is no need to hit-test the children of this stencil-actor
+ if ( isStencil && stencilHit )
{
return hit;
}
HitActor hit;
bool stencilOnLayer = false;
bool stencilHit = false;
+ bool layerConsumesHit = false;
const Vector2& stageSize = Stage::GetCurrent()->GetSize();
for (int i=layers.GetLayerCount()-1; i>=0 && !(hit.actor); --i)
// Recursively hit test all the actors, without crossing into other layers.
hit = HitTestWithinLayer( *layer, results.rayOrigin, results.rayDirection, false, nearClippingPlane, farClippingPlane, hitCheck, stencilOnLayer, stencilHit, false );
}
- // If a stencil on this layer hasn't been hit, then discard hit results for this layer
- if ( stencilOnLayer && !stencilHit )
+
+ // If a stencil on this layer hasn't been hit, then discard hit results for this layer if our current hit actor is renderable
+ if ( stencilOnLayer && !stencilHit &&
+ hit.actor && hit.actor->IsRenderable() )
+ {
+ hit = previousHit;
+ }
+
+ // If this layer is set to consume the hit, then do not check any layers behind it
+ if ( hitCheck.DoesLayerConsumeHit( layer ) )
{
- hit = previousHit;
+ layerConsumesHit = true;
+ break;
}
}
}
results.actorCoordinates.y = hit.y;
return true; // Success
}
+ else if ( layerConsumesHit )
+ {
+ return true; // Also success if layer is consuming the hit
+ }
}
}
}
/**
* Iterate through RenderTaskList and perform hit test.
+ *
+ * @return true if we have a hit, false otherwise
*/
-
-void HitTestForEachRenderTask( LayerList& layers,
+bool HitTestForEachRenderTask( LayerList& layers,
RenderTaskList& taskList,
const Vector2& screenCoordinates,
Results& results,
if ( HitTestRenderTask( layers, renderTask, screenCoordinates, results, hitCheck ) )
{
- // Exit when an actor is hit
- return; // don't bother checking off screen tasks
+ // 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
}
}
if ( HitTestRenderTask( layers, renderTask, screenCoordinates, results, hitCheck ) )
{
- // Exit when an actor is hit
- break;
+ // Return true when an actor is hit (or a layer in our render-task consumes the hit)
+ return true;
}
}
}
+ return false;
}
} // unnamed namespace
-void HitTest( Stage& stage, const Vector2& screenCoordinates, Dali::HitTestAlgorithm::Results& results, Dali::HitTestAlgorithm::HitTestFunction func )
+bool HitTest( Stage& stage, 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();
Results hitTestResults;
HitTestFunctionWrapper hitTestFunctionWrapper( func );
- HitTestForEachRenderTask( layerList, taskList, screenCoordinates, hitTestResults, hitTestFunctionWrapper );
-
- results.actor = hitTestResults.actor;
- results.actorCoordinates = hitTestResults.actorCoordinates;
+ if ( HitTestForEachRenderTask( layerList, taskList, screenCoordinates, hitTestResults, hitTestFunctionWrapper ) )
+ {
+ results.actor = hitTestResults.actor;
+ results.actorCoordinates = hitTestResults.actorCoordinates;
+ wasHit = true;
+ }
+ return wasHit;
}
-void HitTest( Stage& stage, const Vector2& screenCoordinates, Results& results, HitTestInterface& hitTestInterface )
+bool HitTest( Stage& stage, const Vector2& screenCoordinates, Results& results, HitTestInterface& hitTestInterface )
{
+ bool wasHit( false );
+
// Hit-test the system-overlay actors first
SystemOverlay* systemOverlay = stage.GetSystemOverlayInternal();
RenderTaskList& overlayTaskList = systemOverlay->GetOverlayRenderTasks();
LayerList& overlayLayerList = systemOverlay->GetLayerList();
- HitTestForEachRenderTask( overlayLayerList, overlayTaskList, screenCoordinates, results, hitTestInterface );
+ wasHit = HitTestForEachRenderTask( overlayLayerList, overlayTaskList, screenCoordinates, results, hitTestInterface );
}
// Hit-test the regular on-stage actors
- if ( !results.actor )
+ if ( !wasHit )
{
RenderTaskList& taskList = stage.GetRenderTaskList();
LayerList& layerList = stage.GetLayerList();
- HitTestForEachRenderTask( layerList, taskList, screenCoordinates, results, hitTestInterface );
+ wasHit = HitTestForEachRenderTask( layerList, taskList, screenCoordinates, results, hitTestInterface );
}
+ return wasHit;
}
-void HitTest( Stage& stage, const Vector2& screenCoordinates, Results& results )
+bool HitTest( Stage& stage, const Vector2& screenCoordinates, Results& results )
{
ActorTouchableCheck actorTouchableCheck;
- HitTest( stage, screenCoordinates, results, actorTouchableCheck );
+ return HitTest( stage, screenCoordinates, results, actorTouchableCheck );
}
-void HitTest( Stage& stage, RenderTask& renderTask, const Vector2& screenCoordinates,
+bool HitTest( Stage& stage, RenderTask& renderTask, const Vector2& screenCoordinates,
Dali::HitTestAlgorithm::Results& results, Dali::HitTestAlgorithm::HitTestFunction func )
{
+ bool wasHit( false );
Results hitTestResults;
+
HitTestFunctionWrapper hitTestFunctionWrapper( func );
- HitTestRenderTask( stage.GetLayerList(), renderTask, screenCoordinates, hitTestResults, hitTestFunctionWrapper );
- results.actor = hitTestResults.actor;
- results.actorCoordinates = hitTestResults.actorCoordinates;
+ if ( HitTestRenderTask( stage.GetLayerList(), renderTask, screenCoordinates, hitTestResults, hitTestFunctionWrapper ) )
+ {
+ results.actor = hitTestResults.actor;
+ results.actorCoordinates = hitTestResults.actorCoordinates;
+ wasHit = true;
+ }
+ return wasHit;
}
} // namespace HitTestAlgorithm