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.

188 lines
8.1 KiB

// Automatically creates JSON files from an ink placed within the Assets/Ink folder.
using UnityEngine;
using UnityEditor;
using System.IO;
using Debug = UnityEngine.Debug;
using System.Collections.Generic;
using System.Linq;
namespace Ink.UnityIntegration {
class InkPostProcessor : AssetPostprocessor {
// 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.
// This queue tells the compiler which files to recompile after moves have completed.
// 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.
private static List<string> queuedMovedAssets = new List<string>();
// Recompiles any ink files as a result of an ink file (re)import
private static void OnPostprocessAllAssets (string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths) {
if(deletedAssets.Length > 0) {
OnDeleteAssets(deletedAssets);
}
if(movedAssets.Length > 0) {
OnMoveAssets(movedAssets.Except(importedAssets).ToArray());
}
if(importedAssets.Length > 0) {
OnImportAssets(importedAssets);
}
if(InkLibrary.created)
InkLibrary.Clean();
}
private static void OnDeleteAssets (string[] deletedAssets) {
bool deletedInk = false;
foreach (var deletedAssetPath in deletedAssets) {
if(Path.GetExtension(deletedAssetPath) == InkEditorUtils.inkFileExtension) {
deletedInk = true;
break;
}
}
if(!deletedInk)
return;
// bool alsoDeleteJSON = false;
// alsoDeleteJSON = EditorUtility.DisplayDialog("Deleting .ink file", "Also delete the JSON file associated with the deleted .ink file?", "Yes", "No"));
List<InkFile> masterFilesAffected = new List<InkFile>();
for (int i = InkLibrary.Instance.inkLibrary.Count - 1; i >= 0; i--) {
if(InkLibrary.Instance.inkLibrary [i].inkAsset == null) {
if(!InkLibrary.Instance.inkLibrary[i].metaInfo.isMaster && InkLibrary.Instance.inkLibrary[i].metaInfo.masterInkAsset != null && !masterFilesAffected.Contains(InkLibrary.Instance.inkLibrary[i].metaInfo.masterInkFile)) {
masterFilesAffected.Add(InkLibrary.Instance.inkLibrary[i].metaInfo.masterInkFile);
}
if(InkSettings.Instance.handleJSONFilesAutomatically) {
var assetPath = AssetDatabase.GetAssetPath(InkLibrary.Instance.inkLibrary[i].jsonAsset);
if(assetPath != null && assetPath != string.Empty) {
AssetDatabase.DeleteAsset(assetPath);
}
}
InkLibrary.RemoveAt(i);
}
}
// 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.
foreach(InkFile inkFile in InkLibrary.Instance.inkLibrary) {
inkFile.metaInfo.FindIncludedFiles();
}
foreach(InkFile masterFile in masterFilesAffected) {
if(InkSettings.Instance.compileAutomatically || masterFile.compileAutomatically) {
InkCompiler.CompileInk(masterFile);
}
}
}
private static void OnMoveAssets (string[] movedAssets) {
if (!InkSettings.Instance.handleJSONFilesAutomatically)
return;
List<string> validMovedAssets = new List<string>();
for (var i = 0; i < movedAssets.Length; i++) {
if(Path.GetExtension(movedAssets[i]) != InkEditorUtils.inkFileExtension)
continue;
validMovedAssets.Add(movedAssets[i]);
queuedMovedAssets.Add(movedAssets[i]);
}
// Move compiled JSON files.
// This can cause Unity to postprocess assets again.
bool assetMoved = false;
foreach(var inkFilePath in validMovedAssets) {
InkFile inkFile = InkLibrary.GetInkFileWithPath(inkFilePath);
if(inkFile == null) continue;
if(inkFile.jsonAsset == null) continue;
string jsonAssetPath = AssetDatabase.GetAssetPath(inkFile.jsonAsset);
string movedAssetDir = Path.GetDirectoryName(inkFilePath);
string movedAssetFile = Path.GetFileName(inkFilePath);
string newPath = InkEditorUtils.CombinePaths(movedAssetDir, Path.GetFileNameWithoutExtension(movedAssetFile)) + ".json";
AssetDatabase.MoveAsset(jsonAssetPath, newPath);
assetMoved = true;
}
// 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)
if(!assetMoved && queuedMovedAssets.Count > 0) {
List<InkFile> filesToCompile = new List<InkFile>();
// Add the old master file to the files to be recompiled
foreach(var inkFilePath in queuedMovedAssets) {
InkFile inkFile = InkLibrary.GetInkFileWithPath(inkFilePath);
if(inkFile == null) continue;
InkFile masterInkFile = inkFile;
if(!inkFile.metaInfo.isMaster)
masterInkFile = inkFile.metaInfo.masterInkFile;
if(!filesToCompile.Contains(masterInkFile))
filesToCompile.Add(masterInkFile);
}
InkMetaLibrary.RebuildInkFileConnections();
// Add the new file to be recompiled
foreach(var inkFilePath in queuedMovedAssets) {
InkFile inkFile = InkLibrary.GetInkFileWithPath(inkFilePath);
if(inkFile == null) continue;
InkFile masterInkFile = inkFile;
if(!inkFile.metaInfo.isMaster)
masterInkFile = inkFile.metaInfo.masterInkFile;
if(!filesToCompile.Contains(masterInkFile))
filesToCompile.Add(masterInkFile);
}
queuedMovedAssets.Clear();
// Compile any ink files that are deemed master files a rebuild
foreach(var inkFile in filesToCompile) {
if(inkFile.metaInfo.isMaster) {
if(InkSettings.Instance.compileAutomatically || inkFile.compileAutomatically) {
InkCompiler.CompileInk(inkFile);
}
}
}
}
}
private static void OnImportAssets (string[] importedAssets) {
List<string> importedInkAssets = new List<string>();
string inklecateFileLocation = null;
foreach (var importedAssetPath in importedAssets) {
if(Path.GetExtension(importedAssetPath) == InkEditorUtils.inkFileExtension)
importedInkAssets.Add(importedAssetPath);
else if (Path.GetFileName(importedAssetPath) == "inklecate" && Path.GetExtension(importedAssetPath) == "")
inklecateFileLocation = importedAssetPath;
else if (Path.GetExtension(importedAssetPath) == ".asset") {
var obj = AssetDatabase.LoadAssetAtPath<ScriptableObject>(importedAssetPath);
if(obj is InkSettings) {
InkEditorUtils.DeleteAllButOldestScriptableObjects(AssetDatabase.FindAssets("t:"+typeof(InkSettings).Name), typeof(InkSettings).Name);
} else if(obj is InkLibrary) {
InkEditorUtils.DeleteAllButOldestScriptableObjects(AssetDatabase.FindAssets("t:"+typeof(InkLibrary).Name), typeof(InkLibrary).Name);
}
}
}
if(importedInkAssets.Count > 0)
PostprocessInkFiles(importedInkAssets);
if(inklecateFileLocation != null)
PostprocessInklecate(inklecateFileLocation);
}
private static void PostprocessInklecate (string inklecateFileLocation) {
// 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.
// To fix, one day!
Debug.Log("Inklecate updated. Recompiling all Ink files...");
InkEditorUtils.RecompileAll();
}
private static void PostprocessInkFiles (List<string> importedInkAssets) {
if(EditorApplication.isPlaying && InkSettings.Instance.delayInPlayMode) {
foreach(var fileToImport in importedInkAssets) {
if(!InkLibrary.Instance.pendingCompilationStack.Contains(fileToImport))
InkLibrary.Instance.pendingCompilationStack.Add(fileToImport);
}
} else {
InkLibrary.CreateOrReadUpdatedInkFiles (importedInkAssets);
foreach (var inkAssetToCompile in InkCompiler.GetUniqueMasterInkFilesToCompile (importedInkAssets))
InkCompiler.CompileInk(inkAssetToCompile);
}
}
}
}