using System; using System.Xml; using UnityEngine; namespace UnityEditor.XR.ARKit { /// /// Represents metadata associated with a .arobject archive. These archives /// are the source data for . /// /// /// /// public struct ARObjectInfo : IEquatable { /// /// Parses the and constructs a new . /// /// A valid PlistDocument to parse. /// Thrown if is null. public ARObjectInfo(XmlDocument plist) { if (plist == null) throw new ArgumentNullException(nameof(plist)); // Parse the plist var root = new Plist(plist).root; version = root["Version"].AsInt32() ?? 0; trackingDataReference = root["TrackingDataReference"].AsString() ?? ""; imageReference = root["ImageReference"].AsString() ?? ""; var dict = root["ReferenceOrigin"]; if (dict != null) { var rotation = FlipHandedness(dict["rotation"].AsQuaternion() ?? Quaternion.identity); var translation = FlipHandedness(dict["translation"].AsVector3() ?? Vector3.zero); referenceOrigin = new Pose(translation, rotation); } else { referenceOrigin = Pose.identity; } } static Vector3 FlipHandedness(Vector3 value) => new Vector3(value.x, value.y, -value.z); static Quaternion FlipHandedness(Quaternion value) => new Quaternion(value.x, value.y, -value.z, -value.w); /// /// The filename of an image contained within the archive that can be used as a preview for the scanned object. /// public string imageReference { get; } /// /// The reference origin for the scanned object. /// public Pose referenceOrigin { get; } /// /// The filename of the source data representing the scanned object. /// public string trackingDataReference { get; } /// /// The version of the metadata format. /// public int version { get; } /// /// true if the represents valid data, otherwise false. /// public bool valid => version > 0; /// /// Tests for equality. /// /// The other to compare against. /// `True` if every field in is equal to this , otherwise false. public bool Equals(ARObjectInfo other) { return string.Equals(imageReference, other.imageReference) && referenceOrigin.Equals(other.referenceOrigin) && string.Equals(trackingDataReference, other.trackingDataReference) && (version == other.version); } /// /// Tests for equality. /// /// The `object` to compare against. /// `True` if is of type and /// also returns `true`; otherwise `false`. public override bool Equals(object obj) => obj is ARObjectInfo info && Equals(info); /// /// Generates a hash suitable for use with containers like `HashSet` and `Dictionary`. /// /// A hash code generated from this object's fields. public override int GetHashCode() { unchecked { var hash = (imageReference == null ? 0 : imageReference.GetHashCode()); hash = hash * 486187739 + referenceOrigin.GetHashCode(); hash = hash * 486187739 + (trackingDataReference == null ? 0 : trackingDataReference.GetHashCode()); hash = hash * 486187739 + version.GetHashCode(); return hash; } } /// /// Tests for equality. Same as . /// /// The left-hand side of the comparison. /// The right-hand side of the comparison. /// `True` if is equal to , otherwise `false`. public static bool operator ==(ARObjectInfo lhs, ARObjectInfo rhs) => lhs.Equals(rhs); /// /// Tests for inequality. Same as `!`. /// /// The left-hand side of the comparison. /// The right-hand side of the comparison. /// `True` if is not equal to , otherwise `false`. public static bool operator !=(ARObjectInfo lhs, ARObjectInfo rhs) => !lhs.Equals(rhs); } }