test
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 25ea971cc17caa84a8a2fdf9917af7b4
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,273 @@
|
||||
// ENABLE_VR is not defined on Game Core but the assembly is available with limited features when the XR module is enabled.
|
||||
#if UNITY_INPUT_SYSTEM_ENABLE_XR && (ENABLE_VR || UNITY_GAMECORE) && !UNITY_FORCE_INPUTSYSTEM_XR_OFF || PACKAGE_DOCS_GENERATION
|
||||
using System.Runtime.InteropServices;
|
||||
using Unity.Collections.LowLevel.Unsafe;
|
||||
using UnityEngine.InputSystem.Controls;
|
||||
using UnityEngine.InputSystem.Layouts;
|
||||
using UnityEngine.InputSystem.LowLevel;
|
||||
using UnityEngine.InputSystem.Utilities;
|
||||
using UnityEngine.Scripting;
|
||||
using TrackingState = UnityEngine.XR.InputTrackingState;
|
||||
|
||||
namespace UnityEngine.InputSystem.XR
|
||||
{
|
||||
/// <summary>
|
||||
/// State layout for a single pose.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is the low-level memory representation of a single pose, i.e the
|
||||
/// way poses are internally transmitted and stored in the system. PoseStates are used on devices containing <see cref="PoseControl"/>s.
|
||||
/// </remarks>
|
||||
/// <seealso cref="PoseControl"/>
|
||||
[StructLayout(LayoutKind.Explicit, Size = kSizeInBytes)]
|
||||
public struct PoseState : IInputStateTypeInfo
|
||||
{
|
||||
internal const int kSizeInBytes = 60;
|
||||
|
||||
internal static readonly FourCC s_Format = new FourCC('P', 'o', 's', 'e');
|
||||
|
||||
/// <summary>
|
||||
/// Memory format tag for PoseState.
|
||||
/// </summary>
|
||||
/// <value>Returns "Pose".</value>
|
||||
/// <seealso cref="InputStateBlock.format"/>
|
||||
public FourCC format => s_Format;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor for PoseStates.
|
||||
///
|
||||
/// Useful for creating PoseStates locally (not from <see cref="PoseControl"/>).
|
||||
/// </summary>
|
||||
/// <param name="isTracked">Value to use for <see cref="isTracked"/></param>
|
||||
/// <param name="trackingState">Value to use for <see cref="trackingState"/></param>
|
||||
/// <param name="position">Value to use for <see cref="position"/></param>
|
||||
/// <param name="rotation">Value to use for <see cref="rotation"/></param>
|
||||
/// <param name="velocity">Value to use for <see cref="velocity"/></param>
|
||||
/// <param name="angularVelocity">Value to use for <see cref="angularVelocity"/></param>
|
||||
public PoseState(bool isTracked, TrackingState trackingState, Vector3 position, Quaternion rotation, Vector3 velocity, Vector3 angularVelocity)
|
||||
{
|
||||
this.isTracked = isTracked;
|
||||
this.trackingState = trackingState;
|
||||
this.position = position;
|
||||
this.rotation = rotation;
|
||||
this.velocity = velocity;
|
||||
this.angularVelocity = angularVelocity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether the pose is currently being fully tracked. Otherwise, the tracking is either unavailable, or simulated.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Fully tracked means that the pose is accurate and not using any simulated or extrapolated positions, and the system tracking this pose is able to confidently track this object.
|
||||
/// </remarks>
|
||||
[FieldOffset(0), InputControl(displayName = "Is Tracked", layout = "Button", sizeInBits = 8 /* needed to ensure optimization kicks-in */)]
|
||||
public bool isTracked;
|
||||
|
||||
/// <summary>
|
||||
/// A Flags Enumeration specifying which other fields in the pose state are valid.
|
||||
/// </summary>
|
||||
[FieldOffset(4), InputControl(displayName = "Tracking State", layout = "Integer")]
|
||||
public TrackingState trackingState;
|
||||
|
||||
/// <summary>
|
||||
/// The position in 3D space, relative to the tracking origin where this pose represents.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Positions are represented in meters.
|
||||
/// This field is only valid if <see cref="trackingState"/> contains the <see cref="UnityEngine.XR.InputTrackingState.Position"/> value.
|
||||
/// See <seealso cref="UnityEngine.XR.TrackingOriginModeFlags"/> for information on tracking origins.
|
||||
/// </remarks>
|
||||
[FieldOffset(8), InputControl(displayName = "Position", noisy = true)]
|
||||
public Vector3 position;
|
||||
|
||||
/// <summary>
|
||||
/// The rotation in 3D space, relative to the tracking origin where this pose represents.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This field is only valid if <see cref="trackingState"/> contains the <see cref="UnityEngine.XR.InputTrackingState.Rotation"/> value.
|
||||
/// See <seealso cref="UnityEngine.XR.TrackingOriginModeFlags"/> for information on tracking origins.
|
||||
/// </remarks>
|
||||
[FieldOffset(20), InputControl(displayName = "Rotation", noisy = true)]
|
||||
public Quaternion rotation;
|
||||
|
||||
/// <summary>
|
||||
/// The velocity in 3D space, relative to the tracking origin where this pose represents.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Velocities are represented in meters per second.
|
||||
/// This field is only valid if <see cref="trackingState"/> contains the <see cref="UnityEngine.XR.InputTrackingState.Velocity"/> value.
|
||||
/// See <seealso cref="UnityEngine.XR.TrackingOriginModeFlags"/> for information on tracking origins.
|
||||
/// </remarks>
|
||||
[FieldOffset(36), InputControl(displayName = "Velocity", noisy = true)]
|
||||
public Vector3 velocity;
|
||||
|
||||
/// <summary>
|
||||
/// The angular velocity in 3D space, relative to the tracking origin where this pose represents.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This field is only valid if <see cref="trackingState"/> contains the <see cref="UnityEngine.XR.InputTrackingState.AngularVelocity"/> value.
|
||||
/// See <seealso cref="UnityEngine.XR.TrackingOriginModeFlags"/> for information on tracking origins.
|
||||
/// </remarks>
|
||||
[FieldOffset(48), InputControl(displayName = "Angular Velocity", noisy = true)]
|
||||
public Vector3 angularVelocity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A control representing a Pose in 3D space, relative to an XR tracking origin
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note that unlike most other control types, <c>PoseControls</c> do not have
|
||||
/// a flexible memory layout. They are hardwired to <see cref="PoseState"/> and
|
||||
/// will not work correctly with a different memory layouts. Additional fields may
|
||||
/// be appended to the struct but what's there in the struct has to be located
|
||||
/// at exactly those memory addresses.
|
||||
///
|
||||
/// For more information on tracking origins see <see cref="UnityEngine.XR.TrackingOriginModeFlags"/>.
|
||||
/// </remarks>
|
||||
[Preserve, InputControlLayout(stateType = typeof(PoseState))]
|
||||
public class PoseControl : InputControl<PoseState>
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents whether this pose is fully tracked or unavailable/simulated.
|
||||
/// </summary>
|
||||
/// <value>Control representing whether the pose is being fully tracked. Maps to the <see cref="PoseState.isTracked"/> value.</value>
|
||||
/// <seealso cref="PoseState.isTracked"/>
|
||||
public ButtonControl isTracked { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The other controls on this <see cref="PoseControl"/> that are currently reporting data.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This can be missing values when the device tracking this pose is restricted or not tracking properly.
|
||||
/// </remarks>
|
||||
/// <value>Control representing whether the pose is being fully tracked. Maps to the <see cref="PoseState.trackingState"/> value of the pose retrieved from this control.</value>
|
||||
/// <seealso cref="PoseState.trackingState"/>
|
||||
public IntegerControl trackingState { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The position, in meters, of this tracked pose relative to the tracking origin.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The data for this control is only valid if the value returned from <see cref="trackingState"/> contains <see cref="UnityEngine.XR.InputTrackingState.Position"/> value.
|
||||
/// </remarks>
|
||||
/// <value>Control representing whether the pose is being fully tracked. Maps to the <see cref="PoseState.position"/> value of the pose retrieved from this control.</value>
|
||||
/// <seealso cref="PoseState.position"/>
|
||||
public Vector3Control position { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The rotation of this tracked pose relative to the tracking origin.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The data for this control is only valid if the value returned from <see cref="trackingState"/> contains <see cref="UnityEngine.XR.InputTrackingState.Rotation"/> value.
|
||||
/// </remarks>
|
||||
/// <value>Control representing whether the pose is being fully tracked. Maps to the <see cref="PoseState.rotation"/> value of the pose retrieved from this control.</value>
|
||||
/// <seealso cref="PoseState.rotation"/>
|
||||
public QuaternionControl rotation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The velocity, in meters per second, of this tracked pose relative to the tracking origin.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The data for this control is only valid if the value returned from <see cref="trackingState"/> contains <see cref="UnityEngine.XR.InputTrackingState.Velocity"/> value.
|
||||
/// </remarks>
|
||||
/// <value>Control representing whether the pose is being fully tracked. Maps to the <see cref="PoseState.velocity"/> value of the pose retrieved from this control.</value>
|
||||
/// <seealso cref="PoseState.velocity"/>
|
||||
public Vector3Control velocity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The angular velocity of this tracked pose relative to the tracking origin.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The data for this control is only valid if the value returned from <see cref="trackingState"/> contains <see cref="UnityEngine.XR.InputTrackingState.AngularVelocity"/> value.
|
||||
/// </remarks>
|
||||
/// <value>Control representing whether the pose is being fully tracked. Maps to the <see cref="PoseState.angularVelocity"/> value of the pose retrieved from this control.</value>
|
||||
/// <seealso cref="PoseState.angularVelocity"/>
|
||||
public Vector3Control angularVelocity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Default-initialize the pose control.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Sets the <see cref="InputStateBlock.format"/> to <c>"Pose"</c>.
|
||||
/// </remarks>
|
||||
public PoseControl()
|
||||
{
|
||||
m_StateBlock.format = PoseState.s_Format;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void FinishSetup()
|
||||
{
|
||||
isTracked = GetChildControl<ButtonControl>("isTracked");
|
||||
trackingState = GetChildControl<IntegerControl>("trackingState");
|
||||
position = GetChildControl<Vector3Control>("position");
|
||||
rotation = GetChildControl<QuaternionControl>("rotation");
|
||||
velocity = GetChildControl<Vector3Control>("velocity");
|
||||
angularVelocity = GetChildControl<Vector3Control>("angularVelocity");
|
||||
|
||||
base.FinishSetup();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override unsafe PoseState ReadUnprocessedValueFromState(void* statePtr)
|
||||
{
|
||||
switch (m_OptimizedControlDataType)
|
||||
{
|
||||
case InputStateBlock.kFormatPose:
|
||||
return *(PoseState*)((byte*)statePtr + (int)m_StateBlock.byteOffset);
|
||||
default:
|
||||
return new PoseState()
|
||||
{
|
||||
isTracked = isTracked.ReadUnprocessedValueFromStateWithCaching(statePtr) > 0.5f,
|
||||
trackingState = (TrackingState)trackingState.ReadUnprocessedValueFromStateWithCaching(statePtr),
|
||||
position = position.ReadUnprocessedValueFromStateWithCaching(statePtr),
|
||||
rotation = rotation.ReadUnprocessedValueFromStateWithCaching(statePtr),
|
||||
velocity = velocity.ReadUnprocessedValueFromStateWithCaching(statePtr),
|
||||
angularVelocity = angularVelocity.ReadUnprocessedValueFromStateWithCaching(statePtr),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override unsafe void WriteValueIntoState(PoseState value, void* statePtr)
|
||||
{
|
||||
switch (m_OptimizedControlDataType)
|
||||
{
|
||||
case InputStateBlock.kFormatPose:
|
||||
*(PoseState*)((byte*)statePtr + (int)m_StateBlock.byteOffset) = value;
|
||||
break;
|
||||
default:
|
||||
isTracked.WriteValueIntoState(value.isTracked, statePtr);
|
||||
trackingState.WriteValueIntoState((uint)value.trackingState, statePtr);
|
||||
position.WriteValueIntoState(value.position, statePtr);
|
||||
rotation.WriteValueIntoState(value.rotation, statePtr);
|
||||
velocity.WriteValueIntoState(value.velocity, statePtr);
|
||||
angularVelocity.WriteValueIntoState(value.angularVelocity, statePtr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected override FourCC CalculateOptimizedControlDataType()
|
||||
{
|
||||
if (
|
||||
m_StateBlock.sizeInBits == PoseState.kSizeInBytes * 8 &&
|
||||
m_StateBlock.bitOffset == 0 &&
|
||||
isTracked.optimizedControlDataType == InputStateBlock.kFormatByte &&
|
||||
trackingState.optimizedControlDataType == InputStateBlock.kFormatInt &&
|
||||
position.optimizedControlDataType == InputStateBlock.kFormatVector3 &&
|
||||
rotation.optimizedControlDataType == InputStateBlock.kFormatQuaternion &&
|
||||
velocity.optimizedControlDataType == InputStateBlock.kFormatVector3 &&
|
||||
angularVelocity.optimizedControlDataType == InputStateBlock.kFormatVector3 &&
|
||||
trackingState.m_StateBlock.byteOffset == isTracked.m_StateBlock.byteOffset + 4 &&
|
||||
position.m_StateBlock.byteOffset == isTracked.m_StateBlock.byteOffset + 8 &&
|
||||
rotation.m_StateBlock.byteOffset == isTracked.m_StateBlock.byteOffset + 20 &&
|
||||
velocity.m_StateBlock.byteOffset == isTracked.m_StateBlock.byteOffset + 36 &&
|
||||
angularVelocity.m_StateBlock.byteOffset == isTracked.m_StateBlock.byteOffset + 48
|
||||
)
|
||||
return InputStateBlock.kFormatPose;
|
||||
|
||||
return InputStateBlock.kFormatInvalid;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 31038076760c2c744a116e944e0e18d7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7ada2e545c685b44a8367bdab267f0dc
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,65 @@
|
||||
// ENABLE_VR is not defined on Game Core but the assembly is available with limited features when the XR module is enabled.
|
||||
// Docs generation is skipped because these are intended to be replaced with the com.unity.xr.googlevr package.
|
||||
#if UNITY_INPUT_SYSTEM_ENABLE_XR && (ENABLE_VR || UNITY_GAMECORE) && !DISABLE_BUILTIN_INPUT_SYSTEM_GOOGLEVR && !UNITY_FORCE_INPUTSYSTEM_XR_OFF && !PACKAGE_DOCS_GENERATION
|
||||
using UnityEngine.InputSystem.Controls;
|
||||
using UnityEngine.InputSystem.Layouts;
|
||||
using UnityEngine.InputSystem.XR;
|
||||
|
||||
namespace Unity.XR.GoogleVr
|
||||
{
|
||||
/// <summary>
|
||||
/// A head-mounted display powered by Google Daydream.
|
||||
/// </summary>
|
||||
[InputControlLayout(displayName = "Daydream Headset", hideInUI = true)]
|
||||
public class DaydreamHMD : XRHMD
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An XR controller powered by Google Daydream.
|
||||
/// </summary>
|
||||
[InputControlLayout(displayName = "Daydream Controller", commonUsages = new[] { "LeftHand", "RightHand" }, hideInUI = true)]
|
||||
public class DaydreamController : XRController
|
||||
{
|
||||
[InputControl]
|
||||
public Vector2Control touchpad { get; protected set; }
|
||||
[InputControl]
|
||||
public ButtonControl volumeUp { get; protected set; }
|
||||
[InputControl]
|
||||
public ButtonControl recentered { get; protected set; }
|
||||
[InputControl]
|
||||
public ButtonControl volumeDown { get; protected set; }
|
||||
[InputControl]
|
||||
public ButtonControl recentering { get; protected set; }
|
||||
[InputControl]
|
||||
public ButtonControl app { get; protected set; }
|
||||
[InputControl]
|
||||
public ButtonControl home { get; protected set; }
|
||||
[InputControl]
|
||||
public ButtonControl touchpadClicked { get; protected set; }
|
||||
[InputControl]
|
||||
public ButtonControl touchpadTouched { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control deviceVelocity { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control deviceAcceleration { get; protected set; }
|
||||
|
||||
protected override void FinishSetup()
|
||||
{
|
||||
base.FinishSetup();
|
||||
|
||||
touchpad = GetChildControl<Vector2Control>("touchpad");
|
||||
volumeUp = GetChildControl<ButtonControl>("volumeUp");
|
||||
recentered = GetChildControl<ButtonControl>("recentered");
|
||||
volumeDown = GetChildControl<ButtonControl>("volumeDown");
|
||||
recentering = GetChildControl<ButtonControl>("recentering");
|
||||
app = GetChildControl<ButtonControl>("app");
|
||||
home = GetChildControl<ButtonControl>("home");
|
||||
touchpadClicked = GetChildControl<ButtonControl>("touchpadClicked");
|
||||
touchpadTouched = GetChildControl<ButtonControl>("touchpadTouched");
|
||||
deviceVelocity = GetChildControl<Vector3Control>("deviceVelocity");
|
||||
deviceAcceleration = GetChildControl<Vector3Control>("deviceAcceleration");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 44353112a58c73347adde914844b7642
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,241 @@
|
||||
// ENABLE_VR is not defined on Game Core but the assembly is available with limited features when the XR module is enabled.
|
||||
// Docs generation is skipped because these are intended to be replaced with the com.unity.xr.oculus package.
|
||||
#if UNITY_INPUT_SYSTEM_ENABLE_XR && (ENABLE_VR || UNITY_GAMECORE) && !DISABLE_BUILTIN_INPUT_SYSTEM_OCULUS && !UNITY_FORCE_INPUTSYSTEM_XR_OFF && !PACKAGE_DOCS_GENERATION
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.InputSystem.Controls;
|
||||
using UnityEngine.InputSystem.Layouts;
|
||||
using UnityEngine.InputSystem.XR;
|
||||
|
||||
namespace Unity.XR.Oculus.Input
|
||||
{
|
||||
/// <summary>
|
||||
/// An Oculus VR headset (such as the Oculus Rift series of devices).
|
||||
/// </summary>
|
||||
[InputControlLayout(displayName = "Oculus Headset", hideInUI = true)]
|
||||
public class OculusHMD : XRHMD
|
||||
{
|
||||
[InputControl]
|
||||
[InputControl(name = "trackingState", layout = "Integer", aliases = new[] { "devicetrackingstate" })]
|
||||
[InputControl(name = "isTracked", layout = "Button", aliases = new[] { "deviceistracked" })]
|
||||
public ButtonControl userPresence { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control deviceAngularVelocity { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control deviceAcceleration { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control deviceAngularAcceleration { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control leftEyeAngularVelocity { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control leftEyeAcceleration { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control leftEyeAngularAcceleration { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control rightEyeAngularVelocity { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control rightEyeAcceleration { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control rightEyeAngularAcceleration { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control centerEyeAngularVelocity { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control centerEyeAcceleration { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control centerEyeAngularAcceleration { get; protected set; }
|
||||
|
||||
|
||||
protected override void FinishSetup()
|
||||
{
|
||||
base.FinishSetup();
|
||||
|
||||
userPresence = GetChildControl<ButtonControl>("userPresence");
|
||||
deviceAngularVelocity = GetChildControl<Vector3Control>("deviceAngularVelocity");
|
||||
deviceAcceleration = GetChildControl<Vector3Control>("deviceAcceleration");
|
||||
deviceAngularAcceleration = GetChildControl<Vector3Control>("deviceAngularAcceleration");
|
||||
leftEyeAngularVelocity = GetChildControl<Vector3Control>("leftEyeAngularVelocity");
|
||||
leftEyeAcceleration = GetChildControl<Vector3Control>("leftEyeAcceleration");
|
||||
leftEyeAngularAcceleration = GetChildControl<Vector3Control>("leftEyeAngularAcceleration");
|
||||
rightEyeAngularVelocity = GetChildControl<Vector3Control>("rightEyeAngularVelocity");
|
||||
rightEyeAcceleration = GetChildControl<Vector3Control>("rightEyeAcceleration");
|
||||
rightEyeAngularAcceleration = GetChildControl<Vector3Control>("rightEyeAngularAcceleration");
|
||||
centerEyeAngularVelocity = GetChildControl<Vector3Control>("centerEyeAngularVelocity");
|
||||
centerEyeAcceleration = GetChildControl<Vector3Control>("centerEyeAcceleration");
|
||||
centerEyeAngularAcceleration = GetChildControl<Vector3Control>("centerEyeAngularAcceleration");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An Oculus Touch controller.
|
||||
/// </summary>
|
||||
[InputControlLayout(displayName = "Oculus Touch Controller", commonUsages = new[] { "LeftHand", "RightHand" }, hideInUI = true)]
|
||||
public class OculusTouchController : XRControllerWithRumble
|
||||
{
|
||||
[InputControl(aliases = new[] { "Primary2DAxis", "Joystick" })]
|
||||
public Vector2Control thumbstick { get; protected set; }
|
||||
|
||||
[InputControl]
|
||||
public AxisControl trigger { get; protected set; }
|
||||
[InputControl]
|
||||
public AxisControl grip { get; protected set; }
|
||||
|
||||
[InputControl(aliases = new[] { "A", "X", "Alternate" })]
|
||||
public ButtonControl primaryButton { get; protected set; }
|
||||
[InputControl(aliases = new[] { "B", "Y", "Primary" })]
|
||||
public ButtonControl secondaryButton { get; protected set; }
|
||||
[InputControl(aliases = new[] { "GripButton" })]
|
||||
public ButtonControl gripPressed { get; protected set; }
|
||||
[InputControl]
|
||||
public ButtonControl start { get; protected set; }
|
||||
[InputControl(aliases = new[] { "JoystickOrPadPressed", "thumbstickClick" })]
|
||||
public ButtonControl thumbstickClicked { get; protected set; }
|
||||
[InputControl(aliases = new[] { "ATouched", "XTouched", "ATouch", "XTouch" })]
|
||||
public ButtonControl primaryTouched { get; protected set; }
|
||||
[InputControl(aliases = new[] { "BTouched", "YTouched", "BTouch", "YTouch" })]
|
||||
public ButtonControl secondaryTouched { get; protected set; }
|
||||
[InputControl(aliases = new[] { "indexTouch", "indexNearTouched" })]
|
||||
public AxisControl triggerTouched { get; protected set; }
|
||||
[InputControl(aliases = new[] { "indexButton", "indexTouched" })]
|
||||
public ButtonControl triggerPressed { get; protected set; }
|
||||
[InputControl(aliases = new[] { "JoystickOrPadTouched", "thumbstickTouch" })]
|
||||
[InputControl(name = "trackingState", layout = "Integer", aliases = new[] { "controllerTrackingState" })]
|
||||
[InputControl(name = "isTracked", layout = "Button", aliases = new[] { "ControllerIsTracked" })]
|
||||
[InputControl(name = "devicePosition", layout = "Vector3", aliases = new[] { "controllerPosition" })]
|
||||
[InputControl(name = "deviceRotation", layout = "Quaternion", aliases = new[] { "controllerRotation" })]
|
||||
public ButtonControl thumbstickTouched { get; protected set; }
|
||||
[InputControl(noisy = true, aliases = new[] { "controllerVelocity" })]
|
||||
public Vector3Control deviceVelocity { get; protected set; }
|
||||
[InputControl(noisy = true, aliases = new[] { "controllerAngularVelocity" })]
|
||||
public Vector3Control deviceAngularVelocity { get; protected set; }
|
||||
[InputControl(noisy = true, aliases = new[] { "controllerAcceleration" })]
|
||||
public Vector3Control deviceAcceleration { get; protected set; }
|
||||
[InputControl(noisy = true, aliases = new[] { "controllerAngularAcceleration" })]
|
||||
public Vector3Control deviceAngularAcceleration { get; protected set; }
|
||||
|
||||
protected override void FinishSetup()
|
||||
{
|
||||
base.FinishSetup();
|
||||
|
||||
thumbstick = GetChildControl<Vector2Control>("thumbstick");
|
||||
trigger = GetChildControl<AxisControl>("trigger");
|
||||
triggerTouched = GetChildControl<AxisControl>("triggerTouched");
|
||||
grip = GetChildControl<AxisControl>("grip");
|
||||
|
||||
primaryButton = GetChildControl<ButtonControl>("primaryButton");
|
||||
secondaryButton = GetChildControl<ButtonControl>("secondaryButton");
|
||||
gripPressed = GetChildControl<ButtonControl>("gripPressed");
|
||||
start = GetChildControl<ButtonControl>("start");
|
||||
thumbstickClicked = GetChildControl<ButtonControl>("thumbstickClicked");
|
||||
primaryTouched = GetChildControl<ButtonControl>("primaryTouched");
|
||||
secondaryTouched = GetChildControl<ButtonControl>("secondaryTouched");
|
||||
thumbstickTouched = GetChildControl<ButtonControl>("thumbstickTouched");
|
||||
triggerPressed = GetChildControl<ButtonControl>("triggerPressed");
|
||||
|
||||
deviceVelocity = GetChildControl<Vector3Control>("deviceVelocity");
|
||||
deviceAngularVelocity = GetChildControl<Vector3Control>("deviceAngularVelocity");
|
||||
deviceAcceleration = GetChildControl<Vector3Control>("deviceAcceleration");
|
||||
deviceAngularAcceleration = GetChildControl<Vector3Control>("deviceAngularAcceleration");
|
||||
}
|
||||
}
|
||||
|
||||
public class OculusTrackingReference : TrackedDevice
|
||||
{
|
||||
[InputControl(aliases = new[] { "trackingReferenceTrackingState" })]
|
||||
public new IntegerControl trackingState { get; protected set; }
|
||||
[InputControl(aliases = new[] { "trackingReferenceIsTracked" })]
|
||||
public new ButtonControl isTracked { get; protected set; }
|
||||
|
||||
protected override void FinishSetup()
|
||||
{
|
||||
base.FinishSetup();
|
||||
|
||||
trackingState = GetChildControl<IntegerControl>("trackingState");
|
||||
isTracked = GetChildControl<ButtonControl>("isTracked");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An Oculus Remote controller.
|
||||
/// </summary>
|
||||
[InputControlLayout(displayName = "Oculus Remote", hideInUI = true)]
|
||||
public class OculusRemote : InputDevice
|
||||
{
|
||||
[InputControl]
|
||||
public ButtonControl back { get; protected set; }
|
||||
[InputControl]
|
||||
public ButtonControl start { get; protected set; }
|
||||
[InputControl]
|
||||
public Vector2Control touchpad { get; protected set; }
|
||||
|
||||
protected override void FinishSetup()
|
||||
{
|
||||
base.FinishSetup();
|
||||
|
||||
back = GetChildControl<ButtonControl>("back");
|
||||
start = GetChildControl<ButtonControl>("start");
|
||||
touchpad = GetChildControl<Vector2Control>("touchpad");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A Standalone VR headset that includes on-headset controls.
|
||||
/// </summary>
|
||||
[InputControlLayout(displayName = "Oculus Headset (w/ on-headset controls)", hideInUI = true)]
|
||||
public class OculusHMDExtended : OculusHMD
|
||||
{
|
||||
[InputControl]
|
||||
public ButtonControl back { get; protected set; }
|
||||
[InputControl]
|
||||
public Vector2Control touchpad { get; protected set; }
|
||||
|
||||
protected override void FinishSetup()
|
||||
{
|
||||
base.FinishSetup();
|
||||
|
||||
back = GetChildControl<ButtonControl>("back");
|
||||
touchpad = GetChildControl<Vector2Control>("touchpad");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A Gear VR controller.
|
||||
/// </summary>
|
||||
[InputControlLayout(displayName = "GearVR Controller", commonUsages = new[] { "LeftHand", "RightHand" }, hideInUI = true)]
|
||||
public class GearVRTrackedController : XRController
|
||||
{
|
||||
[InputControl]
|
||||
public Vector2Control touchpad { get; protected set; }
|
||||
[InputControl]
|
||||
public AxisControl trigger { get; protected set; }
|
||||
[InputControl]
|
||||
public ButtonControl back { get; protected set; }
|
||||
[InputControl]
|
||||
public ButtonControl triggerPressed { get; protected set; }
|
||||
[InputControl]
|
||||
public ButtonControl touchpadClicked { get; protected set; }
|
||||
[InputControl]
|
||||
public ButtonControl touchpadTouched { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control deviceAngularVelocity { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control deviceAcceleration { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control deviceAngularAcceleration { get; protected set; }
|
||||
|
||||
protected override void FinishSetup()
|
||||
{
|
||||
base.FinishSetup();
|
||||
|
||||
touchpad = GetChildControl<Vector2Control>("touchpad");
|
||||
trigger = GetChildControl<AxisControl>("trigger");
|
||||
back = GetChildControl<ButtonControl>("back");
|
||||
triggerPressed = GetChildControl<ButtonControl>("triggerPressed");
|
||||
touchpadClicked = GetChildControl<ButtonControl>("touchpadClicked");
|
||||
touchpadTouched = GetChildControl<ButtonControl>("touchpadTouched");
|
||||
|
||||
deviceAngularVelocity = GetChildControl<Vector3Control>("deviceAngularVelocity");
|
||||
deviceAcceleration = GetChildControl<Vector3Control>("deviceAcceleration");
|
||||
deviceAngularAcceleration = GetChildControl<Vector3Control>("deviceAngularAcceleration");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 150936adb4fc13049a1001992b86c43e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,251 @@
|
||||
// ENABLE_VR is not defined on Game Core but the assembly is available with limited features when the XR module is enabled.
|
||||
// Docs generation is skipped because these are intended to be replaced with the com.unity.xr.openvr package.
|
||||
#if UNITY_INPUT_SYSTEM_ENABLE_XR && (ENABLE_VR || UNITY_GAMECORE) && !DISABLE_BUILTIN_INPUT_SYSTEM_OPENVR && !UNITY_FORCE_INPUTSYSTEM_XR_OFF && !PACKAGE_DOCS_GENERATION
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.InputSystem.Controls;
|
||||
using UnityEngine.InputSystem.Layouts;
|
||||
using UnityEngine.InputSystem.XR;
|
||||
|
||||
namespace Unity.XR.OpenVR
|
||||
{
|
||||
[InputControlLayout(displayName = "OpenVR Headset", hideInUI = true)]
|
||||
public class OpenVRHMD : XRHMD
|
||||
{
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control deviceVelocity { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control deviceAngularVelocity { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control leftEyeVelocity { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control leftEyeAngularVelocity { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control rightEyeVelocity { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control rightEyeAngularVelocity { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control centerEyeVelocity { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control centerEyeAngularVelocity { get; protected set; }
|
||||
|
||||
protected override void FinishSetup()
|
||||
{
|
||||
base.FinishSetup();
|
||||
|
||||
deviceVelocity = GetChildControl<Vector3Control>("deviceVelocity");
|
||||
deviceAngularVelocity = GetChildControl<Vector3Control>("deviceAngularVelocity");
|
||||
leftEyeVelocity = GetChildControl<Vector3Control>("leftEyeVelocity");
|
||||
leftEyeAngularVelocity = GetChildControl<Vector3Control>("leftEyeAngularVelocity");
|
||||
rightEyeVelocity = GetChildControl<Vector3Control>("rightEyeVelocity");
|
||||
rightEyeAngularVelocity = GetChildControl<Vector3Control>("rightEyeAngularVelocity");
|
||||
centerEyeVelocity = GetChildControl<Vector3Control>("centerEyeVelocity");
|
||||
centerEyeAngularVelocity = GetChildControl<Vector3Control>("centerEyeAngularVelocity");
|
||||
}
|
||||
}
|
||||
|
||||
[InputControlLayout(displayName = "Windows MR Controller (OpenVR)", commonUsages = new[] { "LeftHand", "RightHand" }, hideInUI = true)]
|
||||
public class OpenVRControllerWMR : XRController
|
||||
{
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control deviceVelocity { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control deviceAngularVelocity { get; protected set; }
|
||||
|
||||
[InputControl(aliases = new[] { "primary2DAxisClick", "joystickOrPadPressed" })]
|
||||
public ButtonControl touchpadClick { get; protected set; }
|
||||
[InputControl(aliases = new[] { "primary2DAxisTouch", "joystickOrPadTouched" })]
|
||||
public ButtonControl touchpadTouch { get; protected set; }
|
||||
[InputControl]
|
||||
public ButtonControl gripPressed { get; protected set; }
|
||||
[InputControl]
|
||||
public ButtonControl triggerPressed { get; protected set; }
|
||||
[InputControl(aliases = new[] { "primary" })]
|
||||
public ButtonControl menu { get; protected set; }
|
||||
|
||||
[InputControl]
|
||||
public AxisControl trigger { get; protected set; }
|
||||
[InputControl]
|
||||
public AxisControl grip { get; protected set; }
|
||||
|
||||
[InputControl(aliases = new[] { "secondary2DAxis" })]
|
||||
public Vector2Control touchpad { get; protected set; }
|
||||
[InputControl(aliases = new[] { "primary2DAxis" })]
|
||||
public Vector2Control joystick { get; protected set; }
|
||||
|
||||
protected override void FinishSetup()
|
||||
{
|
||||
base.FinishSetup();
|
||||
|
||||
deviceVelocity = GetChildControl<Vector3Control>("deviceVelocity");
|
||||
deviceAngularVelocity = GetChildControl<Vector3Control>("deviceAngularVelocity");
|
||||
|
||||
touchpadClick = GetChildControl<ButtonControl>("touchpadClick");
|
||||
touchpadTouch = GetChildControl<ButtonControl>("touchpadTouch");
|
||||
gripPressed = GetChildControl<ButtonControl>("gripPressed");
|
||||
triggerPressed = GetChildControl<ButtonControl>("triggerPressed");
|
||||
menu = GetChildControl<ButtonControl>("menu");
|
||||
|
||||
trigger = GetChildControl<AxisControl>("trigger");
|
||||
grip = GetChildControl<AxisControl>("grip");
|
||||
|
||||
touchpad = GetChildControl<Vector2Control>("touchpad");
|
||||
joystick = GetChildControl<Vector2Control>("joystick");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An HTC Vive Wand controller.
|
||||
/// </summary>
|
||||
[InputControlLayout(displayName = "Vive Wand", commonUsages = new[] { "LeftHand", "RightHand" }, hideInUI = true)]
|
||||
public class ViveWand : XRControllerWithRumble
|
||||
{
|
||||
[InputControl]
|
||||
public AxisControl grip { get; protected set; }
|
||||
[InputControl]
|
||||
public ButtonControl gripPressed { get; protected set; }
|
||||
[InputControl]
|
||||
public ButtonControl primary { get; protected set; }
|
||||
[InputControl(aliases = new[] { "primary2DAxisClick", "joystickOrPadPressed" })]
|
||||
public ButtonControl trackpadPressed { get; protected set; }
|
||||
[InputControl(aliases = new[] { "primary2DAxisTouch", "joystickOrPadTouched" })]
|
||||
public ButtonControl trackpadTouched { get; protected set; }
|
||||
[InputControl(aliases = new[] { "Primary2DAxis" })]
|
||||
public Vector2Control trackpad { get; protected set; }
|
||||
[InputControl]
|
||||
public AxisControl trigger { get; protected set; }
|
||||
[InputControl]
|
||||
public ButtonControl triggerPressed { get; protected set; }
|
||||
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control deviceVelocity { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control deviceAngularVelocity { get; protected set; }
|
||||
|
||||
protected override void FinishSetup()
|
||||
{
|
||||
base.FinishSetup();
|
||||
|
||||
grip = GetChildControl<AxisControl>("grip");
|
||||
primary = GetChildControl<ButtonControl>("primary");
|
||||
gripPressed = GetChildControl<ButtonControl>("gripPressed");
|
||||
trackpadPressed = GetChildControl<ButtonControl>("trackpadPressed");
|
||||
trackpadTouched = GetChildControl<ButtonControl>("trackpadTouched");
|
||||
trackpad = GetChildControl<Vector2Control>("trackpad");
|
||||
trigger = GetChildControl<AxisControl>("trigger");
|
||||
triggerPressed = GetChildControl<ButtonControl>("triggerPressed");
|
||||
|
||||
deviceVelocity = GetChildControl<Vector3Control>("deviceVelocity");
|
||||
deviceAngularVelocity = GetChildControl<Vector3Control>("deviceAngularVelocity");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An HTC Vive lighthouse.
|
||||
/// </summary>
|
||||
[InputControlLayout(displayName = "Vive Lighthouse", hideInUI = true)]
|
||||
public class ViveLighthouse : TrackedDevice
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An HTC Vive tracker.
|
||||
/// </summary>
|
||||
[InputControlLayout(displayName = "Vive Tracker")]
|
||||
public class ViveTracker : TrackedDevice
|
||||
{
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control deviceVelocity { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control deviceAngularVelocity { get; protected set; }
|
||||
|
||||
protected override void FinishSetup()
|
||||
{
|
||||
base.FinishSetup();
|
||||
|
||||
deviceVelocity = GetChildControl<Vector3Control>("deviceVelocity");
|
||||
deviceAngularVelocity = GetChildControl<Vector3Control>("deviceAngularVelocity");
|
||||
}
|
||||
}
|
||||
|
||||
[InputControlLayout(displayName = "Handed Vive Tracker", commonUsages = new[] { "LeftHand", "RightHand" }, hideInUI = true)]
|
||||
public class HandedViveTracker : ViveTracker
|
||||
{
|
||||
[InputControl]
|
||||
public AxisControl grip { get; protected set; }
|
||||
[InputControl]
|
||||
public ButtonControl gripPressed { get; protected set; }
|
||||
[InputControl]
|
||||
public ButtonControl primary { get; protected set; }
|
||||
[InputControl(aliases = new[] { "JoystickOrPadPressed" })]
|
||||
public ButtonControl trackpadPressed { get; protected set; }
|
||||
[InputControl]
|
||||
public ButtonControl triggerPressed { get; protected set; }
|
||||
|
||||
protected override void FinishSetup()
|
||||
{
|
||||
grip = GetChildControl<AxisControl>("grip");
|
||||
primary = GetChildControl<ButtonControl>("primary");
|
||||
gripPressed = GetChildControl<ButtonControl>("gripPressed");
|
||||
trackpadPressed = GetChildControl<ButtonControl>("trackpadPressed");
|
||||
triggerPressed = GetChildControl<ButtonControl>("triggerPressed");
|
||||
|
||||
base.FinishSetup();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An Oculus Touch controller.
|
||||
/// </summary>
|
||||
[InputControlLayout(displayName = "Oculus Touch Controller (OpenVR)", commonUsages = new[] { "LeftHand", "RightHand" }, hideInUI = true)]
|
||||
public class OpenVROculusTouchController : XRControllerWithRumble
|
||||
{
|
||||
[InputControl]
|
||||
public Vector2Control thumbstick { get; protected set; }
|
||||
|
||||
[InputControl]
|
||||
public AxisControl trigger { get; protected set; }
|
||||
[InputControl]
|
||||
public AxisControl grip { get; protected set; }
|
||||
|
||||
// Primary & Secondary are switched in order to retain consistency with the Oculus SDK
|
||||
[InputControl(aliases = new[] { "Alternate" })]
|
||||
public ButtonControl primaryButton { get; protected set; }
|
||||
[InputControl(aliases = new[] { "Primary" })]
|
||||
public ButtonControl secondaryButton { get; protected set; }
|
||||
|
||||
[InputControl]
|
||||
public ButtonControl gripPressed { get; protected set; }
|
||||
[InputControl]
|
||||
public ButtonControl triggerPressed { get; protected set; }
|
||||
[InputControl(aliases = new[] { "primary2DAxisClicked" })]
|
||||
public ButtonControl thumbstickClicked { get; protected set; }
|
||||
[InputControl(aliases = new[] { "primary2DAxisTouch" })]
|
||||
public ButtonControl thumbstickTouched { get; protected set; }
|
||||
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control deviceVelocity { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control deviceAngularVelocity { get; protected set; }
|
||||
|
||||
protected override void FinishSetup()
|
||||
{
|
||||
base.FinishSetup();
|
||||
|
||||
thumbstick = GetChildControl<Vector2Control>("thumbstick");
|
||||
|
||||
trigger = GetChildControl<AxisControl>("trigger");
|
||||
grip = GetChildControl<AxisControl>("grip");
|
||||
|
||||
primaryButton = GetChildControl<ButtonControl>("primaryButton");
|
||||
secondaryButton = GetChildControl<ButtonControl>("secondaryButton");
|
||||
gripPressed = GetChildControl<ButtonControl>("gripPressed");
|
||||
thumbstickClicked = GetChildControl<ButtonControl>("thumbstickClicked");
|
||||
thumbstickTouched = GetChildControl<ButtonControl>("thumbstickTouched");
|
||||
triggerPressed = GetChildControl<ButtonControl>("triggerPressed");
|
||||
|
||||
deviceVelocity = GetChildControl<Vector3Control>("deviceVelocity");
|
||||
deviceAngularVelocity = GetChildControl<Vector3Control>("deviceAngularVelocity");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8a2cdc9fdde66bb49afa0763a7557ff9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,118 @@
|
||||
// ENABLE_VR is not defined on Game Core but the assembly is available with limited features when the XR module is enabled.
|
||||
// Docs generation is skipped because these are intended to be replaced with the com.unity.xr.windowsmr package.
|
||||
#if UNITY_INPUT_SYSTEM_ENABLE_XR && (ENABLE_VR || UNITY_GAMECORE) && !DISABLE_BUILTIN_INPUT_SYSTEM_WINDOWSMR && !UNITY_FORCE_INPUTSYSTEM_XR_OFF && !PACKAGE_DOCS_GENERATION
|
||||
using UnityEngine.InputSystem.Controls;
|
||||
using UnityEngine.InputSystem.Layouts;
|
||||
using UnityEngine.InputSystem.XR;
|
||||
|
||||
namespace UnityEngine.XR.WindowsMR.Input
|
||||
{
|
||||
/// <summary>
|
||||
/// A Windows Mixed Reality XR headset.
|
||||
/// </summary>
|
||||
[InputControlLayout(displayName = "Windows MR Headset", hideInUI = true)]
|
||||
public class WMRHMD : XRHMD
|
||||
{
|
||||
[InputControl]
|
||||
[InputControl(name = "devicePosition", layout = "Vector3", aliases = new[] { "HeadPosition" })]
|
||||
[InputControl(name = "deviceRotation", layout = "Quaternion", aliases = new[] { "HeadRotation" })]
|
||||
public ButtonControl userPresence { get; protected set; }
|
||||
|
||||
protected override void FinishSetup()
|
||||
{
|
||||
base.FinishSetup();
|
||||
|
||||
userPresence = GetChildControl<ButtonControl>("userPresence");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A Windows Mixed Reality XR controller.
|
||||
/// </summary>
|
||||
[InputControlLayout(displayName = "HoloLens Hand", commonUsages = new[] { "LeftHand", "RightHand" }, hideInUI = true)]
|
||||
public class HololensHand : XRController
|
||||
{
|
||||
[InputControl(noisy = true, aliases = new[] { "gripVelocity" })]
|
||||
public Vector3Control deviceVelocity { get; protected set; }
|
||||
[InputControl(aliases = new[] { "triggerbutton" })]
|
||||
public ButtonControl airTap { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public AxisControl sourceLossRisk { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control sourceLossMitigationDirection { get; protected set; }
|
||||
|
||||
protected override void FinishSetup()
|
||||
{
|
||||
base.FinishSetup();
|
||||
|
||||
airTap = GetChildControl<ButtonControl>("airTap");
|
||||
deviceVelocity = GetChildControl<Vector3Control>("deviceVelocity");
|
||||
sourceLossRisk = GetChildControl<AxisControl>("sourceLossRisk");
|
||||
sourceLossMitigationDirection = GetChildControl<Vector3Control>("sourceLossMitigationDirection");
|
||||
}
|
||||
}
|
||||
|
||||
[InputControlLayout(displayName = "Windows MR Controller", commonUsages = new[] { "LeftHand", "RightHand" }, hideInUI = true)]
|
||||
public class WMRSpatialController : XRControllerWithRumble
|
||||
{
|
||||
[InputControl(aliases = new[] { "Primary2DAxis", "thumbstickaxes" })]
|
||||
public Vector2Control joystick { get; protected set; }
|
||||
[InputControl(aliases = new[] { "Secondary2DAxis", "touchpadaxes" })]
|
||||
public Vector2Control touchpad { get; protected set; }
|
||||
[InputControl(aliases = new[] { "gripaxis" })]
|
||||
public AxisControl grip { get; protected set; }
|
||||
[InputControl(aliases = new[] { "gripbutton" })]
|
||||
public ButtonControl gripPressed { get; protected set; }
|
||||
[InputControl(aliases = new[] { "Primary", "menubutton" })]
|
||||
public ButtonControl menu { get; protected set; }
|
||||
[InputControl(aliases = new[] { "triggeraxis" })]
|
||||
public AxisControl trigger { get; protected set; }
|
||||
[InputControl(aliases = new[] { "triggerbutton" })]
|
||||
public ButtonControl triggerPressed { get; protected set; }
|
||||
[InputControl(aliases = new[] { "thumbstickpressed" })]
|
||||
public ButtonControl joystickClicked { get; protected set; }
|
||||
[InputControl(aliases = new[] { "joystickorpadpressed", "touchpadpressed" })]
|
||||
public ButtonControl touchpadClicked { get; protected set; }
|
||||
[InputControl(aliases = new[] { "joystickorpadtouched", "touchpadtouched" })]
|
||||
public ButtonControl touchpadTouched { get; protected set; }
|
||||
[InputControl(noisy = true, aliases = new[] { "gripVelocity" })]
|
||||
public Vector3Control deviceVelocity { get; protected set; }
|
||||
[InputControl(noisy = true, aliases = new[] { "gripAngularVelocity" })]
|
||||
public Vector3Control deviceAngularVelocity { get; protected set; }
|
||||
|
||||
[InputControl(noisy = true)]
|
||||
public AxisControl batteryLevel { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public AxisControl sourceLossRisk { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control sourceLossMitigationDirection { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control pointerPosition { get; protected set; }
|
||||
[InputControl(noisy = true, aliases = new[] { "PointerOrientation" })]
|
||||
public QuaternionControl pointerRotation { get; protected set; }
|
||||
|
||||
protected override void FinishSetup()
|
||||
{
|
||||
base.FinishSetup();
|
||||
joystick = GetChildControl<Vector2Control>("joystick");
|
||||
trigger = GetChildControl<AxisControl>("trigger");
|
||||
touchpad = GetChildControl<Vector2Control>("touchpad");
|
||||
grip = GetChildControl<AxisControl>("grip");
|
||||
gripPressed = GetChildControl<ButtonControl>("gripPressed");
|
||||
menu = GetChildControl<ButtonControl>("menu");
|
||||
joystickClicked = GetChildControl<ButtonControl>("joystickClicked");
|
||||
triggerPressed = GetChildControl<ButtonControl>("triggerPressed");
|
||||
touchpadClicked = GetChildControl<ButtonControl>("touchpadClicked");
|
||||
touchpadTouched = GetChildControl<ButtonControl>("touchPadTouched");
|
||||
deviceVelocity = GetChildControl<Vector3Control>("deviceVelocity");
|
||||
deviceAngularVelocity = GetChildControl<Vector3Control>("deviceAngularVelocity");
|
||||
|
||||
batteryLevel = GetChildControl<AxisControl>("batteryLevel");
|
||||
sourceLossRisk = GetChildControl<AxisControl>("sourceLossRisk");
|
||||
sourceLossMitigationDirection = GetChildControl<Vector3Control>("sourceLossMitigationDirection");
|
||||
pointerPosition = GetChildControl<Vector3Control>("pointerPosition");
|
||||
pointerRotation = GetChildControl<QuaternionControl>("pointerRotation");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9231fc068a549684f8ece75b66d6095b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,129 @@
|
||||
// ENABLE_VR is not defined on Game Core but the assembly is available with limited features when the XR module is enabled.
|
||||
#if UNITY_INPUT_SYSTEM_ENABLE_XR && (ENABLE_VR || UNITY_GAMECORE) && !UNITY_FORCE_INPUTSYSTEM_XR_OFF || PACKAGE_DOCS_GENERATION
|
||||
using UnityEngine.InputSystem.Controls;
|
||||
using UnityEngine.InputSystem.XR.Haptics;
|
||||
using UnityEngine.InputSystem.Layouts;
|
||||
using UnityEngine.XR;
|
||||
|
||||
namespace UnityEngine.InputSystem.XR
|
||||
{
|
||||
[InputControlLayout(isGenericTypeOfDevice = true, displayName = "XR HMD", canRunInBackground = true)]
|
||||
public class XRHMD : TrackedDevice
|
||||
{
|
||||
/// <summary>
|
||||
/// The base type of all XR head mounted displays. This can help organize shared behaviour across all HMDs.
|
||||
/// </summary>
|
||||
///
|
||||
/// <remarks>
|
||||
///
|
||||
/// To give your head tracking an extra update before rendering:
|
||||
/// First, enable before render updates on your Device.
|
||||
///
|
||||
/// <sample>
|
||||
/// <code>
|
||||
/// // JSON
|
||||
/// {
|
||||
/// "name" : "MyHMD",
|
||||
/// "extend" : "HMD",
|
||||
/// "beforeRender" : "Update"
|
||||
/// }
|
||||
/// </code>
|
||||
/// </sample>
|
||||
///
|
||||
/// Then, make sure you put extra `StateEvents` for your HMD on the queue right in time before rendering. Also, if your HMD is a combination of non-tracking and tracking controls, you can update just the tracking by sending a delta event instead of a full state event.
|
||||
///
|
||||
/// </remarks>
|
||||
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control leftEyePosition { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public QuaternionControl leftEyeRotation { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control rightEyePosition { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public QuaternionControl rightEyeRotation { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public Vector3Control centerEyePosition { get; protected set; }
|
||||
[InputControl(noisy = true)]
|
||||
public QuaternionControl centerEyeRotation { get; protected set; }
|
||||
|
||||
protected override void FinishSetup()
|
||||
{
|
||||
base.FinishSetup();
|
||||
|
||||
centerEyePosition = GetChildControl<Vector3Control>("centerEyePosition");
|
||||
centerEyeRotation = GetChildControl<QuaternionControl>("centerEyeRotation");
|
||||
leftEyePosition = GetChildControl<Vector3Control>("leftEyePosition");
|
||||
leftEyeRotation = GetChildControl<QuaternionControl>("leftEyeRotation");
|
||||
rightEyePosition = GetChildControl<Vector3Control>("rightEyePosition");
|
||||
rightEyeRotation = GetChildControl<QuaternionControl>("rightEyeRotation");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The base type for all XR handed controllers.
|
||||
/// </summary>
|
||||
[InputControlLayout(commonUsages = new[] { "LeftHand", "RightHand" }, isGenericTypeOfDevice = true, displayName = "XR Controller")]
|
||||
public class XRController : TrackedDevice
|
||||
{
|
||||
/// <summary>
|
||||
/// A quick accessor for the currently active left handed device.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If there is no left hand connected, this will be null.
|
||||
/// This also matches any currently tracked device that contains the 'LeftHand' device usage.
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// // To set up an Action to specifically target
|
||||
/// // the left-hand XR controller:
|
||||
///
|
||||
/// var action = new InputAction(binding: "/<XRController>{leftHand}/position");
|
||||
/// </code>
|
||||
/// </example>
|
||||
///
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// // To make the left-hand XR controller behave like the right-hand one
|
||||
/// var controller = XRController.leftHand;
|
||||
/// InputSystem.SetUsage(controller, CommonUsages.RightHand);
|
||||
/// </code>
|
||||
/// </example>
|
||||
/// </remarks>
|
||||
public static XRController leftHand => InputSystem.GetDevice<XRController>(CommonUsages.LeftHand);
|
||||
|
||||
/// <summary>
|
||||
/// A quick accessor for the currently active right handed device. This is also tracked via usages on the device.
|
||||
/// </summary>
|
||||
/// <remarks>If there is no left hand connected, this will be null. This also matches any currently tracked device that contains the 'RightHand' device usage.</remarks>
|
||||
public static XRController rightHand => InputSystem.GetDevice<XRController>(CommonUsages.RightHand);
|
||||
|
||||
protected override void FinishSetup()
|
||||
{
|
||||
base.FinishSetup();
|
||||
|
||||
var capabilities = description.capabilities;
|
||||
var deviceDescriptor = XRDeviceDescriptor.FromJson(capabilities);
|
||||
|
||||
if (deviceDescriptor != null)
|
||||
{
|
||||
if ((deviceDescriptor.characteristics & InputDeviceCharacteristics.Left) != 0)
|
||||
InputSystem.SetDeviceUsage(this, CommonUsages.LeftHand);
|
||||
else if ((deviceDescriptor.characteristics & InputDeviceCharacteristics.Right) != 0)
|
||||
InputSystem.SetDeviceUsage(this, CommonUsages.RightHand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Identifies a controller that is capable of rumble or haptics.
|
||||
/// </summary>
|
||||
public class XRControllerWithRumble : XRController
|
||||
{
|
||||
public void SendImpulse(float amplitude, float duration)
|
||||
{
|
||||
var command = SendHapticImpulseCommand.Create(0, amplitude, duration);
|
||||
ExecuteCommand(ref command);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 929bef69d71fe4223b4148865a0a5e42
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8529451a1ee99484a891bdea2f5219f3
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,29 @@
|
||||
// ENABLE_VR is not defined on Game Core but the assembly is available with limited features when the XR module is enabled.
|
||||
#if UNITY_INPUT_SYSTEM_ENABLE_XR && (ENABLE_VR || UNITY_GAMECORE) || PACKAGE_DOCS_GENERATION
|
||||
namespace UnityEngine.InputSystem.XR.Haptics
|
||||
{
|
||||
public struct BufferedRumble
|
||||
{
|
||||
public HapticCapabilities capabilities { get; private set; }
|
||||
InputDevice device { get; set; }
|
||||
|
||||
public BufferedRumble(InputDevice device)
|
||||
{
|
||||
if (device == null)
|
||||
throw new System.ArgumentNullException(nameof(device));
|
||||
|
||||
this.device = device;
|
||||
|
||||
var command = GetHapticCapabilitiesCommand.Create();
|
||||
device.ExecuteCommand(ref command);
|
||||
capabilities = command.capabilities;
|
||||
}
|
||||
|
||||
public void EnqueueRumble(byte[] samples)
|
||||
{
|
||||
var command = SendBufferedHapticCommand.Create(samples);
|
||||
device.ExecuteCommand(ref command);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f1e8cf3dc2c11ed47a2666fcf0d3a938
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,50 @@
|
||||
// ENABLE_VR is not defined on Game Core but the assembly is available with limited features when the XR module is enabled.
|
||||
#if UNITY_INPUT_SYSTEM_ENABLE_XR && (ENABLE_VR || UNITY_GAMECORE) || PACKAGE_DOCS_GENERATION
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine.InputSystem.LowLevel;
|
||||
using UnityEngine.InputSystem.Utilities;
|
||||
|
||||
namespace UnityEngine.InputSystem.XR.Haptics
|
||||
{
|
||||
public struct HapticState
|
||||
{
|
||||
public HapticState(uint samplesQueued, uint samplesAvailable)
|
||||
{
|
||||
this.samplesQueued = samplesQueued;
|
||||
this.samplesAvailable = samplesAvailable;
|
||||
}
|
||||
|
||||
public uint samplesQueued { get; private set; }
|
||||
public uint samplesAvailable { get; private set; }
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Size = kSize)]
|
||||
public struct GetCurrentHapticStateCommand : IInputDeviceCommandInfo
|
||||
{
|
||||
static FourCC Type => new FourCC('X', 'H', 'S', '0');
|
||||
|
||||
const int kSize = InputDeviceCommand.kBaseCommandSize + (sizeof(uint) * 2);
|
||||
|
||||
public FourCC typeStatic => Type;
|
||||
|
||||
[FieldOffset(0)]
|
||||
InputDeviceCommand baseCommand;
|
||||
|
||||
[FieldOffset(InputDeviceCommand.kBaseCommandSize)]
|
||||
public uint samplesQueued;
|
||||
|
||||
[FieldOffset(InputDeviceCommand.kBaseCommandSize + sizeof(int))]
|
||||
public uint samplesAvailable;
|
||||
|
||||
public HapticState currentState => new HapticState(samplesQueued, samplesAvailable);
|
||||
|
||||
public static GetCurrentHapticStateCommand Create()
|
||||
{
|
||||
return new GetCurrentHapticStateCommand
|
||||
{
|
||||
baseCommand = new InputDeviceCommand(Type, kSize),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0049e966b9953774fa3d07808a5555a9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,159 @@
|
||||
// ENABLE_VR is not defined on Game Core but the assembly is available with limited features when the XR module is enabled.
|
||||
#if UNITY_INPUT_SYSTEM_ENABLE_XR && (ENABLE_VR || UNITY_GAMECORE) || PACKAGE_DOCS_GENERATION
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine.InputSystem.LowLevel;
|
||||
using UnityEngine.InputSystem.Utilities;
|
||||
|
||||
namespace UnityEngine.InputSystem.XR.Haptics
|
||||
{
|
||||
/// <summary>
|
||||
/// Describes the haptic capabilities of a specific device.
|
||||
/// </summary>
|
||||
public struct HapticCapabilities
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes and returns an instance of <see cref="HapticCapabilities"/>.
|
||||
/// </summary>
|
||||
/// <param name="numChannels">The number of haptic channels available on this device.</param>
|
||||
/// <param name="supportsImpulse">This device supports sending a haptic impulse.</param>
|
||||
/// <param name="supportsBuffer">This device supports sending a haptic buffer.</param>
|
||||
/// <param name="frequencyHz">The buffer frequency the device operates at in Hertz.</param>
|
||||
/// <param name="maxBufferSize">The max amount of buffer data that can be stored by the device.</param>
|
||||
/// <param name="optimalBufferSize">The optimal size of a device's buffer, taking into account frequency and latency.</param>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deprecated. Use <see cref="HapticCapabilities(uint, bool, bool, uint, uint, uint)"/> instead.
|
||||
/// This constructor did not match the native haptic capabilities struct and was missing properties.
|
||||
/// </summary>
|
||||
/// <param name="numChannels">The number of haptic channels available on this device.</param>
|
||||
/// <param name="frequencyHz">The buffer frequency the device operates at in Hertz.</param>
|
||||
/// <param name="maxBufferSize">The max amount of buffer data that can be stored by the device.</param>
|
||||
public HapticCapabilities(uint numChannels, uint frequencyHz, uint maxBufferSize)
|
||||
: this(numChannels, false, false, frequencyHz, maxBufferSize, 0U)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The number of haptic channels available on this device.
|
||||
/// </summary>
|
||||
public uint numChannels { get; }
|
||||
|
||||
/// <summary>
|
||||
/// This device supports sending a haptic impulse.
|
||||
/// </summary>
|
||||
/// <seealso cref="SendHapticImpulseCommand"/>
|
||||
public bool supportsImpulse { get; }
|
||||
|
||||
/// <summary>
|
||||
/// This device supports sending a haptic buffer.
|
||||
/// </summary>
|
||||
/// <seealso cref="SendBufferedHapticCommand"/>
|
||||
public bool supportsBuffer { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The buffer frequency the device operates at in Hertz. This impacts how fast the device consumes buffered haptic data.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This value is greater than 0 if <see cref="supportsBuffer"/> is <see langword="true"/>, and 0 otherwise.
|
||||
/// </remarks>
|
||||
public uint frequencyHz { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The max amount of buffer data that can be stored by the device.
|
||||
/// </summary>
|
||||
public uint maxBufferSize { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The optimal size of a device's buffer, taking into account frequency and latency.
|
||||
/// </summary>
|
||||
public uint optimalBufferSize { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Input device command struct for retrieving the haptic capabilities of a device.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Explicit, Size = kSize)]
|
||||
public struct GetHapticCapabilitiesCommand : IInputDeviceCommandInfo
|
||||
{
|
||||
static FourCC Type => new FourCC('X', 'H', 'C', '0');
|
||||
|
||||
// 20 bytes of data from uint(4) + bool(1) + bool(1) + padding + uint(4) + uint(4) + uint(4)
|
||||
const int kSize = InputDeviceCommand.kBaseCommandSize + 20;
|
||||
|
||||
/// <inheritdoc />
|
||||
public FourCC typeStatic => Type;
|
||||
|
||||
[FieldOffset(0)]
|
||||
InputDeviceCommand baseCommand;
|
||||
|
||||
/// <summary>
|
||||
/// The number of haptic channels available on this device.
|
||||
/// </summary>
|
||||
[FieldOffset(InputDeviceCommand.kBaseCommandSize)]
|
||||
public uint numChannels;
|
||||
|
||||
/// <summary>
|
||||
/// This device supports sending a haptic impulse.
|
||||
/// </summary>
|
||||
/// <seealso cref="SendHapticImpulseCommand"/>
|
||||
[FieldOffset(InputDeviceCommand.kBaseCommandSize + 4)]
|
||||
public bool supportsImpulse;
|
||||
|
||||
/// <summary>
|
||||
/// This device supports sending a haptic buffer.
|
||||
/// </summary>
|
||||
/// <seealso cref="SendBufferedHapticCommand"/>
|
||||
[FieldOffset(InputDeviceCommand.kBaseCommandSize + 5)]
|
||||
public bool supportsBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// The buffer frequency the device operates at in Hertz. This impacts how fast the device consumes buffered haptic data.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This value is greater than 0 if <see cref="supportsBuffer"/> is <see langword="true"/>, and 0 otherwise.
|
||||
/// </remarks>
|
||||
[FieldOffset(InputDeviceCommand.kBaseCommandSize + 8)]
|
||||
public uint frequencyHz;
|
||||
|
||||
/// <summary>
|
||||
/// The max amount of buffer data that can be stored by the device.
|
||||
/// </summary>
|
||||
[FieldOffset(InputDeviceCommand.kBaseCommandSize + 12)]
|
||||
public uint maxBufferSize;
|
||||
|
||||
/// <summary>
|
||||
/// The optimal size of a device's buffer, taking into account frequency and latency.
|
||||
/// </summary>
|
||||
[FieldOffset(InputDeviceCommand.kBaseCommandSize + 16)]
|
||||
public uint optimalBufferSize;
|
||||
|
||||
/// <summary>
|
||||
/// The haptic capabilities of the device, populated after this command is executed.
|
||||
/// </summary>
|
||||
public HapticCapabilities capabilities => new HapticCapabilities(numChannels, supportsImpulse, supportsBuffer, frequencyHz, maxBufferSize, optimalBufferSize);
|
||||
|
||||
/// <summary>
|
||||
/// Creates and returns a new initialized input device command struct for retrieving
|
||||
/// the haptic capabilities of a device when executed.
|
||||
/// </summary>
|
||||
/// <returns>Returns a new command struct with the data header initialized, making it ready to execute.</returns>
|
||||
/// <seealso cref="InputDevice.ExecuteCommand{TCommand}(ref TCommand)"/>
|
||||
public static GetHapticCapabilitiesCommand Create()
|
||||
{
|
||||
return new GetHapticCapabilitiesCommand
|
||||
{
|
||||
baseCommand = new InputDeviceCommand(Type, kSize),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2ade21199e79d394ab34f4e6887f1c09
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,56 @@
|
||||
// ENABLE_VR is not defined on Game Core but the assembly is available with limited features when the XR module is enabled.
|
||||
#if UNITY_INPUT_SYSTEM_ENABLE_XR && (ENABLE_VR || UNITY_GAMECORE) || PACKAGE_DOCS_GENERATION
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine.InputSystem.LowLevel;
|
||||
using UnityEngine.InputSystem.Utilities;
|
||||
|
||||
namespace UnityEngine.InputSystem.XR.Haptics
|
||||
{
|
||||
[StructLayout(LayoutKind.Explicit, Size = kSize)]
|
||||
public unsafe struct SendBufferedHapticCommand : IInputDeviceCommandInfo
|
||||
{
|
||||
static FourCC Type => new FourCC('X', 'H', 'U', '0');
|
||||
|
||||
private const int kMaxHapticBufferSize = 1024;
|
||||
private const int kSize = InputDeviceCommand.kBaseCommandSize + (sizeof(int) * 2) + (kMaxHapticBufferSize * sizeof(byte));
|
||||
|
||||
public FourCC typeStatic => Type;
|
||||
|
||||
[FieldOffset(0)]
|
||||
private InputDeviceCommand baseCommand;
|
||||
|
||||
[FieldOffset(InputDeviceCommand.kBaseCommandSize)]
|
||||
private int channel;
|
||||
|
||||
[FieldOffset(InputDeviceCommand.kBaseCommandSize + sizeof(int))]
|
||||
private int bufferSize;
|
||||
|
||||
[FieldOffset(InputDeviceCommand.kBaseCommandSize + (sizeof(int) * 2))]
|
||||
private fixed byte buffer[kMaxHapticBufferSize];
|
||||
|
||||
public static SendBufferedHapticCommand Create(byte[] rumbleBuffer)
|
||||
{
|
||||
if (rumbleBuffer == null)
|
||||
throw new System.ArgumentNullException(nameof(rumbleBuffer));
|
||||
|
||||
var rumbleBufferSize = Mathf.Min(kMaxHapticBufferSize, rumbleBuffer.Length);
|
||||
var newCommand = new SendBufferedHapticCommand
|
||||
{
|
||||
baseCommand = new InputDeviceCommand(Type, kSize),
|
||||
bufferSize = rumbleBufferSize
|
||||
};
|
||||
|
||||
//TODO TOMB: There must be a more effective, bulk copy operation for fixed buffers than this.
|
||||
//Replace if found.
|
||||
var commandPtr = &newCommand;
|
||||
fixed(byte* src = rumbleBuffer)
|
||||
{
|
||||
for (int cpyIndex = 0; cpyIndex < rumbleBufferSize; cpyIndex++)
|
||||
commandPtr->buffer[cpyIndex] = src[cpyIndex];
|
||||
}
|
||||
|
||||
return newCommand;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e553fed0b97be3349aff36916eb6fefc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,53 @@
|
||||
// ENABLE_VR is not defined on Game Core but the assembly is available with limited features when the XR module is enabled.
|
||||
#if UNITY_INPUT_SYSTEM_ENABLE_XR && (ENABLE_VR || UNITY_GAMECORE) || PACKAGE_DOCS_GENERATION
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine.InputSystem.LowLevel;
|
||||
using UnityEngine.InputSystem.Utilities;
|
||||
|
||||
namespace UnityEngine.InputSystem.XR.Haptics
|
||||
{
|
||||
/// <summary>
|
||||
/// A device command sent to a device to set it's motor rumble amplitude for a set duration.
|
||||
/// </summary>
|
||||
/// <remarks>This is directly used by the <see cref="XRControllerWithRumble"/> class. For clearer details of using this command, see that class.</remarks>
|
||||
[StructLayout(LayoutKind.Explicit, Size = kSize)]
|
||||
public struct SendHapticImpulseCommand : IInputDeviceCommandInfo
|
||||
{
|
||||
static FourCC Type => new FourCC('X', 'H', 'I', '0');
|
||||
|
||||
private const int kSize = InputDeviceCommand.kBaseCommandSize + sizeof(int) + (sizeof(float) * 2);
|
||||
|
||||
[FieldOffset(0)]
|
||||
InputDeviceCommand baseCommand;
|
||||
|
||||
[FieldOffset(InputDeviceCommand.kBaseCommandSize)]
|
||||
private int channel;
|
||||
|
||||
[FieldOffset(InputDeviceCommand.kBaseCommandSize + sizeof(int))]
|
||||
private float amplitude;
|
||||
|
||||
[FieldOffset(InputDeviceCommand.kBaseCommandSize + sizeof(int) + (sizeof(float)))]
|
||||
private float duration;
|
||||
|
||||
public FourCC typeStatic => Type;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a device command that can then be sent to a specific device.
|
||||
/// </summary>
|
||||
/// <param name="motorChannel">The desired motor you want to rumble</param>
|
||||
/// <param name="motorAmplitude">The desired motor amplitude that should be within a [0-1] range.</param>
|
||||
/// <param name="motorDuration">The desired duration of the impulse in seconds.</param>
|
||||
/// <returns>The command that should be sent to the device via <c>InputDevice.ExecuteCommand</c>.</returns>
|
||||
public static SendHapticImpulseCommand Create(int motorChannel, float motorAmplitude, float motorDuration)
|
||||
{
|
||||
return new SendHapticImpulseCommand
|
||||
{
|
||||
baseCommand = new InputDeviceCommand(Type, kSize),
|
||||
channel = motorChannel,
|
||||
amplitude = motorAmplitude,
|
||||
duration = motorDuration
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5f84d6a1bd34ea6428fa1db0e9f459cb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c2fadf230d1919748a9aa21d40f74619
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 7b8bfaee8f8631c4789ac62373cbc2d4, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,344 @@
|
||||
// ENABLE_VR is not defined on Game Core but the assembly is available with limited features when the XR module is enabled.
|
||||
#if UNITY_INPUT_SYSTEM_ENABLE_XR && (ENABLE_VR || UNITY_GAMECORE) && !UNITY_FORCE_INPUTSYSTEM_XR_OFF
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.InputSystem.LowLevel;
|
||||
using UnityEngine.InputSystem.Utilities;
|
||||
using System.Text;
|
||||
using UnityEngine.InputSystem.Layouts;
|
||||
using UnityEngine.XR;
|
||||
|
||||
namespace UnityEngine.InputSystem.XR
|
||||
{
|
||||
internal class XRLayoutBuilder
|
||||
{
|
||||
private string parentLayout;
|
||||
private string interfaceName;
|
||||
private XRDeviceDescriptor descriptor;
|
||||
|
||||
private static uint GetSizeOfFeature(XRFeatureDescriptor featureDescriptor)
|
||||
{
|
||||
switch (featureDescriptor.featureType)
|
||||
{
|
||||
case FeatureType.Binary:
|
||||
return sizeof(byte);
|
||||
case FeatureType.DiscreteStates:
|
||||
return sizeof(int);
|
||||
case FeatureType.Axis1D:
|
||||
return sizeof(float);
|
||||
case FeatureType.Axis2D:
|
||||
return sizeof(float) * 2;
|
||||
case FeatureType.Axis3D:
|
||||
return sizeof(float) * 3;
|
||||
case FeatureType.Rotation:
|
||||
return sizeof(float) * 4;
|
||||
case FeatureType.Hand:
|
||||
return sizeof(uint) * 26;
|
||||
case FeatureType.Bone:
|
||||
return sizeof(uint) + (sizeof(float) * 3) + (sizeof(float) * 4);
|
||||
case FeatureType.Eyes:
|
||||
return (sizeof(float) * 3) * 3 + ((sizeof(float) * 4) * 2) + (sizeof(float) * 2);
|
||||
case FeatureType.Custom:
|
||||
return featureDescriptor.customSize;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static string SanitizeString(string original, bool allowPaths = false)
|
||||
{
|
||||
var stringLength = original.Length;
|
||||
var sanitizedName = new StringBuilder(stringLength);
|
||||
for (var i = 0; i < stringLength; i++)
|
||||
{
|
||||
var letter = original[i];
|
||||
if (char.IsUpper(letter) || char.IsLower(letter) || char.IsDigit(letter) || letter == '_' || (allowPaths && (letter == '/')))
|
||||
{
|
||||
sanitizedName.Append(letter);
|
||||
}
|
||||
}
|
||||
return sanitizedName.ToString();
|
||||
}
|
||||
|
||||
internal static string OnFindLayoutForDevice(ref InputDeviceDescription description, string matchedLayout,
|
||||
InputDeviceExecuteCommandDelegate executeCommandDelegate)
|
||||
{
|
||||
// If the device isn't a XRInput, we're not interested.
|
||||
if (description.interfaceName != XRUtilities.InterfaceCurrent && description.interfaceName != XRUtilities.InterfaceV1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// If the description doesn't come with a XR SDK descriptor, we're not
|
||||
// interested either.
|
||||
if (string.IsNullOrEmpty(description.capabilities))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Try to parse the XR descriptor.
|
||||
XRDeviceDescriptor deviceDescriptor;
|
||||
try
|
||||
{
|
||||
deviceDescriptor = XRDeviceDescriptor.FromJson(description.capabilities);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (deviceDescriptor == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(matchedLayout))
|
||||
{
|
||||
const InputDeviceCharacteristics controllerCharacteristics = InputDeviceCharacteristics.HeldInHand | InputDeviceCharacteristics.Controller;
|
||||
if ((deviceDescriptor.characteristics & InputDeviceCharacteristics.HeadMounted) != 0)
|
||||
matchedLayout = "XRHMD";
|
||||
else if ((deviceDescriptor.characteristics & controllerCharacteristics) == controllerCharacteristics)
|
||||
matchedLayout = "XRController";
|
||||
}
|
||||
|
||||
string layoutName;
|
||||
if (string.IsNullOrEmpty(description.manufacturer))
|
||||
{
|
||||
layoutName = $"{SanitizeString(description.interfaceName)}::{SanitizeString(description.product)}";
|
||||
}
|
||||
else
|
||||
{
|
||||
layoutName =
|
||||
$"{SanitizeString(description.interfaceName)}::{SanitizeString(description.manufacturer)}::{SanitizeString(description.product)}";
|
||||
}
|
||||
|
||||
var layout = new XRLayoutBuilder { descriptor = deviceDescriptor, parentLayout = matchedLayout, interfaceName = description.interfaceName };
|
||||
InputSystem.RegisterLayoutBuilder(() => layout.Build(), layoutName, matchedLayout);
|
||||
|
||||
return layoutName;
|
||||
}
|
||||
|
||||
private static string ConvertPotentialAliasToName(InputControlLayout layout, string nameOrAlias)
|
||||
{
|
||||
var internedNameOrAlias = new InternedString(nameOrAlias);
|
||||
var controls = layout.controls;
|
||||
for (var i = 0; i < controls.Count; i++)
|
||||
{
|
||||
var controlItem = controls[i];
|
||||
|
||||
if (controlItem.name == internedNameOrAlias)
|
||||
return nameOrAlias;
|
||||
|
||||
var aliases = controlItem.aliases;
|
||||
for (var j = 0; j < aliases.Count; j++)
|
||||
{
|
||||
if (aliases[j] == nameOrAlias)
|
||||
return controlItem.name.ToString();
|
||||
}
|
||||
}
|
||||
return nameOrAlias;
|
||||
}
|
||||
|
||||
private bool IsSubControl(string name)
|
||||
{
|
||||
return name.Contains('/');
|
||||
}
|
||||
|
||||
private string GetParentControlName(string name)
|
||||
{
|
||||
int idx = name.IndexOf('/');
|
||||
return name.Substring(0, idx);
|
||||
}
|
||||
|
||||
static readonly string[] poseSubControlNames =
|
||||
{
|
||||
"/isTracked",
|
||||
"/trackingState",
|
||||
"/position",
|
||||
"/rotation",
|
||||
"/velocity",
|
||||
"/angularVelocity"
|
||||
};
|
||||
|
||||
static readonly FeatureType[] poseSubControlTypes =
|
||||
{
|
||||
FeatureType.Binary,
|
||||
FeatureType.DiscreteStates,
|
||||
FeatureType.Axis3D,
|
||||
FeatureType.Rotation,
|
||||
FeatureType.Axis3D,
|
||||
FeatureType.Axis3D
|
||||
};
|
||||
|
||||
// A PoseControl consists of 6 subcontrols with specific names and types
|
||||
private bool IsPoseControl(List<XRFeatureDescriptor> features, int startIndex)
|
||||
{
|
||||
for (var i = 0; i < 6; i++)
|
||||
{
|
||||
if (!features[startIndex + i].name.EndsWith(poseSubControlNames[i]) ||
|
||||
features[startIndex + i].featureType != poseSubControlTypes[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private InputControlLayout Build()
|
||||
{
|
||||
var builder = new InputControlLayout.Builder
|
||||
{
|
||||
stateFormat = new FourCC('X', 'R', 'S', '0'),
|
||||
extendsLayout = parentLayout,
|
||||
updateBeforeRender = true
|
||||
};
|
||||
|
||||
var inheritedLayout = !string.IsNullOrEmpty(parentLayout)
|
||||
? InputSystem.LoadLayout(parentLayout)
|
||||
: null;
|
||||
|
||||
var parentControls = new List<string>();
|
||||
var currentUsages = new List<string>();
|
||||
|
||||
uint currentOffset = 0;
|
||||
for (var i = 0; i < descriptor.inputFeatures.Count; i++)
|
||||
{
|
||||
var feature = descriptor.inputFeatures[i];
|
||||
currentUsages.Clear();
|
||||
|
||||
if (feature.usageHints != null)
|
||||
{
|
||||
foreach (var usageHint in feature.usageHints)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(usageHint.content))
|
||||
currentUsages.Add(usageHint.content);
|
||||
}
|
||||
}
|
||||
|
||||
var featureName = feature.name;
|
||||
featureName = SanitizeString(featureName, true);
|
||||
if (inheritedLayout != null)
|
||||
featureName = ConvertPotentialAliasToName(inheritedLayout, featureName);
|
||||
|
||||
featureName = featureName.ToLower();
|
||||
|
||||
if (IsSubControl(featureName))
|
||||
{
|
||||
string parentControl = GetParentControlName(featureName);
|
||||
if (!parentControls.Contains(parentControl))
|
||||
{
|
||||
if (IsPoseControl(descriptor.inputFeatures, i))
|
||||
{
|
||||
builder.AddControl(parentControl)
|
||||
.WithLayout("Pose")
|
||||
.WithByteOffset(0);
|
||||
parentControls.Add(parentControl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint nextOffset = GetSizeOfFeature(feature);
|
||||
if (interfaceName == XRUtilities.InterfaceV1)
|
||||
{
|
||||
#if UNITY_ANDROID
|
||||
if (nextOffset < 4)
|
||||
nextOffset = 4;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nextOffset >= 4 && (currentOffset % 4 != 0))
|
||||
currentOffset += (4 - (currentOffset % 4));
|
||||
}
|
||||
|
||||
|
||||
switch (feature.featureType)
|
||||
{
|
||||
case FeatureType.Binary:
|
||||
{
|
||||
builder.AddControl(featureName)
|
||||
.WithLayout("Button")
|
||||
.WithByteOffset(currentOffset)
|
||||
.WithFormat(InputStateBlock.FormatBit)
|
||||
.WithUsages(currentUsages);
|
||||
break;
|
||||
}
|
||||
case FeatureType.DiscreteStates:
|
||||
{
|
||||
builder.AddControl(featureName)
|
||||
.WithLayout("Integer")
|
||||
.WithByteOffset(currentOffset)
|
||||
.WithFormat(InputStateBlock.FormatInt)
|
||||
.WithUsages(currentUsages);
|
||||
break;
|
||||
}
|
||||
case FeatureType.Axis1D:
|
||||
{
|
||||
builder.AddControl(featureName)
|
||||
.WithLayout("Analog")
|
||||
.WithRange(-1, 1)
|
||||
.WithByteOffset(currentOffset)
|
||||
.WithFormat(InputStateBlock.FormatFloat)
|
||||
.WithUsages(currentUsages);
|
||||
break;
|
||||
}
|
||||
case FeatureType.Axis2D:
|
||||
{
|
||||
builder.AddControl(featureName)
|
||||
.WithLayout("Stick")
|
||||
.WithByteOffset(currentOffset)
|
||||
.WithFormat(InputStateBlock.FormatVector2)
|
||||
.WithUsages(currentUsages);
|
||||
|
||||
builder.AddControl(featureName + "/x")
|
||||
.WithLayout("Analog")
|
||||
.WithRange(-1, 1);
|
||||
builder.AddControl(featureName + "/y")
|
||||
.WithLayout("Analog")
|
||||
.WithRange(-1, 1);
|
||||
break;
|
||||
}
|
||||
case FeatureType.Axis3D:
|
||||
{
|
||||
builder.AddControl(featureName)
|
||||
.WithLayout("Vector3")
|
||||
.WithByteOffset(currentOffset)
|
||||
.WithFormat(InputStateBlock.FormatVector3)
|
||||
.WithUsages(currentUsages);
|
||||
break;
|
||||
}
|
||||
case FeatureType.Rotation:
|
||||
{
|
||||
builder.AddControl(featureName)
|
||||
.WithLayout("Quaternion")
|
||||
.WithByteOffset(currentOffset)
|
||||
.WithFormat(InputStateBlock.FormatQuaternion)
|
||||
.WithUsages(currentUsages);
|
||||
break;
|
||||
}
|
||||
case FeatureType.Hand:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case FeatureType.Bone:
|
||||
{
|
||||
builder.AddControl(featureName)
|
||||
.WithLayout("Bone")
|
||||
.WithByteOffset(currentOffset)
|
||||
.WithUsages(currentUsages);
|
||||
break;
|
||||
}
|
||||
case FeatureType.Eyes:
|
||||
{
|
||||
builder.AddControl(featureName)
|
||||
.WithLayout("Eyes")
|
||||
.WithByteOffset(currentOffset)
|
||||
.WithUsages(currentUsages);
|
||||
break;
|
||||
}
|
||||
}
|
||||
currentOffset += nextOffset;
|
||||
}
|
||||
|
||||
return builder.Build();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f06ed8c4023b8420784a262e45338aa3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a9be5e04bc92741ccbe2c262bfaa517f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user