using System; using UnityEngine.SubsystemsImplementation; namespace UnityEngine.XR.ARSubsystems { /// /// Capabilities of a face subsystem implementation. /// [Flags] public enum FaceSubsystemCapabilities { /// /// The subsystem has no capabilities /// None = 0, /// /// The subsystem can produce a Pose for a face. /// Pose = 1 << 0, /// /// The subsystem can generate vertices and triangle indices for a mesh that represents a face. /// MeshVerticesAndIndices = 1 << 1, /// /// The subsystem can supply texture coordinates for a face mesh. /// MeshUVs = 1 << 2, /// /// The subsystem can supply normals for a face mesh. /// MeshNormals = 1 << 3, /// /// The subsystem can supply eye tracking data for a face. /// EyeTracking = 1 << 4 } /// /// This struct is an initializer for the creation of a . /// /// /// During InitializeOnLoad, the Face Tracking data provider should create a descriptor using /// the parameters here to specify which of the XRFaceSubsystem features it supports. /// public struct FaceSubsystemParams : IEquatable { /// /// The string identifier for a specific implementation. /// public string id { get; set; } /// /// Specifies the provider implementation type to use for instantiation. /// /// /// The provider implementation type to use for instantiation. /// public Type providerType { get; set; } /// /// Specifies the XRFaceSubsystem-derived type that forwards casted calls to its provider. /// /// /// The type of the subsystem to use for instantiation. If null, XRFaceSubsystem will be instantiated. /// public Type subsystemTypeOverride { get; set; } /// /// The concrete Type which will be instantiated if Create is called on this subsystem descriptor. /// [Obsolete("XRFaceSubsystem no longer supports the deprecated set of base classes for subsystems as of Unity 2020.2. Use providerType and, optionally, subsystemTypeOverride instead.", true)] public Type subsystemImplementationType { get; set; } /// /// Whether the subsystem supports getting a pose for the face. /// public bool supportsFacePose { get => (m_Capabilities & FaceSubsystemCapabilities.Pose) != 0; set { if (value) { m_Capabilities |= FaceSubsystemCapabilities.Pose; } else { m_Capabilities &= ~FaceSubsystemCapabilities.Pose; } } } /// /// Whether the subsystem supports getting vertices and triangle indices describing a face mesh. /// public bool supportsFaceMeshVerticesAndIndices { get => (m_Capabilities & FaceSubsystemCapabilities.MeshVerticesAndIndices) != 0; set { if (value) { m_Capabilities |= FaceSubsystemCapabilities.MeshVerticesAndIndices; } else { m_Capabilities &= ~FaceSubsystemCapabilities.MeshVerticesAndIndices; } } } /// /// Whether the subsystem supports texture coordinates for the face mesh. /// public bool supportsFaceMeshUVs { get => (m_Capabilities & FaceSubsystemCapabilities.MeshUVs) != 0; set { if (value) { m_Capabilities |= FaceSubsystemCapabilities.MeshUVs; } else { m_Capabilities &= ~FaceSubsystemCapabilities.MeshUVs; } } } /// /// Whether the subsystem supports normals for the face mesh. /// public bool supportsFaceMeshNormals { get => (m_Capabilities & FaceSubsystemCapabilities.MeshNormals) != 0; set { if (value) { m_Capabilities |= FaceSubsystemCapabilities.MeshNormals; } else { m_Capabilities &= ~FaceSubsystemCapabilities.MeshNormals; } } } /// /// Whether the subsystem supports eye tracking for each detected face. /// public bool supportsEyeTracking { get => (m_Capabilities & FaceSubsystemCapabilities.EyeTracking) != 0; set { if (value) { m_Capabilities |= FaceSubsystemCapabilities.EyeTracking; } else { m_Capabilities &= FaceSubsystemCapabilities.EyeTracking; } } } FaceSubsystemCapabilities m_Capabilities; /// /// Tests for equality. /// /// The other to compare against. /// `True` if every field in is equal to this , otherwise false. public bool Equals(FaceSubsystemParams other) { return m_Capabilities == other.m_Capabilities && ReferenceEquals(id, other.id) && ReferenceEquals(providerType, other.providerType) && ReferenceEquals(subsystemTypeOverride, other.subsystemTypeOverride); } /// /// Tests for equality. /// /// The `object` to compare against. /// `True` if is of type and /// also returns `true`; otherwise `false`. public override bool Equals(object obj) => (obj is FaceSubsystemParams) && Equals((FaceSubsystemParams)obj); /// /// Generates a hash suitable for use with containers like `HashSet` and `Dictionary`. /// /// A hash code generated from this object's fields. public override int GetHashCode() { unchecked { int hashCode = HashCodeUtil.ReferenceHash(id); hashCode = 486187739 * hashCode + HashCodeUtil.ReferenceHash(providerType); hashCode = 486187739 * hashCode + HashCodeUtil.ReferenceHash(subsystemTypeOverride); hashCode = 486187739 * hashCode + ((int)m_Capabilities).GetHashCode(); return hashCode; } } /// /// Tests for equality. Same as . /// /// The left-hand side of the comparison. /// The right-hand side of the comparison. /// `True` if is equal to , otherwise `false`. public static bool operator==(FaceSubsystemParams lhs, FaceSubsystemParams rhs) => lhs.Equals(rhs); /// /// Tests for inequality. Same as `!`. /// /// The left-hand side of the comparison. /// The right-hand side of the comparison. /// `True` if is not equal to , otherwise `false`. public static bool operator!=(FaceSubsystemParams lhs, FaceSubsystemParams rhs) => lhs.Equals(rhs); } /// /// The descriptor of the that shows which face tracking features are available on that XRSubsystem. /// /// /// Use the Create factory method along with struct to construct and /// register one of these from each face tracking data provider. /// public class XRFaceSubsystemDescriptor : SubsystemDescriptorWithProvider { XRFaceSubsystemDescriptor(FaceSubsystemParams descriptorParams) { id = descriptorParams.id; providerType = descriptorParams.providerType; subsystemTypeOverride = descriptorParams.subsystemTypeOverride; supportsFacePose = descriptorParams.supportsFacePose; supportsFaceMeshVerticesAndIndices = descriptorParams.supportsFaceMeshVerticesAndIndices; supportsFaceMeshUVs = descriptorParams.supportsFaceMeshUVs; supportsFaceMeshNormals = descriptorParams.supportsFaceMeshNormals; supportsEyeTracking = descriptorParams.supportsEyeTracking; } /// /// Whether the subsystem can produce a Pose for each detected face. /// public bool supportsFacePose { get; } /// /// Whether the subsystem supports face meshes and can produce vertices and triangle indices that represent a face mesh. /// public bool supportsFaceMeshVerticesAndIndices { get; } /// /// Whether the subsystem supports texture coordinates for each face mesh. /// public bool supportsFaceMeshUVs { get; } /// /// Whether the subsystem supports normals for each face mesh. /// public bool supportsFaceMeshNormals { get; } /// /// Whether the subsystem supports eye tracking for each detected face. /// public bool supportsEyeTracking { get; } /// /// Creates a subsystem descriptor. Used to register an implementation of the . /// /// Parameters describing the . public static void Create(FaceSubsystemParams descriptorParams) { var descriptor = new XRFaceSubsystemDescriptor(descriptorParams); SubsystemDescriptorStore.RegisterDescriptor(descriptor); } } }