123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970 |
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Text;
- using Leopotam.Ecs;
- using UnityEditor;
- using UnityEditor.SceneManagement;
- using UnityEditorInternal;
- using UnityEngine;
- using UnityEngine.SceneManagement;
- using Object = UnityEngine.Object;
- namespace Asset_Cleaner {
- class FileResultTag { }
- enum TargetTypeEnum {
- File = 0,
- Directory = 1,
- Scene = 2,
- ObjectInScene = 3,
- ObjectInStage = 4
- }
- class SysWindowGui : IEcsRunSystem, IEcsInitSystem {
- EcsFilter<Result, SearchResultGui, InSceneResult> SceneResultRows = null;
- EcsFilter<SceneResult, SceneDetails> ScenePaths = null;
- EcsFilter<SearchArg>.Exclude<InSceneResult> SearchArgMain = null;
- EcsFilter<Result, SearchResultGui, FileResultTag> FileResultRows = null;
- public void Init() {
- BacklinkStoreDirty(true);
- VisualSettingDirty(true);
- }
- public void Run() {
- var windowData = Globals<WindowData>.Value;
- _toolbarSelection = GUILayout.Toolbar(_toolbarSelection, _toolbarStrings, GUILayout.ExpandWidth(false));
- var conf = Globals<Config>.Value;
- switch (_toolbarSelection) {
- case 0: {
- ShowTabMain(conf, windowData);
- break;
- }
- case 1: {
- ShowTabSettings(conf);
- break;
- }
- }
- }
- string[] _toolbarStrings = {"Main", "Settings"};
- const int _progressBarShowFromLevel = 10;
- int _toolbarSelection = 0;
- int _settingIgnoredPathsHash1;
- bool BacklinkStoreDirty(bool set) {
- var res = Hash() != _settingIgnoredPathsHash1;
- if (set) _settingIgnoredPathsHash1 = Hash();
- return res;
- int Hash() {
- var conf = Globals<Config>.Value;
- return DirtyUtils.HashCode(conf.IgnorePathContainsCombined,
- conf.IgnoreMaterial,
- conf.IgnoreScriptable);
- }
- }
- int _settingCodeHash1;
- bool VisualSettingDirty(bool set) {
- var res = Hash() != _settingCodeHash1;
- if (set) _settingCodeHash1 = Hash();
- return res;
- int Hash() {
- var conf = Globals<Config>.Value;
- return DirtyUtils.HashCode(
- conf.MarkRed,
- conf.ShowInfoBox,
- conf.RebuildCacheOnDemand);
- }
- }
- void ShowTabSettings(Config conf) {
- using (new EditorGUILayout.VerticalScope()) {
- EditorGUILayout.Space();
- var enabled = GUI.enabled;
- GUI.enabled = true;
- using (new EditorGUILayout.VerticalScope()) {
- conf.MarkRed = GUILayout.Toggle(conf.MarkRed, "Display counters and red overlay in Project View");
- conf.ShowInfoBox = GUILayout.Toggle(conf.ShowInfoBox, "Help suggestions");
- conf.RebuildCacheOnDemand = GUILayout.Toggle(conf.RebuildCacheOnDemand, "Rebuild cache on demand (when scripts are updated often)");
- EditorGUILayout.Space();
- conf.IgnoreMaterial = GUILayout.Toggle(conf.IgnoreMaterial, "Ignore Materials");
- conf.IgnoreScriptable = GUILayout.Toggle(conf.IgnoreScriptable, "Ignore ScriptableObjects");
- }
- EditorGUILayout.Space();
- GUI.enabled = enabled;
- EditorGUILayout.LabelField("Ignore Path(s) contains:");
- conf.IgnorePathContainsCombined = GUILayout.TextArea(conf.IgnorePathContainsCombined);
- using (new EditorGUILayout.HorizontalScope(GUILayout.ExpandWidth(false))) {
- EditorGUILayout.Space();
- var previous = GUI.enabled;
- GUI.enabled = BacklinkStoreDirty(false) || VisualSettingDirty(false);
- if (GUILayout.Button("Apply")) {
- conf.IgnorePathContains = conf.IgnorePathContainsCombined.Split(';')
- .Where(s => !string.IsNullOrWhiteSpace(s)).ToArray();
- Apply();
- }
- GUI.enabled = previous;
- var selectedGuids = Selection.assetGUIDs;
- var assetPaths = new List<string>();
- if (selectedGuids.Length > 0) {
- foreach (var guid in selectedGuids) {
- var realAssetPath = AssetDatabase.GUIDToAssetPath(guid);
- var obj = AssetDatabase.LoadAssetAtPath<Object>(realAssetPath);
- var assetPath = realAssetPath.Replace("Assets/", string.Empty);
- if (obj is DefaultAsset &&
- !conf.IgnorePathContains.Any(p => (StringComparer.Ordinal.Equals(p, assetPath)))) {
- assetPaths.Add(assetPath);
- }
- }
- }
- GUI.enabled = (assetPaths.Count > 0);
- var foldersList = string.Join(", ", assetPaths);
- if (GUILayout.Button("Add Selected Path")) {
- var choice = EditorUtility.DisplayDialog(
- title: "Asset Cleaner",
- message:
- $"Do you really want to add these folder(s) to ignored list: \"{foldersList}\"?",
- ok: "Ignore",
- cancel: "Cancel");
- if (choice) {
- conf.IgnorePathContainsCombined += $"{foldersList};";
- conf.IgnorePathContains = conf.IgnorePathContainsCombined.Split(';')
- .Where(s => !string.IsNullOrWhiteSpace(s)).ToArray();
- Apply();
- }
- }
- GUI.enabled = true;
- if (GUILayout.Button("Reset")) {
- var choice = EditorUtility.DisplayDialog(
- title: "Asset Cleaner",
- message:
- $"Do you really want to reset to the factory settings?",
- ok: "Reset",
- cancel: "Cancel");
- if (choice) {
- var serializable = AufSerializableData.Default();
- AufSerializableData.OnDeserialize(in serializable, ref conf);
- Apply();
- }
- }
- GUI.enabled = previous;
- }
- EditorGUILayout.Space();
- EditorGUILayout.LabelField(conf.InitializationTime);
- var buf = GUI.enabled;
- GUI.enabled = Selection.objects.Length > 0;
- if (GUILayout.Button("Reserialize selected assets", GUILayout.ExpandWidth(false))) {
- var paths = Selection.objects.Select(AssetDatabase.GetAssetPath);
- AssetDatabase.ForceReserializeAssets(paths);
- EditorApplication.ExecuteMenuItem("File/Save Project");
- AssetDatabase.Refresh();
- }
- GUI.enabled = buf;
- EditorGUILayout.Space();
- }
- void Apply() {
- var rebuild = BacklinkStoreDirty(true);
- VisualSettingDirty(true);
- PersistenceUtils.Save(in conf);
- AufCtx.World.NewEntityWith(out RequestRepaintEvt _);
- if (rebuild)
- Globals<BacklinkStore>.Value.UpdateUnusedAssets();
- InternalEditorUtility.RepaintAllViews();
- }
- }
- void ShowTabMain(Config conf, WindowData windowData) {
- var store = Globals<BacklinkStore>.Value;
- EditorGUIUtility.labelWidth = windowData.Window.position.width * .7f;
- int Hash() => DirtyUtils.HashCode(conf.Locked);
- var active = SearchArgMain.Get1[0];
- if (conf.Locked && (windowData.FindFrom == FindModeEnum.File &&
- (active == null || active.Main == null || !AssetDatabase.Contains(active.Main)))) {
- conf.Locked = false;
- AufCtx.World.NewEntityWith(out RequestRepaintEvt _);
- }
- var style = windowData.Style;
- var hash = Hash();
- if (hash != Hash()) {
- PersistenceUtils.Save(in conf);
- AufCtx.World.NewEntityWith(out RequestRepaintEvt _);
- }
- // if (Globals<WindowData>.Get() == null) return;
- EditorGUILayout.Space();
- SearchArg arg = default;
- foreach (var i in SearchArgMain) {
- arg = SearchArgMain.Get1[i];
- if (arg != null && arg.Main != null) {
- break;
- }
- }
- if (arg == default)
- return;
- var targetTypeEnum = GetTargetType(windowData, arg?.Main);
- BacklinkStore.UnusedQty unusedQty = new BacklinkStore.UnusedQty(0, 0, 0);
- using (new EditorGUILayout.HorizontalScope()) {
- var enabledBuf = GUI.enabled;
- var selectedGuids = Selection.assetGUIDs;
- var undoRedoState = Globals<UndoRedoState>.Value;
- GUI.enabled = selectedGuids != null && !conf.Locked && undoRedoState.UndoEnabled;
- if (GUILayout.Button(style.ArrowL, style.ArrowBtn)) {
- AufCtx.World.NewEntityWith(out UndoEvt _);
- }
- GUI.enabled = selectedGuids != null && !conf.Locked && undoRedoState.RedoEnabled;
- if (GUILayout.Button(style.ArrowR, style.ArrowBtn)) {
- AufCtx.World.NewEntityWith(out RedoEvt _);
- }
- GUI.enabled = enabledBuf;
- if (conf.Locked) {
- if (GUILayout.Button(style.Lock, style.LockBtn)) {
- AufCtx.World.NewEntityWith(out SelectionChanged selectionChanged);
- conf.Locked = false;
- if (Selection.activeObject != arg.Target) {
- selectionChanged.From = FindModeEnum.Scene;
- selectionChanged.Scene = SceneManager.GetActiveScene();
- selectionChanged.Target = Selection.activeObject;
- }
- else if (Selection.assetGUIDs is string[] guids) {
- // todo show info box multiple selection is unsupported
- if (guids.Length > 0) {
- var path = AssetDatabase.GUIDToAssetPath(guids[0]);
- selectionChanged.Target = AssetDatabase.LoadAssetAtPath<Object>(path);
- switch (Selection.selectionChanged.Target) {
- case DefaultAsset _:
- selectionChanged.From = FindModeEnum.File;
- break;
- case GameObject go when go.scene.isLoaded:
- selectionChanged.From = FindModeEnum.Scene;
- selectionChanged.Scene = SceneManager.GetActiveScene();
- break;
- default:
- selectionChanged.From = FindModeEnum.File;
- break;
- }
- }
- else if (Selection.activeObject is GameObject go && go.scene.isLoaded) {
- selectionChanged.From = FindModeEnum.Scene;
- selectionChanged.Target = Selection.activeObject;
- selectionChanged.Scene = SceneManager.GetActiveScene();
- }
- }
- }
- }
- else {
- var enabled = GUI.enabled;
- GUI.enabled = selectedGuids != null && selectedGuids.Length == 1;
- if (GUILayout.Button(style.Unlock, style.UnlockBtn)) {
- conf.Locked = true;
- }
- GUI.enabled = enabled;
- }
- unusedQty = ShowObjectName(store, windowData, targetTypeEnum, arg, selectedGuids);
- }
- bool isMultiSelect = Selection.assetGUIDs != null && Selection.assetGUIDs.Length > 1;
- if (conf.ShowInfoBox) {
- if (isMultiSelect && (unusedQty.UnusedFilesQty + unusedQty.UnusedScenesQty > 0)) {
- var msgUnusedFiles = (unusedQty.UnusedFilesQty > 0)
- ? $"unused files ({unusedQty.UnusedFilesQty}),"
- : "";
- var msgUnusedScenes = (unusedQty.UnusedScenesQty > 0)
- ? $"unused scenes ({unusedQty.UnusedScenesQty}),"
- : "";
- var msgMultiSelect = $"This multi-selection contains: " +
- msgUnusedFiles + msgUnusedScenes +
- $"\nYou could delete them pressing corresponding button to the right.";
- EditorGUILayout.HelpBox(msgMultiSelect, MessageType.Info);
- }
- else if (TryGetHelpInfo(arg, out var msg, out var msgType)) {
- EditorGUILayout.HelpBox(msg, msgType);
- }
- }
- if (targetTypeEnum != TargetTypeEnum.Directory && !isMultiSelect) {
- var windowData2 = Globals<WindowData>.Value;
- EditorGUILayout.BeginVertical();
- {
- windowData2.ScrollPos = EditorGUILayout.BeginScrollView(windowData2.ScrollPos);
- {
- RenderRows(windowData2); //TODO?
- EditorGUILayout.Space();
- }
- EditorGUILayout.EndScrollView();
- }
- EditorGUILayout.EndVertical();
- EditorGUILayout.Space();
- }
- }
- static bool TryGetHelpInfo(SearchArg arg, out string msg, out MessageType msgType) {
- msgType = MessageType.Info;
- if (arg == null) {
- msg = default;
- return false;
- }
- var path = arg.FilePath;
- if (string.IsNullOrEmpty(path)) {
- msg = default;
- return false;
- }
- if (SearchUtils.IgnoredPaths(path, out var subPath)) {
- msg = $"Paths containing '{subPath}' are ignored. You could add or remove it in Settings tab";
- return true;
- }
- if (SearchUtils.IgnoredNonAssets(path) && !path.Eq("Assets")) {
- msg = $"Asset is outside of Assets folder";
- return true;
- }
- if (IgnoreTypes.Check(path, out var type)) {
- if (AssetDatabase.IsValidFolder(path)) {
- var scenes = arg.UnusedScenesFiltered?.Count;
- var files = arg.UnusedAssetsFiltered?.Count;
- if (scenes == 0 && files == 0) {
- msg = default;
- return false;
- }
- var b = new StringBuilder();
- b.Append("This directory contains: ");
- var any = false;
- if (files > 0) {
- any = true;
- b.Append($"unused files ({files})");
- }
- if (scenes > 0) {
- if (any)
- b.Append(", ");
- b.Append($"unused scenes ({scenes})");
- }
- b.Append(
- ".\nYou could delete them pressing corresponding button to the right.\nIf you don't want it to be inspected, please add it to Ignore list in the Settings tab");
- msg = b.ToString();
- return true;
- }
- msg = $"Assets of type '{type.Name}' are ignored. Please contact support if you need to change it";
- return true;
- }
- // if (Filters.ScenePaths.GetEntitiesCount() == 0 && Filters.FileResultRows.GetEntitiesCount() == 0) {
- if (SearchUtils.IsUnused(path)) {
- type = AssetDatabase.GetMainAssetTypeAtPath(path);
- var name = type.IsAssignableFromInverse(typeof(SceneAsset)) ? "scene" : "file";
- msg =
- $"This {name} has no explicit serialized usages and potentially could be removed. If you don't want it to be inspected, please add the containing folder to ignore list";
- return true;
- }
- msgType = default;
- msg = default;
- return false;
- }
- static TargetTypeEnum GetTargetType(WindowData windowData1, Object obj) {
- if (obj == null) return TargetTypeEnum.File;
- var targetTypeEnum = TargetTypeEnum.Directory;
- var path = AssetDatabase.GetAssetPath(obj);
- switch (windowData1.FindFrom) {
- case FindModeEnum.File when obj is DefaultAsset:
- targetTypeEnum = TargetTypeEnum.Directory;
- break;
- case FindModeEnum.File when path.LastIndexOf(".unity", StringComparison.Ordinal) != -1:
- targetTypeEnum = TargetTypeEnum.Scene;
- break;
- case FindModeEnum.File:
- targetTypeEnum = TargetTypeEnum.File;
- break;
- case FindModeEnum.Scene:
- targetTypeEnum = TargetTypeEnum.ObjectInScene;
- break;
- case FindModeEnum.Stage:
- targetTypeEnum = TargetTypeEnum.ObjectInStage;
- break;
- }
- return targetTypeEnum;
- }
- GUIContent _contentBuf = new GUIContent();
- GUIContent _buf2 = new GUIContent();
- BacklinkStore.UnusedQty ShowObjectName(BacklinkStore store, WindowData windowData, TargetTypeEnum targetTypeEnum, SearchArg arg, string[] selectedGuids) {
- float TextWidth() {
- _buf2.text = _contentBuf.text;
- return 20f + GUI.skin.button.CalcSize(_buf2).x;
- }
- if (arg == null || arg.Main == null) return new BacklinkStore.UnusedQty();
- bool isMultiSelect = selectedGuids != null && selectedGuids.Length > 1;
- if (_contentBuf == null) {
- _contentBuf = new GUIContent {tooltip = $"Click to ping"};
- }
- _contentBuf.image = isMultiSelect
- ? windowData.Style.MultiSelect.image
- : AssetPreview.GetMiniThumbnail(arg.Target);
- _contentBuf.text = string.Empty;
- _contentBuf.tooltip = string.Empty;
- if (!isMultiSelect) {
- switch (targetTypeEnum) {
- case TargetTypeEnum.Directory:
- if (!SearchArgMain.IsEmpty()) {
- _contentBuf.text = $"{arg.Main.name} (Folder)";
- if (GUILayout.Button(_contentBuf, windowData.Style.CurrentBtn,
- GUILayout.MinWidth(TextWidth()))) {
- EditorGUIUtility.PingObject(arg.Main);
- }
- if (AskDeleteUnusedFiles(arg, arg.UnusedAssetsFiltered, windowData))
- return new BacklinkStore.UnusedQty();
- if (AskDeleteUnusedScenes(arg, arg.UnusedScenesFiltered, windowData))
- return new BacklinkStore.UnusedQty();
- }
- break;
- case TargetTypeEnum.File:
- _contentBuf.text = $"{arg.Main.name} (File Asset)";
- if (GUILayout.Button(_contentBuf, windowData.Style.CurrentBtn,
- GUILayout.MinWidth(TextWidth()))) {
- EditorGUIUtility.PingObject(arg.Main);
- }
- bool hasUnusedFile = SearchUtils.IsUnused(arg.FilePath);
- var previous = GUI.enabled;
- GUI.enabled = hasUnusedFile;
- if (GUILayout.Button(windowData.Style.RemoveFile,
- windowData.Style.RemoveUnusedBtn)) {
- var choice = EditorUtility.DisplayDialog(
- title: "Asset Cleaner",
- message:
- $"Do you really want to remove file: \"{arg.Main.name}\"?",
- ok: "Remove",
- cancel: "Cancel");
- if (choice) {
- EditorApplication.ExecuteMenuItem("File/Save Project");
- DeleteWithMeta(arg.FilePath);
- AssetDatabase.Refresh();
- SearchUtils.Upd(arg);
- }
- }
- GUI.enabled = previous;
- break;
- case TargetTypeEnum.Scene:
- _contentBuf.text = $"{arg.Main.name} (Scene)";
- if (GUILayout.Button(_contentBuf, windowData.Style.CurrentBtn,
- GUILayout.MinWidth(TextWidth()))) {
- EditorGUIUtility.PingObject(arg.Main);
- }
- bool hasUnusedScene = SearchUtils.IsUnused(arg.FilePath);
- previous = GUI.enabled;
- GUI.enabled = hasUnusedScene;
- if (GUILayout.Button(windowData.Style.RemoveScene,
- windowData.Style.RemoveUnusedBtn)) {
- var choice = EditorUtility.DisplayDialog(
- title: "Asset Cleaner",
- message:
- $"Do you really want to remove scene: {arg.Main.name}?",
- ok: "Remove",
- cancel: "Cancel");
- if (choice) {
- EditorApplication.ExecuteMenuItem("File/Save Project");
- DeleteWithMeta(arg.FilePath);
- AssetDatabase.Refresh();
- SearchUtils.Upd(arg);
- }
- }
- GUI.enabled = previous;
- break;
- case TargetTypeEnum.ObjectInScene:
- _contentBuf.text = $"{arg.Main.name} (Object in Scene)";
- if (GUILayout.Button(_contentBuf, windowData.Style.CurrentBtn,
- GUILayout.MinWidth(TextWidth()))) {
- EditorGUIUtility.PingObject(arg.Main);
- }
- break;
- case TargetTypeEnum.ObjectInStage:
- _contentBuf.image = AssetPreview.GetMiniThumbnail(arg.Target);
- _contentBuf.text = $"{arg.Main.name} (Object in Staging)";
- if (GUILayout.Button(_contentBuf,
- windowData.Style.RemoveUnusedBtn)) {
- EditorGUIUtility.PingObject(arg.Main);
- }
- break;
- default:
- if (GUILayout.Button($"{arg.Main.name} (Unknown Object Type)",
- windowData.Style.RemoveUnusedBtn)) {
- EditorGUIUtility.PingObject(arg.Main);
- }
- break;
- }
- }
- else {
- var unusedAssets = new List<string>();
- var unusedScenes = new List<string>();
- foreach (var guid in selectedGuids) {
- var path = AssetDatabase.GUIDToAssetPath(guid);
- if (store.UnusedFiles.TryGetValue(path, out _))
- unusedAssets.Add(path);
- else if (store.UnusedScenes.TryGetValue(path, out _))
- unusedScenes.Add(path);
- if (store.FoldersWithQty.TryGetValue(path, out _)) {
- SearchArg searchArg = new SearchArg() {
- FilePath = path,
- Target = AssetDatabase.LoadAssetAtPath<DefaultAsset>(path),
- Main = AssetDatabase.LoadAssetAtPath<DefaultAsset>(path)
- };
- SearchUtils.Upd(searchArg);
- foreach (var unusedAssetPath in searchArg.UnusedAssetsFiltered)
- if (store.UnusedFiles.TryGetValue(unusedAssetPath, out _))
- unusedAssets.Add(unusedAssetPath);
- foreach (var unusedScenePath in searchArg.UnusedScenesFiltered)
- if (store.UnusedScenes.TryGetValue(unusedScenePath, out _))
- unusedScenes.Add(unusedScenePath);
- }
- }
- unusedAssets = unusedAssets.Distinct().ToList();
- unusedScenes = unusedScenes.Distinct().ToList();
- var assetSize = unusedAssets.Sum(CommonUtils.Size);
- var sceneSize = unusedScenes.Sum(CommonUtils.Size);
- _contentBuf.text =
- $"Assets: {unusedAssets.Count} ({CommonUtils.BytesToString(assetSize)}), Scenes: {unusedScenes.Count} ({CommonUtils.BytesToString(sceneSize)})";
- ;
- GUILayout.Button(_contentBuf, windowData.Style.CurrentBtn, GUILayout.MinWidth(TextWidth()));
- if (AskDeleteUnusedFiles(arg, unusedAssets, windowData))
- return new BacklinkStore.UnusedQty();
- if (AskDeleteUnusedScenes(arg, unusedScenes, windowData))
- return new BacklinkStore.UnusedQty();
- return new BacklinkStore.UnusedQty(unusedAssets.Count, unusedScenes.Count, assetSize + sceneSize);
- }
- return new BacklinkStore.UnusedQty();
- }
- static bool AskDeleteUnusedFiles(SearchArg arg, List<string> unusedAssets, WindowData windowData) {
- if (arg == null || unusedAssets == null) return false;
- var hasUnusedAssets = unusedAssets.Count > 0;
- var previous = GUI.enabled;
- GUI.enabled = hasUnusedAssets;
- var guiContentRemoveAssets = windowData.Style.RemoveFile;
- if (GUILayout.Button(guiContentRemoveAssets,
- windowData.Style.RemoveUnusedBtn)) {
- var choice = EditorUtility.DisplayDialog(
- title: "Asset Cleaner",
- message:
- $"Do you really want to remove {unusedAssets.Count} asset(s)?",
- ok: "Remove",
- cancel: "Cancel");
- if (choice) {
- EditorApplication.ExecuteMenuItem("File/Save Project");
- var i = 0f;
- var total = (float) unusedAssets.Count;
- foreach (var f in unusedAssets) {
- var path = Application.dataPath.Replace("Assets", f);
- DeleteWithMeta(path);
-
- var percent = i * 100 / total;
- if (total >= _progressBarShowFromLevel) {
- if (Math.Abs(percent % 5f) < 0.01f) {
- if (EditorUtility.DisplayCancelableProgressBar(
- "Please wait...",
- "Deleting assets...", percent))
- throw new Exception("Deleting aborted");
- }
- i++;
- }
- }
- if (total >= _progressBarShowFromLevel) {
- EditorUtility.ClearProgressBar();
- }
- AssetDatabase.Refresh();
- SearchUtils.Upd(arg);
- }
- GUI.enabled = previous;
- return true;
- }
- GUI.enabled = previous;
- return false;
- }
- static void DeleteWithMeta(string path) {
- FileUtil.DeleteFileOrDirectory(path);
- var metaPath = AssetDatabase.GetTextMetaFilePathFromAssetPath(path);
- if (!string.IsNullOrEmpty(metaPath))
- FileUtil.DeleteFileOrDirectory(metaPath);
- }
- static bool AskDeleteUnusedScenes(SearchArg arg, List<string> unusedScenes, WindowData windowData) {
- if (arg == null || unusedScenes == null) return false;
- var hasUnusedScenes = unusedScenes.Count > 0;
- var previous = GUI.enabled;
- GUI.enabled = hasUnusedScenes;
- var guiContentRemoveScenes = windowData.Style.RemoveScene;
- if (GUILayout.Button(guiContentRemoveScenes,
- windowData.Style.RemoveUnusedBtn)) {
- var choice = EditorUtility.DisplayDialog(
- title: "Asset Cleaner",
- message:
- $"Do you really want to remove {unusedScenes.Count} scene(s)?",
- ok: "Remove",
- cancel: "Cancel");
- if (choice) {
- EditorApplication.ExecuteMenuItem("File/Save Project");
- var i = 0f;
- var total = (float) unusedScenes.Count;
- foreach (var scene in unusedScenes) {
- var path = Application.dataPath.Replace("Assets", scene);
- DeleteWithMeta(path);
- if (total >= _progressBarShowFromLevel) {
- var percent = i * 100 / total;
- if (Math.Abs(percent % 5f) < 0.01f) {
- if (EditorUtility.DisplayCancelableProgressBar(
- "Please wait...",
- "Deleting scenes...", percent))
- throw new Exception("Deleting aborted");
- }
- i++;
- }
- }
- if (total >= _progressBarShowFromLevel) {
- EditorUtility.ClearProgressBar();
- }
- AssetDatabase.Refresh();
- SearchUtils.Upd(arg);
- }
- GUI.enabled = previous;
- return true;
- }
- GUI.enabled = previous;
- return false;
- }
- void RenderRows(WindowData windowData) {
- // todo show spinner until scene is loaded,
- if (FileResultRows.GetEntitiesCount() > 0) {
- windowData.ExpandFiles =
- EditorGUILayout.Foldout(windowData.ExpandFiles,
- $"Usages in Project: {FileResultRows.GetEntitiesCount()}");
- }
- if (SearchArgMain.IsEmpty())
- return;
- if (windowData.ExpandFiles && windowData.FindFrom == FindModeEnum.File)
- foreach (var i in FileResultRows.Out(out var get1, out var get2, out _, out _))
- DrawRowFile(get1[i], get2[i], windowData);
- var sceneMessage = $"Usages in Scenes: {ScenePaths.GetEntitiesCount()}";
- if (ScenePaths.GetEntitiesCount() > 0) {
- windowData.ExpandScenes =
- EditorGUILayout.Foldout(windowData.ExpandScenes, sceneMessage);
- }
- if (!windowData.ExpandScenes) return;
- if (windowData.ExpandScenes && windowData.FindFrom == FindModeEnum.Scene) {
- foreach (var (grp, indices) in SceneResultRows.Out(out _, out var get2, out _, out _)
- .GroupBy1(ResultComp.Instance)) {
- using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) {
- var count = 0;
- foreach (var i in indices) {
- if (count++ == 0)
- if (GUILayout.Button(get2[i].Label, windowData.Style.RowMainAssetBtn)) {
- if (windowData.Click.IsDoubleClick(grp.RootGo)) {
- // _selectionChangedByArrows = false;
- Selection.activeObject = grp.RootGo;
- }
- else
- EditorGUIUtility.PingObject(grp.RootGo);
- windowData.Click = new PrevClick(grp.RootGo);
- }
- DrawRowScene(get2[i]);
- }
- }
- }
- }
- using (new GUILayout.HorizontalScope()) {
- GUILayout.Space(windowData.Style.SceneIndent1);
- using (new EditorGUILayout.VerticalScope()) {
- foreach (var i1 in ScenePaths.Out(out var get1, out var get2, out _)) {
- windowData.SceneFoldout.text = get1[i1].PathNicified;
- var details = get2[i1];
- details.SearchRequested = details.Scene.isLoaded;
- details.SearchRequested = EditorGUILayout.Foldout(details.SearchRequested,
- windowData.SceneFoldout, EditorStyles.foldout);
- if (details.SearchRequested && details.Scene.isLoaded && !details.SearchDone) {
- var mainArg = SearchArgMain.GetSingle();
- mainArg.Scene = SceneManager.GetSceneByPath(details.Scene.path);
- SearchUtils.InScene(mainArg, details.Scene);
- details.SearchDone = true;
- }
- if (!details.SearchRequested) {
- if (!details.Scene.isLoaded) continue;
- if (!details.WasOpened) {
- // to clean up on selection change
- AufCtx.World.NewEntityWith(out SceneToClose comp);
- comp.Scene = details.Scene;
- comp.ForceClose = true;
- }
- foreach (var row in SceneResultRows.Out(out _, out _, out var get3, out var entities)) {
- if (!get3[row].ScenePath.Eq(details.Path))
- continue;
- entities[row].Destroy();
- }
- details.SearchDone = false;
- }
- else {
- if (!details.Scene.isLoaded) {
- details.Scene = EditorSceneManager.OpenScene(details.Path, OpenSceneMode.Additive);
- // to clean up on selection change
- AufCtx.World.NewEntityWith(out SceneToClose comp);
- comp.Scene = details.Scene;
- comp.SelectionId = Globals<PersistentUndoRedoState>.Value.Id;
- #if UNITY_2019_1_OR_NEWER
- EditorSceneManager.SetSceneCullingMask(details.Scene, 0);
- #endif
- details.SearchRequested = true;
- // todo Scope component
- #if later
- if (details.Scene.isLoaded)
- EditorSceneManager.CloseScene(details.Scene, false);
- #endif
- }
- else if (SceneResultRows.IsEmpty())
- EditorGUILayout.LabelField("No in-scene dependencies found.");
- else
- using (new GUILayout.HorizontalScope()) {
- GUILayout.Space(windowData.Style.SceneIndent2);
- using (new EditorGUILayout.VerticalScope())
- foreach (var (grp, indices) in SceneResultRows
- .Out(out var g1, out var g2, out var g3, out _)
- .GroupBy1(ResultComp.Instance)) {
- var any = false;
- foreach (var i3 in indices) {
- if (!g3[i3].ScenePath.Eq(details.Path))
- continue;
- any = true;
- break;
- }
- if (!any)
- continue;
- using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) {
- var count = 0;
- foreach (var i2 in indices) {
- if (!g3[i2].ScenePath.Eq(details.Path))
- continue;
- if (count++ == 0) {
- Result comp = g1[i2];
- if (GUILayout.Button(g2[i2].Label,
- windowData.Style.RowMainAssetBtn)) {
- if (windowData.Click.IsDoubleClick(grp.RootGo)) {
- // _selectionChangedByArrows = false;
- Selection.activeObject = comp.RootGo;
- }
- else
- EditorGUIUtility.PingObject(comp.RootGo);
- windowData.Click = new PrevClick(comp.RootGo);
- }
- }
- DrawRowScene(g2[i2]);
- }
- }
- }
- }
- }
- }
- }
- }
- }
- class ResultComp : IEqualityComparer<Result> {
- public static ResultComp Instance { get; } = new ResultComp();
- public bool Equals(Result x, Result y) => GetHashCode(x) == GetHashCode(y);
- public int GetHashCode(Result obj) => obj.RootGo.GetInstanceID();
- }
- static void DrawRowScene(SearchResultGui gui) {
- EditorGUI.BeginChangeCheck();
- // if (data.TargetGo || data.TargetComponent)
- foreach (var prop in gui.Properties) {
- {
- var locked = prop.Property.objectReferenceValue is MonoScript;
- var f = GUI.enabled;
- if (locked) GUI.enabled = false;
- EditorGUILayout.PropertyField(prop.Property, prop.Content, false);
- if (locked) GUI.enabled = f;
- }
- }
- if (EditorGUI.EndChangeCheck())
- gui.SerializedObject.ApplyModifiedProperties();
- }
- static void DrawRowFile(Result data, SearchResultGui gui, WindowData windowData) {
- using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) {
- var buf = GUI.color;
- var pingGo = data.MainFile == null ? data.RootGo : data.MainFile;
- if (GUILayout.Button(gui.Label, windowData.Style.RowMainAssetBtn)) {
- if (windowData.Click.IsDoubleClick(pingGo)) {
- // _selectionChangedByArrows = false;
- Selection.activeObject = pingGo;
- }
- else {
- EditorGUIUtility.PingObject(pingGo);
- }
- windowData.Click = new PrevClick(pingGo);
- }
- GUI.color = buf;
- EditorGUI.BeginChangeCheck();
- if (data.File) {
- foreach (var prop in gui.Properties) {
- using (new EditorGUILayout.HorizontalScope()) {
- var locked = prop.Property.objectReferenceValue is MonoScript;
- var f = GUI.enabled;
- if (locked) GUI.enabled = false;
- EditorGUILayout.PropertyField(prop.Property, prop.Content, false);
- if (locked) GUI.enabled = f;
- }
- }
- }
- if (EditorGUI.EndChangeCheck()) {
- gui.SerializedObject.ApplyModifiedProperties();
- // dependency.SerializedObject.Update();
- }
- }
- }
- }
- }
|