Beispiel #1
0
        void DrawEditAndCompileDates(InkFile masterInkFile)
        {
            editedAfterLastCompile = false;
            string   editAndCompileDateString = "";
            DateTime lastEditDate             = File.GetLastWriteTime(inkFile.absoluteFilePath);

            editAndCompileDateString += "Last edit date " + lastEditDate.ToString();
            if (inkFile.isMaster && inkFile.jsonAsset != null)
            {
                DateTime lastCompileDate = File.GetLastWriteTime(Path.Combine(Application.dataPath, AssetDatabase.GetAssetPath(masterInkFile.jsonAsset).Substring(7)));
                editAndCompileDateString += "\nLast compile date " + lastCompileDate.ToString();
                if (lastEditDate > lastCompileDate)
                {
                    editedAfterLastCompile = true;
                    EditorGUILayout.HelpBox(editAndCompileDateString, MessageType.Warning);
                    if (GUILayout.Button("Recompile"))
                    {
                        InkCompiler.CompileInk(masterInkFile);
                    }
                }
                else
                {
                    EditorGUILayout.HelpBox(editAndCompileDateString, MessageType.None);
                }
            }
            else
            {
                EditorGUILayout.HelpBox(editAndCompileDateString, MessageType.None);
            }
        }
        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)
                        AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(InkLibrary.Instance.inkLibrary[i].jsonAsset));
                    InkLibrary.Instance.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) {
                InkCompiler.CompileInk(masterFile);
            }
        }
Beispiel #3
0
 static void CompilePendingFiles()
 {
     InkLibrary.CreateOrReadUpdatedInkFiles(InkLibrary.Instance.pendingCompilationStack);
     foreach (var pendingMasterFile in GetUniqueMasterInkFilesToCompile(InkLibrary.Instance.pendingCompilationStack))
     {
         InkCompiler.CompileInk(pendingMasterFile);
     }
 }
        public static void RecompileAll()
        {
            InkCompiler.CompileInk(InkLibrary.FilesCompiledByRecompileAll().ToArray());
            string logString = InkLibrary.FilesCompiledByRecompileAll().Any() ?
                               "Recompile All will compile " + string.Join(", ", InkLibrary.FilesCompiledByRecompileAll().Select(x => Path.GetFileName(x.filePath)).ToArray()) :
                               "No valid ink found. Note that only files with 'Compile Automatic' checked are compiled if not set to compile all files automatically in InkSettings file.";

            Debug.Log(logString);
        }
Beispiel #5
0
 static void CompilePendingFiles()
 {
     InkLibrary.CreateOrReadUpdatedInkFiles(InkLibrary.Instance.pendingCompilationStack);
     foreach (var pendingFile in GetUniqueMasterInkFilesToCompile(InkLibrary.Instance.pendingCompilationStack))
     {
         InkCompiler.CompileInk(pendingFile);
     }
     // Files are removed when they're compiled, but we clear the list now just in case.
     InkLibrary.Instance.pendingCompilationStack.Clear();
 }
 private static void PostprocessInkFiles(List<string> importedInkAssets)
 {
     //			foreach (var importedAssetPath in importedInkAssets) {
     //				Debug.Log("Imported Ink: "+importedAssetPath);
     //			}
     CreateOrReadUpdatedInkFiles (importedInkAssets);
     foreach (var inkAssetToCompile in GetUniqueMasterInkFilesToCompile (importedInkAssets)) {
         InkCompiler.CompileInk(inkAssetToCompile);
     }
 }
Beispiel #7
0
        public static void RecompileAll()
        {
            InkLibrary.Rebuild();
            List <InkFile> masterInkFiles = InkLibrary.GetMasterInkFiles();

            foreach (InkFile masterInkFile in masterInkFiles)
            {
                InkCompiler.CompileInk(masterInkFile);
            }
        }
        public static void RecompileAll()
        {
            InkLibrary.Rebuild();
            List <InkFile> masterInkFiles = InkLibrary.GetMasterInkFiles();

            foreach (InkFile masterInkFile in masterInkFiles)
            {
                if (InkSettings.Instance.compileAutomatically || masterInkFile.compileAutomatically)
                {
                    InkCompiler.CompileInk(masterInkFile);
                }
            }
        }
 private static void PostprocessInkFiles(List <string> importedInkAssets)
 {
     if (EditorApplication.isPlaying && InkSettings.Instance.delayInPlayMode)
     {
         foreach (var fileToImport in importedInkAssets)
         {
             InkLibrary.AddToPendingCompilationStack(fileToImport);
         }
     }
     else
     {
         InkLibrary.CreateOrReadUpdatedInkFiles(importedInkAssets);
         InkCompiler.CompileInk(InkCompiler.GetUniqueMasterInkFilesToCompile(importedInkAssets).ToArray());
     }
 }
        public static void RecompileAll()
        {
            List <string> compiledFiles = new List <string>();

            foreach (InkFile masterInkFile in InkLibrary.FilesCompiledByRecompileAll())
            {
                InkCompiler.CompileInk(masterInkFile);
                compiledFiles.Add(Path.GetFileName(masterInkFile.filePath));
            }
            string logString = compiledFiles.Count == 0 ?
                               "No valid ink found. Note that only files with 'Compile Automatic' checked are compiled if not set to compile all files automatically in InkSettings file." :
                               "Recompile All will compile " + string.Join(", ", compiledFiles.ToArray());

            Debug.Log(logString);
        }
Beispiel #11
0
        private static void OnPlayModeChange(PlayModeStateChange change)
        {
            if (!EditorApplication.isPlayingOrWillChangePlaymode && EditorApplication.isPlaying && InkLibrary.Instance.pendingCompilationStack.Count > 0)
            {
                InkLibrary.CreateOrReadUpdatedInkFiles(InkLibrary.Instance.pendingCompilationStack);
                foreach (var pendingFile in GetUniqueMasterInkFilesToCompile(InkLibrary.Instance.pendingCompilationStack))
                {
                    InkCompiler.CompileInk(pendingFile);
                }
                InkLibrary.Instance.pendingCompilationStack.Clear();
            }

            if (EditorApplication.isPlayingOrWillChangePlaymode && EditorApplication.isPlaying && compiling)
            {
                Debug.LogWarning("Entered Play Mode while Ink was still compiling. Recommend exiting and re-entering play mode.");
            }
        }
Beispiel #12
0
 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);
         }
     }
 }
        static void PostprocessInkFiles(List <string> importedInkAssets)
        {
            InkLibrary.Refresh();
            List <string> inkAssetsToCompile = new List <string>();

            foreach (var importedAssetPath in importedInkAssets)
            {
                InkFile file = InkLibrary.GetInkFileWithPath(importedAssetPath);
                if (file.master != null && !inkAssetsToCompile.Contains(file.master.absoluteFilePath))
                {
                    inkAssetsToCompile.Add(file.master.absoluteFilePath);
                }
                else if (!inkAssetsToCompile.Contains(file.absoluteFilePath))
                {
                    inkAssetsToCompile.Add(file.absoluteFilePath);
                }
            }

            foreach (var inkAssetToCompile in inkAssetsToCompile)
            {
                InkCompiler.CompileInk(inkAssetToCompile);
            }
        }
Beispiel #14
0
        void DrawCompileButton(InkFile masterInkFile)
        {
            bool drawButton = false;

            if (masterInkFile.hasErrors)
            {
                EditorGUILayout.HelpBox("Last compiled failed", MessageType.Error);
                drawButton = true;
            }
            else if (masterInkFile.hasWarnings)
            {
                EditorGUILayout.HelpBox("Last compile had errors", MessageType.Warning);
                drawButton = true;
            }
            else if (masterInkFile.jsonAsset == null)
            {
                EditorGUILayout.HelpBox("Ink file has not been compiled", MessageType.Warning);
                drawButton = true;
            }
            if (drawButton && GUILayout.Button("Compile"))
            {
                InkCompiler.CompileInk(masterInkFile);
            }
        }
Beispiel #15
0
        public override void OnInspectorGUI()
        {
            editor.Repaint();
            serializedObject.Update();
            if (inkFile == null)
            {
                EditorGUILayout.HelpBox("Ink File is not in library.", MessageType.Warning);
                if (GUILayout.Button("Rebuild Library"))
                {
                    InkLibrary.Rebuild();
                    Rebuild();
                }
                return;
            }

            if (InkCompiler.IsInkFileOnCompilationStack(inkFile))
            {
                EditorGUILayout.HelpBox("File is compiling...", MessageType.Info);
                return;
            }

            if (!inkFile.isMaster)
            {
                EditorGUI.BeginChangeCheck();
                var newCompileAsIfMaster = EditorGUILayout.Toggle(new GUIContent("Compile As If Master File", "This file is included by another ink file. Typically, these files don't want to be compiled, but this option enables them to be for special purposes."), InkSettings.instance.includeFilesToCompileAsMasterFiles.Contains(inkFile.inkAsset));
                if (EditorGUI.EndChangeCheck())
                {
                    if (newCompileAsIfMaster)
                    {
                        InkSettings.instance.includeFilesToCompileAsMasterFiles.Add(inkFile.inkAsset);
                        EditorUtility.SetDirty(InkSettings.instance);
                    }
                    else
                    {
                        InkSettings.instance.includeFilesToCompileAsMasterFiles.Remove(inkFile.inkAsset);
                        EditorUtility.SetDirty(InkSettings.instance);
                    }
                }
                EditorApplication.RepaintProjectWindow();
            }

            if (inkFile.compileAsMasterFile)
            {
                DrawMasterFileHeader();
                DrawEditAndCompileDates(inkFile);
                if (inkFile.hasUnhandledCompileErrors)
                {
                    EditorGUILayout.HelpBox("Last compiled failed", MessageType.Error);
                }
                if (inkFile.hasErrors)
                {
                    EditorGUILayout.HelpBox("Last compiled had errors", MessageType.Error);
                }
                else if (inkFile.hasWarnings)
                {
                    EditorGUILayout.HelpBox("Last compile had warnings", MessageType.Warning);
                }
                else if (inkFile.jsonAsset == null)
                {
                    EditorGUILayout.HelpBox("Ink file has not been compiled", MessageType.Warning);
                }
                if (inkFile.requiresCompile && GUILayout.Button("Compile"))
                {
                    InkCompiler.CompileInk(inkFile);
                }

                DrawCompileErrors();
                DrawErrors();
                DrawWarnings();
                DrawTODOList();
            }
            else
            {
                EditorGUILayout.LabelField("Include File", EditorStyles.boldLabel);
            }

            DrawListOfMasterFiles();
            DrawIncludedFiles();
            DrawFileContents();


            serializedObject.ApplyModifiedProperties();
        }
        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 (!InkEditorUtils.IsInkFile(movedAssets[i]))
                {
                    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;
                    }
                    foreach (var masterInkFile in inkFile.masterInkFilesIncludingSelf)
                    {
                        if (!filesToCompile.Contains(inkFile))
                        {
                            filesToCompile.Add(inkFile);
                        }
                    }
                }

                InkLibrary.RebuildInkFileConnections();

                // Add the new file to be recompiled
                foreach (var inkFilePath in queuedMovedAssets)
                {
                    InkFile inkFile = InkLibrary.GetInkFileWithPath(inkFilePath);
                    if (inkFile == null)
                    {
                        continue;
                    }

                    foreach (var masterInkFile in inkFile.masterInkFilesIncludingSelf)
                    {
                        if (!filesToCompile.Contains(inkFile))
                        {
                            filesToCompile.Add(inkFile);
                        }
                    }
                }

                queuedMovedAssets.Clear();

                // Compile any ink files that are deemed master files a rebuild
                foreach (var inkFile in filesToCompile)
                {
                    if (inkFile.isMaster)
                    {
                        if (InkSettings.Instance.compileAutomatically || inkFile.compileAutomatically)
                        {
                            InkCompiler.CompileInk(inkFile);
                        }
                    }
                }
            }
        }
        public override void OnInspectorGUI()
        {
            editor.Repaint();
            serializedObject.Update();
            if (inkFile == null)
            {
                EditorGUILayout.HelpBox("Ink File is not in library.", MessageType.Warning);
                if (GUILayout.Button("Rebuild Library"))
                {
                    InkLibrary.Rebuild();
                    Rebuild();
                }
                return;
            }

            if (InkLibrary.GetCompilationStackItem(inkFile) != null)
            {
                EditorGUILayout.HelpBox("File is compiling...", MessageType.Info);
                return;
            }

            InkFile masterInkFile = inkFile.metaInfo.masterInkFileIncludingSelf;

            if (inkFile.metaInfo.isMaster)
            {
                DrawMasterFileHeader();
            }
            else
            {
                DrawSubFileHeader(masterInkFile);
            }

            DrawEditAndCompileDates(masterInkFile);
            if (masterInkFile.metaInfo.hasUnhandledCompileErrors)
            {
                EditorGUILayout.HelpBox("Last compiled failed", MessageType.Error);
            }
            if (masterInkFile.metaInfo.hasErrors)
            {
                EditorGUILayout.HelpBox("Last compiled had errors", MessageType.Error);
            }
            else if (masterInkFile.metaInfo.hasWarnings)
            {
                EditorGUILayout.HelpBox("Last compile had warnings", MessageType.Warning);
            }
            else if (masterInkFile.jsonAsset == null)
            {
                EditorGUILayout.HelpBox("Ink file has not been compiled", MessageType.Warning);
            }
            if (inkFile.metaInfo.requiresCompile && GUILayout.Button("Compile"))
            {
                InkCompiler.CompileInk(masterInkFile);
            }

            DrawIncludedFiles();

            DrawCompileErrors();
            DrawErrors();
            DrawWarnings();
            DrawTODOList();
            DrawFileContents();

            serializedObject.ApplyModifiedProperties();
        }
        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 (!InkEditorUtils.IsInkFile(movedAssets[i]))
                {
                    continue;
                }
                validMovedAssets.Add(movedAssets[i]);
                queuedMovedInkFileAssets.Add(movedAssets[i]);
            }
            // Move compiled JSON files.
            // This can cause Unity to postprocess assets again.
            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";

                // On moving an ink file, we either recompile it, creating a new json file in the correct location, or we move the json file.
                if (InkSettings.instance.ShouldCompileInkFileAutomatically(inkFile))
                {
                    // We have to delay this, or it doesn't properly inform unity (there's no version of "ImportAsset" for delete); I guess it doesn't want OnPostprocessAllAssets to fire recursively.
                    EditorApplication.delayCall += () => {
                        AssetDatabase.DeleteAsset(jsonAssetPath);
                        AssetDatabase.Refresh();
                    };
                }
                else
                {
                    if (string.IsNullOrEmpty(AssetDatabase.ValidateMoveAsset(jsonAssetPath, newPath)))
                    {
                        Debug.Assert(newPath == inkFile.jsonPath);
                        EditorApplication.delayCall += () => {
                            AssetDatabase.MoveAsset(jsonAssetPath, newPath);
                            AssetDatabase.ImportAsset(newPath);
                            AssetDatabase.Refresh();
                            inkFile.FindCompiledJSONAsset();
                        };
                        // Debug.Log(jsonAssetPath+" to "+newPath);
                    }
                    else
                    {
                        // This will fire if the JSON file is also moved with the ink - in this case the json file will be in movedAssets.
                        // Debug.Log($"Failed to move asset from path '{jsonAssetPath}' to '{newPath}'.");
                    }
                }
            }
            // 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 (queuedMovedInkFileAssets.Count > 0)
            {
                List <InkFile> filesToCompile = new List <InkFile>();

                // Add the old master file to the files to be recompiled
                foreach (var inkFilePath in queuedMovedInkFileAssets)
                {
                    InkFile inkFile = InkLibrary.GetInkFileWithPath(inkFilePath);
                    if (inkFile == null)
                    {
                        continue;
                    }
                    foreach (var masterInkFile in inkFile.masterInkFilesIncludingSelf)
                    {
                        if (InkSettings.instance.ShouldCompileInkFileAutomatically(masterInkFile) && !filesToCompile.Contains(masterInkFile))
                        {
                            filesToCompile.Add(masterInkFile);
                        }
                    }
                }

                InkLibrary.RebuildInkFileConnections();

                // If rebuilding connections caused a file that was previously considered a master file to no longer be, then we remove it.
                for (int i = filesToCompile.Count - 1; i >= 0; i--)
                {
                    if (!filesToCompile[i].compileAsMasterFile)
                    {
                        filesToCompile.RemoveAt(i);
                    }
                }

                // Add the new file to be recompiled
                foreach (var inkFilePath in queuedMovedInkFileAssets)
                {
                    InkFile inkFile = InkLibrary.GetInkFileWithPath(inkFilePath);
                    if (inkFile == null)
                    {
                        continue;
                    }

                    foreach (var masterInkFile in inkFile.masterInkFilesIncludingSelf)
                    {
                        if (InkSettings.instance.ShouldCompileInkFileAutomatically(masterInkFile) && !filesToCompile.Contains(masterInkFile))
                        {
                            filesToCompile.Add(masterInkFile);
                        }
                    }
                }

                queuedMovedInkFileAssets.Clear();


                // Compile any ink files that are deemed master files a rebuild
                InkCompiler.CompileInk(filesToCompile.ToArray(), compileImmediatelyOnImport);
            }
        }
        private static void OnDeleteAssets(string[] deletedAssets)
        {
            bool deletedInk = false;

            foreach (var deletedAssetPath in deletedAssets)
            {
                if (InkEditorUtils.IsInkFile(deletedAssetPath))
                {
                    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--)
            {
                var inkFile = InkLibrary.instance.inkLibrary[i];
                // If this file was deleted...
                if (inkFile.inkAsset == null)
                {
                    // Mark the master files to be recompiled (note that those files might also have been deleted)
                    if (!inkFile.compileAsMasterFile)
                    {
                        foreach (var masterInkAsset in inkFile.masterInkAssets)
                        {
                            if (masterInkAsset != null)
                            {
                                var masterInkFile = InkLibrary.GetInkFileWithFile(masterInkAsset);
                                if (!masterFilesAffected.Contains(masterInkFile))
                                {
                                    masterFilesAffected.Add(masterInkFile);
                                }
                            }
                        }
                    }
                    // Delete the associated json file
                    if (InkSettings.instance.handleJSONFilesAutomatically)
                    {
                        var assetPath = AssetDatabase.GetAssetPath(inkFile.jsonAsset);
                        if (assetPath != null && assetPath != string.Empty)
                        {
                            AssetDatabase.DeleteAsset(assetPath);
                        }
                    }
                    // Finally, remove it from the ink library
                    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.FindIncludedFiles();
            }
            foreach (var masterInkFile in masterFilesAffected)
            {
                if (InkSettings.instance.ShouldCompileInkFileAutomatically(masterInkFile))
                {
                    InkCompiler.CompileInk(masterInkFile);
                }
            }
        }
        public override void OnInspectorGUI()
        {
            serializedObject.Update();

            if (inkFile == null)
            {
                return;
            }

            InkFile masterInkFile = inkFile;

            if (inkFile.master == null)
            {
                EditorGUI.BeginDisabledGroup(true);
                EditorGUILayout.ObjectField("JSON Asset", inkFile.jsonAsset, typeof(TextAsset), false);
                EditorGUI.EndDisabledGroup();

                if (GUILayout.Button("Play"))
                {
                    InkPlayerWindow.LoadAndPlay(inkFile.jsonAsset);
                }
                if (includesFileList != null)
                {
                    includesFileList.DoLayoutList();
                }
            }
            else
            {
                masterInkFile = inkFile.master;
                EditorGUILayout.HelpBox("This file is included by a master file.", MessageType.Info);
                EditorGUI.BeginDisabledGroup(true);
                EditorGUILayout.ObjectField("Master Ink File", masterInkFile.inkFile, typeof(Object), false);
                EditorGUI.EndDisabledGroup();
            }

            DateTime lastEditDate = File.GetLastWriteTime(inkFile.absoluteFilePath);

            EditorGUILayout.LabelField("Last edit date " + lastEditDate.ToString());

            if (masterInkFile.jsonAsset == null)
            {
                EditorGUILayout.HelpBox("Ink file has not been compiled", MessageType.Info);
                if (GUILayout.Button("Compile"))
                {
                    InkCompiler.CompileInk(masterInkFile);
                }
            }
            else
            {
                DateTime lastCompileDate = File.GetLastWriteTime(Path.Combine(Application.dataPath, AssetDatabase.GetAssetPath(masterInkFile.jsonAsset).Substring(7)));
                EditorGUILayout.LabelField("Last compile date " + lastCompileDate.ToString());

                if (lastEditDate > lastCompileDate && GUILayout.Button("Recompile"))
                {
                    InkCompiler.CompileInk(masterInkFile);
                }

                if (exception != null)
                {
                    EditorGUILayout.HelpBox("Story is invalid\n" + exception.ToString(), MessageType.Error);
                }
            }

            if (todosList != null)
            {
                todosList.DoLayoutList();
            }

            DrawFileContents();

            serializedObject.ApplyModifiedProperties();
        }