DunGenFolderCleaningWindow.cs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. using System.Collections.Generic;
  2. using System.IO;
  3. using UnityEditor;
  4. using UnityEngine;
  5. namespace DunGen.Editor.Windows
  6. {
  7. public class DunGenFolderCleaningWindow : EditorWindow
  8. {
  9. #region Statics
  10. [InitializeOnLoadMethod]
  11. private static void OnLoad()
  12. {
  13. if (!DunGenSettings.Instance.CheckForUnusedFiles)
  14. return;
  15. EditorApplication.delayCall += () =>
  16. {
  17. CleanDunGenDirectory();
  18. };
  19. }
  20. public static void CleanDunGenDirectory()
  21. {
  22. string relativeDunGenRootDirectory = GetRelativeDunGenRootDirectory();
  23. string absoluteDunGenRootDirectory = RelativeToAbsolutePath(relativeDunGenRootDirectory);
  24. if (relativeDunGenRootDirectory == null || !Directory.Exists(absoluteDunGenRootDirectory))
  25. return;
  26. var filesToRemove = GetFilesToRemove(relativeDunGenRootDirectory);
  27. if(filesToRemove == null || filesToRemove.Count == 0)
  28. return;
  29. var window = GetWindow<DunGenFolderCleaningWindow>("DunGen Cleaner");
  30. window.minSize = new Vector2(500, 280);
  31. window.relativeDunGenRootDirectory = relativeDunGenRootDirectory;
  32. window.absoluteDunGenRootDirectory = absoluteDunGenRootDirectory;
  33. window.filesToRemove = filesToRemove;
  34. window.Show();
  35. }
  36. private static HashSet<string> GetFilesToRemove(string dungenRootDirectory)
  37. {
  38. string filesToRemovePath = Path.Combine(dungenRootDirectory, "removed-files.txt");
  39. if (!File.Exists(filesToRemovePath))
  40. return new HashSet<string>();
  41. try
  42. {
  43. var filesToRemove = new HashSet<string>();
  44. foreach(var filePath in File.ReadAllLines(filesToRemovePath))
  45. {
  46. string absolutePath = Path.Combine(dungenRootDirectory, filePath);
  47. if(File.Exists(absolutePath))
  48. filesToRemove.Add(filePath);
  49. }
  50. return filesToRemove;
  51. }
  52. catch (System.Exception ex)
  53. {
  54. Debug.LogError($"An error occurred while reading the removed-files.txt: {ex.Message}");
  55. return new HashSet<string>();
  56. }
  57. }
  58. private static string RelativeToAbsolutePath(string relativePath)
  59. {
  60. string absolutePath = Path.Combine(
  61. Application.dataPath.Substring(0, Application.dataPath.Length - "Assets".Length),
  62. relativePath);
  63. // Normalize directory separators to the current platform's separator
  64. absolutePath = absolutePath.Replace('\\', Path.DirectorySeparatorChar);
  65. absolutePath = absolutePath.Replace('/', Path.DirectorySeparatorChar);
  66. return absolutePath;
  67. }
  68. private static string GetRelativeDunGenRootDirectory()
  69. {
  70. var type = typeof(Tile);
  71. // Search all MonoScript assets in the project
  72. foreach (var guid in AssetDatabase.FindAssets("t:MonoScript"))
  73. {
  74. var path = AssetDatabase.GUIDToAssetPath(guid);
  75. var monoScript = AssetDatabase.LoadAssetAtPath<MonoScript>(path);
  76. if (monoScript != null && monoScript.GetClass() == type)
  77. {
  78. // path will be something like "Assets/DunGen/Code/Tile.cs"
  79. // We want to get "Assets/DunGen"
  80. // "Assets/DunGen/Code"
  81. var directory = Path.GetDirectoryName(path);
  82. if (directory != null)
  83. {
  84. // "Assets/DunGen"
  85. directory = directory.Substring(0, directory.Length - 5);
  86. // For safety, assume we didn't find the directory if it doesn't end with "DunGen"
  87. if (!directory.EndsWith("DunGen"))
  88. return null;
  89. return directory;
  90. }
  91. }
  92. }
  93. return null;
  94. }
  95. #endregion
  96. private string relativeDunGenRootDirectory;
  97. private string absoluteDunGenRootDirectory;
  98. private HashSet<string> filesToRemove;
  99. private Vector2 scrollPosition;
  100. private void OnGUI()
  101. {
  102. EditorGUILayout.LabelField("The following files are no longer used by DunGen and can be deleted. If you've made any changes to any of these files, you may want to consider backing them up first. This utility can be run again at any time from the DunGen project settings.", EditorStyles.wordWrappedLabel);
  103. EditorGUILayout.Space(10);
  104. EditorGUILayout.LabelField("Files to Remove:", EditorStyles.boldLabel);
  105. scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);
  106. EditorGUILayout.BeginVertical(GUI.skin.box);
  107. foreach (var file in filesToRemove)
  108. {
  109. string displayPath = Path.Combine(relativeDunGenRootDirectory, file).Replace('\\', '/');
  110. EditorGUILayout.LabelField(displayPath);
  111. }
  112. EditorGUILayout.EndVertical();
  113. EditorGUILayout.EndScrollView();
  114. EditorGUILayout.Space(10);
  115. EditorGUI.BeginChangeCheck();
  116. var settings = DunGenSettings.Instance;
  117. bool dontAskAgain = EditorGUILayout.Toggle("Don't ask me again", !settings.CheckForUnusedFiles);
  118. if(EditorGUI.EndChangeCheck())
  119. {
  120. settings.CheckForUnusedFiles = !dontAskAgain;
  121. EditorUtility.SetDirty(settings);
  122. }
  123. EditorGUILayout.Space(10);
  124. if (GUILayout.Button("Delete Files"))
  125. {
  126. if (EditorUtility.DisplayDialog("Confirm Deletion", "Are you sure you want to delete the selected files? This action cannot be undone.", "Yes", "No"))
  127. {
  128. if (DeleteFiles())
  129. EditorUtility.DisplayDialog("DunGen Folder Cleaned", "The unused files have been deleted.", "OK");
  130. else
  131. EditorUtility.DisplayDialog("Error", "An error occurred while trying to delete the files. Some or all of the files were not deleted. Please check the console for more details.", "OK");
  132. AssetDatabase.Refresh();
  133. Close();
  134. }
  135. }
  136. if (GUILayout.Button("Cancel"))
  137. Close();
  138. }
  139. private bool DeleteFiles()
  140. {
  141. bool success = true;
  142. foreach (var file in filesToRemove)
  143. {
  144. var filePath = Path.GetFullPath(Path.Combine(absoluteDunGenRootDirectory, file));
  145. // Never delete files outside of the DunGen root directory
  146. if (!filePath.StartsWith(absoluteDunGenRootDirectory))
  147. continue;
  148. try
  149. {
  150. if (File.Exists(filePath))
  151. File.Delete(filePath);
  152. var metaFilePath = filePath + ".meta";
  153. if (File.Exists(metaFilePath))
  154. File.Delete(metaFilePath);
  155. }
  156. catch(System.Exception ex)
  157. {
  158. Debug.LogError($"Failed to delete '{filePath}': {ex.Message}");
  159. success = false;
  160. }
  161. }
  162. return success;
  163. }
  164. }
  165. }