using AOT;
using System;
using System.Runtime.InteropServices;
using UnityEngine.Scripting;
using UnityEngine.XR.ARSubsystems;
namespace UnityEngine.XR.ARKit
{
///
/// ARKit implementation of the XRSessionSubsystem. Do not create this directly. Use the SubsystemManager instead.
///
[Preserve]
public sealed class ARKitSessionSubsystem : XRSessionSubsystem
{
///
/// true if [Coaching Overlay](https://developer.apple.com/documentation/arkit/arcoachingoverlayview) is supported, otherwise false.
///
public static bool coachingOverlaySupported
{
get
{
#if UNITY_IOS && !UNITY_EDITOR
return NativeApi.UnityARKit_coachingOverlay_isSupported();
#else
return false;
#endif
}
}
///
/// Whether the [Coaching Overlay](https://developer.apple.com/documentation/arkit/arcoachingoverlayview)
/// activates automatically or not. By default, it does not.
///
public bool coachingActivatesAutomatically
{
get => NativeApi.UnityARKit_coachingOverlay_getActivatesAutomatically();
set => NativeApi.UnityARKit_coachingOverlay_setActivatesAutomatically(value);
}
///
/// Defines the [Coaching Goal](https://developer.apple.com/documentation/arkit/arcoachingoverlayview/3192180-goal).
/// This should be based on your app's tracking requirements and affects the UI that the coaching overlay presents.
///
public ARCoachingGoal coachingGoal
{
get => NativeApi.UnityARKit_coachingOverlay_getGoal();
set => NativeApi.UnityARKit_coachingOverlay_setGoal(value);
}
///
/// true if the [Coaching Overlay](https://developer.apple.com/documentation/arkit/arcoachingoverlayview) is active.
///
public bool coachingActive => NativeApi.UnityARKit_coachingOverlay_isActive();
///
/// Activates or deactivates the [Coaching Overlay](https://developer.apple.com/documentation/arkit/arcoachingoverlayview)
///
/// Whether the coaching overlay should be active or not.
/// The type of transition to use when showing or hiding the coaching overlay.
public void SetCoachingActive(bool active, ARCoachingOverlayTransition transition)
{
NativeApi.UnityARKit_coachingOverlay_setActive(active, transition == ARCoachingOverlayTransition.Animated);
}
///
/// Asynchronously create an . An ARWorldMap
/// represents the state of the session and can be serialized to a byte
/// array to persist the session data, or send it to another device for
/// shared AR experiences.
/// It is a wrapper for ARKit's ARWorldMap.
///
/// An which can be used to determine the status
/// of the request and get the ARWorldMap when complete.
///
///
public ARWorldMapRequest GetARWorldMapAsync()
{
var requestId = NativeApi.UnityARKit_createWorldMapRequest();
return new ARWorldMapRequest(requestId);
}
///
///
/// Asynchronously create an . An ARWorldMap
/// represents the state of the session and can be serialized to a byte
/// array to persist the session data, or send it to another device for
/// shared AR experiences.
///
///
/// It is a wrapper for ARKit's ARWorldMap.
///
///
/// If the is , then
/// the resulting must be disposed to avoid leaking native resources. Otherwise,
/// the is not valid, and need not be disposed.
///
///
/// A method to invoke when the world map has either been created, or determined
/// that it could not be created. Check the value of the parameter
/// to determine whether the world map was successfully created.
///
///
public void GetARWorldMapAsync(
Action onComplete)
{
var handle = GCHandle.Alloc(onComplete);
var context = GCHandle.ToIntPtr(handle);
NativeApi.UnityARKit_createWorldMapRequestWithCallback(s_OnAsyncWorldMapCompleted, context);
}
///
/// Detect support. ARWorldMap requires iOS 12 or greater.
///
/// true if ARWorldMaps are supported, otherwise false.
///
public static bool worldMapSupported
{
get
{
#if UNITY_IOS && !UNITY_EDITOR
return NativeApi.UnityARKit_worldMapSupported();
#else
return false;
#endif
}
}
///
/// Get the world mapping status. Used to determine the suitability of the current session for
/// creating an .
///
/// The of the session.
public ARWorldMappingStatus worldMappingStatus => NativeApi.UnityARKit_session_getWorldMappingStatus();
///
/// Apply an existing to the session. This will attempt
/// to relocalize the current session to the given .
/// If relocalization is successful, the stored planes and anchors from
/// the will be added to the current session.
/// This is equivalent to setting the initialWorldMap
/// property on the session's ARWorldTrackingConfiguration.
///
/// An with which to relocalize the session.
public void ApplyWorldMap(ARWorldMap worldMap)
{
if (worldMap.nativeHandle == ARWorldMap.k_InvalidHandle)
throw new InvalidOperationException("ARWorldMap has been disposed.");
NativeApi.UnityARKit_applyWorldMap(worldMap.nativeHandle);
}
///
/// Get or set whether collaboration is enabled. When collaboration is enabled, collaboration
/// data is accumulated by the subsystem until you read it out with .
///
///
/// Note: If you change this value, the new value may not be reflected until the next frame.
///
///
///
///
public bool collaborationEnabled
{
get => NativeApi.UnityARKit_session_getCollaborationEnabled();
set
{
if (supportsCollaboration)
{
NativeApi.UnityARKit_session_setCollaborationRequested(value);
}
else if (value)
{
throw new NotSupportedException("ARCollaborationData is not supported by this version of iOS.");
}
}
}
///
/// True if collaboration is supported. Collaboration is only supported on iOS versions 13.0 and later.
///
///
public static bool supportsCollaboration => s_SupportsCollaboration;
///
/// The number of s in the queue. Obtain
/// with .
///
///
///
public int collaborationDataCount => NativeApi.UnityARKit_session_getCollaborationDataQueueSize();
///
/// Dequeues the oldest collaboration data in the queue. After calling this method,
/// will be decremented by one.
///
/// Thrown if is false.
/// Thrown if is zero.
///
public ARCollaborationData DequeueCollaborationData()
{
if (!supportsCollaboration)
throw new NotSupportedException("ARCollaborationData is not supported by this version of iOS.");
if (collaborationDataCount == 0)
throw new InvalidOperationException("There is no collaboration data to dequeue.");
return new ARCollaborationData(NativeApi.UnityARKit_session_dequeueCollaborationData());
}
///
/// Applies to the session.
///
/// Thrown if is false.
/// Thrown if is not valid.
public void UpdateWithCollaborationData(ARCollaborationData collaborationData)
{
if (!supportsCollaboration)
throw new NotSupportedException("ARCollaborationData is not supported by this version of iOS.");
if (!collaborationData.valid)
throw new InvalidOperationException("Invalid collaboration data.");
NativeApi.UnityARKit_session_updateWithCollaborationData(collaborationData.m_NativePtr);
}
///
/// Creates the provider interface.
///
/// The provider interface for ARKit
protected override Provider CreateProvider() => new ARKitProvider();
static ARKitSessionSubsystem()
{
s_OnAsyncWorldMapCompleted = OnAsyncConversionComplete;
#if UNITY_IOS && !UNITY_EDITOR
s_SupportsCollaboration = NativeApi.UnityARKit_session_getCollaborationSupported();
#else
s_SupportsCollaboration = false;
#endif
}
static NativeApi.OnAsyncConversionCompleteDelegate s_OnAsyncWorldMapCompleted;
static bool s_SupportsCollaboration;
[MonoPInvokeCallback(typeof(NativeApi.OnAsyncConversionCompleteDelegate))]
static unsafe void OnAsyncConversionComplete(ARWorldMapRequestStatus status, int worldMapId, IntPtr context)
{
var handle = GCHandle.FromIntPtr(context);
var onComplete = (Action)handle.Target;
if (status.IsError())
{
onComplete(status, default(ARWorldMap));
}
else
{
var worldMap = new ARWorldMap(worldMapId);
onComplete(status, worldMap);
}
handle.Free();
}
class ARKitProvider : Provider
{
public ARKitProvider() => NativeApi.UnityARKit_session_construct();
public override void Resume() => NativeApi.UnityARKit_session_resume();
public override void Pause() => NativeApi.UnityARKit_session_pause();
public override void Update(XRSessionUpdateParams updateParams) => NativeApi.UnityARKit_session_update();
public override void Destroy() => NativeApi.UnityARKit_session_destroy();
public override void Reset() => NativeApi.UnityARKit_session_reset();
public override Promise GetAvailabilityAsync()
{
var result = NativeApi.UnityARKit_session_getAvailability();
var retVal = SessionAvailability.None;
if (result == NativeApi.Availability.Supported)
retVal = SessionAvailability.Installed | SessionAvailability.Supported;
return Promise.CreateResolvedPromise(retVal);
}
public override Promise InstallAsync() =>
throw new NotSupportedException("ARKit cannot be installed.");
public override IntPtr nativePtr => NativeApi.UnityARKit_session_getNativePtr();
public override TrackingState trackingState => NativeApi.UnityARKit_session_getTrackingState();
public override NotTrackingReason notTrackingReason => NativeApi.UnityARKit_session_getNotTrackingReason();
public override Guid sessionId => NativeApi.UnityARKit_session_getSessionId();
public override bool matchFrameRate
{
get => NativeApi.UnityARKit_session_getMatchFrameRateEnabled();
set => NativeApi.UnityARKit_session_setMatchFrameRateEnabled(value);
}
public override int frameRate => NativeApi.UnityARKit_Session_GetFrameRate();
}
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
static void RegisterDescriptor()
{
#if UNITY_IOS && !UNITY_EDITOR
NativeApi.UnityARKit_ensureRootViewIsSetup();
XRSessionSubsystemDescriptor.RegisterDescriptor(new XRSessionSubsystemDescriptor.Cinfo
{
id = "ARKit-Session",
subsystemImplementationType = typeof(ARKitSessionSubsystem),
supportsInstall = false,
supportsMatchFrameRate = true
});
#endif
}
static class NativeApi
{
// Should match ARKitAvailability in ARKitXRSessionProvider.mm
public enum Availability
{
None,
Supported
}
public delegate void OnAsyncConversionCompleteDelegate(
ARWorldMapRequestStatus status,
int worldMapId,
IntPtr context);
[DllImport("__Internal")]
public static extern int UnityARKit_createWorldMapRequest();
[DllImport("__Internal")]
public static extern void UnityARKit_createWorldMapRequestWithCallback(
OnAsyncConversionCompleteDelegate callback,
IntPtr context);
[DllImport("__Internal")]
public static extern bool UnityARKit_worldMapSupported();
[DllImport("__Internal")]
public static extern ARWorldMappingStatus UnityARKit_session_getWorldMappingStatus();
[DllImport("__Internal")]
public static extern void UnityARKit_applyWorldMap(int worldMapId);
[DllImport("__Internal")]
public static extern IntPtr UnityARKit_session_getNativePtr();
[DllImport("__Internal")]
public static extern Availability UnityARKit_session_getAvailability();
[DllImport("__Internal")]
public static extern void UnityARKit_session_update();
[DllImport("__Internal")]
public static extern void UnityARKit_session_construct();
[DllImport("__Internal")]
public static extern void UnityARKit_session_destroy();
[DllImport("__Internal")]
public static extern void UnityARKit_session_resume();
[DllImport("__Internal")]
public static extern void UnityARKit_session_pause();
[DllImport("__Internal")]
public static extern void UnityARKit_session_reset();
[DllImport("__Internal")]
public static extern TrackingState UnityARKit_session_getTrackingState();
[DllImport("__Internal")]
public static extern NotTrackingReason UnityARKit_session_getNotTrackingReason();
[DllImport("__Internal")]
public static extern bool UnityARKit_session_getCollaborationSupported();
[DllImport("__Internal")]
public static extern IntPtr UnityARKit_session_dequeueCollaborationData();
[DllImport("__Internal")]
public static extern int UnityARKit_session_getCollaborationDataQueueSize();
[DllImport("__Internal")]
public static extern void UnityARKit_session_updateWithCollaborationData(IntPtr data);
[DllImport("__Internal")]
public static extern bool UnityARKit_session_getCollaborationEnabled();
[DllImport("__Internal")]
public static extern void UnityARKit_session_setCollaborationRequested(bool requested);
[DllImport("__Internal")]
public static extern Guid UnityARKit_session_getSessionId();
[DllImport("__Internal")]
public static extern bool UnityARKit_session_getMatchFrameRateEnabled();
[DllImport("__Internal")]
public static extern void UnityARKit_session_setMatchFrameRateEnabled(bool enabled);
[DllImport("__Internal")]
public static extern int UnityARKit_Session_GetFrameRate();
[DllImport("__Internal")]
public static extern bool UnityARKit_coachingOverlay_getActivatesAutomatically();
[DllImport("__Internal")]
public static extern void UnityARKit_coachingOverlay_setActivatesAutomatically(bool activatesAutomatically);
[DllImport("__Internal")]
public static extern bool UnityARKit_coachingOverlay_isActive();
[DllImport("__Internal")]
public static extern void UnityARKit_coachingOverlay_setGoal(ARCoachingGoal goal);
[DllImport("__Internal")]
public static extern ARCoachingGoal UnityARKit_coachingOverlay_getGoal();
[DllImport("__Internal")]
public static extern void UnityARKit_coachingOverlay_setActive(bool active, bool animated);
[DllImport("__Internal")]
public static extern void UnityARKit_ensureRootViewIsSetup();
[DllImport("__Internal")]
public static extern bool UnityARKit_coachingOverlay_isSupported();
}
}
}