Skip to content

Commit c7f97ee

Browse files
authored
Merge pull request #6982 from thalbern/user/bethalha/bb_proximity
Fixed proximity calculations in proximityeffect and added tests
2 parents d2aaa45 + 30c4c91 commit c7f97ee

File tree

6 files changed

+143
-28
lines changed

6 files changed

+143
-28
lines changed

Assets/MixedRealityToolkit.SDK/Experimental/Features/UX/BoundsControl/Visuals/Configuration/LinksConfiguration.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace Microsoft.MixedReality.Toolkit.Experimental.UI.BoundsControl
99
/// Configuration for <see cref="Links"/> used in <see cref="BoundsControl"/>
1010
/// This class provides all data members needed to create a link of a bounds control
1111
/// </summary>
12-
[CreateAssetMenu(fileName = "LinksConfiguration", menuName = "Mixed Reality Toolkit/Bounds Control/Links Configuration")]
12+
[CreateAssetMenu(fileName = "LinksConfiguration", menuName = "Mixed Reality Toolkit/Experimental/Bounds Control/Links Configuration")]
1313
public class LinksConfiguration : ScriptableObject
1414
{
1515
#region Serialized Properties

Assets/MixedRealityToolkit.SDK/Experimental/Features/UX/BoundsControl/Visuals/Configuration/RotationHandlesConfiguration.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace Microsoft.MixedReality.Toolkit.Experimental.UI.BoundsControl
77
/// Configuration for <see cref="RotationHandles"/> used in <see cref="BoundsControl"/>
88
/// This class provides all data members needed to create rotation handles for <see cref="BoundsControl"/>
99
/// </summary>
10-
[CreateAssetMenu(fileName = "RotationHandlesConfiguration", menuName = "Mixed Reality Toolkit/Bounds Control/Rotation Handles Configuration")]
10+
[CreateAssetMenu(fileName = "RotationHandlesConfiguration", menuName = "Mixed Reality Toolkit/Experimental/Bounds Control/Rotation Handles Configuration")]
1111
public class RotationHandlesConfiguration : HandlesBaseConfiguration
1212
{
1313

Assets/MixedRealityToolkit.SDK/Experimental/Features/UX/BoundsControl/Visuals/Configuration/ScaleHandlesConfiguration.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace Microsoft.MixedReality.Toolkit.Experimental.UI.BoundsControl
77
/// Configuration for <see cref="ScaleHandles"/> used in <see cref="BoundsControl"/>
88
/// This class provides all data members needed to create scale handles for <see cref="BoundsControl"/>
99
/// </summary>
10-
[CreateAssetMenu(fileName = "ScaleHandlesConfiguration", menuName = "Mixed Reality Toolkit/Bounds Control/Scale Handles Configuration")]
10+
[CreateAssetMenu(fileName = "ScaleHandlesConfiguration", menuName = "Mixed Reality Toolkit/Experimental/Bounds Control/Scale Handles Configuration")]
1111
public class ScaleHandlesConfiguration : HandlesBaseConfiguration
1212
{
1313
#region serialized fields

Assets/MixedRealityToolkit.SDK/Experimental/Features/UX/BoundsControl/Visuals/ProximityEffect/ProximityEffect.cs

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -137,30 +137,34 @@ public void UpdateScaling(Vector3 boundsCenter, Vector3 boundsExtents)
137137
{
138138
foreach (var pointer in inputSource.Pointers)
139139
{
140-
if (pointer.IsInteractionEnabled && !proximityPointers.Contains(pointer))
140+
// don't use IsInteractionEnabled for near pointers as the pointers might have a different radius when deciding
141+
// if they can interact with a near-by object - we might still want to show proximity scaling even if
142+
// eg. grab pointer decides it's too far away to actually perform the interaction
143+
if (pointer.IsActive && !proximityPointers.Contains(pointer))
141144
{
142145
proximityPointers.Add(pointer);
143146
}
144147
}
145148
}
146149

147-
// Get the max radius possible of our current bounds plus the proximity
148-
float maxRadius = Mathf.Max(Mathf.Max(boundsExtents.x, boundsExtents.y), boundsExtents.z);
149-
maxRadius *= maxRadius;
150-
maxRadius += config.ObjectCloseProximity + config.ObjectMediumProximity;
150+
// Get the max radius possible of our current bounds and extent the range to include proximity scaled objects. This is done by adjusting the original bounds to include the ObjectMediumProximity range in x, y and z axis
151+
float squareMaxLength = boundsExtents.sqrMagnitude + (3 * config.ObjectMediumProximity * config.ObjectMediumProximity);
151152

152153
// Grab points within sphere of influence from valid pointers
153154
foreach (var pointer in proximityPointers)
154155
{
155-
if (IsPointWithinBounds(boundsCenter, pointer.Position, maxRadius))
156+
if (IsPointWithinBounds(boundsCenter, pointer.Position, squareMaxLength))
156157
{
157158
proximityPoints.Add(pointer.Position);
158159
}
159-
160-
Vector3? point = pointer.Result?.Details.Point;
161-
if (point.HasValue && IsPointWithinBounds(boundsCenter, pointer.Result.Details.Point, maxRadius))
162-
{
163-
proximityPoints.Add(pointer.Result.Details.Point);
160+
161+
if (pointer.Result?.CurrentPointerTarget != null)
162+
{
163+
Vector3? point = pointer.Result?.Details.Point;
164+
if (point.HasValue && IsPointWithinBounds(boundsCenter, pointer.Result.Details.Point, squareMaxLength))
165+
{
166+
proximityPoints.Add(pointer.Result.Details.Point);
167+
}
164168
}
165169
}
166170

@@ -267,7 +271,7 @@ private void ScaleObject(ProximityState state, Transform scaleVisual, float obje
267271
[MethodImpl(MethodImplOptions.AggressiveInlining)]
268272
private bool IsPointWithinBounds(Vector3 position, Vector3 point, float radiusSqr)
269273
{
270-
return (position - point).sqrMagnitude < radiusSqr;
274+
return (position - point).sqrMagnitude <= radiusSqr;
271275
}
272276

273277

@@ -278,11 +282,11 @@ private bool IsPointWithinBounds(Vector3 position, Vector3 point, float radiusSq
278282
/// <returns>ProximityState for given distance</returns>
279283
private ProximityState GetProximityState(float sqrDistance)
280284
{
281-
if (sqrDistance < config.ObjectCloseProximity * config.ObjectCloseProximity)
285+
if (sqrDistance <= config.ObjectCloseProximity * config.ObjectCloseProximity)
282286
{
283287
return ProximityState.CloseProximity;
284288
}
285-
else if (sqrDistance < config.ObjectMediumProximity * config.ObjectMediumProximity)
289+
else if (sqrDistance <= config.ObjectMediumProximity * config.ObjectMediumProximity)
286290
{
287291
return ProximityState.MediumProximity;
288292
}

Assets/MixedRealityToolkit.SDK/Experimental/Features/UX/BoundsControl/Visuals/ProximityEffect/ProximityEffectConfiguration.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace Microsoft.MixedReality.Toolkit.Experimental.UI.BoundsControl
88
/// Scaling is done on three different stages: far / medium and close proximity whereas material switching
99
/// will only be done on close proximity.
1010
/// </summary>
11-
[CreateAssetMenu(fileName = "ProximityEffect", menuName = "Mixed Reality Toolkit/Bounds Control/Proximity Effect")]
11+
[CreateAssetMenu(fileName = "ProximityEffect", menuName = "Mixed Reality Toolkit/Experimental/Bounds Control/Proximity Effect")]
1212
public class ProximityEffectConfiguration : ScriptableObject
1313
{
1414
[SerializeField]
@@ -18,7 +18,7 @@ public class ProximityEffectConfiguration : ScriptableObject
1818
/// <summary>
1919
/// Determines whether proximity feature (scaling and material toggling) is activated
2020
/// </summary>
21-
public bool ProximityEffectActive => proximityEffectActive;
21+
public bool ProximityEffectActive { get => proximityEffectActive; set => proximityEffectActive = value; }
2222

2323
[SerializeField]
2424
[Tooltip("How far away should the hand be from an object before it starts scaling the object?")]
@@ -27,7 +27,7 @@ public class ProximityEffectConfiguration : ScriptableObject
2727
/// <summary>
2828
/// Distance the hand has to be in to start scaling objects.
2929
/// </summary>
30-
public float ObjectMediumProximity => objectMediumProximity;
30+
public float ObjectMediumProximity { get => objectMediumProximity; set => objectMediumProximity = value; }
3131

3232
[SerializeField]
3333
[Tooltip("How far away should the hand be from an object before it activates the close-proximity scaling effect?")]
@@ -36,7 +36,7 @@ public class ProximityEffectConfiguration : ScriptableObject
3636
/// <summary>
3737
/// Distance the hand has to be in to start the close proximity scaling effect.
3838
/// </summary>
39-
public float ObjectCloseProximity => objectCloseProximity;
39+
public float ObjectCloseProximity { get => objectCloseProximity; set => objectCloseProximity = value; }
4040

4141
[SerializeField]
4242
[Tooltip("A Proximity-enabled object scales by this amount when a hand moves out of range. Default is 0, invisible object.")]
@@ -45,7 +45,7 @@ public class ProximityEffectConfiguration : ScriptableObject
4545
/// <summary>
4646
/// A Proximity-enabled object scales by this amount when a hand moves out of range. Default is 0, invisible object.
4747
/// </summary>
48-
public float FarScale => farScale;
48+
public float FarScale { get => farScale; set => farScale = value; }
4949

5050
[SerializeField]
5151
[Tooltip("A Proximity-enabled object scales by this amount when a hand moves into the Medium Proximity range. Default is 1.0, original object size.")]
@@ -54,7 +54,7 @@ public class ProximityEffectConfiguration : ScriptableObject
5454
/// <summary>
5555
/// A Proximity-enabled object scales by this amount when a hand moves into the Medium Proximity range. Default is 1.0, original object size.
5656
/// </summary>
57-
public float MediumScale => mediumScale;
57+
public float MediumScale { get => mediumScale; set => mediumScale = value; }
5858

5959
[SerializeField]
6060
[Tooltip("A Proximity-enabled object scales by this amount when a hand moves into the Close Proximity range. Default is 1.5, larger object size.")]
@@ -63,7 +63,7 @@ public class ProximityEffectConfiguration : ScriptableObject
6363
/// <summary>
6464
/// A Proximity-enabled object scales by this amount when a hand moves into the Close Proximity range. Default is 1.5, larger object size
6565
/// </summary>
66-
public float CloseScale => closeScale;
66+
public float CloseScale { get => closeScale; set => closeScale = value; }
6767

6868
[SerializeField]
6969
[Tooltip("At what rate should a Proximity-scaled object scale when the Hand moves from Medium proximity to Far proximity?")]
@@ -72,7 +72,7 @@ public class ProximityEffectConfiguration : ScriptableObject
7272
/// <summary>
7373
/// Rate a proximity scaled object scales when the hand moves from medium to far proximity.
7474
/// </summary>
75-
public float FarGrowRate => farGrowRate;
75+
public float FarGrowRate { get => farGrowRate; set => farGrowRate = value; }
7676

7777
[SerializeField]
7878
[Tooltip("At what rate should a Proximity-scaled Object scale when the Hand moves to a distance that activates Medium Scale ?")]
@@ -81,7 +81,7 @@ public class ProximityEffectConfiguration : ScriptableObject
8181
/// <summary>
8282
/// Rate a proximity scaled object scales when the hand moves from medium to close proximity.
8383
/// </summary>
84-
public float MediumGrowRate => mediumGrowRate;
84+
public float MediumGrowRate { get => mediumGrowRate; set => mediumGrowRate = value; }
8585

8686
[SerializeField]
8787
[Tooltip("At what rate should a Proximity-scaled object scale when the Hand moves to a distance that activates Close Scale ?")]
@@ -90,6 +90,6 @@ public class ProximityEffectConfiguration : ScriptableObject
9090
/// <summary>
9191
/// Rate a proximity scaled object scales when the hand moves from close proximity to object center
9292
/// </summary>
93-
public float CloseGrowRate => closeGrowRate;
93+
public float CloseGrowRate { get => closeGrowRate; set => closeGrowRate = value; }
9494
}
9595
}

Assets/MixedRealityToolkit.Tests/PlayModeTests/Experimental/BoundsControlTests.cs

Lines changed: 112 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ private BoundsControl InstantiateSceneAndDefaultBbox()
5757
p =>
5858
{
5959
p.position = Vector3.zero;
60-
p.LookAt(cube.transform.position);
60+
p.LookAt(boundsControlStartCenter);
6161
});
6262

6363
bbox.transform.localScale = boundsControlStartScale;
@@ -335,6 +335,117 @@ public IEnumerator DisableObject()
335335
Assert.AreEqual(afterTransformScale, bbox.transform.localScale);
336336
}
337337

338+
/// <summary>
339+
/// Tests proximity scaling on scale handles of bounds control
340+
/// Verifies default behavior of handles with effect enabled / disabled as well as custom runtime configured scaling / distance values
341+
/// </summary>
342+
[UnityTest]
343+
public IEnumerator ProximityOnScaleHandles()
344+
{
345+
var bbox = InstantiateSceneAndDefaultBbox();
346+
yield return VerifyInitialBoundsCorrect(bbox);
347+
348+
// 1. test no proximity scaling active per default
349+
ScaleHandlesConfiguration scaleHandleConfig = bbox.ScaleHandlesConfiguration;
350+
Vector3 defaultHandleSize = Vector3.one * scaleHandleConfig.HandleSize;
351+
352+
Vector3 initialHandPosition = new Vector3(0, 0, 0f);
353+
// this is specific to scale handles
354+
Transform scaleHandle = bbox.gameObject.transform.Find("rigRoot/corner_3");
355+
Transform proximityScaledVisual = scaleHandle.GetChild(0)?.GetChild(0);
356+
var frontRightCornerPos = scaleHandle.position; // front right corner is corner
357+
Assert.IsNotNull(proximityScaledVisual, "Couldn't get visual gameobject for scale handle");
358+
Assert.IsTrue(proximityScaledVisual.name == "visuals", "scale visual has unexpected name");
359+
360+
yield return null;
361+
// verify no proximity scaling applied per default
362+
Assert.AreEqual(proximityScaledVisual.localScale, defaultHandleSize, "Handle was scaled even though proximity effect wasn't active");
363+
TestHand hand = new TestHand(Handedness.Left);
364+
Vector3 initialScale = bbox.transform.localScale;
365+
366+
// Hands grab object at initial position
367+
yield return hand.Show(initialHandPosition);
368+
yield return hand.SetGesture(ArticulatedHandPose.GestureId.OpenSteadyGrabPoint);
369+
yield return hand.MoveTo(frontRightCornerPos);
370+
yield return null;
371+
372+
// we're in poximity scaling range - check if proximity scaling wasn't applied
373+
Assert.AreEqual(proximityScaledVisual.localScale, defaultHandleSize, "Handle was scaled even though proximity effect wasn't active");
374+
375+
//// reset hand
376+
yield return hand.MoveTo(initialHandPosition);
377+
378+
// 2. enable proximity scaling and test defaults
379+
ProximityEffectConfiguration proximityConfig = bbox.HandleProximityEffectConfiguration;
380+
proximityConfig.ProximityEffectActive = true;
381+
proximityConfig.CloseGrowRate = 1.0f;
382+
proximityConfig.MediumGrowRate = 1.0f;
383+
proximityConfig.FarGrowRate = 1.0f;
384+
bbox.CreateRig();
385+
yield return null; // wait so rig gameobjects get recreated
386+
yield return TestCurrentProximityConfiguration(bbox, hand, "Defaults");
387+
388+
// reset hand
389+
yield return hand.MoveTo(initialHandPosition);
390+
391+
// 3. now test custom configuration is applied during runtime
392+
proximityConfig.CloseScale = 4.0f;
393+
proximityConfig.MediumScale = 3.0f;
394+
proximityConfig.FarScale = 2.0f;
395+
396+
proximityConfig.ObjectMediumProximity = 0.2f;
397+
proximityConfig.ObjectCloseProximity = 0.1f;
398+
399+
bbox.CreateRig();
400+
yield return null; // wait so rig gameobjects get recreated
401+
yield return TestCurrentProximityConfiguration(bbox, hand, "Custom runtime config max");
402+
}
403+
404+
/// <summary>
405+
/// This tests far, medium and close proximity scaling on scale handles by moving the test hand in the corresponding distance ranges
406+
/// </summary>
407+
/// <param name="bbox">Bounds Control to test on</param>
408+
/// <param name="hand">Test hand to use for testing proximity to handle</param>
409+
private IEnumerator TestCurrentProximityConfiguration(BoundsControl bbox, TestHand hand, string testDescription)
410+
{
411+
// get config and scaling handle
412+
ScaleHandlesConfiguration scaleHandleConfig = bbox.ScaleHandlesConfiguration;
413+
Vector3 defaultHandleSize = Vector3.one * scaleHandleConfig.HandleSize;
414+
Transform scaleHandle = bbox.gameObject.transform.Find("rigRoot/corner_3");
415+
Transform proximityScaledVisual = scaleHandle.GetChild(0)?.GetChild(0);
416+
var frontRightCornerPos = scaleHandle.position;
417+
// check far scale applied
418+
ProximityEffectConfiguration proximityConfig = bbox.HandleProximityEffectConfiguration;
419+
Vector3 expectedFarScale = defaultHandleSize * proximityConfig.FarScale;
420+
Assert.AreEqual(proximityScaledVisual.localScale, expectedFarScale, testDescription + " - Proximity far scale wasn't applied to handle");
421+
422+
// move into medium range and check if scale was applied
423+
Vector3 mediumProximityTestDist = frontRightCornerPos;
424+
mediumProximityTestDist.x += proximityConfig.ObjectMediumProximity;
425+
yield return hand.MoveTo(mediumProximityTestDist);
426+
Vector3 expectedMediumScale = defaultHandleSize * proximityConfig.MediumScale;
427+
Assert.AreEqual(proximityScaledVisual.localScale, expectedMediumScale, testDescription + " - Proximity medium scale wasn't applied to handle");
428+
429+
// move into close scale range and check if scale was applied
430+
Vector3 closeProximityTestDir = frontRightCornerPos;
431+
closeProximityTestDir.x += proximityConfig.ObjectCloseProximity;
432+
yield return hand.MoveTo(closeProximityTestDir);
433+
Vector3 expectedCloseScale = defaultHandleSize * proximityConfig.CloseScale;
434+
Assert.AreEqual(proximityScaledVisual.localScale, expectedCloseScale, testDescription + " - Proximity close scale wasn't applied to handle");
435+
436+
// move out of close scale again - should fall back to medium proximity
437+
closeProximityTestDir = mediumProximityTestDist;
438+
yield return hand.MoveTo(closeProximityTestDir);
439+
Assert.AreEqual(proximityScaledVisual.localScale, expectedMediumScale, testDescription + " - Proximity medium scale wasn't applied to handle");
440+
441+
// move out of medium proximity and check if far scaling is applied
442+
mediumProximityTestDist = Vector3.zero;
443+
yield return hand.MoveTo(mediumProximityTestDist);
444+
Assert.AreEqual(proximityScaledVisual.localScale, expectedFarScale, testDescription + " - Proximity far scale wasn't applied to handle");
445+
446+
yield return null;
447+
}
448+
338449
/// <summary>
339450
/// Tests setting a target in code that is a different gameobject than the gameobject the bounds control component is attached to
340451
/// </summary>

0 commit comments

Comments
 (0)