using System.Collections.Generic; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using UnityEngine; #if UNITY_6000_3_OR_NEWER using UnityEngine.Assemblies; #endif namespace Unity.Pipeline { /// /// Version-stable handle to a Unity object id. In 6000.4 Unity replaced the int instance id with /// (a ulong-backed handle), made Object.GetInstanceID() / /// EditorUtility.InstanceIDToObject(int) obsolete-as-error, and is removing the /// EntityId<->int conversions. This struct stores the concrete id type for the /// running editor — on 6000.4+, int below — and converts implicitly to /// it so it can be passed straight to Unity APIs. All version branching for object ids is confined /// here. It (de)serializes as a single JSON integer (the raw ulong on 6000.4+, the int below). /// [JsonConverter(typeof(ObjectIdConverter))] public readonly struct ObjectId : System.IEquatable { #if UNITY_6000_4_OR_NEWER readonly EntityId m_Value; /// Wrap an . /// The entity id to wrap. public ObjectId(EntityId value) { m_Value = value; } /// Unwrap to the underlying . /// The id to unwrap. /// The underlying entity id. public static implicit operator EntityId(ObjectId id) => id.m_Value; /// Wrap an . /// The entity id to wrap. /// The wrapped id. public static implicit operator ObjectId(EntityId value) => new ObjectId(value); /// Raw 64-bit id — the canonical wire / serialization form. public ulong RawValue => EntityId.ToULong(m_Value); /// Reconstruct an from its raw wire value. /// The raw wire value. /// The reconstructed id. public static ObjectId FromRaw(ulong raw) => new ObjectId(EntityId.FromULong(raw)); /// Value-equality on the underlying id. /// The id to compare against. /// True if the underlying ids are equal. public bool Equals(ObjectId other) => m_Value.Equals(other.m_Value); /// Hash of the underlying id. /// The hash code. public override int GetHashCode() => m_Value.GetHashCode(); #else readonly int m_Value; /// Wrap a raw instance id. /// The instance id to wrap. public ObjectId(int value) { m_Value = value; } /// Unwrap to the underlying instance id. /// The id to unwrap. /// The underlying instance id. public static implicit operator int(ObjectId id) => id.m_Value; /// Wrap a raw instance id. /// The instance id to wrap. /// The wrapped id. public static implicit operator ObjectId(int value) => new ObjectId(value); /// Raw id — the canonical wire / serialization form. public long RawValue => m_Value; /// Reconstruct an from its raw wire value. /// The raw wire value. /// The reconstructed id. public static ObjectId FromRaw(long raw) => new ObjectId((int)raw); /// Value-equality on the underlying id. /// The id to compare against. /// True if the underlying ids are equal. public bool Equals(ObjectId other) => m_Value == other.m_Value; /// Hash of the underlying id. /// The hash code. public override int GetHashCode() => m_Value; #endif /// Value-equality on the underlying id. /// The object to compare against. /// True if is an equal . public override bool Equals(object obj) => obj is ObjectId other && Equals(other); /// The canonical numeric wire form (see ). /// The numeric string form. public override string ToString() => RawValue.ToString(); /// Parse the canonical numeric form produced by . /// The numeric string to parse. /// The parsed id. public static ObjectId Parse(string s) { #if UNITY_6000_4_OR_NEWER return FromRaw(ulong.Parse(s)); #else return FromRaw(long.Parse(s)); #endif } /// Try to parse the canonical numeric form produced by . /// The numeric string to parse. /// The parsed id, if successful. /// True if was a valid numeric form. public static bool TryParse(string s, out ObjectId id) { #if UNITY_6000_4_OR_NEWER if (ulong.TryParse(s, out var raw)) { id = FromRaw(raw); return true; } #else if (long.TryParse(s, out var raw)) { id = FromRaw(raw); return true; } #endif id = default; return false; } } /// JSON converter: an is a single integer on the wire. sealed class ObjectIdConverter : JsonConverter { /// Write an as its raw numeric wire value. /// The JSON writer. /// The id to write. /// The active serializer. public override void WriteJson(JsonWriter writer, ObjectId value, JsonSerializer serializer) { writer.WriteValue(value.RawValue); } /// Read an from either its numeric or string wire form. /// The JSON reader. /// The declared property type. /// The existing value, if any. /// Whether is valid. /// The active serializer. /// The parsed id, or default for an unrecognized token type. public override ObjectId ReadJson(JsonReader reader, System.Type objectType, ObjectId existingValue, bool hasExistingValue, JsonSerializer serializer) { var token = JToken.Load(reader); switch (token.Type) { case JTokenType.Integer: #if UNITY_6000_4_OR_NEWER return ObjectId.FromRaw(token.Value()); #else return ObjectId.FromRaw(token.Value()); #endif case JTokenType.String: return ObjectId.Parse((string)token); default: return default; } } } /// Small cross-Unity-version compatibility shims used across the package. public static class PipelineUtils { /// The on-disk path Unity loaded an assembly from. /// The assembly to query. /// The assembly's loaded path. public static string GetLoadedAssemblyPath(System.Reflection.Assembly a) { #if UNITY_6000_5_OR_NEWER return a.GetLoadedAssemblyPath(); #else return a.Location; #endif } /// Load a compiled assembly from raw bytes (used by the code-reload/eval compilers). /// The assembly image. /// The matching portable PDB, if any. /// The loaded assembly. public static System.Reflection.Assembly LoadFromBytes(byte[] bytes, byte[] pdb = null) { #if UNITY_6000_5_OR_NEWER return UnityEngine.Assemblies.CurrentAssemblies.LoadFromBytes(bytes, pdb); #else return System.Reflection.Assembly.Load(bytes, pdb); #endif } /// Find every loaded object of type , including inactive ones. /// The object type to search for. /// All matching objects. public static T[] FindObjectsByType() where T : Object { #if UNITY_6000_4_OR_NEWER return GameObject.FindObjectsByType(); #else return GameObject.FindObjectsByType(FindObjectsSortMode.None) ; #endif } /// All assemblies currently loaded in the domain. /// The loaded assemblies. public static IReadOnlyList GetLoadedAssemblies() { #if UNITY_6000_5_OR_NEWER return CurrentAssemblies.GetLoadedAssemblies(); #else return System.AppDomain.CurrentDomain.GetAssemblies(); #endif } /// The object's id as a version-stable (EntityId on 6000.4+, int below). /// The object to get an id for. /// The object's version-stable id. public static ObjectId GetObjectId(Object obj) { #if UNITY_6000_4_OR_NEWER return new ObjectId(obj.GetEntityId()); #else return new ObjectId(obj.GetInstanceID()); #endif } #if UNITY_EDITOR /// Resolve a loaded/scene object from its , or null if not found. public static Object IdToObject(ObjectId id) { #if UNITY_6000_4_OR_NEWER return UnityEditor.EditorUtility.EntityIdToObject(id); #elif UNITY_6000_3_OR_NEWER // EntityIdToObject is the non-obsolete resolver from 6000.3, but the ulong-backed ObjectId // (GetRawData/FromULong) doesn't exist until 6000.4 — so ObjectId is still int-backed here and // we route the int through the (non-obsolete on 6.3) int->EntityId conversion. return UnityEditor.EditorUtility.EntityIdToObject((int)id); #else return UnityEditor.EditorUtility.InstanceIDToObject((int)id); #endif } #endif } }