AR Design
UBC EML collab with UBC SALA - visualizing IoT data in AR
RawInteractionInputSource.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 using System;
5 using System.Collections.Generic;
6 using UnityEngine;
7 
8 #if UNITY_WSA && !UNITY_2017_2_OR_NEWER
9 using UnityEngine.VR.WSA.Input;
10 #endif
11 
12 namespace HoloToolkit.Unity.InputModule
13 {
24  [Obsolete("Will be removed in a future release")]
26  {
30  private class SourceData
31  {
32  public SourceData(uint sourceId)
33  {
34  SourceId = sourceId;
35  HasPosition = false;
36  SourcePosition = Vector3.zero;
37  IsSourceDown = false;
38  IsSourceDownPending = false;
39  SourceStateChanged = false;
40  SourceStateUpdateTimer = -1;
41  }
42 
43  public readonly uint SourceId;
44  public bool HasPosition;
45  public Vector3 SourcePosition;
46  public bool IsSourceDown;
47  public bool IsSourceDownPending;
48  public bool SourceStateChanged;
49  public float SourceStateUpdateTimer;
50  }
51 
56  private const float SourcePressDelay = 0.07f;
57 
58  [Tooltip("Use unscaled time. This is useful for games that have a pause mechanism or otherwise adjust the game timescale.")]
59  public bool UseUnscaledTime = true;
60 
64  private readonly Dictionary<uint, SourceData> sourceIdToData = new Dictionary<uint, SourceData>(4);
65  private readonly List<uint> pendingSourceIdDeletes = new List<uint>();
66 
67  // HashSets used to be able to quickly update the sources data when they become visible / not visible
68  private readonly HashSet<uint> currentSources = new HashSet<uint>();
69  private readonly HashSet<uint> newSources = new HashSet<uint>();
70 
71  public override SupportedInputInfo GetSupportedInputInfo(uint sourceId)
72  {
74 
75  SourceData sourceData;
76  if (sourceIdToData.TryGetValue(sourceId, out sourceData))
77  {
78  if (sourceData.HasPosition)
79  {
80  retVal |= SupportedInputInfo.Position;
81  }
82  }
83 
84  return retVal;
85  }
86 
87  public override bool TryGetMenu(uint sourceId, out bool isPressed)
88  {
89  throw new NotImplementedException();
90  }
91 
92  public override bool TryGetPointerPosition(uint sourceId, out Vector3 position)
93  {
94  SourceData sourceData;
95  if (sourceIdToData.TryGetValue(sourceId, out sourceData))
96  {
97  if (sourceData.HasPosition)
98  {
99  position = sourceData.SourcePosition;
100  return true;
101  }
102  }
103 
104  // Else, the source doesn't have positional information
105  position = Vector3.zero;
106  return false;
107  }
108 
109  public override bool TryGetPointerRotation(uint sourceId, out Quaternion orientation)
110  {
111  // Orientation is not supported by any Windows interaction sources
112  orientation = Quaternion.identity;
113  return false;
114  }
115 
116  public override bool TryGetSourceKind(uint sourceId, out InteractionSourceInfo sourceKind)
117  {
118  throw new NotImplementedException();
119  }
120 
121  public override bool TryGetGripPosition(uint sourceId, out Vector3 position)
122  {
123  throw new NotImplementedException();
124  }
125 
126  public override bool TryGetGripRotation(uint sourceId, out Quaternion rotation)
127  {
128  throw new NotImplementedException();
129  }
130 
131  public override bool TryGetThumbstick(uint sourceId, out bool isPressed, out Vector2 position)
132  {
133  throw new NotImplementedException();
134  }
135 
136  public override bool TryGetTouchpad(uint sourceId, out bool isPressed, out bool isTouched, out Vector2 position)
137  {
138  throw new NotImplementedException();
139  }
140 
141  public override bool TryGetSelect(uint sourceId, out bool isPressed, out double pressedValue)
142  {
143  throw new NotImplementedException();
144  }
145 
146  public override bool TryGetGrasp(uint sourceId, out bool isPressed)
147  {
148  throw new NotImplementedException();
149  }
150 
151  public override bool TryGetPointingRay(uint sourceId, out Ray pointingRay)
152  {
153  throw new NotImplementedException();
154  }
155 
156  private void Update()
157  {
158  newSources.Clear();
159  currentSources.Clear();
160 
161  UpdateSourceData();
162  SendSourceVisibilityEvents();
163  }
164 
168  private void UpdateSourceData()
169  {
170 #if UNITY_WSA && !UNITY_2017_2_OR_NEWER
171  // Poll for updated reading from hands
172  InteractionSourceState[] sourceStates = InteractionManager.GetCurrentReading();
173  if (sourceStates != null)
174  {
175  for (var i = 0; i < sourceStates.Length; ++i)
176  {
177  InteractionSourceState handSource = sourceStates[i];
178  SourceData sourceData = GetOrAddSourceData(handSource.source);
179  currentSources.Add(handSource.source.id);
180 
181  UpdateSourceState(handSource, sourceData);
182  }
183  }
184 #endif
185  }
186 
187 #if UNITY_WSA && !UNITY_2017_2_OR_NEWER
188  private SourceData GetOrAddSourceData(InteractionSource interactionSource)
194  {
195  SourceData sourceData;
196  if (!sourceIdToData.TryGetValue(interactionSource.id, out sourceData))
197  {
198  sourceData = new SourceData(interactionSource.id);
199  sourceIdToData.Add(sourceData.SourceId, sourceData);
200  newSources.Add(sourceData.SourceId);
201  }
202 
203  return sourceData;
204  }
205 
211  private void UpdateSourceState(InteractionSourceState interactionSource, SourceData sourceData)
212  {
213  // Update source position
214  Vector3 sourcePosition;
215  if (interactionSource.properties.location.TryGetPosition(out sourcePosition))
216  {
217  sourceData.HasPosition = true;
218  sourceData.SourcePosition = sourcePosition;
219  }
220 
221  // Check for source presses
222  if (interactionSource.pressed != sourceData.IsSourceDownPending)
223  {
224  sourceData.IsSourceDownPending = interactionSource.pressed;
225  sourceData.SourceStateUpdateTimer = SourcePressDelay;
226  }
227 
228  // Source presses are delayed to mitigate issue with hand position shifting during air tap
229  sourceData.SourceStateChanged = false;
230  if (sourceData.SourceStateUpdateTimer >= 0)
231  {
232  float deltaTime = UseUnscaledTime
233  ? Time.unscaledDeltaTime
234  : Time.deltaTime;
235 
236  sourceData.SourceStateUpdateTimer -= deltaTime;
237  if (sourceData.SourceStateUpdateTimer < 0)
238  {
239  sourceData.IsSourceDown = sourceData.IsSourceDownPending;
240  sourceData.SourceStateChanged = true;
241  }
242  }
243 
244  SendSourceStateEvents(sourceData);
245  }
246 #endif
247 
252  private void SendSourceStateEvents(SourceData sourceData)
253  {
254  // Source pressed/released events
255  if (sourceData.SourceStateChanged)
256  {
257  if (sourceData.IsSourceDown)
258  {
259  InputManager.Instance.RaiseSourceDown(this, sourceData.SourceId, InteractionSourcePressInfo.Select);
260  }
261  else
262  {
263  InputManager.Instance.RaiseSourceUp(this, sourceData.SourceId, InteractionSourcePressInfo.Select);
264  }
265  }
266  }
267 
271  private void SendSourceVisibilityEvents()
272  {
273  // Send event for new sources that were added
274  foreach (uint newSource in newSources)
275  {
276  InputManager.Instance.RaiseSourceDetected(this, newSource);
277  }
278 
279  // Send event for sources that are no longer visible and remove them from our dictionary
280  foreach (uint existingSource in sourceIdToData.Keys)
281  {
282  if (!currentSources.Contains(existingSource))
283  {
284  pendingSourceIdDeletes.Add(existingSource);
285  InputManager.Instance.RaiseSourceLost(this, existingSource);
286  }
287  }
288 
289  // Remove pending source IDs
290  for (int i = 0; i < pendingSourceIdDeletes.Count; ++i)
291  {
292  sourceIdToData.Remove(pendingSourceIdDeletes[i]);
293  }
294  pendingSourceIdDeletes.Clear();
295  }
296  }
297 }
override bool TryGetPointingRay(uint sourceId, out Ray pointingRay)
Returns the pointing ray of the input source, if available. Not all input sources support pointing in...
override bool TryGetSelect(uint sourceId, out bool isPressed, out double pressedValue)
override bool TryGetGripRotation(uint sourceId, out Quaternion rotation)
Returns the rotation of the input source, if available. Not all input sources support rotation inform...
Input Manager is responsible for managing input sources and dispatching relevant events to the approp...
Definition: InputManager.cs:19
override bool TryGetTouchpad(uint sourceId, out bool isPressed, out bool isTouched, out Vector2 position)
SupportedInputInfo
Flags used to indicate which input information is supported by an input source.
Input source for raw interactions sources information, which gives finer details about current source...
override bool TryGetGrasp(uint sourceId, out bool isPressed)
static T Instance
Returns the Singleton instance of the classes type. If no instance is found, then we search for an in...
Definition: Singleton.cs:26
override bool TryGetSourceKind(uint sourceId, out InteractionSourceInfo sourceKind)
override bool TryGetThumbstick(uint sourceId, out bool isPressed, out Vector2 position)
override bool TryGetGripPosition(uint sourceId, out Vector3 position)
Returns the position of the input source, if available. Not all input sources support positional info...
override bool TryGetMenu(uint sourceId, out bool isPressed)
override bool TryGetPointerPosition(uint sourceId, out Vector3 position)
Returns the position of the input source, if available. Not all input sources support positional info...
Base class for an input source.
override SupportedInputInfo GetSupportedInputInfo(uint sourceId)
Returns the input info that the input source can provide.
override bool TryGetPointerRotation(uint sourceId, out Quaternion orientation)
Returns the rotation of the input source, if available. Not all input sources support rotation inform...