Skip to content

Commit ff24e15

Browse files
committed
Add layer mask prioritization for ui elements
Ended up needing a container to be able to store the layer mask index. Also used the new generix MaxOrDefault
1 parent 764f6d9 commit ff24e15

File tree

2 files changed

+42
-44
lines changed

2 files changed

+42
-44
lines changed

Assets/HoloToolkit/Utilities/Scripts/Extensions/EventSystemExtensions.cs

Lines changed: 11 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,53 +10,32 @@ namespace HoloToolkit.Unity
1010
public static class EventSystemExtensions
1111
{
1212
private static readonly List<RaycastResult> RaycastResults = new List<RaycastResult>();
13+
private static readonly List<ComparableRaycastResult> ComparableRaycastResults = new List<ComparableRaycastResult>();
1314
private static readonly RaycastResultComparer RaycastResultComparer = new RaycastResultComparer();
1415

1516
/// <summary>
1617
/// Executes a raycast all and returns the closest element. Fixes the current issue with Unitys raycast sorting which does not
1718
/// consider separate canvases.
1819
/// </summary>
1920
/// <returns>RaycastResult if hit, or an empty RaycastResult if nothing was hit</returns>
20-
public static RaycastResult Raycast(this EventSystem eventSystem, PointerEventData pointerEventData, IEnumerable<LayerMask> layerMasks)
21+
public static RaycastResult Raycast(this EventSystem eventSystem, PointerEventData pointerEventData, LayerMask[] layerMasks)
2122
{
2223
RaycastResults.Clear();
2324
eventSystem.RaycastAll(pointerEventData, RaycastResults);
24-
return FindClosestRaycastHitInLayerMasks(layerMasks);
25+
return PrioritizeRaycastResult(layerMasks);
2526
}
2627

27-
/// <summary>
28-
/// Find the closest raycast hit in the list of RaycastResults that is also included in the LayerMask list.
29-
/// </summary>
30-
/// <param name="layerMaskList">List of layers to support</param>
31-
/// <returns>RaycastResult if hit, or an empty RaycastResult if nothing was hit</returns>
32-
private static RaycastResult FindClosestRaycastHitInLayerMasks(IEnumerable<LayerMask> layerMaskList)
33-
{
34-
int combinedLayerMask = layerMaskList.Combine();
35-
36-
for (var i = RaycastResults.Count - 1; i >= 0; i--)
37-
{
38-
var candidate = RaycastResults[i];
39-
if (candidate.gameObject && candidate.gameObject.layer.IsInLayerMask(combinedLayerMask)) continue;
40-
RaycastResults.Remove(candidate);
41-
}
42-
;
43-
return RaycastResults.Count > 0 ? GetClosestRaycast() : default(RaycastResult);
44-
}
45-
46-
private static RaycastResult GetClosestRaycast()
28+
private static RaycastResult PrioritizeRaycastResult(LayerMask[] layerMaskPrio)
4729
{
48-
var max = RaycastResults[0];
49-
50-
for (var i = 1; i < RaycastResults.Count; i++)
30+
ComparableRaycastResults.Clear();
31+
foreach (var raycastResult in RaycastResults)
5132
{
52-
if (RaycastResultComparer.Compare(max, RaycastResults[i]) > 0)
53-
{
54-
max = RaycastResults[i];
55-
}
33+
if (raycastResult.gameObject == null) { continue; }
34+
var layerMaskIndex = raycastResult.gameObject.layer.FindLayerListIndex(layerMaskPrio);
35+
if (layerMaskIndex == -1) { continue; }
36+
ComparableRaycastResults.Add(new ComparableRaycastResult(raycastResult, layerMaskIndex));
5637
}
57-
58-
return max;
38+
return ComparableRaycastResults.MaxOrDefault(RaycastResultComparer).RaycastResult;
5939
}
60-
6140
}
6241
}

Assets/HoloToolkit/Utilities/Scripts/RaycastResultComparer.cs

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,30 @@
77

88
namespace HoloToolkit.Unity
99
{
10-
public class RaycastResultComparer : IComparer<RaycastResult>
10+
public struct ComparableRaycastResult
1111
{
12-
private static readonly List<Func<RaycastResult, RaycastResult, int>> Comparers = new List<Func<RaycastResult, RaycastResult, int>>
12+
public readonly int LayerMaskIndex;
13+
public readonly RaycastResult RaycastResult;
14+
15+
public ComparableRaycastResult(RaycastResult raycastResult, int layerMaskIndex = 0)
1316
{
17+
RaycastResult = raycastResult;
18+
LayerMaskIndex = layerMaskIndex;
19+
}
20+
}
21+
22+
public class RaycastResultComparer : IComparer<ComparableRaycastResult>
23+
{
24+
private static readonly List<Func<ComparableRaycastResult, ComparableRaycastResult, int>> Comparers = new List<Func<ComparableRaycastResult, ComparableRaycastResult, int>>
25+
{
26+
CompareRaycastsByLayerMaskPrioritization,
1427
CompareRaycastsBySortingLayer,
1528
CompareRaycastsBySortingOrder,
1629
CompareRaycastsByCanvasDepth,
1730
CompareRaycastsByDistance,
1831
};
1932

20-
public int Compare(RaycastResult left, RaycastResult right)
33+
public int Compare(ComparableRaycastResult left, ComparableRaycastResult right)
2134
{
2235
for (var i = 0; i < Comparers.Count; i++)
2336
{
@@ -30,33 +43,39 @@ public int Compare(RaycastResult left, RaycastResult right)
3043
return 0;
3144
}
3245

33-
private static int CompareRaycastsBySortingOrder(RaycastResult left, RaycastResult right)
46+
private static int CompareRaycastsByLayerMaskPrioritization(ComparableRaycastResult left, ComparableRaycastResult right)
47+
{
48+
//Lower is better, -1 is not relevant
49+
return right.LayerMaskIndex.CompareTo(left.LayerMaskIndex);
50+
}
51+
52+
private static int CompareRaycastsBySortingLayer(ComparableRaycastResult left, ComparableRaycastResult right)
3453
{
3554
//Higher is better
36-
return right.sortingOrder.CompareTo(left.sortingOrder);
55+
return left.RaycastResult.sortingLayer.CompareTo(right.RaycastResult.sortingLayer);
3756
}
3857

39-
private static int CompareRaycastsBySortingLayer(RaycastResult left, RaycastResult right)
58+
private static int CompareRaycastsBySortingOrder(ComparableRaycastResult left, ComparableRaycastResult right)
4059
{
4160
//Higher is better
42-
return right.sortingLayer.CompareTo(left.sortingLayer);
61+
return left.RaycastResult.sortingOrder.CompareTo(right.RaycastResult.sortingOrder);
4362
}
4463

45-
private static int CompareRaycastsByCanvasDepth(RaycastResult left, RaycastResult right)
64+
private static int CompareRaycastsByCanvasDepth(ComparableRaycastResult left, ComparableRaycastResult right)
4665
{
4766
//Module is the graphic raycaster on the canvases.
48-
if (left.module.transform.IsParentOrChildOf(right.module.transform))
67+
if (left.RaycastResult.module.transform.IsParentOrChildOf(right.RaycastResult.module.transform))
4968
{
5069
//Higher is better
51-
return right.depth.CompareTo(left.depth);
70+
return left.RaycastResult.depth.CompareTo(right.RaycastResult.depth);
5271
}
5372
return 0;
5473
}
5574

56-
private static int CompareRaycastsByDistance(RaycastResult left, RaycastResult right)
75+
private static int CompareRaycastsByDistance(ComparableRaycastResult left, ComparableRaycastResult right)
5776
{
5877
//Lower is better
59-
return left.distance.CompareTo(right.distance);
78+
return right.RaycastResult.distance.CompareTo(left.RaycastResult.distance);
6079
}
6180
}
6281
}

0 commit comments

Comments
 (0)