using System; using Unity.Collections; using UnityEngine.SubsystemsImplementation; namespace UnityEngine.XR.ARSubsystems { /// /// This subsystem provides information regarding the detection of planes (that is, flat surfaces) in the real-world /// environment. /// /// /// This is a base class with an abstract provider type to be implemented by provider plug-in packages. /// This class itself does not implement plane detection. /// public class XRPlaneSubsystem : TrackingSubsystem { #if DEVELOPMENT_BUILD || UNITY_EDITOR ValidationUtility m_ValidationUtility = new(); #endif /// /// Do not invoke this constructor directly. /// /// /// If you are implementing your own custom subsystem [Lifecycle management](xref:xr-plug-in-management-provider#lifecycle-management), /// use the [SubsystemManager](xref:UnityEngine.SubsystemManager) /// to enumerate the available s, then call /// XRPlaneSubsystemDescriptor.Register() on the desired descriptor. /// public XRPlaneSubsystem() { } /// /// Get or set the requested to enable different modes of detection. /// /// Thrown if is set to /// something other than when plane detection is not supported. public PlaneDetectionMode requestedPlaneDetectionMode { get => provider.requestedPlaneDetectionMode; set => provider.requestedPlaneDetectionMode = value; } /// /// Get the current in use by the provider. /// public PlaneDetectionMode currentPlaneDetectionMode => provider.currentPlaneDetectionMode; /// /// Gets a struct containing any changes to detected planes since the last /// time you called this method. You are responsible to the returned /// TrackableChanges instance. /// /// An Allocator to use for the returned NativeArrays. /// The . /// /// The struct returned by this method contains separate /// objects for the added, updated, and removed planes. These arrays are created /// using the type specified by . /// public override TrackableChanges GetChanges(Allocator allocator) { var changes = provider.GetChanges(BoundedPlane.defaultValue, allocator); #if DEVELOPMENT_BUILD || UNITY_EDITOR m_ValidationUtility.ValidateAndDisposeIfThrown(changes); #endif return changes; } /// /// Gets the boundary vertices of a given based on its . /// /// The of a . /// An to use if needs to be created. /// is not supported. Use if you need temporary memory. /// The boundary vertices will be stored here. If the given array is the same length as /// the number of vertices, it is overwritten with the new data. Otherwise, it is disposed and recreated with /// the correct length. public void GetBoundary( TrackableId trackableId, Allocator allocator, ref NativeArray boundary) { switch (allocator) { case Allocator.Temp: throw new InvalidOperationException("Allocator.Temp is not supported. Use Allocator.TempJob if you wish to use a temporary allocator."); case Allocator.None: throw new InvalidOperationException("Allocator.None is not a valid allocator."); default: provider.GetBoundary(trackableId, allocator, ref boundary); break; } } /// /// Creates or resizes the if necessary. If has been allocated /// and its length is equal to , then this method does nothing. If its length is /// different, then it is first disposed before being assigned to a new NativeArray. /// /// The length that will have after this method returns. /// If allocation is necessary, this allocator will be used to create the new NativeArray. /// The array to create or resize. /// The type of elements held by the . protected static void CreateOrResizeNativeArrayIfNecessary( int length, Allocator allocator, ref NativeArray array) where T : struct { if (array.IsCreated) { if (array.Length != length) { array.Dispose(); array = new NativeArray(length, allocator); } } else { array = new NativeArray(length, allocator); } } /// /// The provider API for -derived classes to implement. /// public abstract class Provider : SubsystemProvider { /// /// Creates or resizes the if necessary. If /// has been allocated and its length is equal to , then this method /// does nothing. If its length is different, then it is first disposed before being assigned /// to a new NativeArray. /// /// The length that will have after this method returns. /// If allocation is necessary, this allocator will be used to create the new NativeArray. /// The array to create or resize. /// The type of elements held by the . protected static void CreateOrResizeNativeArrayIfNecessary( int length, Allocator allocator, ref NativeArray array) where T : struct { if (array.IsCreated) { if (array.Length != length) { array.Dispose(); array = new NativeArray(length, allocator); } } else { array = new NativeArray(length, allocator); } } /// /// Gets the boundary vertices of a given based on its . /// /// The of a . /// An to use if needs to be created. /// is not supported. Use if you need temporary memory. /// The boundary vertices will be stored here. If the given array is the same length as /// the number of vertices, it is overwritten with the new data. Otherwise, it is disposed and recreated with /// the correct length. /// /// See for a helper method implementation. /// public virtual void GetBoundary( TrackableId trackableId, Allocator allocator, ref NativeArray boundary) { throw new NotSupportedException("Boundary vertices are not supported."); } /// /// Gets a struct containing any changes to detected planes since the last /// time you called this method. You are responsible to the returned /// TrackableChanges instance. /// /// The default plane. You should use this to initialize the returned /// instance by passing it to the constructor /// . /// /// An Allocator to use when allocating the returned NativeArrays. /// The changes to planes since the last call to this method. public abstract TrackableChanges GetChanges(BoundedPlane defaultPlane, Allocator allocator); /// /// Get or set the requested . /// public abstract PlaneDetectionMode requestedPlaneDetectionMode { get; set; } /// /// Get the current plane detection mode in use by the provider. /// public virtual PlaneDetectionMode currentPlaneDetectionMode => PlaneDetectionMode.None; } } }