private static void Update() { // If we're not compiling but have locked C# compilation then now is the time to reset if ((!InkLibrary.created || !compiling) && hasLockedUnityCompilation) { hasLockedUnityCompilation = false; EditorApplication.UnlockReloadAssemblies(); } if (!InkLibrary.created) { return; } if (compiling) { // Check for timeouts, in case of an unhandled bug with this system/the ink compiler! for (int i = InkLibrary.Instance.compilationStack.Count - 1; i >= 0; i--) { var compilingFile = InkLibrary.Instance.compilationStack [i]; if (compilingFile.state == CompilationStackItem.State.Compiling) { if (compilingFile.timeTaken > InkSettings.Instance.compileTimeout) { // TODO - Cancel the thread if it's still going. Not critical, since its kinda fine if it compiles a bit later, but it's not clear. RemoveCompilingFile(i); Debug.LogError("Ink Compiler timed out for " + compilingFile.inkAbsoluteFilePath + ".\nCompilation 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" + string.Join("\n", compilingFile.unhandledErrorOutput.ToArray())); TryCompileNextFileInStack(); } } } // When all files have compiled, run the complete function. if (InkLibrary.NumFilesInCompilingStackInState(CompilationStackItem.State.Compiling) == 0) { if (InkLibrary.NumFilesInCompilingStackInState(CompilationStackItem.State.Queued) == 0) { DelayedComplete(); } else { // We used to avoid calling this here in favour of calling it CompileInkThreaded but it seems that it doesn't run when called there, for some reason. // If someone can make this work please let me know! TryCompileNextFileInStack(); } } } // If we're not showing a progress bar in Linux this whole step is superfluous #if !UNITY_EDITOR_LINUX UpdateProgressBar(); #endif }
static void UpdateProgressBar() { if (InkLibrary.Instance.compilationStack.Count == 0) { return; } int numCompiling = InkLibrary.NumFilesInCompilingStackInState(CompilationStackItem.State.Compiling); string message = "Compiling .Ink File " + (InkLibrary.Instance.compilationStack.Count - numCompiling) + " of " + InkLibrary.Instance.compilationStack.Count + "."; if (playModeBlocked) { message += " Will enter play mode when complete."; } if (buildBlocked || playModeBlocked || EditorApplication.isPlaying) { EditorUtility.DisplayProgressBar("Compiling Ink...", message, GetEstimatedCompilationProgress()); } else { EditorUtility.ClearProgressBar(); } }
// 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(); }