using System; using System.Collections; using System.Collections.Generic; #if UNITY_EDITOR using System.Linq; using UnityEditor; #endif namespace UnityEngine.XR.ARSubsystems { /// /// A reference image library is a collection of images to search for in the physical environment when image /// tracking is enabled. /// /// /// Image libraries are immutable at runtime. To create and manipulate an image library via Editor scripts, use the /// extension methods in [XRReferenceImageLibraryExtensions](UnityEditor.XR.ARSubsystems.XRReferenceImageLibraryExtensions). /// If you need to mutate the library at runtime, see . /// [CreateAssetMenu(fileName="ReferenceImageLibrary", menuName="XR/Reference Image Library", order=1001)] [HelpURL("features/image-tracking")] public class XRReferenceImageLibrary : ScriptableObject , IReferenceImageLibrary , ISerializationCallbackReceiver , IEnumerable { /// /// The number of images in the library. /// public int count => m_Images.Count; /// /// (Read Only) Binary data associated with a string key. /// /// /// This is used by providers to associate provider-specific data with the library. During Player Build (in an /// [IPreprocessBuildWithReport.OnPreprocessBuild](xref:UnityEditor.Build.IPreprocessBuildWithReport.OnPreprocessBuild(UnityEditor.Build.Reporting.BuildReport)) /// callback), the data store is first cleared. Each enabled provider then has an opportunity to add one or more /// entries for itself. /// /// Providers can use this to store a serialized version of the image library specific to that provider. /// Set data with . /// public IReadOnlyDictionary dataStore => m_DataStore.dictionary; /// /// Gets an enumerator which can be used to iterate over the reference images in this library. /// /// /// This examples iterates over the reference images contained in the library. /// /// XRReferenceImageLibrary imageLibrary = ... /// foreach (var referenceImage in imageLibrary) /// { /// Debug.LogFormat("Image guid: {0}", referenceImage.guid); /// } /// /// /// Returns an enumerator which can be used to iterate over the reference images in the library. public List.Enumerator GetEnumerator() => m_Images.GetEnumerator(); /// /// Gets an enumerator which can be used to iterate over the reference images in this library. /// /// Returns an object which can be used to iterate over the reference images in this library. IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); /// /// Gets an enumerator which can be used to iterate over the reference images in this library. /// /// Returns an object which can be used to iterate over the reference images in this library. IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); /// /// Get an image by index. /// /// The index of the image in the library. Must be between 0 and count - 1. /// The at . /// Thrown if is not between 0 and - 1. public XRReferenceImage this[int index] { get { if (count == 0) throw new IndexOutOfRangeException("The reference image library is empty; cannot index into it."); if (index < 0 || index >= count) throw new IndexOutOfRangeException(string.Format("{0} is out of range. 'index' must be between 0 and {1}", index, count - 1)); return m_Images[index]; } } /// /// Get the index of in the image library. /// /// The to find. /// The zero-based index of the , or -1 if not found. public int indexOf(XRReferenceImage referenceImage) { return m_Images.IndexOf(referenceImage); } /// /// A GUID associated with this reference library. /// The GUID is used to uniquely identify this library at runtime. /// public Guid guid => GuidUtil.Compose(m_GuidLow, m_GuidHigh); /// /// Invoked before serialization. /// void ISerializationCallbackReceiver.OnBeforeSerialize() => m_DataStore.Serialize(); /// /// Invoked after serialization. /// void ISerializationCallbackReceiver.OnAfterDeserialize() => m_DataStore.Deserialize(); #if UNITY_EDITOR internal static IEnumerable All() => AssetDatabase .FindAssets($"t:{nameof(XRReferenceImageLibrary)}") .Select(AssetDatabase.GUIDToAssetPath) .Select(AssetDatabase.LoadAssetAtPath); void Awake() { // We need to generate a new guid for new assets var shouldGenerateNewGuid = (m_GuidLow == 0 && m_GuidHigh == 0); // If this asset was duplicated from another, then we need to generate a unique guid, so // check against all existing XRReferenceImageLibraries in the asset database. if (!shouldGenerateNewGuid) { var currentGuid = guid; shouldGenerateNewGuid = All().Any(library => library != this && library.guid.Equals(currentGuid)); } if (shouldGenerateNewGuid) { var bytes = Guid.NewGuid().ToByteArray(); m_GuidLow = BitConverter.ToUInt64(bytes, 0); m_GuidHigh = BitConverter.ToUInt64(bytes, 8); EditorUtility.SetDirty(this); } } internal void InternalClearDataStore() { m_DataStore.dictionary.Clear(); EditorUtility.SetDirty(this); } internal void InternalSetDataForKey(string key, byte[] data) { bool isDirty; if (data == null) { isDirty = m_DataStore.dictionary.Remove(key); } else { m_DataStore.dictionary[key] = data; isDirty = true; } if (isDirty) { EditorUtility.SetDirty(this); } } #endif #pragma warning disable CS0649 [SerializeField] ulong m_GuidLow; [SerializeField] ulong m_GuidHigh; #pragma warning restore CS0649 [SerializeField] SerializableDictionary m_DataStore = new SerializableDictionary(); [SerializeField] internal List m_Images = new List(); } }