Rasagar/Library/PackageCache/com.unity.probuilder/AssetIdRemapUtility/Editor/AssetId.cs

380 lines
11 KiB
C#
Raw Normal View History

2024-08-26 13:07:20 -07:00
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEditor;
using UObject = UnityEngine.Object;
namespace UnityEngine.ProBuilder.AssetIdRemapUtility
{
[Serializable]
sealed class AssetIdentifierTuple
{
public AssetId source;
public AssetId destination;
public AssetIdentifierTuple()
{
source = null;
destination = null;
}
public AssetIdentifierTuple(AssetId src, AssetId dest)
{
source = src ?? new AssetId();
destination = dest ?? new AssetId();
}
public bool AssetEquals(AssetIdentifierTuple other)
{
return AssetId.IsValid(source) == AssetId.IsValid(other.source) &&
source.AssetEquals(other.source) &&
AssetId.IsValid(destination) == AssetId.IsValid(other.destination) &&
destination.AssetEquals(other.destination);
}
}
[Serializable]
class StringTuple
{
public string key;
public string value;
public StringTuple(string k, string v)
{
key = k;
value = v;
}
}
enum Origin
{
Source,
Destination
}
[Serializable]
class AssetIdRemapObject
{
public List<string> sourceDirectory = new List<string>();
public string destinationDirectory = null;
public List<AssetIdentifierTuple> map = new List<AssetIdentifierTuple>();
public AssetIdentifierTuple this[int i]
{
get { return map[i]; }
set { map[i] = value; }
}
public void Clear(Origin origin)
{
switch (origin)
{
case Origin.Source:
sourceDirectory.Clear();
for (int i = 0, c = map.Count; i < c; i++)
map[i].source.Clear();
break;
case Origin.Destination:
destinationDirectory = "";
for (int i = 0, c = map.Count; i < c; i++)
map[i].destination.Clear();
break;
}
map = map.Where(x => AssetId.IsValid(x.source) || AssetId.IsValid(x.destination)).ToList();
}
public void Delete(IEnumerable<AssetIdentifierTuple> entries)
{
map.RemoveAll(entries.Contains);
}
public void Merge(IEnumerable<AssetIdentifierTuple> entries)
{
var types = entries.SelectMany(x => new[] { x.source.assetType, x.destination.assetType });
if (types.Where(x => !string.IsNullOrEmpty(x)).Distinct().Count() > 1)
{
Debug.LogError("Attempting to map entries of multiple types! This is not allowed.");
return;
}
var arr = entries as AssetIdentifierTuple[] ?? entries.ToArray();
var src = arr.Where(x => AssetId.IsValid(x.source) && !AssetId.IsValid(x.destination)).ToArray();
var dst = arr.Where(x => AssetId.IsValid(x.destination)).ToArray();
if (dst.Length != 1)
{
Debug.LogError("Merging AssetId entries requires only one valid destination entry be selected.");
return;
}
var d = dst.First().destination;
foreach (var s in src)
map.Add(new AssetIdentifierTuple(new AssetId(s.source), new AssetId(d)));
map.RemoveAll(src.Contains);
map.RemoveAll(x => dst.Contains(x) && !AssetId.IsValid(x.source));
}
}
[Serializable]
class AssetId : IEquatable<AssetId>
{
const string k_MonoScriptTypeString = "UnityEditor.MonoScript";
static readonly string[] k_MonoScriptTypeSplit = new string[1] {"::"};
enum AssetType
{
Unknown = 0,
Default = 1,
MonoScript = 2,
// add more as special cases require
}
/// <summary>
/// A path relative to the root asset directory (ex, ProBuilder/About/Hello.cs).
/// Stored per-asset because the path may change between upgrades. A single file name is stored at the tuple
/// level.
/// </summary>
public string localPath
{
get { return m_LocalPath; }
}
public string name
{
get { return m_Name; }
}
/// <summary>
/// Return the backing type of this asset. If the asset is a MonoScript, the associated mono class will be
/// returned. To get the Unity asset type use assetType.
/// </summary>
public string type
{
get { return IsMonoScript() ? m_MonoScriptClass : m_Type; }
}
public string assetType
{
get { return IsMonoScript() ? k_MonoScriptTypeString : m_Type; }
}
/// <summary>
/// File Ids associated with this asset.
/// </summary>
public string fileId
{
get { return m_FileId; }
}
/// <summary>
/// Asset GUID.
/// </summary>
public string guid
{
get { return m_Guid; }
}
[SerializeField]
string m_Guid;
[SerializeField]
string m_FileId;
[SerializeField]
string m_LocalPath;
[SerializeField]
string m_Name;
[SerializeField]
string m_Type;
// the remaining properties are only relevant to monoscript files
AssetType m_InternalType = AssetType.Unknown;
string m_MonoScriptClass = null;
#pragma warning disable 414
bool m_IsEditorScript = false;
#pragma warning restore 414
public AssetId()
{
Clear();
}
public AssetId(AssetId other)
{
m_Guid = other.m_Guid;
m_FileId = other.m_FileId;
m_LocalPath = other.m_LocalPath;
m_Name = other.m_Name;
m_Type = other.m_Type;
}
public AssetId(UObject obj, string file, string guid, string localPath = null)
{
if (obj == null)
throw new SystemException("Cannot initialize an AssetIdentifier with a null object");
if (string.IsNullOrEmpty(guid))
throw new SystemException("Cannot initialize an AssetIdentifier without a GUID");
if (string.IsNullOrEmpty(file))
throw new SystemException("Cannot initialize an AssetIdentifier without a FileId");
m_FileId = file;
m_Guid = guid;
m_Name = obj.name;
m_LocalPath = localPath;
m_Type = GetUObjectTypeString(obj);
}
static string GetUObjectTypeString(UObject obj)
{
MonoScript ms = obj as MonoScript;
if (ms != null)
return string.Format("{0}{1}{2}", obj.GetType().ToString(), k_MonoScriptTypeSplit[0], ms.GetClass());
return obj.GetType().ToString();
}
public bool Equals(AssetId other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return string.Equals(m_Guid, other.m_Guid) &&
string.Equals(m_FileId, other.m_FileId) &&
string.Equals(m_LocalPath, other.m_LocalPath);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
var id = obj as AssetId;
if (id != null) return Equals(id);
return false;
}
public override int GetHashCode()
{
int hash = 0;
unchecked
{
hash = (hash * 7) + (string.IsNullOrEmpty(m_Guid) ? 0 : m_Guid.GetHashCode());
hash = (hash * 7) + (string.IsNullOrEmpty(m_FileId) ? 0 : m_FileId.GetHashCode());
hash = (hash * 7) + (string.IsNullOrEmpty(m_LocalPath) ? 0 : m_LocalPath.GetHashCode());
}
return hash;
}
public void Clear()
{
m_Guid = "";
m_FileId = "";
m_LocalPath = "";
m_Name = "";
m_Type = "";
m_InternalType = AssetType.Unknown;
m_MonoScriptClass = null;
m_IsEditorScript = false;
}
public void SetPathRelativeTo(string dir)
{
m_LocalPath = m_LocalPath.Replace(dir, "");
}
public static bool IsValid(AssetId id)
{
return !string.IsNullOrEmpty(id == null ? null : id.m_Guid);
}
public bool IsMonoScript()
{
if (m_InternalType == AssetType.Unknown)
{
if (m_Type.StartsWith(k_MonoScriptTypeString))
{
m_InternalType = AssetType.MonoScript;
try
{
m_MonoScriptClass = m_Type.Split(k_MonoScriptTypeSplit, StringSplitOptions.RemoveEmptyEntries)[1];
if (m_LocalPath.EndsWith(".dll", StringComparison.InvariantCultureIgnoreCase))
m_IsEditorScript = m_LocalPath.StartsWith("Editor/") || m_LocalPath.Contains("/Editor/") || PackageImporter.IsEditorPluginEnabled(guid);
else
m_IsEditorScript = m_LocalPath.StartsWith("Editor/") || m_LocalPath.Contains("/Editor/");
}
catch
{
m_MonoScriptClass = "null";
// pb_Log.Debug("Failed parsing type from monoscript \"" + m_Name + "\" (" + m_Type + ")");
}
}
else
{
m_InternalType = AssetType.Default;
}
}
return m_InternalType == AssetType.MonoScript;
}
bool GetNamespaceAndType(string classType, out string namespaceString, out string typeString)
{
namespaceString = null;
typeString = null;
if (string.IsNullOrEmpty(classType))
return false;
int last = classType.LastIndexOf('.');
if (last < 0)
{
typeString = classType;
return true;
}
namespaceString = classType.Substring(0, last);
typeString = classType.Substring(last + 1, (classType.Length - last) - 1);
return true;
}
public bool AssetEquals(AssetId other)
{
if (!assetType.Equals(other.assetType))
return false;
return localPath.Equals(other.localPath);
}
/// <summary>
/// Does the object this id reference exist in the project?
/// </summary>
/// <returns></returns>
public bool ExistsInProject()
{
string assetPath = AssetDatabase.GUIDToAssetPath(m_Guid);
if (string.IsNullOrEmpty(assetPath))
return false;
var assetObj = AssetDatabase.LoadAssetAtPath<UObject>(assetPath);
if (assetObj == null)
return false;
return m_Type.Equals(GetUObjectTypeString(assetObj));
}
}
}