static void RemoveCompilingFile(int index) { InkLibrary.Instance.compilationStack.RemoveAt(index); InkLibrary.SaveToFile(); // 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 RemoveFromPendingCompilationStack(InkFile inkFile) { bool anyChange = false; anyChange = InkLibrary.Instance.pendingCompilationStack.Remove(inkFile.filePath) || anyChange; foreach (var includeFile in inkFile.inkFilesInIncludeHierarchy) { anyChange = InkLibrary.Instance.pendingCompilationStack.Remove(includeFile.filePath) || anyChange; } if (anyChange) { InkLibrary.SaveToFile(); } }
/// <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.SaveToFile(); TryCompileNextFileInStack(); }
public static void CompileInk(InkFile[] inkFiles, bool immediate, Action onComplete) { #if UNITY_2019_4_OR_NEWER if (!InkLibrary.Instance.disallowedAutoRefresh) { InkLibrary.Instance.disallowedAutoRefresh = true; InkLibrary.SaveToFile(); try { AssetDatabase.DisallowAutoRefresh(); } catch (Exception e) { Debug.LogWarning("Failed DisallowAutoRefresh " + e); } } #endif InkLibrary.Validate(); if (onComplete != null) { onCompleteActions.Add(onComplete); } StringBuilder filesCompiledLog = new StringBuilder("Files compiled:"); foreach (var inkFile in inkFiles) { filesCompiledLog.AppendLine().Append(inkFile.filePath); } StringBuilder outputLog = new StringBuilder(); outputLog.Append("Ink compilation started at "); outputLog.AppendLine(DateTime.Now.ToLongTimeString()); outputLog.Append(filesCompiledLog.ToString()); Debug.Log(outputLog); foreach (var inkFile in inkFiles) { CompileInkInternal(inkFile, immediate); } }
static InkCompiler() { #if UNITY_2017_1_OR_NEWER EditorApplication.playModeStateChanged += OnPlayModeChange; #else EditorApplication.playmodeStateChanged += LegacyOnPlayModeChange; #endif EditorApplication.update += Update; // I really don't know if this can fire, since it assumes that it compiled so can't have been locked. But safety first! EditorApplication.UnlockReloadAssemblies(); #if UNITY_2019_4_OR_NEWER // This one, on the other hand, seems to actually occur sometimes - presumably because c# compiles at the same time as the ink. if (InkLibrary.Instance.disallowedAutoRefresh) { InkLibrary.Instance.disallowedAutoRefresh = false; InkLibrary.SaveToFile(); try { AssetDatabase.AllowAutoRefresh(); } catch (Exception e) { Debug.LogWarning("Failed AllowAutoRefresh " + e); } } #endif }
// 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(); }
public static void ClearCompilationStacks() { InkLibrary.Instance.compilationStack.Clear(); InkLibrary.Instance.pendingCompilationStack.Clear(); InkLibrary.SaveToFile(); }