HIDDescriptorWindow.cs 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. #if UNITY_EDITOR
  2. using System;
  3. using System.Collections.Generic;
  4. using UnityEditor;
  5. using UnityEditor.IMGUI.Controls;
  6. using UnityEngine.InputSystem.Layouts;
  7. using UnityEngine.InputSystem.LowLevel;
  8. ////TODO: use two columns for treeview and separate name and value
  9. namespace UnityEngine.InputSystem.HID.Editor
  10. {
  11. /// <summary>
  12. /// A window that dumps a raw HID descriptor in a tree view.
  13. /// </summary>
  14. /// <remarks>
  15. /// Not specific to InputDevices of type <see cref="HID"/> so that it can work with
  16. /// any <see cref="InputDevice"/> created for a device using the "HID" interface.
  17. /// </remarks>
  18. internal class HIDDescriptorWindow : EditorWindow, ISerializationCallbackReceiver
  19. {
  20. public static void CreateOrShowExisting(int deviceId, InputDeviceDescription deviceDescription)
  21. {
  22. // See if we have an existing window for the device and if so pop it
  23. // in front.
  24. if (s_OpenWindows != null)
  25. {
  26. for (var i = 0; i < s_OpenWindows.Count; ++i)
  27. {
  28. var existingWindow = s_OpenWindows[i];
  29. if (existingWindow.m_DeviceId == deviceId)
  30. {
  31. existingWindow.Show();
  32. existingWindow.Focus();
  33. return;
  34. }
  35. }
  36. }
  37. // No, so create a new one.
  38. var window = CreateInstance<HIDDescriptorWindow>();
  39. window.InitializeWith(deviceId, deviceDescription);
  40. window.minSize = new Vector2(270, 200);
  41. window.Show();
  42. window.titleContent = new GUIContent("HID Descriptor");
  43. }
  44. public void Awake()
  45. {
  46. AddToList();
  47. }
  48. public void OnDestroy()
  49. {
  50. RemoveFromList();
  51. }
  52. public void OnGUI()
  53. {
  54. if (!m_Initialized)
  55. InitializeWith(m_DeviceId, m_DeviceDescription);
  56. GUILayout.BeginHorizontal(EditorStyles.toolbar);
  57. GUILayout.Label(m_Label, GUILayout.MinWidth(100), GUILayout.ExpandWidth(true));
  58. GUILayout.EndHorizontal();
  59. var rect = EditorGUILayout.GetControlRect(GUILayout.ExpandHeight(true));
  60. m_TreeView.OnGUI(rect);
  61. }
  62. private void InitializeWith(int deviceId, InputDeviceDescription deviceDescription)
  63. {
  64. m_DeviceId = deviceId;
  65. m_DeviceDescription = deviceDescription;
  66. m_Initialized = true;
  67. // Set up tree view for HID descriptor.
  68. var hidDescriptor = HID.ReadHIDDeviceDescriptor(ref m_DeviceDescription,
  69. (ref InputDeviceCommand command) => InputRuntime.s_Instance.DeviceCommand(m_DeviceId, ref command));
  70. if (m_TreeViewState == null)
  71. m_TreeViewState = new TreeViewState();
  72. m_TreeView = new HIDDescriptorTreeView(m_TreeViewState, hidDescriptor);
  73. m_TreeView.SetExpanded(1, true);
  74. m_Label = new GUIContent(
  75. $"HID Descriptor for '{deviceDescription.manufacturer} {deviceDescription.product}'");
  76. }
  77. [NonSerialized] private bool m_Initialized;
  78. [NonSerialized] private HIDDescriptorTreeView m_TreeView;
  79. [NonSerialized] private GUIContent m_Label;
  80. [SerializeField] private int m_DeviceId;
  81. [SerializeField] private InputDeviceDescription m_DeviceDescription;
  82. [SerializeField] private TreeViewState m_TreeViewState;
  83. private void AddToList()
  84. {
  85. if (s_OpenWindows == null)
  86. s_OpenWindows = new List<HIDDescriptorWindow>();
  87. if (!s_OpenWindows.Contains(this))
  88. s_OpenWindows.Add(this);
  89. }
  90. private void RemoveFromList()
  91. {
  92. if (s_OpenWindows != null)
  93. s_OpenWindows.Remove(this);
  94. }
  95. private static List<HIDDescriptorWindow> s_OpenWindows;
  96. private class HIDDescriptorTreeView : TreeView
  97. {
  98. private HID.HIDDeviceDescriptor m_Descriptor;
  99. public HIDDescriptorTreeView(TreeViewState state, HID.HIDDeviceDescriptor descriptor)
  100. : base(state)
  101. {
  102. m_Descriptor = descriptor;
  103. Reload();
  104. }
  105. protected override TreeViewItem BuildRoot()
  106. {
  107. var id = 0;
  108. var root = new TreeViewItem
  109. {
  110. id = id++,
  111. depth = -1
  112. };
  113. var item = BuildDeviceItem(m_Descriptor, ref id);
  114. root.AddChild(item);
  115. return root;
  116. }
  117. private TreeViewItem BuildDeviceItem(HID.HIDDeviceDescriptor device, ref int id)
  118. {
  119. var item = new TreeViewItem
  120. {
  121. id = id++,
  122. depth = 0,
  123. displayName = "Device"
  124. };
  125. AddChild(item, string.Format("Vendor ID: 0x{0:X}", device.vendorId), ref id);
  126. AddChild(item, string.Format("Product ID: 0x{0:X}", device.productId), ref id);
  127. AddChild(item, string.Format("Usage Page: 0x{0:X} ({1})", (uint)device.usagePage, device.usagePage), ref id);
  128. AddChild(item, string.Format("Usage: 0x{0:X}", device.usage), ref id);
  129. AddChild(item, "Input Report Size: " + device.inputReportSize, ref id);
  130. AddChild(item, "Output Report Size: " + device.outputReportSize, ref id);
  131. AddChild(item, "Feature Report Size: " + device.featureReportSize, ref id);
  132. // Elements.
  133. if (device.elements != null)
  134. {
  135. var elementCount = device.elements.Length;
  136. var elements = AddChild(item, elementCount + " Elements", ref id);
  137. for (var i = 0; i < elementCount; ++i)
  138. BuildElementItem(i, elements, device.elements[i], ref id);
  139. }
  140. else
  141. AddChild(item, "0 Elements", ref id);
  142. ////TODO: collections
  143. return item;
  144. }
  145. private TreeViewItem BuildElementItem(int index, TreeViewItem parent, HID.HIDElementDescriptor element, ref int id)
  146. {
  147. var item = AddChild(parent, string.Format("Element {0} ({1})", index, element.reportType), ref id);
  148. string usagePageString = HID.UsagePageToString(element.usagePage);
  149. string usageString = HID.UsageToString(element.usagePage, element.usage);
  150. AddChild(item, string.Format("Usage Page: 0x{0:X} ({1})", (uint)element.usagePage, usagePageString), ref id);
  151. if (usageString != null)
  152. AddChild(item, string.Format("Usage: 0x{0:X} ({1})", element.usage, usageString), ref id);
  153. else
  154. AddChild(item, string.Format("Usage: 0x{0:X}", element.usage), ref id);
  155. AddChild(item, "Report Type: " + element.reportType, ref id);
  156. AddChild(item, "Report ID: " + element.reportId, ref id);
  157. AddChild(item, "Report Size in Bits: " + element.reportSizeInBits, ref id);
  158. AddChild(item, "Report Bit Offset: " + element.reportOffsetInBits, ref id);
  159. AddChild(item, "Collection Index: " + element.collectionIndex, ref id);
  160. AddChild(item, string.Format("Unit: {0:X}", element.unit), ref id);
  161. AddChild(item, string.Format("Unit Exponent: {0:X}", element.unitExponent), ref id);
  162. AddChild(item, "Logical Min: " + element.logicalMin, ref id);
  163. AddChild(item, "Logical Max: " + element.logicalMax, ref id);
  164. AddChild(item, "Physical Min: " + element.physicalMin, ref id);
  165. AddChild(item, "Physical Max: " + element.physicalMax, ref id);
  166. AddChild(item, "Has Null State?: " + element.hasNullState, ref id);
  167. AddChild(item, "Has Preferred State?: " + element.hasPreferredState, ref id);
  168. AddChild(item, "Is Array?: " + element.isArray, ref id);
  169. AddChild(item, "Is Non-Linear?: " + element.isNonLinear, ref id);
  170. AddChild(item, "Is Relative?: " + element.isRelative, ref id);
  171. AddChild(item, "Is Constant?: " + element.isConstant, ref id);
  172. AddChild(item, "Is Wrapping?: " + element.isWrapping, ref id);
  173. return item;
  174. }
  175. private TreeViewItem AddChild(TreeViewItem parent, string displayName, ref int id)
  176. {
  177. var item = new TreeViewItem
  178. {
  179. id = id++,
  180. depth = parent.depth + 1,
  181. displayName = displayName
  182. };
  183. parent.AddChild(item);
  184. return item;
  185. }
  186. }
  187. public void OnBeforeSerialize()
  188. {
  189. }
  190. public void OnAfterDeserialize()
  191. {
  192. AddToList();
  193. }
  194. }
  195. }
  196. #endif // UNITY_EDITOR