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() { }
}
}
}