Skip to content

Commit d6ac0bd

Browse files
committed
HPUIInteractor refactors to not inherit from poke
1 parent 393427f commit d6ac0bd

File tree

2 files changed

+93
-24
lines changed

2 files changed

+93
-24
lines changed

Runtime/Interaction/HPUIBaseInteractable.cs

+3
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ protected override void OnEnable()
7474
}
7575
#endregion
7676

77+
78+
#region surface point calculations
7779
/// <summary>
7880
/// Compute and store the surface bounds to compute point on surface
7981
/// </summary>
@@ -113,6 +115,7 @@ protected Vector2 ComputeTargetPointOnInteractablePlane(Vector3 targetPoint, Tra
113115
pointOnXZPlane = worldToLocalMatrix.MultiplyPoint3x4(pointOnXZPlane);
114116
return new Vector2(pointOnXZPlane.x, pointOnXZPlane.z);
115117
}
118+
#endregion
116119

117120
#region IHPUIInteractable interface
118121
/// <inheritdoc />

Runtime/Interaction/HPUIInteractor.cs

+90-24
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1-
using System;
21
using System.Collections.Generic;
32
using System.Linq;
43
using UnityEngine;
5-
using UnityEngine.Pool;
6-
using UnityEngine.XR.Hands;
74
using UnityEngine.XR.Interaction.Toolkit;
5+
using UnityEngine.XR.Interaction.Toolkit.Utilities;
86

97
namespace ubco.ovilab.HPUI.Interaction
108
{
@@ -13,10 +11,8 @@ namespace ubco.ovilab.HPUI.Interaction
1311
/// </summary>
1412
[SelectionBase]
1513
[DisallowMultipleComponent]
16-
public class HPUIInteractor: XRPokeInteractor, IHPUIInteractor
14+
public class HPUIInteractor: XRBaseInteractor, IHPUIInteractor
1715
{
18-
public new Handedness handedness;
19-
2016
// TODO move these to an asset?
2117
[SerializeField]
2218
private float tapTimeThreshold;
@@ -27,29 +23,42 @@ public class HPUIInteractor: XRPokeInteractor, IHPUIInteractor
2723
public float TapDistanceThreshold { get => tapDistanceThreshold; set => tapDistanceThreshold = value; }
2824

2925
[SerializeField]
26+
[Tooltip("Event triggered on tap")]
3027
private HPUITapEvent tapEvent = new HPUITapEvent();
3128

32-
/// <summary>
33-
/// Event triggered on tap
34-
/// </summary>
29+
/// <inheritdoc />
3530
public HPUITapEvent TapEvent { get => tapEvent; set => tapEvent = value; }
3631

3732
[SerializeField]
33+
[Tooltip("Event triggered on gesture")]
3834
private HPUIGestureEvent gestureEvent = new HPUIGestureEvent();
3935

36+
/// <inheritdoc />
37+
public HPUIGestureEvent GestureEvent { get => gestureEvent; set => gestureEvent = value; }
38+
39+
[SerializeField]
40+
[Tooltip("Interation hover radius.")]
41+
private float interactionHoverRadius = 0.015f;
42+
4043
/// <summary>
41-
/// Event triggered on gesture
44+
/// Interation hover radius.
4245
/// </summary>
43-
public HPUIGestureEvent GestureEvent { get => gestureEvent; set => gestureEvent = value; }
46+
public float InteractionHoverRadius { get => interactionHoverRadius; set => interactionHoverRadius = value; }
4447

4548
protected IHPUIGestureLogic gestureLogic;
4649
private List<IXRInteractable> validTargets = new List<IXRInteractable>();
50+
private bool justStarted = false;
51+
private Vector3 lastInteractionPoint;
52+
private PhysicsScene physicsScene;
53+
private RaycastHit[] sphereCastHits = new RaycastHit[25];
54+
private Collider[] overlapSphereHits = new Collider[25];
4755

4856
/// <inheritdoc />
4957
protected override void Awake()
5058
{
5159
base.Awake();
5260
keepSelectedTargetValid = true;
61+
physicsScene = gameObject.scene.GetPhysicsScene();
5362
gestureLogic = new HPUIGestureLogicUnified(this, TapTimeThreshold, TapDistanceThreshold);
5463
}
5564

@@ -66,6 +75,13 @@ protected void OnValidate()
6675
}
6776
#endif
6877

78+
/// <inheritdoc />
79+
protected override void OnEnable()
80+
{
81+
base.OnEnable();
82+
justStarted = true;
83+
}
84+
6985
/// <inheritdoc />
7086
protected override void OnSelectEntering(SelectEnterEventArgs args)
7187
{
@@ -80,6 +96,68 @@ protected override void OnSelectExiting(SelectExitEventArgs args)
8096
gestureLogic.OnSelectExiting(args.interactableObject as IHPUIInteractable);
8197
}
8298

99+
/// <inheritdoc />
100+
public override void PreprocessInteractor(XRInteractionUpdateOrder.UpdatePhase updatePhase)
101+
{
102+
base.PreprocessInteractor(updatePhase);
103+
104+
// Following the logic in XRPokeInteractor
105+
if (updatePhase == XRInteractionUpdateOrder.UpdatePhase.Dynamic)
106+
{
107+
validTargets.Clear();
108+
109+
// Hover Check
110+
Vector3 pokeInteractionPoint = GetAttachTransform(null).position;
111+
Vector3 overlapStart = lastInteractionPoint;
112+
Vector3 interFrameEnd = pokeInteractionPoint; // FIXME: Think of getting this of collision points?
113+
114+
BurstPhysicsUtils.GetSphereOverlapParameters(overlapStart, interFrameEnd, out Vector3 normalizedOverlapVector, out float overlapSqrMagnitude, out float overlapDistance);
115+
116+
// If no movement is recorded.
117+
// Check if spherecast size is sufficient for proper cast, or if first frame since last frame poke position will be invalid.
118+
int numberOfOverlaps;
119+
120+
if (justStarted || overlapSqrMagnitude < 0.001f)
121+
{
122+
numberOfOverlaps = physicsScene.OverlapSphere(
123+
interFrameEnd,
124+
InteractionHoverRadius,
125+
overlapSphereHits,
126+
// FIXME: physics layers should be allowed to be set in inpsector
127+
Physics.AllLayers,
128+
// FIXME: QueryTriggerInteraction should be allowed to be set in inpsector
129+
QueryTriggerInteraction.Ignore);
130+
}
131+
else
132+
{
133+
numberOfOverlaps = physicsScene.SphereCast(
134+
overlapStart,
135+
InteractionHoverRadius,
136+
normalizedOverlapVector,
137+
sphereCastHits,
138+
overlapDistance,
139+
// FIXME: physics layers should be allowed to be set in inpsector
140+
Physics.AllLayers,
141+
// FIXME: QueryTriggerInteraction should be allowed to be set in inpsector
142+
QueryTriggerInteraction.Ignore);
143+
144+
}
145+
146+
lastInteractionPoint = pokeInteractionPoint;
147+
justStarted = false;
148+
149+
for (var i = 0; i < numberOfOverlaps; ++i)
150+
{
151+
if (interactionManager.TryGetInteractableForCollider(sphereCastHits[i].collider, out var interactable) &&
152+
interactable is IXRSelectInteractable selectable &&
153+
interactable is IXRHoverInteractable hoverable && hoverable.IsHoverableBy(this))
154+
{
155+
validTargets.Add(interactable);
156+
}
157+
}
158+
}
159+
}
160+
83161
/// <inheritdoc />
84162
public override void ProcessInteractor(XRInteractionUpdateOrder.UpdatePhase updatePhase)
85163
{
@@ -93,25 +171,13 @@ public override void ProcessInteractor(XRInteractionUpdateOrder.UpdatePhase upda
93171
public override void GetValidTargets(List<IXRInteractable> targets)
94172
{
95173
base.GetValidTargets(targets);
96-
if (handedness == Handedness.Invalid)
97-
{
98-
throw new InvalidOperationException("handedness not correcly set.");
99-
}
100-
101-
List<IXRInteractable> recievedTargets = ListPool<IXRInteractable>.Get();
102-
recievedTargets.AddRange(targets.Distinct());
103174

104175
targets.Clear();
105-
validTargets.Clear();
106-
foreach(IXRInteractable target in recievedTargets.Select(t => t as IHPUIInteractable).Where(ht => ht != null).OrderBy(ht => ht.zOrder))
176+
foreach(IXRInteractable target in validTargets.Select(t => t as IHPUIInteractable).Where(ht => ht != null).OrderBy(ht => ht.zOrder))
107177
{
108178
targets.Add(target);
109179
validTargets.Add(target);
110180
}
111-
112-
// TODO check if an interactable with lower z order is selected. If so cancel it.
113-
114-
ListPool<IXRInteractable>.Release(recievedTargets);
115181
}
116182

117183
// NOTE: PokeInteractor has a bug where it doesn't account for the re-prioritization.

0 commit comments

Comments
 (0)