using System; using UnityEngine.XR.ARSubsystems; #if UNITY_ANDROID && !UNITY_EDITOR using System.Runtime.InteropServices; #endif namespace UnityEngine.XR.ARCore { /// /// Represents an /// [ARCore camera configuration](https://developers.google.com/ar/reference/c/group/ar-camera-config), which /// describes the ARCore-related properties of a device camera. /// public struct ArCameraConfig : IDisposable, IEquatable { IntPtr m_Self; ArCameraConfig(IntPtr value) => m_Self = value; /// /// Creates a from an existing native pointer. The native pointer must point /// to an existing . /// /// A pointer to an existing native . /// Returns an whose underlying native pointer is /// . public static ArCameraConfig FromIntPtr(IntPtr value) => new ArCameraConfig(value); /// /// Represents a null , i.e., one whose underlying native pointer is `null`. /// This property is deprecated. Use instead. /// [Obsolete("Use default instead.")] public static ArCameraConfig Null => default; /// /// (Read Only) Indicates whether this is `null`. /// This property is deprecated. Use the equality operator (`==`) to compare with `null` instead. /// [Obsolete("Compare to null instead.")] public bool IsNull => m_Self == IntPtr.Zero; /// /// Gets the underlying native pointer for this . /// /// Returns the underlying native pointer for this . public IntPtr AsIntPtr() => m_Self; /// /// Creates a new camera config object. To prevent memory leaks, this object should be disposed with /// when you no longer need it. /// /// The ARCore session. public ArCameraConfig(ArSession session) => Create(session, out this); /// /// Destroys this and sets its underlying pointer to `null`. /// /// /// You should only dispose an if you explicitly created it, e.g., by calling /// . If you convert an existing config from an /// (e.g., by calling ), then you should not dispose it. /// public void Dispose() { if (m_Self != IntPtr.Zero) { Destroy(this); } m_Self = default; } /// /// Obtains the camera id for this camera config. /// /// The ARCore session. /// Returns the camera id for this camera config. public string GetCameraId(ArSession session) { GetCameraId(session, this, out var cameraId); using (cameraId) { return cameraId.ToString(); } } /// /// Gets the depth sensor usage settings. /// /// The ARCore session. /// Returns the depth sensor usage settings. public ArCameraConfigDepthSensorUsage GetDepthSensorUsage(ArSession session) { GetDepthSensorUsage(session, this, out var value); return value; } /// /// Gets the facing direction of the camera selected by this config. /// /// The ARCore session. /// Returns the facing direction of the camera selected by this config. public ArCameraConfigFacingDirection GetFacingDirection(ArSession session) { GetFacingDirection(session, this, out var value); return value; } /// /// Gets the minimum and maximum camera capture rate in frames per second (fps) for the current camera config. /// /// /// Actual capture frame rate will vary within this range, depending on lighting conditions. Frame rates will /// generally be lower under poor lighting conditions to accommodate longer exposure times. /// /// The ARCore session. /// Returns the minimum and maximum camera capture rate in frames per second supported by this camera /// config. public (int minFps, int maxFps) GetFpsRange(ArSession session) { GetFpsRange(session, this, out var min, out var max); return (min, max); } /// /// Gets the camera image dimensions for this camera config. /// /// The ARCore session. /// Returns the camera image dimensions for this camera config. public (int width, int height) GetImageDimensions(ArSession session) { GetImageDimensions(session, this, out var width, out var height); return (width, height); } /// /// Gets the camera texture dimensions for this camera config. /// /// The ARCore session. /// Returns the camera texture dimensions for this camera config. public (int width, int height) GetTextureDimensions(ArSession session) { GetTextureDimensions(session, this, out var width, out var height); return (width, height); } /// /// Casts an to its underlying native pointer. /// /// The to cast. /// Returns the underlying native pointer for public static explicit operator IntPtr(ArCameraConfig cameraConfig) => cameraConfig.AsIntPtr(); /// /// Tests for equality. /// /// /// Two s are considered equal if their underlying pointers are equal. /// /// The to compare against. /// Returns `true` if the underlying native pointers are the same. Returns `false` otherwise. public bool Equals(ArCameraConfig other) => m_Self == other.m_Self; /// /// Tests for equality. /// /// An to compare against. /// Returns `true` if is an and it compares /// equal to this one using . public override bool Equals(object obj) => obj is ArCameraConfig other && Equals(other); /// /// Generates a hash code suitable for use with a `HashSet` or `Dictionary` /// /// Returns a hash code for this . public override int GetHashCode() => m_Self.GetHashCode(); /// /// Tests for equality. Same as . /// /// The to compare with . /// The to compare with . /// Returns `true` if is equal to using /// . Returns `false` otherwise. public static bool operator ==(ArCameraConfig lhs, ArCameraConfig rhs) => lhs.Equals(rhs); /// /// Tests for inequality. Same as the negation of . /// /// The to compare with . /// The to compare with . /// Returns `false` if is equal to using /// . Returns `true` otherwise. public static bool operator !=(ArCameraConfig lhs, ArCameraConfig rhs) => !lhs.Equals(rhs); /// /// Tests for equality. /// /// /// This equality operator lets you to compare an with `null` to determine whether its /// underlying pointer is null. This allows for a more natural comparison with the native ARCore object: /// /// /// bool TestForNull(ArCameraConfig obj) /// { /// if (obj == null) /// { /// // obj.AsIntPtr() is IntPtr.Zero /// } /// } /// /// /// /// The nullable to compare with . /// The nullable to compare with . /// Returns true if any of these conditions are met: /// - and are both not null and their underlying pointers are equal. /// - is null and 's underlying pointer is null. /// - is null and 's underlying pointer is null. /// - Both and are null. /// /// Returns false otherwise. /// public static bool operator ==(ArCameraConfig? lhs, ArCameraConfig? rhs) => NativeObject.ArePointersEqual(lhs?.m_Self, rhs?.m_Self); /// /// Tests for inequality. /// /// /// This inequality operator lets you to compare an with `null` to determine whether its /// underlying pointer is null. This allows for a more natural comparison with the native ARCore object: /// /// /// bool TestForNull(ArCameraConfig obj) /// { /// if (obj != null) /// { /// // obj.AsIntPtr() is not IntPtr.Zero /// } /// } /// /// /// /// The native object to compare with . /// The native object to compare with . /// Returns false if any of these conditions are met: /// - and are both not null and their underlying pointers are equal. /// - is null and 's underlying pointer is null. /// - is null and 's underlying pointer is null. /// - Both and are null. /// /// Returns true otherwise. /// public static bool operator !=(ArCameraConfig? lhs, ArCameraConfig? rhs) => !(lhs == rhs); #if UNITY_ANDROID && !UNITY_EDITOR [DllImport("arcore_sdk_c", EntryPoint = "ArCameraConfig_create")] static extern void Create(ArSession session, out ArCameraConfig value); [DllImport("arcore_sdk_c", EntryPoint = "ArCameraConfig_destroy")] static extern void Destroy(ArCameraConfig self); [DllImport("arcore_sdk_c", EntryPoint = "ArCameraConfig_getCameraId")] static extern void GetCameraId(ArSession session, ArCameraConfig self, out ArString valueOut); [DllImport("arcore_sdk_c", EntryPoint = "ArCameraConfig_getDepthSensorUsage")] static extern void GetDepthSensorUsage(ArSession session, ArCameraConfig self, out ArCameraConfigDepthSensorUsage valueOut); [DllImport("arcore_sdk_c", EntryPoint = "ArCameraConfig_getFacingDirection")] static extern void GetFacingDirection(ArSession session, ArCameraConfig self, out ArCameraConfigFacingDirection valueOut); [DllImport("arcore_sdk_c", EntryPoint = "ArCameraConfig_getFpsRange")] static extern void GetFpsRange(ArSession session, ArCameraConfig self, out int minFps, out int maxFps); [DllImport("arcore_sdk_c", EntryPoint = "ArCameraConfig_getImageDimensions")] static extern void GetImageDimensions(ArSession session, ArCameraConfig self, out int width, out int height); [DllImport("arcore_sdk_c", EntryPoint = "ArCameraConfig_getTextureDimensions")] static extern void GetTextureDimensions(ArSession session, ArCameraConfig self, out int width, out int height); #else static void Create(ArSession session, out ArCameraConfig value) => value = default; static void Destroy(ArCameraConfig self) { } static void GetCameraId(ArSession session, ArCameraConfig self, out ArString valueOut) => valueOut = default; static void GetDepthSensorUsage(ArSession session, ArCameraConfig self, out ArCameraConfigDepthSensorUsage valueOut) => valueOut = default; static void GetFacingDirection(ArSession session, ArCameraConfig self, out ArCameraConfigFacingDirection valueOut) => valueOut = default; static void GetFpsRange(ArSession session, ArCameraConfig self, out int minFps, out int maxFps) { minFps = default; maxFps = default; } static void GetImageDimensions(ArSession session, ArCameraConfig self, out int width, out int height) { width = default; height = default; } static void GetTextureDimensions(ArSession session, ArCameraConfig self, out int width, out int height) { width = default; height = default; } #endif } /// /// Extensions to the [XRCameraConfiguration](xref:UnityEngine.XR.ARSubsystems.XRCameraConfiguration) object. /// public static class XRCameraConfigurationExtensions { /// /// Gets as an ARCore . /// /// /// > [!IMPORTANT] /// > Do not the returned . /// /// The /// [XRCameraConfiguration](xref:UnityEngine.XR.ARSubsystems.XRCameraConfiguration) being extended. /// Returns the ARCore-specific representation of . public static ArCameraConfig AsArCameraConfig(this XRCameraConfiguration cameraConfiguration) => ArCameraConfig.FromIntPtr(cameraConfiguration.nativeConfigurationHandle); } }