|
|
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Runtime.Serialization.Formatters.Binary;
- using UnityEditor;
- using UnityEngine;
-
- public class ReferenceFinderData
- {
- //缓存路径
- private const string CACHE_PATH = "Library/ReferenceFinderCache";
- private const string CACHE_VERSION = "V1";
- //资源引用信息字典
- public Dictionary<string, AssetDescription> assetDict = new Dictionary<string, AssetDescription>();
-
- //收集资源引用信息并更新缓存
- public void CollectDependenciesInfo()
- {
- try
- {
- ReadFromCache();
- var allAssets = AssetDatabase.GetAllAssetPaths();
- int totalCount = allAssets.Length;
- for (int i = 0; i < allAssets.Length; i++)
- {
- //每遍历100个Asset,更新一下进度条,同时对进度条的取消操作进行处理
- if ((i % 100 == 0) && EditorUtility.DisplayCancelableProgressBar("Refresh", string.Format("Collecting {0} assets", i), (float)i / totalCount))
- {
- EditorUtility.ClearProgressBar();
- return;
- }
- if (File.Exists(allAssets[i]))
- ImportAsset(allAssets[i]);
- if (i % 2000 == 0)
- GC.Collect();
- }
- //将信息写入缓存
- EditorUtility.DisplayCancelableProgressBar("Refresh", "Write to cache", 1f);
- WriteToChache();
- //生成引用数据
- EditorUtility.DisplayCancelableProgressBar("Refresh", "Generating asset reference info", 1f);
- UpdateReferenceInfo();
- EditorUtility.ClearProgressBar();
- }
- catch(Exception e)
- {
- Debug.LogError(e);
- EditorUtility.ClearProgressBar();
- }
- }
-
- //通过依赖信息更新引用信息
- private void UpdateReferenceInfo()
- {
- foreach(var asset in assetDict)
- {
- foreach(var assetGuid in asset.Value.dependencies)
- {
- assetDict[assetGuid].references.Add(asset.Key);
- }
- }
- }
-
- //生成并加入引用信息
- private void ImportAsset(string path)
- {
- if (!path.StartsWith("Assets/"))
- return;
-
- //通过path获取guid进行储存
- string guid = AssetDatabase.AssetPathToGUID(path);
- //获取该资源的最后修改时间,用于之后的修改判断
- Hash128 assetDependencyHash = AssetDatabase.GetAssetDependencyHash(path);
- //如果assetDict没包含该guid或包含了修改时间不一样则需要更新
- if (!assetDict.ContainsKey(guid) || assetDict[guid].assetDependencyHash != assetDependencyHash.ToString())
- {
- //将每个资源的直接依赖资源转化为guid进行储存
- var guids = AssetDatabase.GetDependencies(path, false).
- Select(p => AssetDatabase.AssetPathToGUID(p)).
- ToList();
-
- //生成asset依赖信息,被引用需要在所有的asset依赖信息生成完后才能生成
- AssetDescription ad = new AssetDescription();
- ad.name = Path.GetFileNameWithoutExtension(path);
- ad.path = path;
- ad.assetDependencyHash = assetDependencyHash.ToString();
- ad.dependencies = guids;
-
- if (assetDict.ContainsKey(guid))
- assetDict[guid] = ad;
- else
- assetDict.Add(guid, ad);
- }
- }
-
- //读取缓存信息
- public bool ReadFromCache()
- {
- assetDict.Clear();
- if (!File.Exists(CACHE_PATH))
- {
- return false;
- }
-
- var serializedGuid = new List<string>();
- var serializedDependencyHash = new List<string>();
- var serializedDenpendencies = new List<int[]>();
- //反序列化数据
- FileStream fs = File.OpenRead(CACHE_PATH);
- try
- {
- BinaryFormatter bf = new BinaryFormatter();
- string cacheVersion = (string) bf.Deserialize(fs);
- if (cacheVersion != CACHE_VERSION)
- {
- return false;
- }
-
- EditorUtility.DisplayCancelableProgressBar("Import Cache", "Reading Cache", 0);
- serializedGuid = (List<string>) bf.Deserialize(fs);
- serializedDependencyHash = (List<string>) bf.Deserialize(fs);
- serializedDenpendencies = (List<int[]>) bf.Deserialize(fs);
- EditorUtility.ClearProgressBar();
- }
- catch
- {
- //兼容旧版本序列化格式
- return false;
- }
- finally
- {
- fs.Close();
- }
-
- for (int i = 0; i < serializedGuid.Count; ++i)
- {
- string path = AssetDatabase.GUIDToAssetPath(serializedGuid[i]);
- if (!string.IsNullOrEmpty(path))
- {
- var ad = new AssetDescription();
- ad.name = Path.GetFileNameWithoutExtension(path);
- ad.path = path;
- ad.assetDependencyHash = serializedDependencyHash[i];
- assetDict.Add(serializedGuid[i], ad);
- }
- }
-
- for(int i = 0; i < serializedGuid.Count; ++i)
- {
- string guid = serializedGuid[i];
- if (assetDict.ContainsKey(guid))
- {
- var guids = serializedDenpendencies[i].
- Select(index => serializedGuid[index]).
- Where(g => assetDict.ContainsKey(g)).
- ToList();
- assetDict[guid].dependencies = guids;
- }
- }
- UpdateReferenceInfo();
- return true;
- }
-
- //写入缓存
- private void WriteToChache()
- {
- if (File.Exists(CACHE_PATH))
- File.Delete(CACHE_PATH);
-
- var serializedGuid = new List<string>();
- var serializedDependencyHash = new List<string>();
- var serializedDenpendencies = new List<int[]>();
- //辅助映射字典
- var guidIndex = new Dictionary<string, int>();
- //序列化
- using (FileStream fs = File.OpenWrite(CACHE_PATH))
- {
- foreach (var pair in assetDict)
- {
- guidIndex.Add(pair.Key, guidIndex.Count);
- serializedGuid.Add(pair.Key);
- serializedDependencyHash.Add(pair.Value.assetDependencyHash);
- }
-
- foreach(var guid in serializedGuid)
- {
- //使用 Where 子句过滤目录
- int[] indexes = assetDict[guid].dependencies.
- Where(s => guidIndex.ContainsKey(s)).
- Select(s => guidIndex[s]).ToArray();
- serializedDenpendencies.Add(indexes);
- }
-
- BinaryFormatter bf = new BinaryFormatter();
- bf.Serialize(fs, CACHE_VERSION);
- bf.Serialize(fs, serializedGuid);
- bf.Serialize(fs, serializedDependencyHash);
- bf.Serialize(fs, serializedDenpendencies);
- }
- }
-
- //更新引用信息状态
- public void UpdateAssetState(string guid)
- {
- AssetDescription ad;
- if (assetDict.TryGetValue(guid,out ad) && ad.state != AssetState.NODATA)
- {
- if (File.Exists(ad.path))
- {
- //修改时间与记录的不同为修改过的资源
- if (ad.assetDependencyHash != AssetDatabase.GetAssetDependencyHash(ad.path).ToString())
- {
- ad.state = AssetState.CHANGED;
- }
- else
- {
- //默认为普通资源
- ad.state = AssetState.NORMAL;
- }
- }
- //不存在为丢失
- else
- {
- ad.state = AssetState.MISSING;
- }
- }
-
- //字典中没有该数据
- else if(!assetDict.TryGetValue(guid, out ad))
- {
- string path = AssetDatabase.GUIDToAssetPath(guid);
- ad = new AssetDescription();
- ad.name = Path.GetFileNameWithoutExtension(path);
- ad.path = path;
- ad.state = AssetState.NODATA;
- assetDict.Add(guid, ad);
- }
- }
-
- //根据引用信息状态获取状态描述
- public static string GetInfoByState(AssetState state)
- {
- if(state == AssetState.CHANGED)
- {
- return "<color=#F0672AFF>Changed</color>";
- }
- else if (state == AssetState.MISSING)
- {
- return "<color=#FF0000FF>Missing</color>";
- }
- else if(state == AssetState.NODATA)
- {
- return "<color=#FFE300FF>No Data</color>";
- }
- return "Normal";
- }
-
- public class AssetDescription
- {
- public string name = "";
- public string path = "";
- public string assetDependencyHash;
- public List<string> dependencies = new List<string>();
- public List<string> references = new List<string>();
- public AssetState state = AssetState.NORMAL;
- }
-
- public enum AssetState
- {
- NORMAL,
- CHANGED,
- MISSING,
- NODATA,
- }
- }
|