AR Design
UBC EML collab with UBC SALA - visualizing IoT data in AR
InteractionSourceExtensions.cs
Go to the documentation of this file.
1 // Copyright (c) Microsoft Corporation. All rights reserved.
2 // Licensed under the MIT License. See LICENSE in the project root for license information.
3 
4 #if UNITY_WSA
5 using UnityEngine;
6 #if !UNITY_2017_2_OR_NEWER
7 using UnityEngine.VR.WSA.Input;
8 #else
9 using UnityEngine.XR.WSA.Input;
10 #if !UNITY_EDITOR
11 using System;
12 using System.Collections.Generic;
13 using Windows.Devices.Haptics;
14 using Windows.Foundation;
15 using Windows.Perception;
16 using Windows.Storage.Streams;
17 using Windows.UI.Input.Spatial;
18 #elif UNITY_EDITOR_WIN
19 using System.Runtime.InteropServices;
20 #endif
21 #endif
22 #endif
23 
24 namespace HoloToolkit.Unity
25 {
29  public static class InteractionSourceExtensions
30  {
31 #if UNITY_2017_2_OR_NEWER
32 #if UNITY_EDITOR_WIN && UNITY_WSA
33  [DllImport("EditorMotionController")]
34  private static extern bool StartHaptics([In] uint controllerId, [In] float intensity, [In] float durationInSeconds);
35 
36  [DllImport("EditorMotionController")]
37  private static extern bool StopHaptics([In] uint controllerId);
38 #endif // UNITY_EDITOR_WIN && UNITY_WSA
39 
40  // This value is standardized according to www.usb.org/developers/hidpage/HUTRR63b_-_Haptics_Page_Redline.pdf
41  private const ushort ContinuousBuzzWaveform = 0x1004;
42 
43 #if UNITY_WSA
44  public static void StartHaptics(this InteractionSource interactionSource, float intensity)
45  {
46  interactionSource.StartHaptics(intensity, float.MaxValue);
47  }
48 
49  public static void StartHaptics(this InteractionSource interactionSource, float intensity, float durationInSeconds)
50  {
51  if (!WindowsApiChecker.UniversalApiContractV4_IsAvailable && !Application.isEditor)
52  {
53  return;
54  }
55 
56 #if !UNITY_EDITOR
57  UnityEngine.WSA.Application.InvokeOnUIThread(() =>
58  {
59  IReadOnlyList<SpatialInteractionSourceState> sources = SpatialInteractionManager.GetForCurrentView().GetDetectedSourcesAtTimestamp(PerceptionTimestampHelper.FromHistoricalTargetTime(DateTimeOffset.Now));
60 
61  foreach (SpatialInteractionSourceState sourceState in sources)
62  {
63  if (sourceState.Source.Id.Equals(interactionSource.id))
64  {
65  SimpleHapticsController simpleHapticsController = sourceState.Source.Controller.SimpleHapticsController;
66  foreach (SimpleHapticsControllerFeedback hapticsFeedback in simpleHapticsController.SupportedFeedback)
67  {
68  if (hapticsFeedback.Waveform.Equals(ContinuousBuzzWaveform))
69  {
70  if (durationInSeconds.Equals(float.MaxValue))
71  {
72  simpleHapticsController.SendHapticFeedback(hapticsFeedback, intensity);
73  }
74  else
75  {
76  simpleHapticsController.SendHapticFeedbackForDuration(hapticsFeedback, intensity, TimeSpan.FromSeconds(durationInSeconds));
77  }
78  return;
79  }
80  }
81  }
82  }
83  }, true);
84 #elif UNITY_EDITOR_WIN
85  StartHaptics(interactionSource.id, intensity, durationInSeconds);
86 #endif // !UNITY_EDITOR
87  }
88 
89  public static void StopHaptics(this InteractionSource interactionSource)
90  {
91  if (!WindowsApiChecker.UniversalApiContractV4_IsAvailable && !Application.isEditor)
92  {
93  return;
94  }
95 
96 #if !UNITY_EDITOR
97  UnityEngine.WSA.Application.InvokeOnUIThread(() =>
98  {
99  IReadOnlyList<SpatialInteractionSourceState> sources = SpatialInteractionManager.GetForCurrentView().GetDetectedSourcesAtTimestamp(PerceptionTimestampHelper.FromHistoricalTargetTime(DateTimeOffset.Now));
100 
101  foreach (SpatialInteractionSourceState sourceState in sources)
102  {
103  if (sourceState.Source.Id.Equals(interactionSource.id))
104  {
105  sourceState.Source.Controller.SimpleHapticsController.StopFeedback();
106  }
107  }
108  }, true);
109 #elif UNITY_EDITOR_WIN
110  StopHaptics(interactionSource.id);
111 #endif // !UNITY_EDITOR
112  }
113 
114 #if !UNITY_EDITOR
115  public static IAsyncOperation<IRandomAccessStreamWithContentType> TryGetRenderableModelAsync(this InteractionSource interactionSource)
116  {
117  IAsyncOperation<IRandomAccessStreamWithContentType> returnValue = null;
118 
120  {
121  UnityEngine.WSA.Application.InvokeOnUIThread(() =>
122  {
123  IReadOnlyList<SpatialInteractionSourceState> sources = SpatialInteractionManager.GetForCurrentView().GetDetectedSourcesAtTimestamp(PerceptionTimestampHelper.FromHistoricalTargetTime(DateTimeOffset.Now));
124 
125  foreach (SpatialInteractionSourceState sourceState in sources)
126  {
127  if (sourceState.Source.Id.Equals(interactionSource.id))
128  {
129  returnValue = sourceState.Source.Controller.TryGetRenderableModelAsync();
130  }
131  }
132  }, true);
133  }
134 
135  return returnValue;
136  }
137 #endif // !UNITY_EDITOR
138 #endif // UNITY_WSA
139 #endif // UNITY_2017_2_OR_NEWER
140  }
141 }
Helper class for determining if a Windows API contract is available.
static bool UniversalApiContractV5_IsAvailable
Is the Universal API Contract v5.0 Available?
Extensions for the InteractionSource class to add haptics and expose the renderable model...
static bool UniversalApiContractV4_IsAvailable
Is the Universal API Contract v4.0 Available?