using System;
using MagicLeap.OpenXR.Features.Planes;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using UnityEngine;
using UnityEngine.XR.ARSubsystems;
namespace MagicLeap.OpenXR.Subsystems
{
public partial class MLXrPlaneSubsystem
{
public class PlaneBoundary
{
private bool Valid => Polygon.VertexCountOutput > 0;
private static void AssignAtomicSafetyHandle<T>(ref NativeArray<T> array, Allocator allocator) where T : struct
{
#if ENABLE_UNITY_COLLECTIONS_CHECKS
var safetyHandle = allocator == Allocator.Temp ? AtomicSafetyHandle.GetTempUnsafePtrSliceHandle() : AtomicSafetyHandle.Create();
NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref array, safetyHandle);
#endif
}
private unsafe void GetPolygon(Allocator allocator, ref NativeArray<Vector2> polygonOut)
{
if (!Valid)
{
throw new InvalidOperationException("This plane boundary is not valid.");
}
CreateOrResizeNativeArrayIfNecessary(PolygonVertexCount, allocator, ref polygonOut);
polygonOut = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray<Vector2>(Polygon.Vertices, PolygonVertexCount, allocator);
AssignAtomicSafetyHandle(ref polygonOut, allocator);
}
public int PolygonVertexCount => (int)Polygon.VertexCountOutput;
internal NativeArray<Vector2> GetPolygon(Allocator allocator)
{
var polygon = new NativeArray<Vector2>();
GetPolygon(allocator, ref polygon);
return polygon;
}
private int HoleCount => Holes.Length;
internal NativeArray<Vector2> GetHole(int index, Allocator allocator)
{
var hole = new NativeArray<Vector2>();
GetHole(index, allocator, ref hole);
return hole;
}
private unsafe void GetHole(int index, Allocator allocator, ref NativeArray<Vector2> polygonOut)
{
if (!Valid)
throw new InvalidOperationException("This plane boundary is not valid.");
if (index < 0)
{
throw new ArgumentOutOfRangeException(nameof(index), "Hole index must be greater than zero.");
}
if (index >= HoleCount)
{
throw new ArgumentOutOfRangeException(nameof(index), $"Hole index must be less than or equal to holeCount ({HoleCount}).");
}
var holes = Holes[index];
CreateOrResizeNativeArrayIfNecessary((int)holes.VertexCountOutput, allocator,ref polygonOut);
polygonOut = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray<Vector2>(holes.Vertices, (int)holes.VertexCountOutput, allocator);
AssignAtomicSafetyHandle(ref polygonOut, allocator);
}
internal NativeArray<XrPlaneDetectorPolygonBuffer> Holes;
internal XrPlaneDetectorPolygonBuffer Polygon;
internal Pose PlanePose;
internal TrackableId Id;
}
}
}