private static void PerformRecursiveHitTest(UIElement element, ref Ray ray, ref Matrix worldViewProj, ICollection<HitTestResult> results) { // if the element is not visible, we also remove all its children if (!element.IsVisible) return; var canBeHit = element.CanBeHitByUser; if (canBeHit || element.ClipToBounds) { Vector3 intersection; var intersect = element.Intersects(ref ray, out intersection); // don't perform the hit test on children if clipped and parent no hit if (element.ClipToBounds && !intersect) return; // Calculate the depth of the element with the depth bias so that hit test corresponds to visuals. Vector4 projectedIntersection; var intersection4 = new Vector4(intersection, 1); Vector4.Transform(ref intersection4, ref worldViewProj, out projectedIntersection); // update the hit results if (canBeHit && intersect) { results.Add(new HitTestResult(element.DepthBias, element, intersection)); } } // test the children foreach (var child in element.HitableChildren) PerformRecursiveHitTest(child, ref ray, ref worldViewProj, results); }
private void PerformRecursiveHitTest(UIElement element, ref Ray ray, ref UIElement clickedElement, ref Vector3 intersectionPoint, ref float smallestDepth) { // if the element is not visible, we also remove all its children if (!element.IsVisible) return; if (element.ClipToBounds || element.CanBeHitByUser) { Vector3 intersection; var intersect = element.Intersects(ref ray, out intersection); // don't perform the hit test on children if clipped and parent no hit if (element.ClipToBounds && !intersect) return; // Calculate the depth of the element with the depth bias so that hit test corresponds to visuals. Vector4 projectedIntersection; var intersection4 = new Vector4(intersection, 1); Vector4.Transform(ref intersection4, ref viewParameters.ViewProjectionMatrix, out projectedIntersection); var depthWithBias = projectedIntersection.Z / projectedIntersection.W - element.DepthBias * BatchBase<int>.DepthBiasShiftOneUnit; // update the closest element hit if (element.CanBeHitByUser && intersect && depthWithBias < smallestDepth) { smallestDepth = depthWithBias; intersectionPoint = intersection; clickedElement = element; } } // render the children foreach (var child in element.HitableChildren) PerformRecursiveHitTest(child, ref ray, ref clickedElement, ref intersectionPoint, ref smallestDepth); }
private static void PerformRecursiveHitTest(UIElement element, ref Ray ray, ref Matrix worldViewProj, ref UIElement hitElement, ref Vector3 intersectionPoint, ref float smallestDepth, ref float highestDepthBias) { // if the element is not visible, we also remove all its children if (!element.IsVisible) return; var canBeHit = element.CanBeHitByUser; if (canBeHit || element.ClipToBounds) { Vector3 intersection; var intersect = element.Intersects(ref ray, out intersection); // don't perform the hit test on children if clipped and parent no hit if (element.ClipToBounds && !intersect) return; // Calculate the depth of the element with the depth bias so that hit test corresponds to visuals. Vector4 projectedIntersection; var intersection4 = new Vector4(intersection, 1); Vector4.Transform(ref intersection4, ref worldViewProj, out projectedIntersection); var depth = projectedIntersection.Z/projectedIntersection.W; // update the closest element hit if (canBeHit && intersect) { if (depth < smallestDepth || (depth == smallestDepth && element.DepthBias > highestDepthBias)) { smallestDepth = depth; highestDepthBias = element.DepthBias; intersectionPoint = intersection; hitElement = element; } } } // test the children foreach (var child in element.HitableChildren) PerformRecursiveHitTest(child, ref ray, ref worldViewProj, ref hitElement, ref intersectionPoint, ref smallestDepth, ref highestDepthBias); }