Files
adriadri6972 d3d9c5f833 upload project
2025-07-31 15:21:08 +02:00

430 lines
19 KiB
C#

using System;
using System.Collections.Generic;
namespace UnityEngine.XR.ARSubsystems
{
/// <summary>
/// A set of flags that represent features available in AR.
/// </summary>
[Flags]
public enum Feature : ulong
{
/// <summary>
/// No features are selected.
/// </summary>
None = 0,
/// <summary>
/// The world-facing camera. On a phone, this is the rear camera.
/// </summary>
WorldFacingCamera = 1 << 0,
/// <summary>
/// The user-facing camera. On a phone, this is the front camera.
/// </summary>
UserFacingCamera = 1 << 1,
/// <summary>
/// Either camera (<see cref="WorldFacingCamera"/> or <see cref="UserFacingCamera"/>).
/// </summary>
AnyCamera = WorldFacingCamera | UserFacingCamera,
/// <summary>
/// Rotation-only tracking (that is, 3 degrees of freedom without positional tracking).
/// </summary>
RotationOnly = 1 << 2,
/// <summary>
/// Both position and rotation tracking (that is, 6 degrees of freedom).
/// </summary>
PositionAndRotation = 1 << 3,
/// <summary>
/// Any tracking mode (<see cref="RotationOnly"/> or <see cref="PositionAndRotation"/>).
/// </summary>
AnyTrackingMode = RotationOnly | PositionAndRotation,
/// <summary>
/// Face detection. See <see cref="XRFaceSubsystem"/>.
/// </summary>
FaceTracking = 1 << 4,
/// <summary>
/// Plane detection. See <see cref="XRPlaneSubsystem"/>.
/// </summary>
PlaneTracking = 1 << 5,
/// <summary>
/// Image detection. See <see cref="XRImageTrackingSubsystem"/>.
/// </summary>
ImageTracking = 1 << 6,
/// <summary>
/// 3D object detection. See <see cref="XRObjectTrackingSubsystem"/>.
/// </summary>
ObjectTracking = 1 << 7,
/// <summary>
/// Environment probes. See <see cref="XREnvironmentProbeSubsystem"/>.
/// </summary>
EnvironmentProbes = 1 << 8,
/// <summary>
/// 2D human body tracking. See <see cref="XRHumanBodySubsystem"/>.
/// </summary>
Body2D = 1 << 9,
/// <summary>
/// 3D human body tracking. See <see cref="XRHumanBodySubsystem"/>.
/// </summary>
Body3D = 1 << 10,
/// <summary>
/// Estimate scale when performing 3D human body tracking. See <see cref="Body3D"/>.
/// </summary>
Body3DScaleEstimation = 1 << 11,
/// <summary>
/// People occlusion with stencil texture enabled. See <see cref="XROcclusionSubsystem"/>.
/// </summary>
PeopleOcclusionStencil = 1 << 12,
/// <summary>
/// People occlusion with depth texture enabled. See <see cref="XROcclusionSubsystem"/>.
/// </summary>
PeopleOcclusionDepth = 1 << 13,
/// <summary>
/// Collaborative session. See <see cref="XRParticipantSubsystem"/>.
/// </summary>
Collaboration = 1 << 14,
/// <summary>
/// Auto focus enabled.
/// </summary>
AutoFocus = 1 << 15,
/// <summary>
/// Light estimation for ambient intensity.
/// </summary>
LightEstimationAmbientIntensity = 1 << 16,
/// <summary>
/// Light estimation for ambient color.
/// </summary>
LightEstimationAmbientColor = 1 << 17,
/// <summary>
/// Light estimation for ambient spherical harmonics.
/// </summary>
LightEstimationAmbientSphericalHarmonics = 1 << 18,
/// <summary>
/// Light estimation for the main light's direction.
/// </summary>
LightEstimationMainLightDirection = 1 << 19,
/// <summary>
/// Light estimation for the main light's intensity.
/// </summary>
LightEstimationMainLightIntensity = 1 << 20,
/// <summary>
/// A value with all light estimation related bits set.
/// </summary>
AnyLightEstimation = LightEstimationAmbientIntensity | LightEstimationAmbientColor | LightEstimationAmbientSphericalHarmonics | LightEstimationMainLightDirection | LightEstimationMainLightIntensity,
/// <summary>
/// Instant and Tracked raycasts.
/// </summary>
Raycast = 1 << 21,
/// <summary>
/// A feature that describes real-time meshing capability.
/// </summary>
Meshing = 1 << 22,
/// <summary>
/// A feature that describes classification for <see cref="Meshing"/>.
/// </summary>
MeshClassification = 1 << 23,
/// <summary>
/// A feature that describes the ability to surface point clouds.
/// </summary>
PointCloud = 1 << 24,
/// <summary>
/// A feature that allows environment depth images to be captured.
/// </summary>
EnvironmentDepth = 1 << 25,
/// <summary>
/// A feature that applies temporal smoothing to environment depth images.
/// </summary>
/// <seealso cref="EnvironmentDepth"/>
EnvironmentDepthTemporalSmoothing = 1 << 26,
/// <summary>
/// Image Stabilization enabled.
/// </summary>
ImageStabilization = 1 << 27,
/// <summary>
/// Camera torch mode enabled.
/// </summary>
CameraTorch = 1 << 28,
}
/// <summary>
/// Extension methods for <see cref="Feature"/> flags.
/// </summary>
public static class FeatureExtensions
{
/// <summary>
/// Tests whether any of the features in <paramref name="features"/> are present in <paramref name="self"/>.
/// </summary>
/// <param name="self">The <see cref="Feature"/> being extended.</param>
/// <param name="features">The Features to test against.</param>
/// <returns><c>true</c> if any of the features in <paramref name="features"/> are also in <paramref name="self"/>,
/// otherwise <c>false</c>.</returns>
public static bool Any(this Feature self, Feature features) => (self & features) != Feature.None;
/// <summary>
/// Tests whether all the features in <paramref name="features"/> are present in <paramref name="self"/>.
/// </summary>
/// <param name="self">The <see cref="Feature"/> being extended.</param>
/// <param name="features">The Features to test against.</param>
/// <returns><c>true</c> if all the features in <paramref name="features"/> are also in <paramref name="self"/>,
/// otherwise <c>false</c>.</returns>
public static bool All(this Feature self, Feature features) => (self & features) == features;
/// <summary>
/// Tests whether there are any common features between <paramref name="self"/> and <paramref name="features"/>.
/// </summary>
/// <param name="self">The <see cref="Feature"/> being extended.</param>
/// <param name="features">The Features to test against.</param>
/// <returns><c>true</c> if none of the features in <paramref name="self"/> are in <paramref name="features"/>,
/// otherwise <c>false</c>.</returns>
public static bool None(this Feature self, Feature features) => (self & features) == Feature.None;
/// <summary>
/// Computes the union of <paramref name="self"/> and <paramref name="features"/> (that is,
/// the set of features in <paramref name="self"/> or <paramref name="features"/> or both).
/// </summary>
/// <param name="self">The <see cref="Feature"/> being extended.</param>
/// <param name="features">Features to union with <paramref name="self"/></param>
/// <returns>The union of <paramref name="self"/> and <paramref name="features"/>
/// (that is, the set of features in <paramref name="self"/> or <paramref name="features"/> or both).</returns>
public static Feature Union(this Feature self, Feature features) => self | features;
/// <summary>
/// Computes the intersection of <paramref name="self"/> and <paramref name="features"/>
/// (that is, the set of features present in both <paramref name="self"/> and <paramref name="features"/>).
/// </summary>
/// <param name="self">The <see cref="Feature"/> being extended.</param>
/// <param name="features">Features to intersect with <paramref name="self"/></param>
/// <returns>The intersection of <paramref name="self"/> and <paramref name="features"/>
/// (that is, the set of features common to both <paramref name="self"/> and <paramref name="features"/>).</returns>
public static Feature Intersection(this Feature self, Feature features) => self & features;
/// <summary>
/// Computes the set difference (that is, removes all flags in <paramref name="features"/> from <paramref name="self"/>).
/// </summary>
/// <param name="self">The <see cref="Feature"/> being extended.</param>
/// <param name="features">Features to remove from <paramref name="self"/></param>
/// <returns>The set difference of <paramref name="self"/> and <paramref name="features"/>
/// (that is, all members of <paramref name="self"/> which do not belong to <paramref name="features"/>).</returns>
public static Feature SetDifference(this Feature self, Feature features) => self & ~features;
/// <summary>
/// Computes the symmetric difference (that is,
/// the set of all features that belong to exactly one of <paramref name="self"/> and <paramref name="features"/>,
/// present in one but not both).
/// </summary>
/// <param name="self">The <see cref="Feature"/> being extended.</param>
/// <param name="features">Features with which to compute the symmetric difference against <paramref name="self"/></param>
/// <returns>The symmetric difference of <paramref name="self"/> and <paramref name="features"/>
/// (that is, the features that belong to <paramref name="self"/> or <paramref name="features"/>, but not both).</returns>
public static Feature SymmetricDifference(this Feature self, Feature features) => self ^ features;
/// <summary>
/// Sets or removes one or more <see cref="Feature"/> flags.
/// </summary>
/// <param name="self">The <see cref="Feature"/> being extended.</param>
/// <param name="feature">The <see cref="Feature"/>(s) to set or remove.</param>
/// <param name="enabled">If <c>true</c>, the flag(s) in <paramref name="feature"/> will be set. If <c>false</c>, it/they will be removed.</param>
/// <returns><paramref name="self"/> with the <see cref="Feature"/>(s) set or removed according to the value of <paramref name="enabled"/>.</returns>
public static Feature SetEnabled(this Feature self, Feature feature, bool enabled) => enabled ? self | feature : self & ~feature;
/// <summary>
/// Filters just the camera-related <see cref="Feature"/> flags.
/// </summary>
/// <param name="self">The <see cref="Feature"/> being extended.</param>
/// <returns>The camera-related <see cref="Feature"/> flags from <paramref name="self"/>.</returns>
/// <seealso cref="Feature.AnyCamera"/>
public static Feature Cameras(this Feature self) => self.Intersection(Feature.AnyCamera);
/// <summary>
/// Filters just the tracking-related <see cref="Feature"/> flags.
/// </summary>
/// <param name="self">The <see cref="Feature"/> being extended.</param>
/// <returns>The tracking-related <see cref="Feature"/> flags from <paramref name="self"/>.</returns>
/// <seealso cref="Feature.AnyTrackingMode"/>
public static Feature TrackingModes(this Feature self) => self.Intersection(Feature.AnyTrackingMode);
/// <summary>
/// Filters just the light estimation related <see cref="Feature"/> flags.
/// </summary>
/// <param name="self">The <see cref="Feature"/> being extended.</param>
/// <returns>The light estimation-related <see cref="Feature"/> flags from <paramref name="self"/>.</returns>
public static Feature LightEstimation(this Feature self) => self.Intersection(Feature.AnyLightEstimation);
/// <summary>
/// Removes all camera and tracking-related <see cref="Feature"/> flags.
/// </summary>
/// <param name="self">The <see cref="Feature"/> being extended.</param>
/// <returns><paramref name="self"/> with camera and tracking-related bits removed.</returns>
/// <seealso cref="Feature.AnyCamera"/>
/// <seealso cref="Feature.AnyTrackingMode"/>
public static Feature WithoutCameraOrTracking(this Feature self) => self.SetDifference(Feature.AnyCamera.Union(Feature.AnyTrackingMode));
static Feature LowestBit(this Feature self)
{
return self & (self ^ (self - 1));
}
/// <summary>
/// Generates a single string representing the list of enabled features separated by <paramref name="separator"/>, or a comma if not specified.
/// </summary>
/// <remarks>
/// This method makes several heap allocations, generating garbage. It is intended for debugging purposes and
/// should not be called frequently in a production application.
/// </remarks>
/// <param name="features">The <see cref="Feature"/> being extended.</param>
/// <param name="separator">The string separator to insert between elements of the list, or ", " if omitted.</param>
/// <returns>A string of <see cref="Feature"/>s separated by <paramref name="separator"/>. If none of the features are enabled, returns "(None)".</returns>
public static string ToStringList(this Feature features, string separator = ", ")
{
var names = new List<string>();
while (features != 0)
{
var feature = features.LowestBit();
switch (feature)
{
case Feature.WorldFacingCamera:
names.Add("World Facing Camera");
break;
case Feature.UserFacingCamera:
names.Add("User Facing Camera");
break;
case Feature.RotationOnly:
names.Add("Rotation Only");
break;
case Feature.PositionAndRotation:
names.Add("Rotation and Orientation");
break;
case Feature.FaceTracking:
names.Add("Face Tracking");
break;
case Feature.PlaneTracking:
names.Add("Plane Tracking");
break;
case Feature.ImageTracking:
names.Add("Image Tracking");
break;
case Feature.ObjectTracking:
names.Add("Object Tracking");
break;
case Feature.EnvironmentProbes:
names.Add("Environment Probes");
break;
case Feature.Body2D:
names.Add("2D Body Tracking");
break;
case Feature.Body3D:
names.Add("3D Body Tracking");
break;
case Feature.Body3DScaleEstimation:
names.Add("3D Body Scale Estimation");
break;
case Feature.PeopleOcclusionStencil:
names.Add("Human Occlusion Stencil");
break;
case Feature.PeopleOcclusionDepth:
names.Add("Human Occlusion Depth");
break;
case Feature.Collaboration:
names.Add("Collaboration");
break;
case Feature.AutoFocus:
names.Add("Auto-Focus");
break;
case Feature.LightEstimationAmbientIntensity:
names.Add("Light Estimation (Ambient Intensity)");
break;
case Feature.LightEstimationAmbientColor:
names.Add("Light Estimation (Ambient Color)");
break;
case Feature.LightEstimationAmbientSphericalHarmonics:
names.Add("Light Estimation (Spherical Harmonics)");
break;
case Feature.LightEstimationMainLightDirection:
names.Add("Light Estimation (Main Light Direction)");
break;
case Feature.LightEstimationMainLightIntensity:
names.Add("Light Estimation (Main Light Intensity)");
break;
case Feature.Raycast:
names.Add("Raycast");
break;
case Feature.Meshing:
names.Add("Meshing");
break;
case Feature.MeshClassification:
names.Add("Mesh Classification");
break;
case Feature.PointCloud:
names.Add("Point Cloud");
break;
case Feature.EnvironmentDepth:
names.Add("Environment Depth");
break;
case Feature.EnvironmentDepthTemporalSmoothing:
names.Add("Environment Depth Temporal Smoothing");
break;
case Feature.ImageStabilization:
names.Add("Image Stabilization");
break;
default:
names.Add(feature.ToString());
break;
}
features &= (features - 1);
}
return names.Count > 0 ? string.Join(separator, names) : "(None)";
}
/// <summary>
/// Calculates the number of enabled features in <paramref name="self"/>.
/// </summary>
/// <param name="self">The <see cref="Feature"/> being extended.</param>
/// <returns>The number of enabled <see cref="Feature"/> flags.</returns>
public static int Count(this Feature self)
{
int count = 0;
ulong features = (ulong)self;
while (features != 0)
{
++count;
// set lowest bit to zero
features &= (features - 1);
}
return count;
}
}
}