// %BANNER_BEGIN% // --------------------------------------------------------------------- // %COPYRIGHT_BEGIN% // Copyright (c) (2021-2022) Magic Leap, Inc. All Rights Reserved. // Use of this file is governed by the Software License Agreement, located here: https://www.magicleap.com/software-license-agreement-ml2 // Terms and conditions applicable to third-party materials accompanying this distribution may also be found in the top-level NOTICE file appearing herein. // %COPYRIGHT_END% // --------------------------------------------------------------------- // %BANNER_END% using System; using Unity.Collections; using Unity.Collections.LowLevel.Unsafe; using Unity.Jobs; namespace UnityEngine.XR.MagicLeap { public partial class PlanesSubsystem { /// /// Represents a collection of concave BoundedPlane boundaries obtained from /// . /// /// /// /// Each Magic Leap plane can have multiple plane boundaries. This collection /// represents the set of all boundaries associated with a particular plane. /// Note that unlike most boundaries associated with BoundedPlanes, /// these are not necessarily convex. /// /// The plane boundaries are tied to native resources which are managed /// by the . Typically, a PlaneBoundaryCollection /// is only valid until the next call to /// , /// so you should not hold onto an instance of this struct past a frame boundary. /// /// /// . public struct PlaneBoundaryCollection : IEquatable { /// /// Whether this collection is valid or not. Check for validity before using the index operator. /// public bool valid { get { return m_Boundaries.IsCreated; } } /// /// The number of boundaries in this collection. /// public int count { get { return m_Boundaries.Length; } } /// /// Attempts to get the plane boundary at index and, if successful, copies it to . /// is resized or created using if necessary. /// /// The index of the boundary to retrieve. /// The Allocator to use if must be recreated. /// Must be Allocator.TempJob or Allocator.Persistent. /// A NativeArray to fill with boundary points. If the array is not the correct size, it is disposed and recreated. /// If this method returns false, boundaryOut is unchanged. /// true if the boundary was successfully retrieved and was populated; otherwise, false. /// Thrown if is false. /// Thrown if is Allocator.Temp or Allocator.None. /// Thrown if is less than zero or greater than or equal to . public PlaneBoundary this[int index] { get { if (!valid) throw new InvalidOperationException("This boundary collection is not valid."); if (index < 0) throw new ArgumentOutOfRangeException(nameof(index), "Boundary index must be greater than zero."); if (index >= count) throw new ArgumentOutOfRangeException(nameof(index), $"Boundary index must be less than the boundary count ({count})."); return new PlaneBoundary(m_Boundaries[index], m_Pose); } } /// /// Get an enumerator, compatible with a duck-typed foreach. You typically would not call /// this directly, but is used by the compiler in a foreach statement. /// /// An Enumerator compatible with a duck-typed foreach. public Enumerator GetEnumerator() { return new Enumerator(this); } /// /// An enumerator which can be used by a foreach statement to iterate over /// the elements in a . /// public struct Enumerator { internal Enumerator(PlaneBoundaryCollection collection) { m_Index = -1; m_Collection = collection; } /// /// Moves to the next element in the collection. /// /// true if the next element is valid, or false if the Enumerator is already at the end of the collection. public bool MoveNext() { return ++m_Index < m_Collection.count; } /// /// Resets the enumerator. /// public void Reset() { m_Index = -1; } /// /// The current element in the enumerator. /// public PlaneBoundary Current { get { return m_Collection[m_Index]; } } /// /// Disposes of the enumerator. /// public void Dispose() { m_Collection = default(PlaneBoundaryCollection); m_Index = -1; } int m_Index; PlaneBoundaryCollection m_Collection; } /// /// Computes a hash code suitable for use in a Dictionary or HashSet. /// /// A hash code suitable for use in a Dictionary or HashSet. public override int GetHashCode() { unchecked { var hash = m_Boundaries.GetHashCode(); hash = hash * 486187739 + m_Pose.GetHashCode(); return hash; } } /// /// IEquatable interface. Compares for equality. /// /// The object to compare for equality. /// true if is of type and compares equal with . public override bool Equals(object obj) { return ((obj is PlaneBoundaryCollection) && Equals((PlaneBoundaryCollection)obj)); } /// /// IEquatable interface. Comapres for equality. /// /// The to compare against. /// true if all fields of this compare equal to . public bool Equals(PlaneBoundaryCollection other) { return m_Boundaries.Equals(other.m_Boundaries) && m_Pose.Equals(other.m_Pose); } /// /// Comapres for equality. Same as . /// /// The left-hand side of the comparison. /// The right-hand side of the comparison. /// true if all fields of this compare equal to . public static bool operator ==(PlaneBoundaryCollection lhs, PlaneBoundaryCollection rhs) { return lhs.Equals(rhs); } /// /// Comapres for inequality. Same as !. /// /// The left-hand side of the comparison. /// The right-hand side of the comparison. /// true if any of the fields of this are not equal to . public static bool operator !=(PlaneBoundaryCollection lhs, PlaneBoundaryCollection rhs) { return !lhs.Equals(rhs); } internal unsafe PlaneBoundaryCollection(Extensions.MLPlaneBoundaries planeBoundaries, Pose planePose) { m_Boundaries = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray( planeBoundaries.boundaries, (int)planeBoundaries.boundaries_count, Allocator.None); #if UNITY_EDITOR var safetyHandle = AtomicSafetyHandle.Create(); NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref m_Boundaries, safetyHandle); #endif m_Pose = planePose; } NativeArray m_Boundaries; Pose m_Pose; } } }