/// <summary> /// Starts a System.Process that compiles a master ink file, creating a playable JSON file that can be parsed by the Ink.Story class /// </summary> /// <param name="inkFile">Ink file.</param> private static void CompileInkInternal(InkFile inkFile, bool immediate) { // If we've not yet locked C# compilation do so now if (!hasLockedUnityCompilation) { hasLockedUnityCompilation = true; EditorApplication.LockReloadAssemblies(); } RemoveFromPendingCompilationStack(inkFile); if (inkFile == null) { Debug.LogError("Tried to compile ink file but input was null."); return; } if (!inkFile.metaInfo.isMaster) { Debug.LogWarning("Compiling InkFile which is an include. Any file created is likely to be invalid. Did you mean to call CompileInk on inkFile.master?"); } if (InkLibrary.GetCompilationStackItem(inkFile) != null) { UnityEngine.Debug.LogWarning("Tried compiling ink file, but file is already compiling. " + inkFile.filePath); return; } string inputPath = InkEditorUtils.CombinePaths(inkFile.absoluteFolderPath, Path.GetFileName(inkFile.filePath)); Debug.Assert(inkFile.absoluteFilePath == inputPath); CompilationStackItem pendingFile = new CompilationStackItem { inkFile = InkLibrary.GetInkFileWithAbsolutePath(inputPath), inkAbsoluteFilePath = inputPath, jsonAbsoluteFilePath = inkFile.jsonPath, state = CompilationStackItem.State.Compiling }; InkLibrary.Instance.compilationStack.Add(pendingFile); InkLibrary.Save(); if (immediate) { CompileInkThreaded(pendingFile); Update(); } else { if (EditorApplication.isCompiling) { Debug.LogWarning("Was compiling scripts when ink compilation started! This seems to cause the thread to cancel and complete, but the work isn't done. It may cause a timeout."); } ThreadPool.QueueUserWorkItem(CompileInkThreaded, pendingFile); } }
static void RemoveCompilingFile(int index) { InkLibrary.Instance.compilationStack.RemoveAt(index); InkLibrary.Save(); // Progress bar prevents delayCall callback from firing in Linux Editor, locking the // compilation until it times out. Let's just not show progress bars in Linux Editor #if !UNITY_EDITOR_LINUX if (InkLibrary.Instance.compilationStack.Count == 0) { EditorUtility.ClearProgressBar(); } #endif }
public static void LoadOrCreateInstance() { InternalEditorUtility.LoadSerializedFileAndForget(absoluteSavePath); if (created) { if (InkEditorUtils.isFirstCompile) { Validate(); } } else { instance = ScriptableObject.CreateInstance <InkLibrary>(); instance.hideFlags = HideFlags.HideAndDontSave; Rebuild(); instance.Save(true); } }
/// <summary> /// Starts a System.Process that compiles a master ink file, creating a playable JSON file that can be parsed by the Ink.Story class /// </summary> /// <param name="inkFile">Ink file.</param> private static void CompileInkInternal(InkFile inkFile, bool immediate) { if (inkFile == null) { Debug.LogError("Tried to compile ink file but input was null."); return; } if (!inkFile.metaInfo.isMaster) { Debug.LogWarning("Compiling InkFile which is an include. Any file created is likely to be invalid. Did you mean to call CompileInk on inkFile.master?"); } // If we've not yet locked C# compilation do so now if (!hasLockedUnityCompilation) { hasLockedUnityCompilation = true; EditorApplication.LockReloadAssemblies(); } RemoveFromPendingCompilationStack(inkFile); if (InkLibrary.GetCompilationStackItem(inkFile) != null) { UnityEngine.Debug.LogWarning("Tried compiling ink file, but file is already compiling. " + inkFile.filePath); return; } string inputPath = InkEditorUtils.CombinePaths(inkFile.absoluteFolderPath, Path.GetFileName(inkFile.filePath)); Debug.Assert(inkFile.absoluteFilePath == inputPath); CompilationStackItem pendingFile = new CompilationStackItem { inkFile = InkLibrary.GetInkFileWithAbsolutePath(inputPath), inkAbsoluteFilePath = inputPath, jsonAbsoluteFilePath = inkFile.absoluteJSONPath, state = CompilationStackItem.State.Queued, immediate = immediate }; InkLibrary.Instance.compilationStack.Add(pendingFile); InkLibrary.Save(); TryCompileNextFileInStack(); }
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 Update() { if (!InkLibrary.created) { return; } for (int i = InkLibrary.Instance.compilationStack.Count - 1; i >= 0; i--) { var compilingFile = InkLibrary.Instance.compilationStack [i]; if (compilingFile.state == CompilationStackItem.State.Compiling) { compilingFile.timeTaken = (float)((DateTime.Now - compilingFile.startTime).TotalSeconds); if (compilingFile.timeTaken > InkSettings.Instance.compileTimeout) { if (compilingFile.process != null) { compilingFile.process.Exited -= OnCompileProcessComplete; compilingFile.process.Kill(); } InkLibrary.Instance.compilationStack.RemoveAt(i); InkLibrary.Save(); if (InkLibrary.Instance.compilationStack.Count == 0) { EditorUtility.ClearProgressBar(); } Debug.LogError("Ink Compiler timed out for " + compilingFile.inkAbsoluteFilePath + ".\n. Compilation should never take more than a few seconds, but for large projects or slow computers you may want to increase the timeout time in the InkSettings file.\nIf this persists there may be another issue; or else check an ink file exists at this path and try Assets/Recompile Ink, else please report as a bug with the following error log at this address: https://github.com/inkle/ink/issues\nError log:\n" + compilingFile.errorOutput); } } else if (compilingFile.state == CompilationStackItem.State.Importing) { // This covers a rare bug that I've not pinned down var timeTaken = (float)((DateTime.Now - compilingFile.startTime).TotalSeconds); if (timeTaken > InkSettings.Instance.compileTimeout + 2) { if (compilingFile.process != null && !compilingFile.process.HasExited) { compilingFile.process.Exited -= OnCompileProcessComplete; compilingFile.process.Kill(); } InkLibrary.Instance.compilationStack.RemoveAt(i); InkLibrary.Save(); if (InkLibrary.Instance.compilationStack.Count == 0) { EditorUtility.ClearProgressBar(); } Debug.LogError("Ink Compiler timed out for " + compilingFile.inkAbsoluteFilePath + " while the file was importing.\n. Please report as a bug with the following error log at this address: https://github.com/inkle/ink/issues\nError log:\n" + compilingFile.errorOutput); } } } if (InkLibrary.Instance.compilationStack.Count > 0) { int numCompiling = InkLibrary.FilesInCompilingStackInState(CompilationStackItem.State.Compiling).Count; string message = "Compiling .Ink File " + (InkLibrary.Instance.compilationStack.Count - numCompiling) + " of " + InkLibrary.Instance.compilationStack.Count; float progress = 0; foreach (var compilingFile in InkLibrary.Instance.compilationStack) { if (compilingFile.state == CompilationStackItem.State.Compiling) { progress += compilingFile.timeTaken / InkSettings.Instance.compileTimeout; } if (compilingFile.state == CompilationStackItem.State.Importing) { progress += 1; } } progress /= InkLibrary.Instance.compilationStack.Count; EditorUtility.DisplayProgressBar("Compiling Ink...", message, progress); } }
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."); } }
/// <summary> /// Starts a System.Process that compiles a master ink file, creating a playable JSON file that can be parsed by the Ink.Story class /// </summary> /// <param name="inkFile">Ink file.</param> public static void CompileInk(InkFile inkFile) { if (inkFile == null) { Debug.LogError("Tried to compile ink file " + inkFile.filePath + ", but input was null."); return; } if (!inkFile.metaInfo.isMaster) { Debug.LogWarning("Compiling InkFile which is an include. Any file created is likely to be invalid. Did you mean to call CompileInk on inkFile.master?"); } if (InkLibrary.GetCompilationStackItem(inkFile) != null) { UnityEngine.Debug.LogWarning("Tried compiling ink file, but file is already compiling. " + inkFile.filePath); return; } string inklecatePath = InkEditorUtils.GetInklecateFilePath(); if (inklecatePath == null) { UnityEngine.Debug.LogWarning("Inklecate (the ink compiler) not found in assets. This will prevent automatic building of JSON TextAsset files from ink story files."); return; } if (Application.platform == RuntimePlatform.OSXEditor) { SetInklecateFilePermissions(inklecatePath); } if (inklecatePath.Contains("'")) { Debug.LogError("Due to a Unity bug, Inklecate path cannot contain an apostrophe. Ink will not compile until this is resolved. Path is '" + inklecatePath + "'"); return; } // This hasn't been affecting us lately. Left it in so we can easily restore it in case of future bugs. /* else if(inklecatePath.Contains(" ")){ * Debug.LogWarning("Inklecate path should not contain a space. This might lead to compilation failing. Path is '"+inklecatePath+"'. If you don't see any compilation errors, you can ignore this warning."); * }*/ string inputPath = InkEditorUtils.CombinePaths(inkFile.absoluteFolderPath, Path.GetFileName(inkFile.filePath)); string outputPath = InkEditorUtils.CombinePaths(inkFile.absoluteFolderPath, Path.GetFileNameWithoutExtension(Path.GetFileName(inkFile.filePath))) + ".json"; string inkArguments = InkSettings.Instance.customInklecateOptions.additionalCompilerOptions + " -c -o " + "\"" + outputPath + "\" \"" + inputPath + "\""; CompilationStackItem pendingFile = new CompilationStackItem(); pendingFile.inkFile = InkLibrary.GetInkFileWithAbsolutePath(inputPath); pendingFile.inkAbsoluteFilePath = inputPath; pendingFile.jsonAbsoluteFilePath = outputPath; pendingFile.state = CompilationStackItem.State.Compiling; InkLibrary.Instance.compilationStack.Add(pendingFile); InkLibrary.Save(); Process process = new Process(); if (InkSettings.Instance.customInklecateOptions.runInklecateWithMono && Application.platform != RuntimePlatform.WindowsEditor) { if (File.Exists(_libraryMono)) { process.StartInfo.FileName = _libraryMono; } else if (File.Exists(_usrMono)) { process.StartInfo.FileName = _usrMono; } else { Debug.LogError("Mono was not found on machine"); return; } process.StartInfo.Arguments = inklecatePath + " " + inkArguments; } else { process.StartInfo.FileName = inklecatePath; process.StartInfo.Arguments = inkArguments; } process.StartInfo.RedirectStandardError = true; process.StartInfo.RedirectStandardOutput = true; process.StartInfo.UseShellExecute = false; process.StartInfo.CreateNoWindow = true; process.EnableRaisingEvents = true; process.OutputDataReceived += OnProcessOutput; // For some reason having this line enabled spams the output and error streams with null and "???" (only on OSX?) // Rather than removing unhandled error detection I thought it'd be best to just catch those messages and ignore them instead. process.ErrorDataReceived += OnProcessError; process.Exited += OnCompileProcessComplete; process.Start(); process.BeginOutputReadLine(); process.BeginErrorReadLine(); pendingFile.process = process; // If you'd like to run this command outside of unity, you could instead run process.StartInfo.Arguments in the command line. }
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.compileErrors.Clear(); compilingFile.inkFile.compileErrors.Add(compilingFile.errorOutput); errorsFound = true; } else { SetOutputLog(compilingFile); bool errorsInEntireStory = false; bool warningsInEntireStory = false; foreach (var inkFile in compilingFile.inkFile.inkFilesInIncludeHierarchy) { if (inkFile.hasErrors) { errorsInEntireStory = true; } if (inkFile.hasWarnings) { warningsInEntireStory = true; } } if (errorsInEntireStory) { listOfFiles += " (With error)"; errorsFound = true; } else { string localJSONAssetPath = compilingFile.jsonAbsoluteFilePath.Substring(Application.dataPath.Length - 6); 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(); EditorUtility.ClearProgressBar(); if (EditorApplication.isPlayingOrWillChangePlaymode) { Debug.LogWarning("Ink just finished recompiling while in play mode. Your runtime story may not be up to date."); } InkLibrary.Save(); }
// 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.Save(); InkMetaLibrary.Save(); #if !UNITY_EDITOR_LINUX EditorUtility.ClearProgressBar(); #endif #if UNITY_2019_4_OR_NEWER AssetDatabase.AllowAutoRefresh(); #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(); }
// 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."); } } }