Skip to content

Commit dfa25f0

Browse files
authored
Merge pull request #9735 from keveleigh/haptics
Add support for controller haptics across legacy, Windows XR Plugin, and OpenXR
2 parents 38626e1 + c33dc10 commit dfa25f0

File tree

5 files changed

+92
-7
lines changed

5 files changed

+92
-7
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
namespace Microsoft.MixedReality.Toolkit.Input
5+
{
6+
/// <summary>
7+
/// Provides access to the haptic capabilities of a device.
8+
/// </summary>
9+
public interface IMixedRealityHapticFeedback
10+
{
11+
/// <summary>
12+
/// Start haptic feedback by the input device.
13+
/// </summary>
14+
/// <param name="intensity">The 0.0 to 1.0 strength of the haptic feedback based on the capability of the input device.</param>
15+
/// <param name="durationInSeconds">The duration in seconds or float.MaxValue for indefinite duration (if supported by the platform).</param>
16+
/// <returns>True if haptic feedback was successfully started.</returns>
17+
bool StartHapticImpulse(float intensity, float durationInSeconds = float.MaxValue);
18+
19+
/// <summary>
20+
/// Terminates haptic feedback by the input device.
21+
/// </summary>
22+
void StopHapticFeedback();
23+
}
24+
}

Assets/MRTK/Core/Interfaces/Devices/IMixedRealityHapticFeedback.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Assets/MRTK/Providers/WindowsMixedReality/XR2018/Controllers/WindowsMixedRealityController.cs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using Microsoft.MixedReality.Toolkit.Input;
55
using Microsoft.MixedReality.Toolkit.Utilities;
6+
using Microsoft.MixedReality.Toolkit.Windows.Input;
67

78
#if UNITY_WSA
89
using Unity.Profiling;
@@ -19,7 +20,7 @@ namespace Microsoft.MixedReality.Toolkit.WindowsMixedReality.Input
1920
new[] { Handedness.Left, Handedness.Right },
2021
"Textures/MotionController",
2122
supportedUnityXRPipelines: SupportedUnityXRPipelines.LegacyXR)]
22-
public class WindowsMixedRealityController : BaseWindowsMixedRealitySource
23+
public class WindowsMixedRealityController : BaseWindowsMixedRealitySource, IMixedRealityHapticFeedback
2324
{
2425
/// <summary>
2526
/// Constructor.
@@ -283,5 +284,23 @@ private async void TryRenderControllerModelWithModelProvider()
283284

284285
#endregion Controller model functions
285286
#endif // UNITY_WSA
287+
288+
#region Haptic feedback functions
289+
290+
public bool StartHapticImpulse(float intensity, float durationInSeconds = float.MaxValue) =>
291+
#if UNITY_WSA
292+
LastSourceStateReading.source.StartHaptics(intensity, durationInSeconds);
293+
#else
294+
false;
295+
#endif // UNITY_WSA
296+
297+
public void StopHapticFeedback()
298+
{
299+
#if UNITY_WSA
300+
LastSourceStateReading.source.StopHaptics();
301+
#endif // UNITY_WSA
302+
}
303+
304+
#endregion Haptic feedback functions
286305
}
287306
}

Assets/MRTK/Providers/WindowsMixedReality/XR2018/Extensions/InteractionSourceExtensions.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,19 +77,19 @@ public static SpatialInteractionSourceState GetSpatialInteractionSourceState(thi
7777
/// </summary>
7878
/// <param name="interactionSource">The source to start haptics on.</param>
7979
/// <param name="intensity">The strength of the haptic feedback from 0.0 (no haptics) to 1.0 (maximum strength).</param>
80-
public static void StartHaptics(this InteractionSource interactionSource, float intensity) => interactionSource.StartHaptics(intensity, float.MaxValue);
80+
public static bool StartHaptics(this InteractionSource interactionSource, float intensity) => interactionSource.StartHaptics(intensity, float.MaxValue);
8181

8282
/// <summary>
8383
/// Start haptic feedback on the interaction source with the specified intensity and continue for the specified amount of time.
8484
/// </summary>
8585
/// <param name="interactionSource">The source to start haptics on.</param>
8686
/// <param name="intensity">The strength of the haptic feedback from 0.0 (no haptics) to 1.0 (maximum strength).</param>
8787
/// <param name="durationInSeconds">The time period expressed in seconds.</param>
88-
public static void StartHaptics(this InteractionSource interactionSource, float intensity, float durationInSeconds)
88+
public static bool StartHaptics(this InteractionSource interactionSource, float intensity, float durationInSeconds)
8989
{
9090
if (!IsHapticsAvailable)
9191
{
92-
return;
92+
return false;
9393
}
9494

9595
#if WINDOWS_UWP || DOTNETWINRT_PRESENT
@@ -98,18 +98,20 @@ public static void StartHaptics(this InteractionSource interactionSource, float
9898
{
9999
if (hapticsFeedback.Waveform.Equals(ContinuousBuzzWaveform))
100100
{
101-
if (durationInSeconds.Equals(float.MaxValue))
101+
if (UnityEngine.Mathf.Approximately(durationInSeconds, float.MaxValue))
102102
{
103103
simpleHapticsController.SendHapticFeedback(hapticsFeedback, intensity);
104104
}
105105
else
106106
{
107107
simpleHapticsController.SendHapticFeedbackForDuration(hapticsFeedback, intensity, TimeSpan.FromSeconds(durationInSeconds));
108108
}
109-
return;
109+
return true;
110110
}
111111
}
112112
#endif // WINDOWS_UWP || DOTNETWINRT_PRESENT
113+
114+
return false;
113115
}
114116

115117
/// <summary>

Assets/MRTK/Providers/XRSDK/Controllers/GenericXRSDKController.cs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ namespace Microsoft.MixedReality.Toolkit.XRSDK.Input
1414
new[] { Handedness.Left, Handedness.Right },
1515
flags: MixedRealityControllerConfigurationFlags.UseCustomInteractionMappings,
1616
supportedUnityXRPipelines: SupportedUnityXRPipelines.XRSDK)]
17-
public class GenericXRSDKController : BaseController
17+
public class GenericXRSDKController : BaseController, IMixedRealityHapticFeedback
1818
{
1919
public GenericXRSDKController(
2020
TrackingState trackingState,
@@ -45,6 +45,11 @@ public GenericXRSDKController(
4545
/// </summary>
4646
protected Quaternion CurrentControllerRotation = Quaternion.identity;
4747

48+
/// <summary>
49+
/// The most recent input device that this controller represents.
50+
/// </summary>
51+
private InputDevice lastInputDevice;
52+
4853
private static readonly ProfilerMarker UpdateControllerPerfMarker = new ProfilerMarker("[MRTK] GenericXRSDKController.UpdateController");
4954

5055
/// <summary>
@@ -81,6 +86,8 @@ public virtual void UpdateController(InputDevice inputDevice)
8186
break;
8287
}
8388
}
89+
90+
lastInputDevice = inputDevice;
8491
}
8592
}
8693

@@ -402,5 +409,27 @@ protected virtual void UpdatePoseData(MixedRealityInteractionMapping interaction
402409
}
403410
}
404411
}
412+
413+
/// <inheritdoc />
414+
public bool StartHapticImpulse(float intensity, float durationInSeconds = float.MaxValue)
415+
{
416+
if (lastInputDevice.TryGetHapticCapabilities(out HapticCapabilities hapticCapabilities) && hapticCapabilities.supportsImpulse)
417+
{
418+
if (Mathf.Approximately(durationInSeconds, float.MaxValue))
419+
{
420+
lastInputDevice.SendHapticImpulse(0, intensity);
421+
}
422+
else
423+
{
424+
lastInputDevice.SendHapticImpulse(0, intensity, durationInSeconds);
425+
}
426+
return true;
427+
}
428+
429+
return false;
430+
}
431+
432+
/// <inheritdoc />
433+
public void StopHapticFeedback() => lastInputDevice.StopHaptics();
405434
}
406435
}

0 commit comments

Comments
 (0)