using System; using System.Runtime.InteropServices; using System.Text; using Unity.Collections; using Unity.Collections.LowLevel.Unsafe; namespace UnityEngine.XR.ARCore { /// /// Represents the context for an ARCore session. /// /// /// This is an opaque object that represents a native /// [ArSession](https://developers.google.com/ar/reference/c/group/ar-session). /// /// /// /// /// public struct ArSession : IEquatable { IntPtr m_Self; ArSession(IntPtr value) => m_Self = value; /// /// Creates an 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 ArSession FromIntPtr(IntPtr value) => new ArSession(value); /// /// Represents a null , i.e., one whose underlying native pointer is `null`. /// This property is obsolete. Use instead. /// [Obsolete("Use default instead.")] public static ArSession 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; /// /// Casts an to its underlying native pointer. /// /// The to cast. /// Returns the underlying native pointer for public static explicit operator IntPtr(ArSession session) => session.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(ArSession 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 ArSession 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 ==(ArSession lhs, ArSession 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 !=(ArSession lhs, ArSession 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(ArSession 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 ==(ArSession? lhs, ArSession? 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(ArSession 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 !=(ArSession? lhs, ArSession? rhs) => !(lhs == rhs); /// /// Sets an MP4 dataset file to playback instead of live camera feed. /// /// /// Restrictions: /// - Can only be called while the session is paused. Playback of the MP4 /// dataset file starts once the session is resumed. /// - The MP4 dataset file must use the same camera facing direction as is /// configured in the session. /// /// When an MP4 dataset file is set: /// - All existing trackables (i.e., anchors and trackables) immediately enter tracking state [TrackingState.None](xref:UnityEngine.XR.ARSubsystems.TrackingState.None). /// - The desired focus mode is ignored, and does not affect the previously recorded camera images. /// - The current camera configuration is immediately set to the default for the device the MP4 dataset file was recorded on. /// - Calls to retrieve the supported camera configurations return camera configs supported by the device the MP4 dataset file was recorded on. /// - Setting a previously obtained camera config has no effect. /// /// A file path to a MP4 dataset file or `null` to use the live camera feed. /// /// - Returns if successful. /// - Returns if called when session is not paused. /// - Returns if playback is incompatible with selected features. /// - Returns if an error occurred with the MP4 dataset file such as not being able to open the file or the file is unable to be decoded. /// public ArStatus SetPlaybackDataset(string path) { unsafe { if (string.IsNullOrEmpty(path)) { return SetPlaybackDataset(this, null); } using (var bytes = path.ToBytes(Encoding.UTF8, Allocator.Temp)) { return SetPlaybackDataset(this, (byte*)bytes.GetUnsafePtr()); } } } [DllImport("arcore_sdk_c", EntryPoint = "ArSession_setPlaybackDataset")] static extern unsafe ArStatus SetPlaybackDataset(ArSession session, byte* mp4DatasetFilePath); /// /// (Read Only) The playback status. /// /// Whether or not the session is playing back a recording (or has stopped because of an error). public ArPlaybackStatus playbackStatus { get { GetPlaybackStatus(this, out var value); return value; } } [DllImport("arcore_sdk_c", EntryPoint = "ArSession_getPlaybackStatus")] static extern void GetPlaybackStatus(ArSession session, out ArPlaybackStatus outPlaybackStatus); /// /// Starts a new MP4 dataset file recording that is written to the specific filesystem path. /// /// /// Existing files are overwritten. /// /// The MP4 video stream (VGA) bitrate is 5Mbps (40Mb per minute). /// /// Recording introduces additional overhead and may affect app performance. /// /// The configuration defined for recording. /// Returns if successful. Returns one of the following values otherwise: /// - /// - /// - /// public ArStatus StartRecording(ArRecordingConfig recordingConfig) => StartRecording(this, recordingConfig); [DllImport("arcore_sdk_c", EntryPoint = "ArSession_startRecording")] static extern ArStatus StartRecording(ArSession session, ArRecordingConfig recordingConfig); /// /// Stops recording and flushes unwritten data to disk. The MP4 dataset file is ready to read after this /// call. /// /// /// Recording can be stopped automatically when the session is paused, /// if auto stop is enabled via . /// Recording errors that would be thrown in are silently /// ignored on session pause. /// /// Returns if successful. Returns /// otherwise. public ArStatus StopRecording() => StopRecording(this); [DllImport("arcore_sdk_c", EntryPoint = "ArSession_stopRecording")] static extern ArStatus StopRecording(ArSession session); /// /// (Read Only) The current recording status. /// /// Whether or not the session is recording (or has stopped because of an error). public ArRecordingStatus recordingStatus { get { GetRecordingStatus(this, out var value); return value; } } [DllImport("arcore_sdk_c", EntryPoint = "ArSession_getRecordingStatus")] static extern void GetRecordingStatus(ArSession session, out ArRecordingStatus outRecordingStatus); } }