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