using System; using Unity.Collections; using Unity.Jobs; using UnityEngine.XR.ARSubsystems; namespace UnityEngine.XR.ARFoundation { /// /// Extension methods for UnityEngine.XR.ARSubsystems.MutableRuntimeReferenceImageLibrary. /// public static class MutableRuntimeReferenceImageLibraryExtensions { /// /// Asynchronously adds to . /// /// /// /// Image addition can take some time (several frames) due to extra processing that /// must occur to insert the image into the library. This is done using /// the [Unity Job System](https://docs.unity3d.com/Manual/JobSystem.html). The returned /// [JobHandle](https://docs.unity3d.com/ScriptReference/Unity.Jobs.JobHandle.html) can be used /// to chain together multiple tasks or to query for completion, but may be safely discarded if you do not need it. /// /// This job, like all Unity jobs, can have dependencies (using the ). If you are adding multiple /// images to the library, it is not necessary to pass a previous ScheduleAddImageJob JobHandle as the input /// dependency to the next ScheduleAddImageJob; they can be processed concurrently. /// /// The bytes of the are copied, so the texture may be safely /// destroyed after this method returns. /// /// /// The MutableRuntimeReferenceImageLibrary being extended. /// The Texture2D to use as image target. /// The name of the image. /// The physical width of the image, in meters. /// Input job dependencies (optional). /// A [JobHandle](https://docs.unity3d.com/ScriptReference/Unity.Jobs.JobHandle.html) which can be used /// to chain together multiple tasks or to query for completion. May be safely discarded. /// Thrown if is null. /// Thrown if is null. /// Thrown if is not readable. public static JobHandle ScheduleAddImageJob( this MutableRuntimeReferenceImageLibrary library, Texture2D texture, string name, float? widthInMeters, JobHandle inputDeps = default(JobHandle)) { if (ReferenceEquals(library, null)) throw new ArgumentNullException(nameof(library)); if (texture == null) throw new ArgumentNullException(nameof(texture)); if (!texture.isReadable) throw new InvalidOperationException("The texture must be readable to be used as the source for a reference image."); var imageBytesCopy = new NativeArray(texture.GetRawTextureData(), Allocator.Persistent); try { Nullable size = null; if (widthInMeters.HasValue) { size = new Vector2(widthInMeters.Value, widthInMeters.Value * (float)texture.height / (float)texture.width); } var referenceImage = new XRReferenceImage(SerializableGuid.empty, SerializableGuid.empty, size, name, texture); var jobHandle = library.ScheduleAddImageJob(imageBytesCopy, new Vector2Int(texture.width, texture.height), texture.format, referenceImage, inputDeps); new DeallocateJob { data = imageBytesCopy }.Schedule(jobHandle); return jobHandle; } catch { imageBytesCopy.Dispose(); throw; } } struct DeallocateJob : IJob { [DeallocateOnJobCompletion] public NativeArray data; public void Execute() {} } } }