using System.Runtime.InteropServices; using UnityEngine; using UnityEngine.InputSystem.Layouts; using UnityEngine.InputSystem.LowLevel; using UnityEngine.InputSystem.Utilities; namespace SC.XR.Unity.Simulation { /// /// Button indices for /// public enum ControllerButton { /// /// The primary face button being pressed on a device, or sole button if only one is available. /// PrimaryButton, /// /// The primary face button being touched on a device. /// PrimaryTouch, /// /// The secondary face button being pressed on a device. /// SecondaryButton, /// /// The secondary face button being touched on a device. /// SecondaryTouch, /// /// A binary measure of whether the device is being gripped. /// GripButton, /// /// A binary measure of whether the index finger is activating the trigger. /// TriggerButton, /// /// Represents a menu button, used to pause, go back, or otherwise exit gameplay. /// MenuButton, /// /// Represents the primary 2D axis being clicked or otherwise depressed. /// Primary2DAxisClick, /// /// Represents the primary 2D axis being touched. /// Primary2DAxisTouch, /// /// Represents the secondary 2D axis being clicked or otherwise depressed. /// Secondary2DAxisClick, /// /// Represents the secondary 2D axis being touched. /// Secondary2DAxisTouch, /// /// Indicates whether the user is present and interacting with the device. /// UserPresence, } /// /// State for input device representing a simulated XR handed controller. /// [StructLayout(LayoutKind.Explicit, Size = 63)] public struct XRSimulatedControllerState : IInputStateTypeInfo { /// /// Memory format identifier for . /// /// public static FourCC formatId => new FourCC('X', 'R', 'S', 'C'); /// /// See IInputStateTypeInfo.format. /// public FourCC format => formatId; /// /// The primary touchpad or joystick on a device. /// [InputControl(usage = "Primary2DAxis", aliases = new[] { "thumbstick", "joystick" })] [FieldOffset(0)] public Vector2 primary2DAxis; /// /// A trigger-like control, pressed with the index finger. /// [InputControl(usage = "Trigger", layout = "Axis")] [FieldOffset(8)] public float trigger; /// /// Represents the user's grip on the controller. /// [InputControl(usage = "Grip", layout = "Axis")] [FieldOffset(12)] public float grip; /// /// A secondary touchpad or joystick on a device. /// [InputControl(usage = "Secondary2DAxis")] [FieldOffset(16)] public Vector2 secondary2DAxis; /// /// All the buttons on this device. /// [InputControl(name = nameof(XRSimulatedController.primaryButton), usage = "PrimaryButton", layout = "Button", bit = (uint)ControllerButton.PrimaryButton)] [InputControl(name = nameof(XRSimulatedController.primaryTouch), usage = "PrimaryTouch", layout = "Button", bit = (uint)ControllerButton.PrimaryTouch)] [InputControl(name = nameof(XRSimulatedController.secondaryButton), usage = "SecondaryButton", layout = "Button", bit = (uint)ControllerButton.SecondaryButton)] [InputControl(name = nameof(XRSimulatedController.secondaryTouch), usage = "SecondaryTouch", layout = "Button", bit = (uint)ControllerButton.SecondaryTouch)] [InputControl(name = nameof(XRSimulatedController.gripButton), usage = "GripButton", layout = "Button", bit = (uint)ControllerButton.GripButton, alias = "gripPressed")] [InputControl(name = nameof(XRSimulatedController.triggerButton), usage = "TriggerButton", layout = "Button", bit = (uint)ControllerButton.TriggerButton, alias = "triggerPressed")] [InputControl(name = nameof(XRSimulatedController.menuButton), usage = "MenuButton", layout = "Button", bit = (uint)ControllerButton.MenuButton)] [InputControl(name = nameof(XRSimulatedController.primary2DAxisClick), usage = "Primary2DAxisClick", layout = "Button", bit = (uint)ControllerButton.Primary2DAxisClick)] [InputControl(name = nameof(XRSimulatedController.primary2DAxisTouch), usage = "Primary2DAxisTouch", layout = "Button", bit = (uint)ControllerButton.Primary2DAxisTouch)] [InputControl(name = nameof(XRSimulatedController.secondary2DAxisClick), usage = "Secondary2DAxisClick", layout = "Button", bit = (uint)ControllerButton.Secondary2DAxisClick)] [InputControl(name = nameof(XRSimulatedController.secondary2DAxisTouch), usage = "Secondary2DAxisTouch", layout = "Button", bit = (uint)ControllerButton.Secondary2DAxisTouch)] [InputControl(name = nameof(XRSimulatedController.userPresence), usage = "UserPresence", layout = "Button", bit = (uint)ControllerButton.UserPresence)] [FieldOffset(24)] public ushort buttons; /// /// Value representing the current battery life of this device. /// [InputControl(usage = "BatteryLevel", layout = "Axis")] [FieldOffset(26)] public float batteryLevel; /// /// Represents the values being tracked for this device. /// [InputControl(usage = "TrackingState", layout = "Integer")] [FieldOffset(30)] public int trackingState; /// /// Informs to the developer whether the device is currently being tracked. /// [InputControl(usage = "IsTracked", layout = "Button")] [FieldOffset(34)] public bool isTracked; /// /// The position of the device. /// [InputControl(usage = "DevicePosition")] [FieldOffset(35)] public Vector3 devicePosition; /// /// The rotation of this device. /// [InputControl(usage = "DeviceRotation")] [FieldOffset(47)] public Quaternion deviceRotation; /// /// Set the button mask for the given . /// /// Button whose state to set. /// Whether to set the bit on or off. /// The same with the change applied. /// public XRSimulatedControllerState WithButton(ControllerButton button, bool state = true) { var bit = 1 << (int)button; if (state) buttons |= (ushort)bit; else buttons &= (ushort)~bit; return this; } /// /// See . /// public void Reset() { primary2DAxis = default; trigger = default; grip = default; secondary2DAxis = default; buttons = default; batteryLevel = default; trackingState = default; isTracked = default; devicePosition = default; deviceRotation = Quaternion.identity; } } }