123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286 |
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using UnityEditor;
- using UnityEditorInternal;
- using Debug = UnityEngine.Debug;
- using Object = UnityEngine.Object;
- namespace Asset_Cleaner {
- class BacklinkStore {
- public bool Initialized { get; private set; }
- public Dictionary<string, long> UnusedFiles { get; private set; }
- public Dictionary<string, long> UnusedScenes { get; private set; }
- public Dictionary<string, BwMeta> Backward { get; private set; }
- public Dictionary<string, UnusedQty> FoldersWithQty { get; private set; }
- Dictionary<string, FwMeta> _forward;
- List<string> Folders { get; set; }
- public void Init() {
- FoldersWithQty = new Dictionary<string, UnusedQty>();
- _forward = new Dictionary<string, FwMeta>();
- Backward = new Dictionary<string, BwMeta>();
- var defaultAss = typeof(DefaultAsset);
- var asmdefAss = typeof(AssemblyDefinitionAsset);
- var paths = AssetDatabase.GetAllAssetPaths()
- .Distinct()
- .Where(s => s.StartsWith("Assets") || s.StartsWith("ProjectSettings"))
- .Where(p => {
- var t = AssetDatabase.GetMainAssetTypeAtPath(p);
- return !t.IsAssignableFromInverse(defaultAss) && !t.IsAssignableFromInverse(asmdefAss);
- })
- .ToArray();
- var i = 0f;
- var total = (float) paths.Length;
- foreach (var path in paths) {
- _FillFwAndBacklinks(path);
- var percent = i * 100f / total;
- if (Math.Abs(percent % 5f) < 0.01f) {
- if (EditorUtility.DisplayCancelableProgressBar(
- "Please wait...",
- "Building the cache...", percent))
- Debug.LogError("Cache build aborted");
- }
- i++;
- }
- EditorUtility.ClearProgressBar();
- // FillFoldersWithQtyByPaths
- List<string> foldersAll = new List<string>();
- foreach (var path in paths) {
- var folders = GetAllFoldersFromPath(path);
- foldersAll.AddRange(folders);
- }
- Folders = foldersAll.Distinct().OrderBy(p => p).ToList();
- UpdateUnusedAssets();
- Initialized = true;
- }
- void _FillFwAndBacklinks(string path) {
- var dependencies = _Dependencies(path);
- var hs = new FwMeta {Dependencies = new HashSet<string>(dependencies)};
- _forward.Add(path, hs);
- foreach (var backPath in dependencies) {
- if (!Backward.TryGetValue(backPath, out var val)) {
- val = new BwMeta();
- val.Lookup = new HashSet<string>();
- Backward.Add(backPath, val);
- }
- val.Lookup.Add(path);
- }
- }
- void UpdateFoldersWithQtyByPath(string path) {
- var folders = GetAllFoldersFromPath(path);
- foreach (var folder in folders) {
- if (!Folders.Exists(p => p == folder))
- Folders.Add(folder);
- }
- }
- static List<string> GetAllFoldersFromPath(string p) {
- var result = new List<string>();
- var i = p.IndexOf('/', 0);
- while (i > 0) {
- var item = p.Substring(0, i);
- result.Add(item);
- i = p.IndexOf('/', i + 1);
- }
- return result.Distinct().ToList();
- }
- public void UpdateUnusedAssets() {
- var all = new HashSet<string>(_forward.Keys);
- var withBacklinks =
- new HashSet<string>(Backward.Where(kv => kv.Value.Lookup.Count > 0).Select(kv => kv.Key));
- all.ExceptWith(withBacklinks);
- all.RemoveWhere(SearchUtils.IsFileIgrnoredBySettings);
- var unusedAssets = all;
- var scenes = unusedAssets.Where(s =>
- AssetDatabase.GetMainAssetTypeAtPath(s).IsAssignableFromInverse(typeof(SceneAsset))).ToArray();
- unusedAssets.ExceptWith(scenes);
- var files = unusedAssets;
- UnusedFiles = new Dictionary<string, long>();
-
- foreach (var file in files) UnusedFiles[file] = CommonUtils.Size(file);
- UnusedScenes = new Dictionary<string, long>();
- foreach (var scene in scenes) UnusedScenes[scene] = CommonUtils.Size(scene);
-
- // UpdateFoldersWithQty();
- foreach (var folder in Folders) {
- var unusedFilesQty = UnusedFiles.Count(p => p.Key.StartsWith(folder));
- var unusedScenesQty = UnusedScenes.Count(p => p.Key.StartsWith(folder));
- long size = 0;
- size = UnusedFiles.Where((p => p.Key.StartsWith(folder))).Sum(p => p.Value);
- size += UnusedScenes.Where(p => p.Key.StartsWith(folder)).Sum(p => p.Value);
- FoldersWithQty.TryGetValue(folder, out var folderWithQty);
- if (folderWithQty == null) {
- FoldersWithQty.Add(folder, new UnusedQty(unusedFilesQty, unusedScenesQty, size));
- }
- else {
- folderWithQty.UnusedFilesQty = unusedFilesQty;
- folderWithQty.UnusedScenesQty = unusedScenesQty;
- folderWithQty.UnusedSize = size;
- }
- }
- }
- public void Remove(string path) {
- if (!_forward.TryGetValue(path, out var fwMeta))
- return;
- foreach (var dependency in fwMeta.Dependencies) {
- if (!Backward.TryGetValue(dependency, out var dep)) continue;
- dep.Lookup.Remove(path);
- }
- _forward.Remove(path);
- UpdateFoldersWithQtyByPath(path);
- }
- public void Replace(string src, string dest) {
- _Upd(_forward);
- _Upd(Backward);
- UpdateFoldersWithQtyByPath(dest);
- void _Upd<T>(Dictionary<string, T> dic) {
- if (!dic.TryGetValue(src, out var refs)) return;
- dic.Remove(src);
- dic.Add(dest, refs);
- }
- }
- public void RebuildFor(string path, bool remove) {
- if (!_forward.TryGetValue(path, out var fwMeta)) {
- fwMeta = new FwMeta();
- _forward.Add(path, fwMeta);
- }
- else if (remove) {
- foreach (var dependency in fwMeta.Dependencies) {
- if (!Backward.TryGetValue(dependency, out var backDep)) continue;
- backDep.Lookup.Remove(path);
- }
- fwMeta.Dependencies = null;
- }
- var dependencies = _Dependencies(path);
- fwMeta.Dependencies = new HashSet<string>(dependencies);
- foreach (var backPath in dependencies) {
- if (!Backward.TryGetValue(backPath, out var bwMeta)) {
- bwMeta = new BwMeta {Lookup = new HashSet<string>()};
- Backward.Add(backPath, bwMeta);
- }
- else if (remove)
- bwMeta.Lookup.Remove(path);
- bwMeta.Lookup.Add(path);
- }
- if (!remove) {
- UpdateFoldersWithQtyByPath(path);
- }
- }
- static string[] _Dependencies(string s) {
- if (s[0] == 'A')
- return AssetDatabase.GetDependencies(s, false);
- var obj = LoadAllOrMain(s)[0];
- return GetDependenciesManualPaths().ToArray();
- Object[] LoadAllOrMain(string assetPath) {
- // prevents error "Do not use readobjectthreaded on scene objects!"
- return typeof(SceneAsset) == AssetDatabase.GetMainAssetTypeAtPath(assetPath)
- ? new[] {AssetDatabase.LoadMainAssetAtPath(assetPath)}
- : AssetDatabase.LoadAllAssetsAtPath(assetPath);
- }
- IEnumerable<string> GetDependenciesManualPaths() {
- if (obj is EditorBuildSettings) {
- foreach (var scene in EditorBuildSettings.scenes)
- yield return scene.path;
- }
- using (var so = new SerializedObject(obj)) {
- var props = so.GetIterator();
- while (props.Next(true)) {
- switch (props.propertyType) {
- case SerializedPropertyType.ObjectReference:
- var propsObjectReferenceValue = props.objectReferenceValue;
- if (!propsObjectReferenceValue) continue;
- var assetPath = AssetDatabase.GetAssetPath(propsObjectReferenceValue);
- yield return assetPath;
- break;
- #if later
- case SerializedPropertyType.Generic:
- case SerializedPropertyType.ExposedReference:
- case SerializedPropertyType.ManagedReference:
- break;
- #endif
- default:
- continue;
- }
- }
- }
- }
- }
- class FwMeta {
- public HashSet<string> Dependencies;
- }
- public class BwMeta {
- public HashSet<string> Lookup;
- }
- public class UnusedQty {
- public int UnusedFilesQty;
- public int UnusedScenesQty;
- public long UnusedSize;
- public UnusedQty() {
- Init(0, 0, 0);
- }
- public UnusedQty(int unusedFilesQty, int unusedScenesQty, long unusedSize) {
- Init(unusedFilesQty, unusedScenesQty, unusedSize);
- }
- private void Init(int unusedFilesQty, int unusedScenesQty, long unusedSize) {
- UnusedFilesQty = unusedFilesQty;
- UnusedScenesQty = unusedScenesQty;
- UnusedSize = unusedSize;
- }
- }
- }
- }
|