using System.Linq; using UnityEngine.InputSystem.Utilities; #if UNITY_EDITOR using UnityEditor; using UnityEngine.InputSystem.Editor; using UnityEngine.InputSystem.HID.Editor; #endif namespace UnityEngine.InputSystem.HID { using ShouldCreateHIDCallback = System.Func; /// /// Adds support for generic HID devices to the input system. /// /// /// Even without this module, HIDs can be used on platforms where we /// support HID has a native backend (Windows and OSX, at the moment). /// However, each supported HID requires a layout specifically targeting /// it as a product. /// /// What this module adds is the ability to turn any HID with usable /// controls into an InputDevice. It will make a best effort to figure /// out a suitable class for the device and will use the HID elements /// present in the HID report descriptor to populate the device. /// /// If there is an existing product-specific layout for a HID, it will /// take precedence and HIDSupport will leave the device alone. /// public static class HIDSupport { /// /// A pair of HID usage page and HID usage number. /// /// /// Used to describe a HID usage for the property. /// public struct HIDPageUsage { /// /// The usage page. /// public HID.UsagePage page; /// /// A number specifying the usage on the usage page. /// public int usage; /// /// Create a HIDPageUsage struct by specifying a page and usage. /// public HIDPageUsage(HID.UsagePage page, int usage) { this.page = page; this.usage = usage; } /// /// Create a HIDPageUsage struct from the GenericDesktop usage page by specifying the usage. /// public HIDPageUsage(HID.GenericDesktop usage) { page = HID.UsagePage.GenericDesktop; this.usage = (int)usage; } } private static HIDPageUsage[] s_SupportedHIDUsages; /// /// An array of HID usages the input is configured to support. /// /// /// The input system will only create s for HIDs with usages /// listed in this array. Any other HID will be ignored. This saves the input system from /// spending resources on creating layouts and devices for HIDs which are not supported or /// not usable for game input. /// /// By default, this includes only , /// and , /// but you can set this property to include any other HID usages. /// /// Note that currently on macOS, the only HID usages which can be enabled are /// , , /// , , /// and . /// public static ReadOnlyArray supportedHIDUsages { get => s_SupportedHIDUsages; set { s_SupportedHIDUsages = value.ToArray(); // Add HIDs we now support. InputSystem.s_Manager.AddAvailableDevicesThatAreNowRecognized(); // Remove HIDs we no longer support. for (var i = 0; i < InputSystem.devices.Count; ++i) { var device = InputSystem.devices[i]; if (device is HID hid && !s_SupportedHIDUsages.Contains(new HIDPageUsage(hid.hidDescriptor.usagePage, hid.hidDescriptor.usage))) { // Remove the entire generated layout. This will also remove all devices based on it. InputSystem.RemoveLayout(device.layout); --i; } } } } /// /// Add support for generic HIDs to InputSystem. /// #if UNITY_DISABLE_DEFAULT_INPUT_PLUGIN_INITIALIZATION public #else internal #endif static void Initialize() { s_SupportedHIDUsages = new[] { new HIDPageUsage(HID.GenericDesktop.Joystick), new HIDPageUsage(HID.GenericDesktop.Gamepad), new HIDPageUsage(HID.GenericDesktop.MultiAxisController), }; InputSystem.RegisterLayout(); InputSystem.onFindLayoutForDevice += HID.OnFindLayoutForDevice; // Add toolbar button to any devices using the "HID" interface. Opens // a windows to browse the HID descriptor of the device. #if UNITY_EDITOR InputDeviceDebuggerWindow.onToolbarGUI += device => { if (device.description.interfaceName == HID.kHIDInterface) { if (GUILayout.Button(s_HIDDescriptor, EditorStyles.toolbarButton)) { HIDDescriptorWindow.CreateOrShowExisting(device.deviceId, device.description); } } }; #endif } #if UNITY_EDITOR private static readonly GUIContent s_HIDDescriptor = new GUIContent("HID Descriptor"); #endif } }