// %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;
}
}
}