AR Design
UBC EML collab with UBC SALA - visualizing IoT data in AR
KeyboardManager.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 UnityEngine;
5 using System;
6 using System.Collections.Generic;
7 
8 namespace HoloToolkit.Unity.InputModule
9 {
13  public class KeyboardManager : Singleton<KeyboardManager>
14  {
15  public enum KeyEvent
16  {
20  KeyDown = 0,
21 
25  KeyHeld,
26 
30  KeyUp
31  };
32 
36  public struct KeyCodeEventPair
37  {
38  public KeyCode KeyCode;
40 
41  public KeyCodeEventPair(KeyCode keyCode, KeyEvent keyEvent)
42  {
43  this.KeyCode = keyCode;
44  this.KeyEvent = keyEvent;
45  }
46 
47  public override bool Equals(object obj)
48  {
49  if (!(obj is KeyCodeEventPair))
50  {
51  return false;
52  }
53 
54  KeyCodeEventPair compare = (KeyCodeEventPair)obj;
55 
56  return KeyCode == compare.KeyCode && KeyEvent == compare.KeyEvent;
57  }
58 
59  public override int GetHashCode()
60  {
61  return (KeyCode.GetHashCode() * 100) ^ KeyEvent.GetHashCode();
62  }
63  };
64 
69  public class KeyboardRegistration : IDisposable
70  {
71  private readonly KeyCodeEventPair keyCodeEvent;
72  private readonly KeyboardCallback callback;
73  private bool isRegistered;
74 
75  public KeyboardRegistration(KeyCodeEventPair keyCodeEvent, KeyboardCallback callback)
76  {
77  this.keyCodeEvent = keyCodeEvent;
78  this.callback = callback;
79  isRegistered = true;
80  }
81 
82  public void Dispose()
83  {
84  if (isRegistered)
85  {
86  var keyboard = KeyboardManager.Instance;
87  if (keyboard)
88  {
89  keyboard.UnregisterKeyEvent(keyCodeEvent, callback);
90  }
91  isRegistered = false;
92  }
93  }
94  }
95 
100  public delegate void KeyboardCallback(KeyCodeEventPair keyCodeEvent);
101 
105  private Dictionary<KeyCodeEventPair, List<KeyboardCallback>> registeredCallbacks
106  = new Dictionary<KeyCodeEventPair, List<KeyboardCallback>>();
107 
111  private List<KeyCodeEventPair> detectedKeyEvents = new List<KeyCodeEventPair>();
112 
116  private List<KeyCodeEventPair> pendingKeyEvents = new List<KeyCodeEventPair>();
117 
118  private void Update()
119  {
120  lock (detectedKeyEvents)
121  {
122  pendingKeyEvents.AddRange(detectedKeyEvents);
123  detectedKeyEvents.Clear();
124  }
125 
126  // Check for all keys that are registered for events
127  foreach (KeyCodeEventPair keyCheck in registeredCallbacks.Keys)
128  {
129  bool eventTriggered = false;
130 
131  switch (keyCheck.KeyEvent)
132  {
133  case KeyEvent.KeyHeld:
134  eventTriggered = Input.GetKey(keyCheck.KeyCode);
135  break;
136  case KeyEvent.KeyDown:
137  eventTriggered = Input.GetKeyDown(keyCheck.KeyCode);
138  break;
139  case KeyEvent.KeyUp:
140  eventTriggered = Input.GetKeyUp(keyCheck.KeyCode);
141  break;
142  }
143 
144  if (eventTriggered)
145  {
146  pendingKeyEvents.Add(keyCheck);
147  }
148  }
149 
150  for (int eventIndex = 0; eventIndex < pendingKeyEvents.Count; eventIndex++)
151  {
152  HandleKeyEvent(pendingKeyEvents[eventIndex]);
153  }
154  pendingKeyEvents.Clear();
155  }
156 
160  private void UnregisterKeyEvent(KeyCodeEventPair keyCodeEvent, KeyboardCallback callback)
161  {
162  if (registeredCallbacks.ContainsKey(keyCodeEvent))
163  {
164  List<KeyboardCallback> callbackList = registeredCallbacks[keyCodeEvent];
165 
166  if (callbackList.Remove(callback))
167  {
168  // remove the list from the dictionary if no callbacks are left
169  if (callbackList.Count == 0)
170  {
171  registeredCallbacks.Remove(keyCodeEvent);
172  }
173  }
174  }
175  }
176 
180  private void HandleKeyEvent(KeyCodeEventPair keyEventPair)
181  {
182  List<KeyboardCallback> callbackList;
183 
184  if (registeredCallbacks.TryGetValue(keyEventPair, out callbackList))
185  {
186  // Create a copy of the list in case a listener unregisters.
187  KeyboardCallback[] callbacksCopy = callbackList.ToArray();
188  foreach (KeyboardCallback callback in callbacksCopy)
189  {
190  callback(keyEventPair);
191  }
192  }
193  }
194 
195  #region Public Functions
196  public KeyboardRegistration RegisterKeyEvent(KeyCodeEventPair keycodeEvent, KeyboardCallback callback)
200  {
201  if (!registeredCallbacks.ContainsKey(keycodeEvent))
202  {
203  registeredCallbacks.Add(keycodeEvent, new List<KeyboardCallback>());
204  }
205 
206  // Don't register the same callback more than once
207  List<KeyboardCallback> callbackList = registeredCallbacks[keycodeEvent];
208  for (int i = 0; i < callbackList.Count; i++)
209  {
210  if (callbackList[i] == callback)
211  {
212  // Duplicate
213  Debug.LogError("Ignoring duplicate keyboard callback.");
214  return null;
215  }
216  }
217 
218  callbackList.Add(callback);
219 
220  // return a registration object, which must be referenced until it's disposed to unregister
221  return new KeyboardRegistration(keycodeEvent, callback);
222  }
223 
228  public void InjectKeyboardEvent(KeyCodeEventPair keycodeEvent)
229  {
230  lock (detectedKeyEvents)
231  {
232  detectedKeyEvents.Add(keycodeEvent);
233  }
234  }
235  #endregion
236  }
237 }
KeyboardRegistration is returned by RegisterKeyEvent. Calling code should maintain a reference to the...
KeyboardManager allows other scripts to register for (or inject) key events.
void InjectKeyboardEvent(KeyCodeEventPair keycodeEvent)
Queue an artificial keyboard event to be handled on the next Update. (This can be called from another...
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
KeyboardRegistration(KeyCodeEventPair keyCodeEvent, KeyboardCallback callback)
Simple struct that holds a KeyCode and KeyEvent
Singleton behaviour class, used for components that should only have one instance.
Definition: Singleton.cs:14