Source code for Ludum Dare 48: Deeper and Deeper entry.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

187 lines
8.1 KiB

  1. // Automatically creates JSON files from an ink placed within the Assets/Ink folder.
  2. using UnityEngine;
  3. using UnityEditor;
  4. using System.IO;
  5. using Debug = UnityEngine.Debug;
  6. using System.Collections.Generic;
  7. using System.Linq;
  8. namespace Ink.UnityIntegration {
  9. class InkPostProcessor : AssetPostprocessor {
  10. // Several assets moved at the same time can cause unity to call OnPostprocessAllAssets several times as a result of moving additional files, or simply due to minor time differences.
  11. // This queue tells the compiler which files to recompile after moves have completed.
  12. // Not a perfect solution - If Unity doesn't move all the files in the same attempt you can expect some error messages to appear on compile.
  13. private static List<string> queuedMovedAssets = new List<string>();
  14. // Recompiles any ink files as a result of an ink file (re)import
  15. private static void OnPostprocessAllAssets (string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths) {
  16. if(deletedAssets.Length > 0) {
  17. OnDeleteAssets(deletedAssets);
  18. }
  19. if(movedAssets.Length > 0) {
  20. OnMoveAssets(movedAssets.Except(importedAssets).ToArray());
  21. }
  22. if(importedAssets.Length > 0) {
  23. OnImportAssets(importedAssets);
  24. }
  25. if(InkLibrary.created)
  26. InkLibrary.Clean();
  27. }
  28. private static void OnDeleteAssets (string[] deletedAssets) {
  29. bool deletedInk = false;
  30. foreach (var deletedAssetPath in deletedAssets) {
  31. if(Path.GetExtension(deletedAssetPath) == InkEditorUtils.inkFileExtension) {
  32. deletedInk = true;
  33. break;
  34. }
  35. }
  36. if(!deletedInk)
  37. return;
  38. // bool alsoDeleteJSON = false;
  39. // alsoDeleteJSON = EditorUtility.DisplayDialog("Deleting .ink file", "Also delete the JSON file associated with the deleted .ink file?", "Yes", "No"));
  40. List<InkFile> masterFilesAffected = new List<InkFile>();
  41. for (int i = InkLibrary.Instance.inkLibrary.Count - 1; i >= 0; i--) {
  42. if(InkLibrary.Instance.inkLibrary [i].inkAsset == null) {
  43. if(!InkLibrary.Instance.inkLibrary[i].metaInfo.isMaster && InkLibrary.Instance.inkLibrary[i].metaInfo.masterInkAsset != null && !masterFilesAffected.Contains(InkLibrary.Instance.inkLibrary[i].metaInfo.masterInkFile)) {
  44. masterFilesAffected.Add(InkLibrary.Instance.inkLibrary[i].metaInfo.masterInkFile);
  45. }
  46. if(InkSettings.Instance.handleJSONFilesAutomatically) {
  47. var assetPath = AssetDatabase.GetAssetPath(InkLibrary.Instance.inkLibrary[i].jsonAsset);
  48. if(assetPath != null && assetPath != string.Empty) {
  49. AssetDatabase.DeleteAsset(assetPath);
  50. }
  51. }
  52. InkLibrary.RemoveAt(i);
  53. }
  54. }
  55. // After deleting files, we might have broken some include references, so we rebuild them. There's probably a faster way to do this, or we could probably just remove any null references, but this is a bit more robust.
  56. foreach(InkFile inkFile in InkLibrary.Instance.inkLibrary) {
  57. inkFile.metaInfo.FindIncludedFiles();
  58. }
  59. foreach(InkFile masterFile in masterFilesAffected) {
  60. if(InkSettings.Instance.compileAutomatically || masterFile.compileAutomatically) {
  61. InkCompiler.CompileInk(masterFile);
  62. }
  63. }
  64. }
  65. private static void OnMoveAssets (string[] movedAssets) {
  66. if (!InkSettings.Instance.handleJSONFilesAutomatically)
  67. return;
  68. List<string> validMovedAssets = new List<string>();
  69. for (var i = 0; i < movedAssets.Length; i++) {
  70. if(Path.GetExtension(movedAssets[i]) != InkEditorUtils.inkFileExtension)
  71. continue;
  72. validMovedAssets.Add(movedAssets[i]);
  73. queuedMovedAssets.Add(movedAssets[i]);
  74. }
  75. // Move compiled JSON files.
  76. // This can cause Unity to postprocess assets again.
  77. bool assetMoved = false;
  78. foreach(var inkFilePath in validMovedAssets) {
  79. InkFile inkFile = InkLibrary.GetInkFileWithPath(inkFilePath);
  80. if(inkFile == null) continue;
  81. if(inkFile.jsonAsset == null) continue;
  82. string jsonAssetPath = AssetDatabase.GetAssetPath(inkFile.jsonAsset);
  83. string movedAssetDir = Path.GetDirectoryName(inkFilePath);
  84. string movedAssetFile = Path.GetFileName(inkFilePath);
  85. string newPath = InkEditorUtils.CombinePaths(movedAssetDir, Path.GetFileNameWithoutExtension(movedAssetFile)) + ".json";
  86. AssetDatabase.MoveAsset(jsonAssetPath, newPath);
  87. assetMoved = true;
  88. }
  89. // Check if no JSON assets were moved (as a result of none needing to move, or this function being called as a result of JSON files being moved)
  90. if(!assetMoved && queuedMovedAssets.Count > 0) {
  91. List<InkFile> filesToCompile = new List<InkFile>();
  92. // Add the old master file to the files to be recompiled
  93. foreach(var inkFilePath in queuedMovedAssets) {
  94. InkFile inkFile = InkLibrary.GetInkFileWithPath(inkFilePath);
  95. if(inkFile == null) continue;
  96. InkFile masterInkFile = inkFile;
  97. if(!inkFile.metaInfo.isMaster)
  98. masterInkFile = inkFile.metaInfo.masterInkFile;
  99. if(!filesToCompile.Contains(masterInkFile))
  100. filesToCompile.Add(masterInkFile);
  101. }
  102. InkMetaLibrary.RebuildInkFileConnections();
  103. // Add the new file to be recompiled
  104. foreach(var inkFilePath in queuedMovedAssets) {
  105. InkFile inkFile = InkLibrary.GetInkFileWithPath(inkFilePath);
  106. if(inkFile == null) continue;
  107. InkFile masterInkFile = inkFile;
  108. if(!inkFile.metaInfo.isMaster)
  109. masterInkFile = inkFile.metaInfo.masterInkFile;
  110. if(!filesToCompile.Contains(masterInkFile))
  111. filesToCompile.Add(masterInkFile);
  112. }
  113. queuedMovedAssets.Clear();
  114. // Compile any ink files that are deemed master files a rebuild
  115. foreach(var inkFile in filesToCompile) {
  116. if(inkFile.metaInfo.isMaster) {
  117. if(InkSettings.Instance.compileAutomatically || inkFile.compileAutomatically) {
  118. InkCompiler.CompileInk(inkFile);
  119. }
  120. }
  121. }
  122. }
  123. }
  124. private static void OnImportAssets (string[] importedAssets) {
  125. List<string> importedInkAssets = new List<string>();
  126. string inklecateFileLocation = null;
  127. foreach (var importedAssetPath in importedAssets) {
  128. if(Path.GetExtension(importedAssetPath) == InkEditorUtils.inkFileExtension)
  129. importedInkAssets.Add(importedAssetPath);
  130. else if (Path.GetFileName(importedAssetPath) == "inklecate" && Path.GetExtension(importedAssetPath) == "")
  131. inklecateFileLocation = importedAssetPath;
  132. else if (Path.GetExtension(importedAssetPath) == ".asset") {
  133. var obj = AssetDatabase.LoadAssetAtPath<ScriptableObject>(importedAssetPath);
  134. if(obj is InkSettings) {
  135. InkEditorUtils.DeleteAllButOldestScriptableObjects(AssetDatabase.FindAssets("t:"+typeof(InkSettings).Name), typeof(InkSettings).Name);
  136. } else if(obj is InkLibrary) {
  137. InkEditorUtils.DeleteAllButOldestScriptableObjects(AssetDatabase.FindAssets("t:"+typeof(InkLibrary).Name), typeof(InkLibrary).Name);
  138. }
  139. }
  140. }
  141. if(importedInkAssets.Count > 0)
  142. PostprocessInkFiles(importedInkAssets);
  143. if(inklecateFileLocation != null)
  144. PostprocessInklecate(inklecateFileLocation);
  145. }
  146. private static void PostprocessInklecate (string inklecateFileLocation) {
  147. // This should probably only recompile files marked to compile automatically, but it's such a rare case, and one where you probably do want to compile.
  148. // To fix, one day!
  149. Debug.Log("Inklecate updated. Recompiling all Ink files...");
  150. InkEditorUtils.RecompileAll();
  151. }
  152. private static void PostprocessInkFiles (List<string> importedInkAssets) {
  153. if(EditorApplication.isPlaying && InkSettings.Instance.delayInPlayMode) {
  154. foreach(var fileToImport in importedInkAssets) {
  155. if(!InkLibrary.Instance.pendingCompilationStack.Contains(fileToImport))
  156. InkLibrary.Instance.pendingCompilationStack.Add(fileToImport);
  157. }
  158. } else {
  159. InkLibrary.CreateOrReadUpdatedInkFiles (importedInkAssets);
  160. foreach (var inkAssetToCompile in InkCompiler.GetUniqueMasterInkFilesToCompile (importedInkAssets))
  161. InkCompiler.CompileInk(inkAssetToCompile);
  162. }
  163. }
  164. }
  165. }