// SPDX-FileCopyrightText: 2025 Unity Technologies and the glTFast authors // SPDX-License-Identifier: Apache-2.0 using System; using System.Runtime.InteropServices; using Unity.Collections; using Unity.Collections.LowLevel.Unsafe; using UnityEngine; namespace GLTFast { /// /// Wraps a managed TIn[] in a NativeArray<TOut>without copying memory. /// Use for internal development instead. /// /// Type of items in an input array. /// Type of items in output NativeArray (might differ from input type TIn). [Obsolete("This is going to be removed from the public API in a future release. " + "For internal development, refer to ReadOnlyNativeArrayFromManagedArray.")] public sealed class ManagedNativeArray : IDisposable where TIn : unmanaged where TOut : unmanaged { NativeArray m_NativeArray; GCHandle m_BufferHandle; #if ENABLE_UNITY_COLLECTIONS_CHECKS AtomicSafetyHandle m_SafetyHandle; #endif readonly bool m_Pinned; /// /// Wraps a managed TIn[] in a NativeArray<TOut>without copying memory. /// /// The original TIn[] to convert into a NativeArray<TOut> public unsafe ManagedNativeArray(TIn[] original) { if (original != null) { m_BufferHandle = GCHandle.Alloc(original, GCHandleType.Pinned); fixed (void* bufferAddress = &original[0]) { m_NativeArray = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray(bufferAddress, original.Length, Allocator.None); #if ENABLE_UNITY_COLLECTIONS_CHECKS m_SafetyHandle = AtomicSafetyHandle.Create(); NativeArrayUnsafeUtility.SetAtomicSafetyHandle(array: ref m_NativeArray, m_SafetyHandle); #endif } m_Pinned = true; } else { m_NativeArray = new NativeArray(); } } /// /// Points to the managed NativeArray<TOut>. /// public NativeArray nativeArray => m_NativeArray; /// /// Disposes the managed NativeArray<TOut>. /// public void Dispose() { if (m_Pinned) { #if ENABLE_UNITY_COLLECTIONS_CHECKS AtomicSafetyHandle.CheckDeallocateAndThrow(m_SafetyHandle); AtomicSafetyHandle.Release(m_SafetyHandle); #endif m_BufferHandle.Free(); } } } }