diff --git a/Assets/Tests/InputSystem/Plugins/XRTests.cs b/Assets/Tests/InputSystem/Plugins/XRTests.cs index 66fc47062e..65bc96c166 100644 --- a/Assets/Tests/InputSystem/Plugins/XRTests.cs +++ b/Assets/Tests/InputSystem/Plugins/XRTests.cs @@ -1140,6 +1140,7 @@ public void Controls_OptimizedControls_PoseControl_IsOptimized() // ISXB-405 [Test] + [Category("Devices")] public void Devices_AddingUnusualDevice_ShouldntCrashTheSystem() { var deviceDescr = @@ -1153,5 +1154,19 @@ public void Devices_AddingUnusualDevice_ShouldntCrashTheSystem() Assert.That(device, Is.Not.Null); } + + [Test] + [Category("Commands")] + public void Commands_GetHapticCapabilitiesCommand_UsesCorrectPayloadSize() + { + unsafe + { + // Check that the payload of the command matches the low-level struct defined in IUnityXRInput.h (UnityXRHapticCapabilities) + // and used in XRInputSubsystem by checking the size. The sizes are required to match for the event to be + // sent to the device. + Assert.That(sizeof(UnityEngine.InputSystem.XR.Haptics.HapticCapabilities), Is.EqualTo(sizeof(UnityEngine.XR.HapticCapabilities))); + Assert.That(sizeof(UnityEngine.InputSystem.XR.Haptics.GetHapticCapabilitiesCommand) - InputDeviceCommand.BaseCommandSize, Is.EqualTo(sizeof(UnityEngine.XR.HapticCapabilities))); + } + } } #endif diff --git a/Packages/com.unity.inputsystem/CHANGELOG.md b/Packages/com.unity.inputsystem/CHANGELOG.md index 73c085d9d1..fc8bbf4d47 100644 --- a/Packages/com.unity.inputsystem/CHANGELOG.md +++ b/Packages/com.unity.inputsystem/CHANGELOG.md @@ -46,6 +46,8 @@ however, it has to be formatted properly to pass verification tests. - Fixed issue of visual elements being null during editing project-wide actions in project settings which prompted console errors. - Fixed case ISX-1436 (UI TK Input Action Asset Editor - Error deleting Bindings with DeleteKey on Windows). - Fixed issue with UI Toolkit based Input Action Editor not restoring it's selected items after Domain Reload. +- Fixed the [`GetHapticCapabilitiesCommand`](xref:UnityEngine.InputSystem.XR.Haptics.GetHapticCapabilitiesCommand) always failing to execute due to a mismatch in the size in bytes of the payload and the size expected by XR devices. Changed [`HapticCapabilities`](xref:UnityEngine.InputSystem.XR.Haptics.HapticCapabilities) to include all properties returned by the XR input subsystem. This makes Input System match the functionality provided by the [XR](https://docs.unity3d.com/Manual/com.unity.modules.xr.html) module's [`InputDevice.TryGetHapticCapabilities`](https://docs.unity3d.com/ScriptReference/XR.InputDevice.TryGetHapticCapabilities.html) and [`HapticCapabilities`](https://docs.unity3d.com/ScriptReference/XR.HapticCapabilities.html). + ## [1.8.0-pre.1] - 2023-09-04 diff --git a/Packages/com.unity.inputsystem/InputSystem/Actions/Composites/Vector2Composite.cs b/Packages/com.unity.inputsystem/InputSystem/Actions/Composites/Vector2Composite.cs index ae09cb1057..c5f001587b 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Actions/Composites/Vector2Composite.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Actions/Composites/Vector2Composite.cs @@ -124,7 +124,7 @@ public class Vector2Composite : InputBindingComposite /// /// /// - public Mode mode = Mode.DigitalNormalized; + public Mode mode; /// public override Vector2 ReadValue(ref InputBindingCompositeContext context) diff --git a/Packages/com.unity.inputsystem/InputSystem/Devices/Commands/IInputDeviceCommandInfo.cs b/Packages/com.unity.inputsystem/InputSystem/Devices/Commands/IInputDeviceCommandInfo.cs index 11128f29a3..534d1ab29b 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Devices/Commands/IInputDeviceCommandInfo.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Devices/Commands/IInputDeviceCommandInfo.cs @@ -7,6 +7,9 @@ namespace UnityEngine.InputSystem.LowLevel /// public interface IInputDeviceCommandInfo { + /// + /// The data format identifier of the device command as a code. + /// FourCC typeStatic { get; } } } diff --git a/Packages/com.unity.inputsystem/InputSystem/Plugins/XR/Haptics/GetHapticCapabilitiesCommand.cs b/Packages/com.unity.inputsystem/InputSystem/Plugins/XR/Haptics/GetHapticCapabilitiesCommand.cs index 081aa58c7d..670ccd158f 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Plugins/XR/Haptics/GetHapticCapabilitiesCommand.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Plugins/XR/Haptics/GetHapticCapabilitiesCommand.cs @@ -6,43 +6,147 @@ namespace UnityEngine.InputSystem.XR.Haptics { + /// + /// Describes the haptic capabilities of a specific device. + /// public struct HapticCapabilities { - public HapticCapabilities(uint numChannels, uint frequencyHz, uint maxBufferSize) + /// + /// Initializes and returns an instance of . + /// + /// The number of haptic channels available on this device. + /// This device supports sending a haptic impulse. + /// This device supports sending a haptic buffer. + /// The buffer frequency the device operates at in Hertz. + /// The max amount of buffer data that can be stored by the device. + /// The optimal size of a device's buffer, taking into account frequency and latency. + public HapticCapabilities(uint numChannels, bool supportsImpulse, bool supportsBuffer, uint frequencyHz, uint maxBufferSize, uint optimalBufferSize) { this.numChannels = numChannels; + this.supportsImpulse = supportsImpulse; + this.supportsBuffer = supportsBuffer; this.frequencyHz = frequencyHz; this.maxBufferSize = maxBufferSize; + this.optimalBufferSize = optimalBufferSize; } - public uint numChannels { get; private set; } - public uint frequencyHz { get; private set; } - public uint maxBufferSize { get; private set; } + /// + /// Deprecated. Use instead. + /// This constructor did not match the native haptic capabilities struct and was missing properties. + /// + /// The number of haptic channels available on this device. + /// The buffer frequency the device operates at in Hertz. + /// The max amount of buffer data that can be stored by the device. + public HapticCapabilities(uint numChannels, uint frequencyHz, uint maxBufferSize) + : this(numChannels, false, false, frequencyHz, maxBufferSize, 0U) + { + } + + /// + /// The number of haptic channels available on this device. + /// + public uint numChannels { get; } + + /// + /// This device supports sending a haptic impulse. + /// + /// + public bool supportsImpulse { get; } + + /// + /// This device supports sending a haptic buffer. + /// + /// + public bool supportsBuffer { get; } + + /// + /// The buffer frequency the device operates at in Hertz. This impacts how fast the device consumes buffered haptic data. + /// + /// + /// This value is greater than 0 if is , and 0 otherwise. + /// + public uint frequencyHz { get; } + + /// + /// The max amount of buffer data that can be stored by the device. + /// + public uint maxBufferSize { get; } + + /// + /// The optimal size of a device's buffer, taking into account frequency and latency. + /// + public uint optimalBufferSize { get; } } + /// + /// Input device command struct for retrieving the haptic capabilities of a device. + /// [StructLayout(LayoutKind.Explicit, Size = kSize)] public struct GetHapticCapabilitiesCommand : IInputDeviceCommandInfo { static FourCC Type => new FourCC('X', 'H', 'C', '0'); - const int kSize = InputDeviceCommand.kBaseCommandSize + sizeof(uint) * 3; + // 20 bytes of data from uint(4) + bool(1) + bool(1) + padding + uint(4) + uint(4) + uint(4) + const int kSize = InputDeviceCommand.kBaseCommandSize + 20; + /// public FourCC typeStatic => Type; [FieldOffset(0)] InputDeviceCommand baseCommand; + /// + /// The number of haptic channels available on this device. + /// [FieldOffset(InputDeviceCommand.kBaseCommandSize)] public uint numChannels; - [FieldOffset(InputDeviceCommand.kBaseCommandSize + sizeof(uint))] + /// + /// This device supports sending a haptic impulse. + /// + /// + [FieldOffset(InputDeviceCommand.kBaseCommandSize + 4)] + public bool supportsImpulse; + + /// + /// This device supports sending a haptic buffer. + /// + /// + [FieldOffset(InputDeviceCommand.kBaseCommandSize + 5)] + public bool supportsBuffer; + + /// + /// The buffer frequency the device operates at in Hertz. This impacts how fast the device consumes buffered haptic data. + /// + /// + /// This value is greater than 0 if is , and 0 otherwise. + /// + [FieldOffset(InputDeviceCommand.kBaseCommandSize + 8)] public uint frequencyHz; - [FieldOffset(InputDeviceCommand.kBaseCommandSize + (sizeof(uint) * 2))] + /// + /// The max amount of buffer data that can be stored by the device. + /// + [FieldOffset(InputDeviceCommand.kBaseCommandSize + 12)] public uint maxBufferSize; - public HapticCapabilities capabilities => new HapticCapabilities(numChannels, frequencyHz, maxBufferSize); + /// + /// The optimal size of a device's buffer, taking into account frequency and latency. + /// + [FieldOffset(InputDeviceCommand.kBaseCommandSize + 16)] + public uint optimalBufferSize; + + /// + /// The haptic capabilities of the device, populated after this command is executed. + /// + public HapticCapabilities capabilities => new HapticCapabilities(numChannels, supportsImpulse, supportsBuffer, frequencyHz, maxBufferSize, optimalBufferSize); + /// + /// Creates and returns a new initialized input device command struct for retrieving + /// the haptic capabilities of a device when executed. + /// + /// Returns a new command struct with the data header initialized, making it ready to execute. + /// public static GetHapticCapabilitiesCommand Create() { return new GetHapticCapabilitiesCommand