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;
}
}
}