using System; using Unity.Collections; using Unity.Jobs; using UnityEngine.XR.ARSubsystems; namespace UnityEngine.XR.ARFoundation { /// /// Extension methods for /// [MutableRuntimeReferenceImageLibrary](xref:UnityEngine.XR.ARSubsystems.MutableRuntimeReferenceImageLibrary). /// public static class MutableRuntimeReferenceImageLibraryExtensions { /// /// Asynchronously adds to . /// /// /// This method is deprecated. Use instead. /// /// 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](xref:Unity.Jobs.JobHandle) can /// be used to chain together multiple tasks or to query for completion, but you can 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 /// `JobHandle` as the input dependency to the next /// ; they can be processed concurrently. /// /// The bytes of the are copied, so you can safely destroy the texture /// after this method returns. /// /// The being extended. /// The [Texture2D](xref:UnityEngine.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](xref:Unity.Jobs.JobHandle) which can be used to chain together multiple tasks or to /// query for completion. Can be safely discarded. /// Thrown if is `null`. /// Thrown if is `null`. /// Thrown if hasn't reached the ready state. /// Thrown if is not readable. [Obsolete("Use " + nameof(ScheduleAddImageWithValidationJob) + " instead. (2020-10-20)")] public static JobHandle ScheduleAddImageJob( this MutableRuntimeReferenceImageLibrary library, Texture2D texture, string name, float? widthInMeters, JobHandle inputDeps = default) => ScheduleAddImageWithValidationJob(library, texture, name, widthInMeters, inputDeps).jobHandle; /// /// Asynchronously adds to . /// /// /// The bytes of the are copied, so the texture may be safely /// destroyed after this method returns. /// /// > [!TIP] /// > Do not call this method on your app's first frame. ARSession.state should /// > be or before you schedule an add image job. You can implement a /// > MonoBehaviour's Start /// > method as a coroutine and `yield` until the AR Session state is SessionTracking. /// /// The being extended. /// The to add to . /// The name of the image. /// The physical width of the image, in meters. /// Input job dependencies (optional). /// Returns an that you can use to query for job completion and /// whether the image was successfully added. /// If image validity can be determined, invalid images will be not be added. /// Thrown if is . /// Thrown if is . /// Thrown if hasn't reached the ready state. /// Thrown if is not readable. public static AddReferenceImageJobState ScheduleAddImageWithValidationJob( this MutableRuntimeReferenceImageLibrary library, Texture2D texture, string name, float? widthInMeters, JobHandle inputDeps = default) { if (ARSession.state < ARSessionState.Ready) throw new InvalidOperationException("The ARSession has not reached the ready state. Ensure that AR is supported and running before you call this method."); 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 { Vector2? size = null; if (widthInMeters.HasValue) { size = new Vector2(widthInMeters.Value, widthInMeters.Value * texture.height / texture.width); } var referenceImage = new XRReferenceImage(SerializableGuid.empty, SerializableGuid.empty, size, name, texture); var state = library.ScheduleAddImageWithValidationJob(imageBytesCopy, new Vector2Int(texture.width, texture.height), texture.format, referenceImage, inputDeps); new DeallocateJob { data = imageBytesCopy }.Schedule(state.jobHandle); return state; } catch { imageBytesCopy.Dispose(); throw; } } struct DeallocateJob : IJob { [DeallocateOnJobCompletion] public NativeArray data; public void Execute() { } } } }