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