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