/// <summary> /// Updates the ink library. Executed whenever an ink file is changed by InkToJSONPostProcessor /// Can be called manually, but incurs a performance cost. /// </summary> public static void Rebuild() { // Remove any old file connections Clean(); // Add any new file connections (if any are found it replaces the old library entirely) string[] inkFilePaths = GetAllInkFilePaths(); bool inkLibraryChanged = false; List <InkFile> newInkLibrary = new List <InkFile>(inkFilePaths.Length); for (int i = 0; i < inkFilePaths.Length; i++) { InkFile inkFile = GetInkFileWithAbsolutePath(inkFilePaths [i]); // If the ink library doesn't have a representation for this file, then make one if (inkFile == null) { inkLibraryChanged = true; string localAssetPath = InkEditorUtils.AbsoluteToUnityRelativePath(inkFilePaths [i]); DefaultAsset inkFileAsset = AssetDatabase.LoadAssetAtPath <DefaultAsset>(localAssetPath); // If the ink file can't be found, it might not yet have been imported. We try to manually import it to fix this. if (inkFileAsset == null) { AssetDatabase.ImportAsset(localAssetPath); inkFileAsset = AssetDatabase.LoadAssetAtPath <DefaultAsset>(localAssetPath); if (inkFileAsset == null) { Debug.LogWarning("Ink File Asset not found at " + localAssetPath + ". This can occur if the .meta file has not yet been created. This issue should resolve itself, but if unexpected errors occur, rebuild Ink Library using Assets > Recompile Ink"); continue; } } inkFile = new InkFile(inkFileAsset); } newInkLibrary.Add(inkFile); } if (inkLibraryChanged) { Instance.inkLibrary = newInkLibrary; SortInkLibrary(); } CreateDictionary(); // Validate the meta files var metaFiles = Instance.inkLibrary.Select(x => x.metaInfo); bool metaFilesChanged = !InkMetaLibrary.Instance.metaLibrary.SequenceEqual(metaFiles); if (metaFilesChanged) { InkMetaLibrary.Instance.metaLibrary = metaFiles.ToList(); } InkMetaLibrary.RebuildInkFileConnections(); foreach (InkFile inkFile in Instance.inkLibrary) { inkFile.FindCompiledJSONAsset(); } SaveToFile(); Debug.Log("Ink Library was rebuilt."); }
private static InkMetaLibrary FindLibrary() { if (EditorPrefs.HasKey(pathPlayerPrefsKey)) { try { InkMetaLibrary library = new InkMetaLibrary(); var libraryJSON = EditorPrefs.GetString(pathPlayerPrefsKey); EditorJsonUtility.FromJsonOverwrite(libraryJSON, library); return(library); } catch { return(null); } } return(null); }
private static void CreateOrReadUpdatedInkFiles(List<string> importedInkAssets) { foreach (var importedAssetPath in importedInkAssets) { InkFile inkFile = InkLibrary.GetInkFileWithPath(importedAssetPath); if(inkFile == null) { DefaultAsset asset = AssetDatabase.LoadAssetAtPath<DefaultAsset>(importedAssetPath); inkFile = new InkFile(asset); InkLibrary.Instance.inkLibrary.Add(inkFile); InkMetaLibrary.Instance.metaLibrary.Add(new InkMetaFile(inkFile)); } else { inkFile.metaInfo.ParseContent(); } } // Now we've updated all the include paths for the ink library we can create master/child references between them. InkMetaLibrary.RebuildInkFileConnections(); }
/// <summary> /// Updates the ink library. Executed whenever an ink file is changed by InkToJSONPostProcessor /// Can be called manually, but incurs a performance cost. /// </summary> public static void Rebuild() { Debug.Log("Rebuilding Ink Library..."); string[] inkFilePaths = GetAllInkFilePaths(); List <InkFile> newInkLibrary = new List <InkFile>(inkFilePaths.Length); for (int i = 0; i < inkFilePaths.Length; i++) { InkFile inkFile = GetInkFileWithAbsolutePath(inkFilePaths [i]); if (inkFile == null) { string localAssetPath = inkFilePaths [i].Substring(Application.dataPath.Length - 6); DefaultAsset inkFileAsset = AssetDatabase.LoadAssetAtPath <DefaultAsset>(localAssetPath); // If the ink file can't be found, it might not yet have been imported. We try to manually import it to fix this. if (inkFileAsset == null) { AssetDatabase.ImportAsset(localAssetPath); inkFileAsset = AssetDatabase.LoadAssetAtPath <DefaultAsset>(localAssetPath); if (inkFileAsset == null) { Debug.LogWarning("Ink File Asset not found at " + localAssetPath + ". This can occur if the .meta file has not yet been created. This issue should resolve itself, but if unexpected errors occur, rebuild Ink Library using > Recompile Ink"); continue; } } inkFile = new InkFile(inkFileAsset); } newInkLibrary.Add(inkFile); } Instance.inkLibrary = newInkLibrary; InkMetaLibrary.Instance.metaLibrary.Clear(); foreach (InkFile inkFile in Instance.inkLibrary) { InkMetaLibrary.Instance.metaLibrary.Add(inkFile.metaInfo); } InkMetaLibrary.RebuildInkFileConnections(); foreach (InkFile inkFile in Instance.inkLibrary) { inkFile.FindCompiledJSONAsset(); } Save(); }
private static InkMetaLibrary FindOrCreateLibrary() { _Instance = FindLibrary(); // If we couldn't find the asset in the project, create a new one. if (_Instance == null) { _Instance = new InkMetaLibrary(); InkMetaLibrary.Rebuild(); } else { bool valid = ValidateLibrary(); if (!valid) { RebuildInkFileConnections(); Debug.LogWarning("Ink Meta Library data corrupted. This can happen when Unity updates its library. Updated file connections but recommend recompiling."); } } return(_Instance); }
public static void CompileInk(params InkFile[] inkFiles) { _postAssetDataBaseRefreshActions.Clear(); AssetDatabase.DisallowAutoRefresh(); try { CompileInk(inkFiles, true, null); //use immediate=true to avoid thread access issues. } finally { AssetDatabase.AllowAutoRefresh(); } AssetDatabase.Refresh(); foreach (var action in _postAssetDataBaseRefreshActions) { action(); } _postAssetDataBaseRefreshActions.Clear(); InkLibrary.Save(); InkMetaLibrary.Save(); }
private static void Delay() { if (InkLibrary.FilesInCompilingStackInState(CompilationStackItem.State.Compiling).Count > 0) { Debug.LogWarning("Delayed, but a file is now compiling! You can ignore this warning."); return; } float longestTimeTaken = 0; bool errorsFound = false; StringBuilder filesCompiledLog = new StringBuilder("Files compiled:"); foreach (var compilingFile in InkLibrary.Instance.compilationStack) { longestTimeTaken = Mathf.Max(compilingFile.timeTaken); filesCompiledLog.AppendLine().Append(compilingFile.inkFile.filePath); if (compilingFile.errorOutput.Count > 0) { filesCompiledLog.Append(" (With unhandled error)"); StringBuilder errorLog = new StringBuilder(); errorLog.Append("Unhandled error(s) occurred compiling Ink file "); errorLog.Append("'"); errorLog.Append(compilingFile.inkFile.filePath); errorLog.Append("'"); errorLog.AppendLine("! Please report following error(s) as a bug:"); foreach (var error in compilingFile.errorOutput) { errorLog.AppendLine(error); } Debug.LogError(errorLog); compilingFile.inkFile.metaInfo.compileErrors = compilingFile.errorOutput; errorsFound = true; } else { SetOutputLog(compilingFile); bool errorsInEntireStory = false; bool warningsInEntireStory = false; foreach (var inkFile in compilingFile.inkFile.metaInfo.inkFilesInIncludeHierarchy) { if (inkFile.metaInfo.hasErrors) { errorsInEntireStory = true; } if (inkFile.metaInfo.hasWarnings) { warningsInEntireStory = true; } } if (errorsInEntireStory) { filesCompiledLog.Append(" (With error)"); errorsFound = true; } else { string localJSONAssetPath = InkEditorUtils.AbsoluteToUnityRelativePath(compilingFile.jsonAbsoluteFilePath); AssetDatabase.ImportAsset(localJSONAssetPath); compilingFile.inkFile.jsonAsset = AssetDatabase.LoadAssetAtPath <TextAsset> (localJSONAssetPath); } if (warningsInEntireStory) { filesCompiledLog.Append(" (With warning)"); } } } if (longestTimeTaken > InkSettings.Instance.compileTimeout * 0.6f) { Debug.LogWarning("Compilation took over 60% of the time required to timeout the compiler. Consider increasing the compile timeout on the InkSettings file."); } foreach (var compilingFile in InkLibrary.Instance.compilationStack) { if (OnCompileInk != null) { OnCompileInk(compilingFile.inkFile); } } StringBuilder outputLog = new StringBuilder(); if (errorsFound) { outputLog.Append("Ink compilation completed with errors at "); outputLog.AppendLine(DateTime.Now.ToLongTimeString()); outputLog.Append(filesCompiledLog.ToString()); Debug.LogWarning(outputLog); } else { outputLog.Append("Ink compilation completed at "); outputLog.AppendLine(DateTime.Now.ToLongTimeString()); outputLog.Append(filesCompiledLog.ToString()); Debug.Log(outputLog); } InkLibrary.Instance.compilationStack.Clear(); InkLibrary.Save(); InkMetaLibrary.Save(); EditorUtility.ClearProgressBar(); if (EditorApplication.isPlayingOrWillChangePlaymode) { Debug.LogWarning("Ink just finished recompiling while in play mode. Your runtime story may not be up to date."); } }
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); } } } } }
// When all files in stack have been compiled. This is called via update because Process events run in another thread. private static void DelayedComplete() { if (InkLibrary.NumFilesInCompilingStackInState(CompilationStackItem.State.Compiling) > 0) { Debug.LogWarning("Delayed, but a file is now compiling! You can ignore this warning."); return; } bool errorsFound = false; StringBuilder filesCompiledLog = new StringBuilder("Files compiled:"); // Create and import compiled files AssetDatabase.StartAssetEditing(); foreach (var compilingFile in InkLibrary.Instance.compilationStack) { // Complete status is also set when an error occured, in these cases 'compiledJson' will be null so there's no import to process if (compilingFile.compiledJson == null) { continue; } // Write new compiled data to the file system File.WriteAllText(compilingFile.jsonAbsoluteFilePath, compilingFile.compiledJson, Encoding.UTF8); AssetDatabase.ImportAsset(compilingFile.inkFile.jsonPath); } AssetDatabase.StopAssetEditing(); foreach (var compilingFile in InkLibrary.Instance.compilationStack) { // Load and store a reference to the compiled file compilingFile.inkFile.FindCompiledJSONAsset(); filesCompiledLog.AppendLine().Append(compilingFile.inkFile.filePath); filesCompiledLog.Append(string.Format(" ({0}s)", compilingFile.timeTaken)); if (compilingFile.unhandledErrorOutput.Count > 0) { filesCompiledLog.Append(" (With unhandled error)"); StringBuilder errorLog = new StringBuilder(); errorLog.Append("Unhandled error(s) occurred compiling Ink file "); errorLog.Append("'"); errorLog.Append(compilingFile.inkFile.filePath); errorLog.Append("'"); errorLog.AppendLine("! Please report following error(s) as a bug:"); foreach (var error in compilingFile.unhandledErrorOutput) { errorLog.AppendLine(error); } Debug.LogError(errorLog); compilingFile.inkFile.metaInfo.unhandledCompileErrors = compilingFile.unhandledErrorOutput; errorsFound = true; } else { SetOutputLog(compilingFile); bool errorsInEntireStory = false; bool warningsInEntireStory = false; foreach (var inkFile in compilingFile.inkFile.metaInfo.inkFilesInIncludeHierarchy) { if (inkFile.metaInfo.hasErrors) { errorsInEntireStory = true; } if (inkFile.metaInfo.hasWarnings) { warningsInEntireStory = true; } } if (errorsInEntireStory) { filesCompiledLog.Append(" (With error)"); errorsFound = true; } if (warningsInEntireStory) { filesCompiledLog.Append(" (With warning)"); } } } foreach (var compilingFile in InkLibrary.Instance.compilationStack) { if (OnCompileInk != null) { OnCompileInk(compilingFile.inkFile); } } StringBuilder outputLog = new StringBuilder(); if (errorsFound) { outputLog.Append("Ink compilation completed with errors at "); outputLog.AppendLine(DateTime.Now.ToLongTimeString()); outputLog.Append(filesCompiledLog.ToString()); Debug.LogError(outputLog); } else { outputLog.Append("Ink compilation completed at "); outputLog.AppendLine(DateTime.Now.ToLongTimeString()); outputLog.Append(filesCompiledLog.ToString()); Debug.Log(outputLog); } InkLibrary.Instance.compilationStack.Clear(); InkLibrary.SaveToFile(); InkMetaLibrary.Save(); #if !UNITY_EDITOR_LINUX EditorUtility.ClearProgressBar(); #endif #if UNITY_2019_4_OR_NEWER if (InkLibrary.Instance.disallowedAutoRefresh) { InkLibrary.Instance.disallowedAutoRefresh = false; InkLibrary.SaveToFile(); try { AssetDatabase.AllowAutoRefresh(); } catch (Exception e) { Debug.LogWarning("Failed AllowAutoRefresh " + e); } } #endif // This is now allowed, if compiled manually. I've left this code commented out because at some point we might want to track what caused a file to compile. // if(EditorApplication.isPlayingOrWillChangePlaymode && InkSettings.Instance.delayInPlayMode) { // Debug.LogError("Ink just finished recompiling while in play mode. This should never happen when InkSettings.Instance.delayInPlayMode is true!"); // } buildBlocked = false; if (playModeBlocked) { playModeBlocked = false; if (!errorsFound) { // Delaying gives the editor a frame to clear the progress bar. EditorApplication.delayCall += () => { Debug.Log("Compilation completed, entering play mode."); EditorApplication.isPlaying = true; }; } else { Debug.LogWarning("Play mode not entered after ink compilation because ink had errors."); } } foreach (var onCompleteAction in onCompleteActions) { if (onCompleteAction != null) { onCompleteAction(); } } onCompleteActions.Clear(); }
/// <summary> /// Rebuilds which files are master files and the connections between the files. /// </summary> public static void RebuildInkFileConnections() { foreach (InkFile inkFile in InkLibrary.Instance.inkLibrary) { inkFile.metaInfo.parent = null; inkFile.metaInfo.masterInkAsset = null; inkFile.metaInfo.ParseContent(); inkFile.metaInfo.FindIncludedFiles(); } // We now set the master file for ink files. As a file can be in an include hierarchy, we need to do this in two passes. // First, we set the master file to the file that includes an ink file. foreach (InkFile inkFile in InkLibrary.Instance.inkLibrary) { if (inkFile.metaInfo.includes.Count == 0) { continue; } foreach (InkFile otherInkFile in InkLibrary.Instance.inkLibrary) { if (inkFile == otherInkFile) { continue; } if (inkFile.metaInfo.includes.Contains(otherInkFile.inkAsset)) { otherInkFile.metaInfo.parent = inkFile.inkAsset; } } } // Next, we create a list of all the files owned by the actual master file, which we obtain by travelling up the parent tree from each file. Dictionary <InkFile, List <InkFile> > masterChildRelationships = new Dictionary <InkFile, List <InkFile> >(); foreach (InkFile inkFile in InkLibrary.Instance.inkLibrary) { if (inkFile.metaInfo.parent == null) { continue; } InkFile parent = inkFile.metaInfo.parentInkFile; while (parent.metaInfo.parent != null) { parent = parent.metaInfo.parentInkFile; } if (!masterChildRelationships.ContainsKey(parent)) { masterChildRelationships.Add(parent, new List <InkFile>()); } masterChildRelationships[parent].Add(inkFile); } // Finally, we set the master file of the children foreach (var inkFileRelationship in masterChildRelationships) { foreach (InkFile childInkFile in inkFileRelationship.Value) { childInkFile.metaInfo.masterInkAsset = inkFileRelationship.Key.inkAsset; if (InkSettings.Instance.handleJSONFilesAutomatically && childInkFile.jsonAsset != null) { AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(childInkFile.jsonAsset)); childInkFile.jsonAsset = null; } } } InkMetaLibrary.Save(); }
/// <summary> /// Rebuilds which files are master files and the connections between the files. /// </summary> public static void RebuildInkFileConnections() { foreach (InkFile inkFile in InkLibrary.Instance.inkLibrary) { inkFile.metaInfo.parents = new List <DefaultAsset>(); inkFile.metaInfo.masterInkAssets = new List <DefaultAsset>(); inkFile.metaInfo.ParseContent(); inkFile.metaInfo.FindIncludedFiles(); } // We now set the master file for ink files. As a file can be in an include hierarchy, we need to do this in two passes. // First, we set the master file to the file that includes an ink file. foreach (InkFile inkFile in InkLibrary.Instance.inkLibrary) { if (inkFile.metaInfo.includes.Count == 0) { continue; } foreach (InkFile otherInkFile in InkLibrary.Instance.inkLibrary) { if (inkFile == otherInkFile) { continue; } if (inkFile.metaInfo.includes.Contains(otherInkFile.inkAsset)) { if (!otherInkFile.metaInfo.parents.Contains(inkFile.inkAsset)) { otherInkFile.metaInfo.parents.Add(inkFile.inkAsset); } } } } // Next, we create a list of all the files owned by the actual master file, which we obtain by travelling up the parent tree from each file. Dictionary <InkFile, List <InkFile> > masterChildRelationships = new Dictionary <InkFile, List <InkFile> >(); foreach (InkFile inkFile in InkLibrary.Instance.inkLibrary) { foreach (var parentInkFile in inkFile.metaInfo.parentInkFiles) { InkFile lastMasterInkFile = parentInkFile; InkFile masterInkFile = parentInkFile; while (masterInkFile.metaInfo.parents.Count != 0) { // This shouldn't just pick first, but iterate the whole lot! // I didn't feel like writing a recursive algorithm until it's actually needed though - a file included by several parents is already a rare enough case! masterInkFile = masterInkFile.metaInfo.parentInkFiles.First(); lastMasterInkFile = masterInkFile; } if (lastMasterInkFile.metaInfo.parents.Count > 1) { Debug.LogError("The ink ownership tree has another master file that is not discovered! This is an oversight of the current implementation. If you requres this feature, please take a look at the comment in the code above - if you solve it let us know and we'll merge it in!"); } if (!masterChildRelationships.ContainsKey(masterInkFile)) { masterChildRelationships.Add(masterInkFile, new List <InkFile>()); } masterChildRelationships[masterInkFile].Add(inkFile); } // if(inkFile.metaInfo.parent == null) // continue; // InkFile parent = inkFile.metaInfo.parentInkFile; // while (parent.metaInfo.parent != null) { // parent = parent.metaInfo.parentInkFile; // } // if(!masterChildRelationships.ContainsKey(parent)) { // masterChildRelationships.Add(parent, new List<InkFile>()); // } // masterChildRelationships[parent].Add(inkFile); } // Finally, we set the master file of the children foreach (var inkFileRelationship in masterChildRelationships) { foreach (InkFile childInkFile in inkFileRelationship.Value) { if (!childInkFile.metaInfo.masterInkAssets.Contains(inkFileRelationship.Key.inkAsset)) { childInkFile.metaInfo.masterInkAssets.Add(inkFileRelationship.Key.inkAsset); } else { Debug.LogWarning("Child file already contained master file reference! This is weird!"); } if (InkSettings.Instance.handleJSONFilesAutomatically && childInkFile.jsonAsset != null) { AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(childInkFile.jsonAsset)); childInkFile.jsonAsset = null; } } } InkMetaLibrary.Save(); }
private static void Delay() { if (InkLibrary.FilesInCompilingStackInState(CompilationStackItem.State.Compiling).Count > 0) { Debug.LogWarning("Delayed, but a file is now compiling! You can ignore this warning."); return; } bool errorsFound = false; string listOfFiles = "\nFiles compiled:"; foreach (var compilingFile in InkLibrary.Instance.compilationStack) { listOfFiles += "\n"; listOfFiles += compilingFile.inkFile.filePath; if (compilingFile.errorOutput != "") { listOfFiles += " (With unhandled error)"; Debug.LogError("Unhandled error occurred compiling Ink file " + compilingFile.inkFile + "! Please report following error as a bug:\n" + compilingFile.errorOutput); compilingFile.inkFile.metaInfo.compileErrors.Clear(); compilingFile.inkFile.metaInfo.compileErrors.Add(compilingFile.errorOutput); errorsFound = true; } else { SetOutputLog(compilingFile); bool errorsInEntireStory = false; bool warningsInEntireStory = false; foreach (var inkFile in compilingFile.inkFile.metaInfo.inkFilesInIncludeHierarchy) { if (inkFile.metaInfo.hasErrors) { errorsInEntireStory = true; } if (inkFile.metaInfo.hasWarnings) { warningsInEntireStory = true; } } if (errorsInEntireStory) { listOfFiles += " (With error)"; errorsFound = true; } else { string localJSONAssetPath = InkEditorUtils.AbsoluteToUnityRelativePath(compilingFile.jsonAbsoluteFilePath); AssetDatabase.ImportAsset(localJSONAssetPath); compilingFile.inkFile.jsonAsset = AssetDatabase.LoadAssetAtPath <TextAsset> (localJSONAssetPath); } if (warningsInEntireStory) { listOfFiles += " (With warning)"; } } } foreach (var compilingFile in InkLibrary.Instance.compilationStack) { if (OnCompileInk != null) { OnCompileInk(compilingFile.inkFile); } } if (errorsFound) { Debug.LogWarning("Ink compilation completed with errors at " + DateTime.Now.ToLongTimeString() + listOfFiles); } else { Debug.Log("Ink compilation completed at " + DateTime.Now.ToLongTimeString() + listOfFiles); } InkLibrary.Instance.compilationStack.Clear(); InkLibrary.Save(); InkMetaLibrary.Save(); EditorUtility.ClearProgressBar(); if (EditorApplication.isPlayingOrWillChangePlaymode) { Debug.LogWarning("Ink just finished recompiling while in play mode. Your runtime story may not be up to date."); } }
// When all files in stack have been compiled. This is called via update because Process events run in another thread. private static void DelayedComplete() { if (InkLibrary.FilesInCompilingStackInState(CompilationStackItem.State.Compiling).Count > 0) { Debug.LogWarning("Delayed, but a file is now compiling! You can ignore this warning."); return; } float longestTimeTaken = 0; bool errorsFound = false; StringBuilder filesCompiledLog = new StringBuilder("Files compiled:"); foreach (var compilingFile in InkLibrary.Instance.compilationStack) { // Complete status is also set when an error occured, in these cases 'compiledJson' will be null so there's no import to process if (compilingFile.compiledJson != null) { // Write new compiled data to the file system File.WriteAllText(compilingFile.jsonAbsoluteFilePath, compilingFile.compiledJson, Encoding.UTF8); AssetDatabase.ImportAsset(compilingFile.jsonAbsoluteFilePath); var jsonObject = AssetDatabase.LoadAssetAtPath <TextAsset>(compilingFile.inkFile.jsonPath); // Update the jsonAsset reference compilingFile.inkFile.jsonAsset = jsonObject; } longestTimeTaken = Mathf.Max(compilingFile.timeTaken); filesCompiledLog.AppendLine().Append(compilingFile.inkFile.filePath); filesCompiledLog.Append(string.Format(" ({0}s)", compilingFile.timeTaken)); if (compilingFile.errorOutput.Count > 0) { filesCompiledLog.Append(" (With unhandled error)"); StringBuilder errorLog = new StringBuilder(); errorLog.Append("Unhandled error(s) occurred compiling Ink file "); errorLog.Append("'"); errorLog.Append(compilingFile.inkFile.filePath); errorLog.Append("'"); errorLog.AppendLine("! Please report following error(s) as a bug:"); foreach (var error in compilingFile.errorOutput) { errorLog.AppendLine(error); } Debug.LogError(errorLog); compilingFile.inkFile.metaInfo.compileErrors = compilingFile.errorOutput; errorsFound = true; } else { SetOutputLog(compilingFile); bool errorsInEntireStory = false; bool warningsInEntireStory = false; foreach (var inkFile in compilingFile.inkFile.metaInfo.inkFilesInIncludeHierarchy) { if (inkFile.metaInfo.hasErrors) { errorsInEntireStory = true; } if (inkFile.metaInfo.hasWarnings) { warningsInEntireStory = true; } } if (errorsInEntireStory) { filesCompiledLog.Append(" (With error)"); errorsFound = true; } if (warningsInEntireStory) { filesCompiledLog.Append(" (With warning)"); } } } if (longestTimeTaken > InkSettings.Instance.compileTimeout * 0.6f) { Debug.LogWarning("Compilation took over 60% of the time required to timeout the compiler. Consider increasing the compile timeout on the InkSettings file."); } foreach (var compilingFile in InkLibrary.Instance.compilationStack) { if (OnCompileInk != null) { OnCompileInk(compilingFile.inkFile); } } StringBuilder outputLog = new StringBuilder(); if (errorsFound) { outputLog.Append("Ink compilation completed with errors at "); outputLog.AppendLine(DateTime.Now.ToLongTimeString()); outputLog.Append(filesCompiledLog.ToString()); Debug.LogError(outputLog); } else { outputLog.Append("Ink compilation completed at "); outputLog.AppendLine(DateTime.Now.ToLongTimeString()); outputLog.Append(filesCompiledLog.ToString()); Debug.Log(outputLog); } InkLibrary.Instance.compilationStack.Clear(); InkLibrary.Save(); InkMetaLibrary.Save(); #if !UNITY_EDITOR_LINUX EditorUtility.ClearProgressBar(); #endif if (EditorApplication.isPlayingOrWillChangePlaymode && InkSettings.Instance.delayInPlayMode) { Debug.LogError("Ink just finished recompiling while in play mode. This should never happen when InkSettings.Instance.delayInPlayMode is true!"); } buildBlocked = false; if (playModeBlocked) { playModeBlocked = false; if (!errorsFound) { // Delaying gives the editor a frame to clear the progress bar. EditorApplication.delayCall += () => { Debug.Log("Compilation completed, entering play mode."); EditorApplication.isPlaying = true; }; } else { Debug.LogWarning("Play mode not entered after ink compilation because ink had errors."); } } }