diff --git a/Assets/Editor.meta b/Assets/Editor.meta deleted file mode 100644 index bcfa9c64..00000000 --- a/Assets/Editor.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 47fb7b72149c1b047a64018d4291259e -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Editor/InkCompilerEditor.cs b/Assets/Editor/InkCompilerEditor.cs deleted file mode 100644 index ee9500f6..00000000 --- a/Assets/Editor/InkCompilerEditor.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System.Reflection; -using UnityEditor; -using UnityEngine; - -namespace Ink.UnityIntegration { - - [CustomEditor(typeof(InkCompiler))] - public class InkCompilerEditor : Editor { - - #pragma warning disable - protected InkCompiler data; - - public void OnEnable() { - data = (InkCompiler) target; - } - - public bool RequiresConstantRepaint() { - return true; - } - - public override void OnInspectorGUI() { - serializedObject.Update(); - var type = typeof(InkCompiler); - - EditorGUILayout.Toggle("Executing Compilation Stack", InkCompiler.executingCompilationStack); - - EditorGUILayout.PropertyField(serializedObject.FindProperty("pendingCompilationStack")); - EditorGUILayout.PropertyField(serializedObject.FindProperty("compilationStack")); - // this.DrawDefaultInspector(); - - var buildBlockedInfo = type.GetField("buildBlocked", BindingFlags.NonPublic | BindingFlags.Static); - bool buildBlocked = (bool)buildBlockedInfo.GetValue(null); - EditorGUILayout.Toggle("Build Blocked", buildBlocked); - - var playModeBlockedInfo = type.GetField("playModeBlocked", BindingFlags.NonPublic | BindingFlags.Static); - bool playModeBlocked = (bool)playModeBlockedInfo.GetValue(null); - EditorGUILayout.Toggle("Play Mode Blocked", playModeBlocked); - - var hasLockedUnityCompilationInfo = type.GetField("hasLockedUnityCompilation", BindingFlags.NonPublic | BindingFlags.Static); - bool hasLockedUnityCompilation = (bool)hasLockedUnityCompilationInfo.GetValue(null); - EditorGUILayout.Toggle("Has Locked Compilation", hasLockedUnityCompilation); - - EditorGUILayout.BeginHorizontal(); - var disallowedAutoRefreshInfo = type.GetProperty("disallowedAutoRefresh", BindingFlags.NonPublic | BindingFlags.Static); - bool disallowedAutoRefresh = (bool)disallowedAutoRefreshInfo.GetValue(null); - EditorGUILayout.Toggle("DisallowedAutoRefresh", disallowedAutoRefresh); - #if UNITY_2019_4_OR_NEWER - if(GUILayout.Button("AllowAutoRefresh")) { - AssetDatabase.AllowAutoRefresh(); - } - EditorGUILayout.EndHorizontal(); - #endif - - - if(GUI.changed && target != null) - EditorUtility.SetDirty(target); - serializedObject.ApplyModifiedProperties(); - } - } -} \ No newline at end of file diff --git a/Assets/Editor/InkCompilerEditor.cs.meta b/Assets/Editor/InkCompilerEditor.cs.meta deleted file mode 100644 index 32b83bca..00000000 --- a/Assets/Editor/InkCompilerEditor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 3c44baac1d0695d478401e949d9950a1 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Editor/InkCompilerEditorWindow.cs b/Assets/Editor/InkCompilerEditorWindow.cs deleted file mode 100644 index be8a428f..00000000 --- a/Assets/Editor/InkCompilerEditorWindow.cs +++ /dev/null @@ -1,29 +0,0 @@ -using UnityEditor; -using UnityEngine; - -namespace Ink.UnityIntegration { - public class InkCompilerEditorWindow : EditorWindow { - - #pragma warning disable - Editor InkCompilerEditor; - - [MenuItem("Window/Ink Compiler Editor Window")] - static void Init() { - var window = (InkCompilerEditorWindow)GetWindow(typeof(InkCompilerEditorWindow)); - window.titleContent = new GUIContent("Ink Compiler Window"); - window.Show(); - } - - public void OnEnable() { - InkCompilerEditor = Editor.CreateEditor(InkCompiler.instance); - } - - void OnInspectorUpdate() { - Repaint(); - } - - public void OnGUI() { - InkCompilerEditor.OnInspectorGUI(); - } - } -} \ No newline at end of file diff --git a/Assets/Editor/InkCompilerEditorWindow.cs.meta b/Assets/Editor/InkCompilerEditorWindow.cs.meta deleted file mode 100644 index 2d8bd54b..00000000 --- a/Assets/Editor/InkCompilerEditorWindow.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 306aadd180ffde748ad3be70879eeebd -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Editor/InkLibraryEditor.cs b/Assets/Editor/InkLibraryEditor.cs deleted file mode 100644 index 38151496..00000000 --- a/Assets/Editor/InkLibraryEditor.cs +++ /dev/null @@ -1,107 +0,0 @@ -using System.Linq; -using UnityEditor; -using UnityEngine; - -namespace Ink.UnityIntegration { - - [CustomEditor(typeof(InkLibrary))] - public class InkLibraryEditor : Editor { - - #pragma warning disable - protected InkLibrary data; - - public void OnEnable() { - data = (InkLibrary) target; - } - - protected override void OnHeaderGUI () { - GUILayout.BeginHorizontal(); - GUILayout.Space(38f); - GUILayout.BeginVertical(); - GUILayout.Space(19f); - GUILayout.BeginHorizontal(); - - GUILayoutUtility.GetRect(10f, 10f, 16f, 16f, EditorStyles.layerMaskField); - GUILayout.FlexibleSpace(); - - - EditorGUI.BeginDisabledGroup(InkCompiler.executingCompilationStack); - if (GUILayout.Button(new GUIContent("Rebuild Library", "Rebuilds the ink library. Do this if you're getting unusual errors"), EditorStyles.miniButton)) { - InkLibrary.Rebuild(); - } - EditorGUI.EndDisabledGroup(); - - GUILayout.EndHorizontal(); - GUILayout.EndVertical(); - GUILayout.EndHorizontal(); - - Rect lastRect = GUILayoutUtility.GetLastRect(); - Rect rect = new Rect(lastRect.x, lastRect.y, lastRect.width, lastRect.height); - Rect iconRect = new Rect(rect.x + 6f, rect.y + 6f, 32f, 32f); - GUI.DrawTexture(iconRect, InkBrowserIcons.inkFileIconLarge); - - Rect titleRect = new Rect(rect.x + 44f, rect.y + 6f, rect.width - 44f - 38f - 4f, 16f); - titleRect.yMin -= 2f; - titleRect.yMax += 2f; - GUI.Label(titleRect, "Ink Library", EditorStyles.largeLabel); - - Rect infoRect = titleRect; - infoRect.y += titleRect.height; - GUI.Label(infoRect, "Caches information about ink files in your project", EditorStyles.miniLabel); - } - - public override void OnInspectorGUI() { - serializedObject.Update(); - - EditorGUI.BeginDisabledGroup(InkCompiler.executingCompilationStack); - if (GUILayout.Button(new GUIContent("Rebuild Library", "Rebuilds the ink library. Do this if you're getting unusual errors"), EditorStyles.miniButton)) { - InkLibrary.Rebuild(); - } - EditorGUI.EndDisabledGroup(); - - if(InkCompiler.executingCompilationStack) { - Rect r = EditorGUILayout.BeginVertical(); - EditorGUI.ProgressBar(r, InkCompiler.GetEstimatedCompilationProgress(), "Compiling..."); - GUILayout.Space(EditorGUIUtility.singleLineHeight); - EditorGUILayout.EndVertical(); - GUILayout.Space(EditorGUIUtility.standardVerticalSpacing); - } else { - var filesRequiringRecompile = InkLibrary.GetFilesRequiringRecompile(); - if(filesRequiringRecompile.Any()) { - var files = string.Join("\n", filesRequiringRecompile.Select(x => x.filePath).ToArray()); - if(EditorApplication.isPlaying && InkSettings.instance.delayInPlayMode) { - EditorGUILayout.HelpBox("Some Ink files marked to compile on exiting play mode.\n"+files, MessageType.Info); - } else { - EditorGUILayout.HelpBox("Some Ink files marked to compile automatically are not compiled! Check they don't have compile errors, or else try compiling now.\n"+files, MessageType.Warning); - } - } else { - EditorGUILayout.HelpBox("All Ink files marked to compile automatically are compiled", MessageType.Info); - } - } - EditorGUI.BeginDisabledGroup(InkCompiler.executingCompilationStack); - if (GUILayout.Button(new GUIContent("Recompile All", "Recompiles all files marked to compile automatically."))) { - InkEditorUtils.RecompileAll(); - } - - if(EditorApplication.isPlaying && InkSettings.instance.delayInPlayMode) { - var filesRequiringRecompile = InkLibrary.GetFilesRequiringRecompile(); - if(filesRequiringRecompile.Any()) { - var files = string.Join("\n", filesRequiringRecompile.Select(x => x.filePath).ToArray()); - if (GUILayout.Button(new GUIContent("Recompile Pending", "Recompiles all files marked to compile on exiting play mode."))) { - InkEditorUtils.RecompileAll(); - } - } - } - - EditorGUI.EndDisabledGroup(); - - EditorGUI.BeginDisabledGroup(true); - EditorGUILayout.PropertyField(serializedObject.FindProperty("inkLibrary"), true); - EditorGUI.EndDisabledGroup(); - - if(GUI.changed && target != null) - EditorUtility.SetDirty(target); - serializedObject.ApplyModifiedProperties(); - } - } -} \ No newline at end of file diff --git a/Assets/Editor/InkLibraryEditor.cs.meta b/Assets/Editor/InkLibraryEditor.cs.meta deleted file mode 100644 index cba65dea..00000000 --- a/Assets/Editor/InkLibraryEditor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a62afd3975a3f3147ba1d63050836c8f -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Editor/InkLibraryEditorWindow.cs b/Assets/Editor/InkLibraryEditorWindow.cs deleted file mode 100644 index f406d10c..00000000 --- a/Assets/Editor/InkLibraryEditorWindow.cs +++ /dev/null @@ -1,29 +0,0 @@ -using UnityEditor; -using UnityEngine; - -namespace Ink.UnityIntegration { - public class InkLibraryEditorWindow : EditorWindow { - - #pragma warning disable - Editor inkLibraryEditor; - - [MenuItem("Window/Ink Library Editor Window")] - static void Init() { - var window = (InkLibraryEditorWindow)GetWindow(typeof(InkLibraryEditorWindow)); - window.titleContent = new GUIContent("Ink Library Window"); - window.Show(); - } - - public void OnEnable() { - inkLibraryEditor = Editor.CreateEditor(InkLibrary.instance); - } - - void OnInspectorUpdate() { - Repaint(); - } - - public void OnGUI() { - inkLibraryEditor.OnInspectorGUI(); - } - } -} \ No newline at end of file diff --git a/Assets/Ink/Demos/Basic Demo/Basic Demo.unity b/Assets/Ink/Demos/Basic Demo/Basic Demo.unity index 330a34c3..fdc5e0b2 100644 --- a/Assets/Ink/Demos/Basic Demo/Basic Demo.unity +++ b/Assets/Ink/Demos/Basic Demo/Basic Demo.unity @@ -219,8 +219,8 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} - m_AnchoredPosition: {x: 325.5, y: 0} - m_SizeDelta: {x: 346, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} m_Pivot: {x: 0.5, y: 0.5} --- !u!114 &1104190023 MonoBehaviour: @@ -313,8 +313,8 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} - m_AnchoredPosition: {x: 325.5, y: 0} - m_SizeDelta: {x: 651, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} m_Pivot: {x: 0.5, y: 0.5} --- !u!114 &1300920512 MonoBehaviour: @@ -500,8 +500,8 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0, y: 0} m_AnchorMax: {x: 0, y: 0} - m_AnchoredPosition: {x: 325.5, y: 0} - m_SizeDelta: {x: 365, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} m_Pivot: {x: 0.5, y: 0.5} --- !u!114 &1767420454 MonoBehaviour: @@ -774,7 +774,8 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 66e957d58a4584a8894329531ec0b096, type: 3} m_Name: m_EditorClassIdentifier: - inkJSONAsset: {fileID: 4900000, guid: 6cf48bb6d89824cc69e35b43f9a1aca6, type: 3} + inkFileAsset: {fileID: 6231892579173505729, guid: 1460e815e969b43b8a83a7caa8b48c27, + type: 3} canvas: {fileID: 1908123726} textPrefab: {fileID: 11456674, guid: 1aab6ef84d87c416f8f0b3e1ef3d77d2, type: 3} buttonPrefab: {fileID: 11455116, guid: 37c108a6c38964f79a6621eccb33ddc1, type: 3} diff --git a/Assets/Ink/Demos/Basic Demo/Ink/included_story.ink b/Assets/Ink/Demos/Basic Demo/Ink/included_story.ink new file mode 100644 index 00000000..e06cdb39 --- /dev/null +++ b/Assets/Ink/Demos/Basic Demo/Ink/included_story.ink @@ -0,0 +1,4 @@ +=== hello_world === +hello world! + +->END \ No newline at end of file diff --git a/Assets/Ink/Demos/Basic Demo/Ink/included_story.ink.meta b/Assets/Ink/Demos/Basic Demo/Ink/included_story.ink.meta new file mode 100644 index 00000000..971d843e --- /dev/null +++ b/Assets/Ink/Demos/Basic Demo/Ink/included_story.ink.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 710d6143aefe9a445b084e31e76bf975 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 11500000, guid: 7dc164402b3932547b62cc35c116c770, type: 3} diff --git a/Assets/Ink/Demos/Basic Demo/Ink/story 1.json b/Assets/Ink/Demos/Basic Demo/Ink/story 1.json deleted file mode 100644 index 85ac92fd..00000000 --- a/Assets/Ink/Demos/Basic Demo/Ink/story 1.json +++ /dev/null @@ -1 +0,0 @@ -{"inkVersion":21,"root":[["^I looked at Monsieur Fogg","\n",["done",{"#f":5,"#n":"g-0"}],null],"done",{"#f":1}],"listDefs":{}} \ No newline at end of file diff --git a/Assets/Ink/Demos/Basic Demo/Ink/story 1.json.meta b/Assets/Ink/Demos/Basic Demo/Ink/story 1.json.meta deleted file mode 100644 index 17f41362..00000000 --- a/Assets/Ink/Demos/Basic Demo/Ink/story 1.json.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 1ee3489200bb34611a3c98e3415ddd84 -TextScriptImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Ink/Demos/Basic Demo/Ink/story.json b/Assets/Ink/Demos/Basic Demo/Ink/story.json deleted file mode 100644 index 8f1868ae..00000000 --- a/Assets/Ink/Demos/Basic Demo/Ink/story.json +++ /dev/null @@ -1 +0,0 @@ -{"inkVersion":21,"root":[[["^I looked at Monsieur Fogg","\n",["ev",{"^->":"0.g-0.2.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-0","flg":18},{"s":["^... and I could contain myself no longer.",{"->":"$r","var":true},null]}],["ev",{"^->":"0.g-0.3.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-1","flg":18},{"s":["^... but I said nothing",{"->":"$r","var":true},null]}],{"c-0":["ev",{"^->":"0.g-0.c-0.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.2.s"},[{"#n":"$r2"}],"\n","^'What is the purpose of our journey, Monsieur?'","\n","^'A wager,' he replied.","\n",[["ev",{"^->":"0.g-0.c-0.11.0.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-0","flg":18},{"s":["^'A wager!'",{"->":"$r","var":true},null]}],["ev",{"^->":"0.g-0.c-0.11.1.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^.'","/str","/ev",{"*":".^.^.c-1","flg":22},{"s":["^'Ah",{"->":"$r","var":true},null]}],{"c-0":["ev",{"^->":"0.g-0.c-0.11.c-0.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.0.s"},[{"#n":"$r2"}],"^ I returned.","\n","^He nodded.","\n",[["ev",{"^->":"0.g-0.c-0.11.c-0.10.0.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-0","flg":18},{"s":["^'But surely that is foolishness!'",{"->":"$r","var":true},null]}],["ev",{"^->":"0.g-0.c-0.11.c-0.10.1.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-1","flg":18},{"s":["^'A most serious matter then!'",{"->":"$r","var":true},null]}],{"c-0":["ev",{"^->":"0.g-0.c-0.11.c-0.10.c-0.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.0.s"},[{"#n":"$r2"}],"\n",{"->":".^.^.g-0"},{"#f":5}],"c-1":["ev",{"^->":"0.g-0.c-0.11.c-0.10.c-1.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.1.s"},[{"#n":"$r2"}],"\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^He nodded again.","\n",["ev",{"^->":"0.g-0.c-0.11.c-0.10.g-0.2.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-2","flg":18},{"s":["^'But can we win?'",{"->":"$r","var":true},null]}],["ev",{"^->":"0.g-0.c-0.11.c-0.10.g-0.3.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","/ev",{"*":".^.^.c-3","flg":18},{"s":["^'A modest wager, I trust?'",{"->":"$r","var":true},null]}],["ev",{"^->":"0.g-0.c-0.11.c-0.10.g-0.4.$r1"},{"temp=":"$r"},"str",{"->":".^.s"},[{"#n":"$r1"}],"/str","str","^.","/str","/ev",{"*":".^.^.c-4","flg":22},{"s":["^I asked nothing further of him then",{"->":"$r","var":true},null]}],{"c-2":["ev",{"^->":"0.g-0.c-0.11.c-0.10.g-0.c-2.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.2.s"},[{"#n":"$r2"}],"\n","^'That is what we will endeavour to find out,' he answered.","\n",{"->":".^.^.^.^.^.g-0"},{"#f":5}],"c-3":["ev",{"^->":"0.g-0.c-0.11.c-0.10.g-0.c-3.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.3.s"},[{"#n":"$r2"}],"\n","^'Twenty thousand pounds,' he replied, quite flatly.","\n",{"->":".^.^.^.^.^.g-0"},{"#f":5}],"c-4":["ev",{"^->":"0.g-0.c-0.11.c-0.10.g-0.c-4.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.4.s"},[{"#n":"$r2"}],"^, and after a final, polite cough, he offered nothing more to me. ","<>","\n",{"->":".^.^.^.^.^.g-0"},{"#f":5}],"#f":5}]}],{"#f":5}],"c-1":["ev",{"^->":"0.g-0.c-0.11.c-1.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.1.s"},[{"#n":"$r2"}],"^,' I replied, uncertain what I thought.","\n",{"->":".^.^.g-0"},{"#f":5}],"g-0":["^After that, ","<>","\n",{"->":"0.g-1"},{"#f":5}]}],{"#f":5}],"c-1":["ev",{"^->":"0.g-0.c-1.$r2"},"/ev",{"temp=":"$r"},{"->":".^.^.3.s"},[{"#n":"$r2"}],"^ and ","<>","\n",{"->":"0.g-1"},{"#f":5}],"#f":5,"#n":"g-0"}],{"g-1":["^we passed the day in silence.","\n",["end",["done",{"#f":5,"#n":"g-3"}],{"#f":5,"#n":"g-2"}],{"#f":5}]}],"done",{"#f":1}],"listDefs":{}} \ No newline at end of file diff --git a/Assets/Ink/Demos/Basic Demo/Ink/story.json.meta b/Assets/Ink/Demos/Basic Demo/Ink/story.json.meta deleted file mode 100644 index a5629d3b..00000000 --- a/Assets/Ink/Demos/Basic Demo/Ink/story.json.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 6cf48bb6d89824cc69e35b43f9a1aca6 -timeCreated: 1512575780 -licenseType: Pro -TextScriptImporter: - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Ink/Demos/Basic Demo/Ink/story_with_include.ink b/Assets/Ink/Demos/Basic Demo/Ink/story_with_include.ink new file mode 100644 index 00000000..0fcd9cf9 --- /dev/null +++ b/Assets/Ink/Demos/Basic Demo/Ink/story_with_include.ink @@ -0,0 +1,11 @@ +INCLUDE included_story.ink + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed dictum, mauris sed tempus volutpat, augue nisi tincidunt justo, ut aliquam velit justo non velit. + +* [Print hello world text] ->hello_world +* [Say hello] ->hello + +=== hello + +HELLO! +->END diff --git a/Assets/Ink/Demos/Basic Demo/Ink/story_with_include.ink.meta b/Assets/Ink/Demos/Basic Demo/Ink/story_with_include.ink.meta new file mode 100644 index 00000000..3158533c --- /dev/null +++ b/Assets/Ink/Demos/Basic Demo/Ink/story_with_include.ink.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: d416ed45ff2bb4444805984e38b29940 +ScriptedImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 2 + userData: + assetBundleName: + assetBundleVariant: + script: {fileID: 11500000, guid: 7dc164402b3932547b62cc35c116c770, type: 3} diff --git a/Assets/Ink/Demos/Basic Demo/Scripts/BasicInkExample.cs b/Assets/Ink/Demos/Basic Demo/Scripts/BasicInkExample.cs index 5b8b4a73..54fe0c34 100644 --- a/Assets/Ink/Demos/Basic Demo/Scripts/BasicInkExample.cs +++ b/Assets/Ink/Demos/Basic Demo/Scripts/BasicInkExample.cs @@ -1,5 +1,6 @@ using System; using Ink.Runtime; +using Ink.UnityIntegration; using UnityEngine; using UnityEngine.UI; @@ -15,7 +16,7 @@ void Awake () { // Creates a new Story object with the compiled story which we can then play! void StartStory () { - story = new Story (inkJSONAsset.text); + story = new Story (inkFileAsset.storyJson); if(OnCreateStory != null) OnCreateStory(story); RefreshView(); } @@ -96,7 +97,7 @@ void RemoveChildren () { } [SerializeField] - private TextAsset inkJSONAsset = null; + private InkFile inkFileAsset = null; public Story story; [SerializeField] diff --git a/Assets/Publishing/Editor/Tools/PublishingTools.cs b/Assets/Publishing/Editor/Tools/PublishingTools.cs index d91330db..d9adb250 100644 --- a/Assets/Publishing/Editor/Tools/PublishingTools.cs +++ b/Assets/Publishing/Editor/Tools/PublishingTools.cs @@ -49,7 +49,7 @@ public static void SyncPackageJsonVersion() { var match = Regex.Match(json, pattern); var prevVersion = match.Groups[1].Value; - var nextVersion = InkLibrary.unityIntegrationVersionCurrent.ToString(); + var nextVersion = InkFile.unityIntegrationVersionCurrent.ToString(); if (prevVersion == nextVersion) { Debug.LogWarning("SyncPackageJsonVersion: package.json version was already " + nextVersion + ". Did you forget to update it in InkLibrary?"); } else { @@ -134,7 +134,7 @@ public static void CreatePackage () { AssetDatabase.Refresh(); // Create a .unitypackage - var version = InkLibrary.unityIntegrationVersionCurrent; + var version = InkFile.unityIntegrationVersionCurrent; var packageExportPath = string.Format("../Ink Unity Integration {0}.{1}.{2}.unitypackage", version.Major, version.Minor, version.Build); AssetDatabase.ExportPackage("Assets/Ink", packageExportPath, ExportPackageOptions.Recurse); @@ -166,7 +166,7 @@ public static void ShowWindow () { void OnGUI () { EditorGUILayout.BeginVertical(); - EditorGUILayout.LabelField("Version "+InkLibrary.unityIntegrationVersionCurrent, EditorStyles.centeredGreyMiniLabel); + EditorGUILayout.LabelField("Version "+InkFile.unityIntegrationVersionCurrent, EditorStyles.centeredGreyMiniLabel); if (GUILayout.Button("Unlock")) { EditorApplication.UnlockReloadAssemblies(); @@ -179,9 +179,9 @@ void OnGUI () { } if (GUILayout.Button("Draft GitHub Release")) { // 1.1.7 - var version = UnityWebRequest.EscapeURL($"{InkLibrary.unityIntegrationVersionCurrent}"); + var version = UnityWebRequest.EscapeURL($"{InkFile.unityIntegrationVersionCurrent}"); - var title = UnityWebRequest.EscapeURL($"{InkLibrary.unityIntegrationVersionCurrent} is out!"); + var title = UnityWebRequest.EscapeURL($"{InkFile.unityIntegrationVersionCurrent} is out!"); var packageDirectory = InkEditorUtils.FindAbsolutePluginDirectory(); var changelogText = File.ReadAllText(Path.Combine(packageDirectory, "CHANGELOG.md")); diff --git a/Packages/Ink/Editor/Core/Compiler/Auto Compiler.meta b/Packages/Ink/Editor/Core/Compiler/Auto Compiler.meta deleted file mode 100644 index 6bf1061a..00000000 --- a/Packages/Ink/Editor/Core/Compiler/Auto Compiler.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 8703f7b604fcd824a8d75ac62b730b6b -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Packages/Ink/Editor/Core/Compiler/Auto Compiler/InkPostProcessor.cs b/Packages/Ink/Editor/Core/Compiler/Auto Compiler/InkPostProcessor.cs deleted file mode 100644 index 1d7f2f65..00000000 --- a/Packages/Ink/Editor/Core/Compiler/Auto Compiler/InkPostProcessor.cs +++ /dev/null @@ -1,212 +0,0 @@ -// Automatically creates JSON files from an ink placed within the Assets/Ink folder. -using UnityEngine; -using UnityEditor; -using System.IO; -using Debug = UnityEngine.Debug; -using System.Collections.Generic; -using System.Linq; - -namespace Ink.UnityIntegration { - - public class InkPostProcessor : AssetPostprocessor { - // Several assets moved at the same time can cause unity to call OnPostprocessAllAssets several times as a result of moving additional files, or simply due to minor time differences. - // This queue tells the compiler which files to recompile after moves have completed. - // Not a perfect solution - If Unity doesn't move all the files in the same attempt you can expect some error messages to appear on compile. - private static List queuedMovedInkFileAssets = new List(); - - // We should make this a stack, similar to GUI.BeginDisabledGroup. - public static bool disabled = false; - // I'd like to make this a public facing setting sometime. Options are async or immediate. - public static bool compileImmediatelyOnImport = false; - // Recompiles any ink files as a result of an ink file (re)import - private static void OnPostprocessAllAssets (string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths) { - if(disabled) return; - if(deletedAssets.Length > 0) { - OnDeleteAssets(deletedAssets); - } - if(movedAssets.Length > 0) { - OnMoveAssets(movedAssets); - } - if(importedAssets.Length > 0) { - // Assets that are renamed are both moved and imported. We do all the work in OnMoveAssets, so do nothing here. - var importedAssetsThatWerentRenames = importedAssets.Except(movedAssets).ToArray(); - OnImportAssets(importedAssetsThatWerentRenames); - } - #if !UNITY_2020_1_OR_NEWER - if(InkLibrary.created) - #endif - InkLibrary.Clean(); - } - - 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 masterFilesAffected = new List(); - 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.isMaster) { - 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. - InkLibrary.RebuildInkFileConnections(); - - foreach(var masterInkFile in masterFilesAffected) { - if(InkSettings.instance.ShouldCompileInkFileAutomatically(masterInkFile)) { - InkCompiler.CompileInk(masterInkFile); - } - } - } - - private static void OnMoveAssets (string[] movedAssets) { - if (!InkSettings.instance.handleJSONFilesAutomatically) - return; - - List validMovedAssets = new List(); - 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 filesToCompile = new List(); - - // 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].isMaster) - 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 OnImportAssets (string[] importedAssets) { - List importedInkAssets = new List(); - string inklecateFileLocation = null; - foreach (var importedAssetPath in importedAssets) { - if(InkEditorUtils.IsInkFile(importedAssetPath)) - importedInkAssets.Add(importedAssetPath); - else if (Path.GetFileName(importedAssetPath) == "inklecate" && Path.GetExtension(importedAssetPath) == "") - inklecateFileLocation = importedAssetPath; - } - if(importedInkAssets.Count > 0) - PostprocessInkFiles(importedInkAssets); - if(inklecateFileLocation != null) - PostprocessInklecate(inklecateFileLocation); - } - - private static void PostprocessInklecate (string inklecateFileLocation) { - // This should probably only recompile files marked to compile automatically, but it's such a rare case, and one where you probably do want to compile. - // To fix, one day! - Debug.Log("Inklecate updated. Recompiling all Ink files..."); - InkEditorUtils.RecompileAll(); - } - - private static void PostprocessInkFiles (List importedInkAssets) { - if(EditorApplication.isPlaying && InkSettings.instance.delayInPlayMode) { - foreach(var fileToImport in importedInkAssets) { - InkCompiler.AddToPendingCompilationStack(fileToImport); - } - } else { - InkLibrary.CreateOrReadUpdatedInkFiles (importedInkAssets); - InkCompiler.CompileInk(InkCompiler.GetUniqueMasterInkFilesToCompile (importedInkAssets).ToArray()); - } - } - } -} \ No newline at end of file diff --git a/Packages/Ink/Editor/Core/Compiler/Auto Compiler/InkPostProcessor.cs.meta b/Packages/Ink/Editor/Core/Compiler/Auto Compiler/InkPostProcessor.cs.meta deleted file mode 100644 index 89ca4390..00000000 --- a/Packages/Ink/Editor/Core/Compiler/Auto Compiler/InkPostProcessor.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: 45a9c84618e20498993d11d2bb89946e -timeCreated: 1459667420 -licenseType: Pro -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Packages/Ink/Editor/Core/Compiler/InkCompiler.cs b/Packages/Ink/Editor/Core/Compiler/InkCompiler.cs deleted file mode 100644 index d31ba5bb..00000000 --- a/Packages/Ink/Editor/Core/Compiler/InkCompiler.cs +++ /dev/null @@ -1,822 +0,0 @@ -using UnityEngine; -using UnityEditor; -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; -using System.Threading; -using Debug = UnityEngine.Debug; - -namespace Ink.UnityIntegration { - // Ink Compiler handles the compilation of Ink Files, storing and logging todos, warnings and errors. - // It manages a queue of items, ensuring that each file is completed in sequence. - - // Ink compilation is handled automatically when ink files change (via InkPostProcessor), but you can also manually trigger compilation. - // The simplest usage is InkCompiler.CompileInk(inkFile). - // You can also specify if the compilation should be immediate or async, and provide a callback for when the queue completes. - // Logs are fired when compilation begins and completes. - - // To ensure that compilation always completes reliably, this class also manages delaying entering play mode and cancels builds kicked off while mid-compile. - - // InkCompiler is designed as a ScriptableObject and is saved to the Library folder so that the queue persists across compilation. - // The way we currently handle threads isn't great. I'd love for a member of the community to find a better way to do it! - #if UNITY_2020_1_OR_NEWER - [FilePath("Library/InkCompiler.asset", FilePathAttribute.Location.ProjectFolder)] - public class InkCompiler : ScriptableSingleton { - #else - public class InkCompiler : ScriptableObject { - #endif - #region Legacy ScriptableSingleton - #if !UNITY_2020_1_OR_NEWER - public static bool created { - get { - return (_instance != (UnityEngine.Object) null); - } - } - private static InkCompiler _instance; - public static InkCompiler instance { - get { - if(!created) - LoadOrCreateInstance(); - return _instance; - } private set { - if(_instance == value) return; - _instance = value; - } - } - - static string absoluteSavePath { - get { - return System.IO.Path.GetFullPath(System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(),"Library","InkCompiler.asset")); - } - } - public static void LoadOrCreateInstance () { - InternalEditorUtility.LoadSerializedFileAndForget(absoluteSavePath); - if(created) { - if(InkEditorUtils.isFirstCompile) { - ClearCompilationStacks(); - } - } else { - instance = ScriptableObject.CreateInstance(); - instance.hideFlags = HideFlags.HideAndDontSave; - } - } - public void Save (bool saveAsText) { - InternalEditorUtility.SaveToSerializedFileAndForget((UnityEngine.Object[]) new InkCompiler[1] {this}, absoluteSavePath, saveAsText); - } - - protected InkCompiler () { - if (created) - Debug.LogError((object) "ScriptableSingleton already exists. Did you query the singleton in a constructor?"); - else { - instance = this; - } - } - #endif - #endregion - - - #region Public Facing - // If any items are queued, compiling, or complete! - // If any items are in the queue, one is guaranteed to be compiling (or should begin to or complete imminently). - public static bool executingCompilationStack { - get { - return instance.compilationStack.Count > 0; - } - } - - // This runs once when the compilation stack completes. - public delegate void OnCompleteInkCompliationStackEvent (InkFile[] inkFiles); - public static event OnCompleteInkCompliationStackEvent OnCompileInk; - - - [Serializable] - public enum CompilationStackItemState { - // Default state, item is about to be queued for compilation - Queued, - - // Item is now owned by the thread pool and being compiled - Compiling, - - // Compilation has finished, item to be processed for errors and result handled - Complete, - } - - - public static void CompileInk (params InkFile[] inkFiles) { - CompileInk(inkFiles, false, null); - } - public static void CompileInk (InkFile[] inkFiles, bool immediate, Action onComplete = null) { - if(inkFiles == null || inkFiles.Length == 0) return; - #if UNITY_2019_4_OR_NEWER - if(!disallowedAutoRefresh) { - disallowedAutoRefresh = true; - 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); - } - } - - - public static void SetBuildBlocked () { - buildBlocked = true; - } - - - public static void AddToPendingCompilationStack (string filePath) { - if(!instance.pendingCompilationStack.Contains(filePath)) { - instance.pendingCompilationStack.Add(filePath); - instance.Save(true); - } - } - - public static void RemoveFromPendingCompilationStack (InkFile inkFile) { - bool anyChange = false; - anyChange = instance.pendingCompilationStack.Remove(inkFile.filePath) || anyChange; - foreach(var includeFile in inkFile.includesInkFiles) { - anyChange = instance.pendingCompilationStack.Remove(includeFile.filePath) || anyChange; - } - if(anyChange) - instance.Save(true); - } - - public static bool AnyOfStateInCompilationStack (CompilationStackItemState state) { - foreach(var compilationStackItem in instance.compilationStack) { - if(compilationStackItem.state == state) - return true; - } - return false; - } - public static int CountOfStateInCompilationStack (CompilationStackItemState state) { - int count = 0; - foreach(var compilationStackItem in instance.compilationStack) { - if(compilationStackItem.state == state) - count++; - } - return count; - } - static CompilationStackItem GetCurrentlyCompilingFile () { - foreach(var compilationStackItem in instance.compilationStack) { - if(compilationStackItem.state == CompilationStackItemState.Compiling) { - return compilationStackItem; - } - } - return null; - } - - public static bool IsInkFileOnCompilationStack (InkFile inkFile) { - foreach(var compilationStackItem in instance.compilationStack) { - if(compilationStackItem.inkFile == inkFile) - return true; - } - return false; - } - - // Find all the master ink files in a list of assets given by path. - public static List GetUniqueMasterInkFilesToCompile (List importedInkAssets) { - List masterInkFiles = new List(); - foreach (var importedAssetPath in importedInkAssets) { - foreach(var masterInkFile in GetMasterFilesIncludingInkAssetPath(importedAssetPath)) { - if (!masterInkFiles.Contains(masterInkFile) && InkSettings.instance.ShouldCompileInkFileAutomatically(masterInkFile)) { - masterInkFiles.Add(masterInkFile); - } - } - } - return masterInkFiles; - - // An ink file might actually have several owners! Return them all. - IEnumerable GetMasterFilesIncludingInkAssetPath (string importedAssetPath) { - InkFile inkFile = InkLibrary.GetInkFileWithPath(importedAssetPath); - // Trying to catch a rare (and not especially important) bug that seems to happen occasionally when opening a project - // It's probably this - I've noticed it before in another context. - Debug.Assert(InkSettings.instance != null, "No ink settings file. This is a bug. For now you should be able to fix this via Assets > Rebuild Ink Library"); - // I've caught it here before - Debug.Assert(inkFile != null, "No internal InkFile reference at path "+importedAssetPath+". This is a bug. For now you can fix this via Assets > Rebuild Ink Library"); - Debug.Assert(inkFile != null); - return inkFile.masterInkFilesIncludingSelf; - } - } - #endregion - - - #region Static Private Variables - // If we just blocked a build because of an ink compile - static bool buildBlocked = false; - // If we just blocked entering play mode because of an ink compile - static bool playModeBlocked = false; - - - // Track if we've currently locked compilation of Unity C# Scripts - static bool hasLockedUnityCompilation = false; - - // When compiling we call AssetDatabase.DisallowAutoRefresh. - // We NEED to remember to re-allow it or unity stops registering file changes! - // The issue is that you need to pair calls perfectly, and you can't even use a try-catch to get around it. - // So - we cache if we've disabled auto refresh here, since this persists across plays. - static bool disallowedAutoRefresh { - get => SessionState.GetBool("InkLibraryDisallowedAutoRefresh", false); - set => SessionState.SetBool("InkLibraryDisallowedAutoRefresh", value); - } - - // Actions that are passed into the CompileInk function, to run and then clear when we complete the compilation stack. - // To recieve an event each time the stack completes, see OnCompileInk. - static List onCompleteActions = new List(); - - // Thread lock - static bool compileThreadActive { - get { - lock(_compileThreadActiveLock) { - return _compileThreadActive; - } - } - set { - lock(_compileThreadActiveLock) { - _compileThreadActive = value; - } - } - } - static bool _compileThreadActive; - static object _compileThreadActiveLock = new object(); - #endregion - - #if UNITY_2020_2_OR_NEWER - // ID for the Unity Progress API, which shows progress of the compile in the bottom right of Unity. - static int compileProgressID; - #endif - - #region Serialized Private Variables - // If InkSettings' delayInPlayMode option is true, dirty files are added here when they're changed in play mode - // This ensures they're remembered when you exit play mode and can be compiled - // TODO - It might be safer for this to track the DefaultAsset for the ink file, rather than the path? - [SerializeField] - List pendingCompilationStack = new List(); - - // The state of files currently being compiled. - [SerializeField] - List compilationStack = new List(); - #endregion - - [System.Serializable] - class CompilationStackItem { - public CompilationStackItemState state = CompilationStackItemState.Queued; - public bool immediate; - public InkFile inkFile; - public string compiledJson; - public string inkAbsoluteFilePath; - public string jsonAbsoluteFilePath; - public List logOutput = new List(); - public List unhandledErrorOutput = new List(); - public DateTime startTime; - public DateTime endTime; - - public float timeTaken { - get { - if(state == CompilationStackItemState.Complete) return (float)(endTime - startTime).TotalSeconds; - else return (float)(DateTime.Now - startTime).TotalSeconds; - } - } - - public CompilationStackItem () {} - - // Sets errors, warnings and todos to the ink file, and logs them to the console. - public void SetOutputLog () { - inkFile.errors.Clear(); - inkFile.warnings.Clear(); - inkFile.todos.Clear(); - - foreach(var childInkFile in inkFile.includesInkFiles) { - childInkFile.unhandledCompileErrors.Clear(); - childInkFile.errors.Clear(); - childInkFile.warnings.Clear(); - childInkFile.todos.Clear(); - } - - foreach(var output in logOutput) { - if(output.type == ErrorType.Error) { - inkFile.errors.Add(output); - Debug.LogError("Ink "+output.type+" for "+Path.GetFileName(inkFile.filePath)+": "+output.content + " (at "+output.relativeFilePath+":"+output.lineNumber+")", inkFile.inkAsset); - } else if (output.type == ErrorType.Warning) { - inkFile.warnings.Add(output); - Debug.LogWarning("Ink "+output.type+" for "+Path.GetFileName(inkFile.filePath)+": "+output.content + " (at "+output.relativeFilePath+" "+output.lineNumber+")", inkFile.inkAsset); - } else if (output.type == ErrorType.Author) { - inkFile.todos.Add(output); - if(InkSettings.instance.printInkLogsInConsoleOnCompile) - Debug.Log("Ink Log for "+Path.GetFileName(inkFile.filePath)+": "+output.content + " (at "+output.relativeFilePath+" "+output.lineNumber+")", inkFile.inkAsset); - } - } - } - } - - - #region Init, Update, Saving - // Ensure we save the InkCompiler state when we save assets. - class AssetSaver : UnityEditor.AssetModificationProcessor { - static string[] OnWillSaveAssets(string[] paths) { - InkCompiler.instance.Save(true); - return paths; - } - } - - // This is called when Unity recompiles. - [InitializeOnLoadMethod] - static void OnProjectLoadedInEditor() { - #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(disallowedAutoRefresh) { - disallowedAutoRefresh = false; - try { - AssetDatabase.AllowAutoRefresh(); - } catch (Exception e) { - Debug.LogWarning("Failed AllowAutoRefresh "+e); - } - } - #endif - } - - // Update loop, using the EditorApplication.update callback. - private static void Update () { - #if UNITY_2020_1_OR_NEWER - // If we're not compiling but have locked C# compilation then now is the time to reset - if (!executingCompilationStack && hasLockedUnityCompilation) { - hasLockedUnityCompilation = false; - EditorApplication.UnlockReloadAssemblies(); - } - #else - // 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; - #endif - - // If we're working through the stack. This is true as soon as an item is added to the stack. - if(executingCompilationStack) { - // Check for timeouts, in case of an unhandled bug with this system/the ink compiler! - for (int i = instance.compilationStack.Count - 1; i >= 0; i--) { - var compilingFile = instance.compilationStack [i]; - if (compilingFile.state == CompilationStackItemState.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. - compileThreadActive = false; - 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(!AnyOfStateInCompilationStack(CompilationStackItemState.Compiling)) { - if(!AnyOfStateInCompilationStack(CompilationStackItemState.Queued)) { - OnCompleteCompilationStack(); - } 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(); - } - } - // When the current item being compiled using threads has finished, we set compileThreadActive to false. - // Here we then set the compiling file's state from Compiling to Complete. - // This roundabout way of doing things ensures that all CompilationStackItem code runs entirely outside of the thread. - else if(!compileThreadActive) { - for (int i = instance.compilationStack.Count - 1; i >= 0; i--) { - var compilingFile = instance.compilationStack [i]; - if (compilingFile.state == CompilationStackItemState.Compiling) { - CompleteCompilingFile(compilingFile); - break; - } - } - } - } - - - // We don't show a progress bar on Linux (there appeared to be a Unity bug on an earlier version), so skip this step there. - #if !UNITY_EDITOR_LINUX - UpdateProgressBar(); - #endif - } - #endregion - - - #region Compilation - - // Move files from the pendingCompilationStack to the compilationStack - static void CompilePendingFiles () { - InkLibrary.CreateOrReadUpdatedInkFiles (instance.pendingCompilationStack); - foreach (var pendingMasterFile in GetUniqueMasterInkFilesToCompile(instance.pendingCompilationStack)) - CompileInk(pendingMasterFile); - } - - /// - /// Starts a System.Process that compiles a master ink file, creating a playable JSON file that can be parsed by the Ink.Story class - /// - /// Ink file. - 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.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(IsInkFileOnCompilationStack(inkFile)) { - 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 = CompilationStackItemState.Queued, - immediate = immediate - }; - - if(instance.compilationStack.Count == 0) OnBeginCompilationStack(); - instance.compilationStack.Add(pendingFile); - instance.Save(true); - - TryCompileNextFileInStack(); - } - - private static void TryCompileNextFileInStack () { - if(!executingCompilationStack) return; - if(AnyOfStateInCompilationStack(CompilationStackItemState.Compiling)) return; - - // Find the next file to compile! - CompilationStackItem fileToCompile = null; - foreach(var compilationItem in instance.compilationStack) { - if(compilationItem.state == CompilationStackItemState.Queued) { - fileToCompile = compilationItem; - break; - } - } - - // If a file was found, compile it according to its settings. - if(fileToCompile != null) { - BeginCompilingFile(fileToCompile); - if(fileToCompile.immediate) { - CompileInkThreaded(fileToCompile); - CompleteCompilingFile(fileToCompile); - } 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."); - compileThreadActive = true; - ThreadPool.QueueUserWorkItem(CompileInkThreaded, fileToCompile); - // CompleteCompilingFile is called in Update when compileThreadActive becomes false. - } - } - } - - // Removes a file from the compilation stack. - static void RemoveCompilingFile (int index) { - instance.compilationStack.RemoveAt(index); - instance.Save(true); - // 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 (instance.compilationStack.Count == 0) EditorUtility.ClearProgressBar(); - #endif - } - - // Marks a CompilationStackItem as Compiling - private static void BeginCompilingFile(CompilationStackItem item) { - if(item.state != CompilationStackItemState.Queued) { - Debug.LogError("Cannot begin compiling ink file because it is "+item.state+"! This is most likely a threading bug. Please report this!"); - return; - } - item.state = CompilationStackItemState.Compiling; - item.startTime = DateTime.Now; - #if UNITY_2020_2_OR_NEWER - Progress.SetStepLabel(compileProgressID, item.inkFile.filePath); - Progress.Report(compileProgressID, instance.compilationStack.IndexOf(item), instance.compilationStack.Count); - #endif - } - - // Marks a CompilationStackItem as Complete - private static void CompleteCompilingFile(CompilationStackItem item) { - if(item.state != CompilationStackItemState.Compiling) { - Debug.LogError("Cannot complete compiling ink file because it is "+item.state+"! This is most likely a threading bug. Please report this!"); - return; - } - item.state = CompilationStackItemState.Complete; - item.endTime = DateTime.Now; - if (item.timeTaken > InkSettings.instance.compileTimeout * 0.6f) - Debug.LogWarning ("Compilation for "+Path.GetFileName(item.inkFile.filePath)+" took over 60% of the time required to timeout the compiler. Consider increasing the compile timeout on the InkSettings file."); - - // If there's nothing left to compile, we can mark the stack as done! - if(!AnyOfStateInCompilationStack(CompilationStackItemState.Compiling) && !AnyOfStateInCompilationStack(CompilationStackItemState.Queued)) - OnCompleteCompilationStack(); - } - - // Runs a new instance of Ink.Compiler, performing the actual compilation process! - // Can be run from a thread or syncronously. - // Ink is not threadsafe, and so this function should never be run twice simultaneously. - // For this reason, this function doesn't set CompilationStackItem.state. - private static void CompileInkThreaded(object itemObj) { - CompilationStackItem item = (CompilationStackItem) itemObj; - if(item.state != CompilationStackItemState.Compiling) Debug.LogError("File passed to CompileInkThreaded is not in Compiling state."); - - var inputString = File.ReadAllText(item.inkAbsoluteFilePath); - var compiler = new Compiler(inputString, new Compiler.Options - { - countAllVisits = true, - fileHandler = new UnityInkFileHandler(Path.GetDirectoryName(item.inkAbsoluteFilePath)), - errorHandler = (string message, ErrorType type) => { - InkCompilerLog log; - if(InkCompilerLog.TryParse(message, out log)) { - if(string.IsNullOrEmpty(log.relativeFilePath)) log.relativeFilePath = Path.GetFileName(item.inkAbsoluteFilePath); - item.logOutput.Add(log); - } else { - Debug.LogWarning("Couldn't parse log "+message); - } - } - }); - - try { - var compiledStory = compiler.Compile(); - if (compiledStory != null) - item.compiledJson = compiledStory.ToJson(); - } catch (SystemException e) { - item.unhandledErrorOutput.Add(string.Format( - "Ink Compiler threw exception \nError: {0}\n---- Trace ----\n{1}\n--------\n", e.Message, - e.StackTrace)); - } - - // This MUST be the very last thing to occur in this function! - compileThreadActive = false; - } - - // When the compilation stack first gains an item - private static void OnBeginCompilationStack () { - #if UNITY_2020_2_OR_NEWER - compileProgressID = Progress.Start("Compiling Ink", null, Progress.Options.None, -1); - #endif - } - - // When all files in stack have been compiled. - // This is called via update because Process events run in another thread. - // It's now also called via CompleteCompilingFile, which enables immediate mode compliation to run synchronously! - private static void OnCompleteCompilationStack () { - if(AnyOfStateInCompilationStack(CompilationStackItemState.Queued)) { - Debug.LogError("OnCompleteCompilationStack was called, but a file is now in the queue!"); - return; - } - if(AnyOfStateInCompilationStack(CompilationStackItemState.Compiling)) { - Debug.LogError("OnCompleteCompilationStack was called, but a file is now compiling!"); - return; - } - // Clone and clear the list. This is a surefire way to ensure the list is cleared in case of unhandled errors in this code. - // A Try-catch would be better but I'm debugging blind as I write this and the nuclear option will definitely work! - List compilationStack = new List(instance.compilationStack); - instance.compilationStack.Clear(); - instance.Save(true); - - - - // Create and import compiled files - AssetDatabase.StartAssetEditing(); - foreach (var compilingFile in 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); - if(compilingFile.inkFile.inkAsset != null) AssetDatabase.ImportAsset(compilingFile.inkFile.jsonPath); - } - AssetDatabase.StopAssetEditing(); - - - // Sets output info for each InkFile (todos, warnings and errors); produces and fires the post-compliation log - bool errorsFound = false; - StringBuilder filesCompiledLog = new StringBuilder("Files compiled:"); - foreach (var compilingFile in compilationStack) { - if(compilingFile.inkFile.inkAsset != null) { - // 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 ("! You may be able to resolve your issue by using Edit > Rebuild Ink Library."); - errorLog.AppendLine ("Please report following error(s) as a bug:"); - foreach (var error in compilingFile.unhandledErrorOutput) - errorLog.AppendLine (error); - Debug.LogError(errorLog); - compilingFile.inkFile.unhandledCompileErrors = compilingFile.unhandledErrorOutput; - errorsFound = true; - } else { - compilingFile.SetOutputLog(); - bool errorsInEntireStory = false; - bool warningsInEntireStory = false; - foreach(var inkFile in compilingFile.inkFile.includesInkFiles) { - if(inkFile.hasErrors) { - errorsInEntireStory = true; - } - if(inkFile.hasWarnings) { - warningsInEntireStory = true; - } - } - if(errorsInEntireStory) { - filesCompiledLog.Append(" (With error)"); - errorsFound = true; - } - if(warningsInEntireStory) { - filesCompiledLog.Append(" (With warning)"); - } - } - } else { - filesCompiledLog.AppendLine().Append(compilingFile.inkAbsoluteFilePath); - filesCompiledLog.Append(" (With post-compile missing file error)"); - Debug.LogError("Ink file at "+compilingFile.inkAbsoluteFilePath+" was not found after compilation"); - } - } - - 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); - } - - - // Clean up locks and progress bars - #if UNITY_2020_2_OR_NEWER - Progress.Remove(compileProgressID); - compileProgressID = -1; - #endif - - #if !UNITY_EDITOR_LINUX - EditorUtility.ClearProgressBar(); - #endif - - #if UNITY_2019_4_OR_NEWER - if(disallowedAutoRefresh) { - disallowedAutoRefresh = false; - 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; - - - // Fires completion events - foreach(var onCompleteAction in onCompleteActions) { - if(onCompleteAction != null) onCompleteAction(); - } - onCompleteActions.Clear(); - - if (OnCompileInk != null) { - InkFile[] inkFilesCompiled = new InkFile[compilationStack.Count]; - for (int i = 0; i < compilationStack.Count; i++) { - inkFilesCompiled[i] = compilationStack[i].inkFile; - } - if(OnCompileInk != null) OnCompileInk (inkFilesCompiled); - } - - - // If we wanted to enter play mode but were blocked because of ink compliation, enter play mode now. - 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."); - } - } - - } - #endregion - - - #region Progress Bar - static void UpdateProgressBar () { - if(instance.compilationStack.Count == 0) return; - if(buildBlocked || playModeBlocked || EditorApplication.isPlaying) ShowProgressBar(); - else EditorUtility.ClearProgressBar(); - } - - public static void ShowProgressBar () { - int numCompiling = CountOfStateInCompilationStack(CompilationStackItemState.Compiling); - var compilingFile = GetCurrentlyCompilingFile(); - string message = ""; - if(compilingFile == null) message += "Compiling..."; - else message += "Compiling "+compilingFile.inkFile.inkAsset.name+" for "+compilingFile.timeTaken+"s"; - message += "\n.Ink File "+(instance.compilationStack.Count-numCompiling)+" of "+instance.compilationStack.Count+"."; - if(playModeBlocked) message += " Will enter play mode when complete."; - EditorUtility.DisplayProgressBar("Compiling Ink...", message, GetEstimatedCompilationProgress()); - } - - public static float GetEstimatedCompilationProgress () { - if(!executingCompilationStack) return 1; - float progress = 0; - foreach (var compilingFile in instance.compilationStack) { - if (compilingFile.state == CompilationStackItemState.Compiling) - progress += compilingFile.timeTaken / InkSettings.instance.compileTimeout; - if (compilingFile.state == CompilationStackItemState.Complete) - progress += 1; - } - progress /= instance.compilationStack.Count; - return progress; - } - #endregion - - - #region Prevent entering Play Mode while mid-compile - #if UNITY_2017_1_OR_NEWER - static void OnPlayModeChange (PlayModeStateChange mode) { - if(mode == PlayModeStateChange.EnteredEditMode && instance.pendingCompilationStack.Count > 0) - CompilePendingFiles(); - if(mode == PlayModeStateChange.ExitingEditMode && executingCompilationStack) - BlockPlayMode(); - if(mode == PlayModeStateChange.EnteredPlayMode && executingCompilationStack) - EnteredPlayModeWhenCompiling(); - } - #else - static void LegacyOnPlayModeChange () { - if(!EditorApplication.isPlayingOrWillChangePlaymode && EditorApplication.isPlaying && instance.pendingCompilationStack.Count > 0) - CompilePendingFiles(); - if(EditorApplication.isPlayingOrWillChangePlaymode && !EditorApplication.isPlaying && compiling) - BlockPlayMode(); - if(EditorApplication.isPlayingOrWillChangePlaymode && EditorApplication.isPlaying && compiling) - EnteredPlayModeWhenCompiling(); - } - #endif - - static void BlockPlayMode () { - EditorApplication.isPlaying = false; - var percentage = String.Format("{0:P0}.", GetEstimatedCompilationProgress()); - Debug.LogWarning("Delayed entering play mode because Ink is still compiling ("+percentage+"). Will enter play mode on completion."); - playModeBlocked = true; - } - - static void EnteredPlayModeWhenCompiling () { - Debug.LogError("Entered Play Mode while Ink was still compiling! Your story will not be up to date. Recommend exiting and re-entering play mode.\nWe normally delay entering play mode when compiling, so you've found an edge case!"); - } - #endregion - } -} \ No newline at end of file diff --git a/Packages/Ink/Editor/Core/Compiler/InkCompiler.cs.meta b/Packages/Ink/Editor/Core/Compiler/InkCompiler.cs.meta deleted file mode 100644 index 8f6d9091..00000000 --- a/Packages/Ink/Editor/Core/Compiler/InkCompiler.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: 430cb8f71c23c438cb8b0ce85cc80fa6 -timeCreated: 1459463931 -licenseType: Pro -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Packages/Ink/Editor/Core/Ink Library/InkCompilerLog.cs b/Packages/Ink/Editor/Core/Ink Library/InkCompilerLog.cs index bd3b7a4b..5ccbdada 100644 --- a/Packages/Ink/Editor/Core/Ink Library/InkCompilerLog.cs +++ b/Packages/Ink/Editor/Core/Ink Library/InkCompilerLog.cs @@ -1,4 +1,5 @@ using System.Text.RegularExpressions; +using UnityEditor; using Debug = UnityEngine.Debug; namespace Ink.UnityIntegration @@ -18,9 +19,8 @@ public InkCompilerLog (Ink.ErrorType type, string content, string relativeFilePa } public string GetAbsoluteFilePath (InkFile masterInkFile) { - Debug.Log(masterInkFile.absoluteFolderPath); - Debug.Log(relativeFilePath); - return System.IO.Path.Combine(masterInkFile.absoluteFolderPath, relativeFilePath); + var assetPath = AssetDatabase.GetAssetPath(masterInkFile); + return InkEditorUtils.UnityRelativeToAbsolutePath(assetPath); } public static bool TryParse (string rawLog, out InkCompilerLog log) { diff --git a/Packages/Ink/Editor/Core/Ink Library/InkFile.cs b/Packages/Ink/Editor/Core/Ink Library/InkFile.cs index 22c4c982..9fc40c00 100644 --- a/Packages/Ink/Editor/Core/Ink Library/InkFile.cs +++ b/Packages/Ink/Editor/Core/Ink Library/InkFile.cs @@ -7,87 +7,22 @@ using UnityEngine; namespace Ink.UnityIntegration { - // Helper class for ink files that maintains INCLUDE connections between ink files + /// + /// ScriptableObject that serves as the imported version of .ink files. + /// [Serializable] - public class InkFile { - // Master files are those that can be compiled - public bool isMaster => !isIncludeFile || isMarkedToCompileAsMasterFile; - // Typically master files are simply those that aren't INCLUDED by another file, but they can also be marked to master files. - public bool isMarkedToCompileAsMasterFile => InkSettings.instance.includeFilesToCompileAsMasterFiles.Contains(inkAsset); - public bool compileAutomatically => InkSettings.instance.filesToCompileAutomatically.Contains(inkAsset); - // A reference to the ink file - public DefaultAsset inkAsset; - - //specify json destination folder (if None, default to same folder as ink file) - public DefaultAsset jsonAssetDirectory; - - // The compiled json file. Use this to start a story. - public TextAsset jsonAsset; - - // The file path relative to the Assets folder (Assets/Ink/Story.ink) - public string filePath { - get { - if(inkAsset == null) - return null; - - return InkEditorUtils.SanitizePathString(AssetDatabase.GetAssetPath(inkAsset)); - } - } - - // The full file path (C:/Users/Inkle/HeavensVault/Assets/Ink/Story.ink) - public string absoluteFilePath { - get { - if(inkAsset == null) - return null; - return InkEditorUtils.UnityRelativeToAbsolutePath(filePath); - } - } - - public string absoluteFolderPath => InkEditorUtils.SanitizePathString(Path.GetDirectoryName(absoluteFilePath)); - - // The path of any compiled json file. Relative to assets folder. - public string jsonPath { - get { - var _filePath = filePath; - Debug.Assert(!string.IsNullOrEmpty(_filePath), "File path for ink file is null! The ink library requires rebuilding. Asset: "+inkAsset); - - DefaultAsset jsonFolder = jsonAssetDirectory; - if (jsonFolder == null) // no path specified for this specific file - { - if(InkSettings.instance.defaultJsonAssetPath != null) - { - // use default path in InkSettings - jsonFolder = InkSettings.instance.defaultJsonAssetPath; - } - - if (jsonFolder == null) - { - //fallback to same folder as .ink file - jsonFolder = AssetDatabase.LoadAssetAtPath(Path.GetDirectoryName(_filePath)); - } - } - - Debug.Assert(jsonFolder != null, "JSON folder not found for ink file at path. File Path: "+_filePath+". Asset: "+inkAsset); - - string _jsonPath = AssetDatabase.GetAssetPath(jsonFolder); - Debug.Assert(Directory.Exists(_jsonPath), "JSON folder path is not a directory! Json Path: "+_jsonPath+". Asset: "+inkAsset); - string strJsonAssetPath = InkEditorUtils.CombinePaths(_jsonPath, Path.GetFileNameWithoutExtension(_filePath)) + ".json"; - return strJsonAssetPath; - } - } - - public string absoluteJSONPath { - get { - if(inkAsset == null) - return null; - return InkEditorUtils.UnityRelativeToAbsolutePath(jsonPath); - } - } - - - + public class InkFile : ScriptableObject { + // TODO: Ink version. This should really come from the core ink code. + public static System.Version inkVersionCurrent = new System.Version(1,2,0); + public static System.Version unityIntegrationVersionCurrent = new System.Version(1,2,1); + /// + /// The compiled JSON story. + /// + public string storyJson => _storyJson; + [SerializeField] + private string _storyJson; // Fatal unhandled errors that should be reported as compiler bugs. public List unhandledCompileErrors = new List(); @@ -106,122 +41,20 @@ public string absoluteJSONPath { public List todos = new List(); public bool hasTodos => todos.Count > 0; - public bool requiresCompile { - get { - if(!isMaster) return false; - return jsonAsset == null || hasUnhandledCompileErrors || lastEditDate > lastCompileDate; - } - } - - /// - /// Gets the last compile date of the story. - /// - /// The last compile date of the story. - public DateTime lastCompileDate { - get { - if(isMaster) { - if(jsonAsset == null) - return default; - - string fullJSONFilePath = InkEditorUtils.UnityRelativeToAbsolutePath(AssetDatabase.GetAssetPath(jsonAsset)); - return File.GetLastWriteTime(fullJSONFilePath); - } else { - return default; - } - } - } - /// /// Gets the last edit date of the file. /// /// The last edit date of the file. - public DateTime lastEditDate => File.GetLastWriteTime(absoluteFilePath); + public DateTime lastEditDate => File.GetLastWriteTime(AssetDatabase.GetAssetPath(this)); - public List masterInkAssets = new List(); - public IEnumerable masterInkFiles { - get { - foreach(var masterInkAsset in masterInkAssets) { - yield return InkLibrary.GetInkFileWithFile(masterInkAsset); - } - } - } - public IEnumerable masterInkFilesIncludingSelf { - get { - // A file can be both a master file AND be included by many other files. Return all the master files fitting this description. - if(isMaster) yield return this; - foreach(var masterInkFile in masterInkFiles) { - yield return masterInkFile; - } - } - } - - // Is this ink file included by another ink file? - public bool isIncludeFile => masterInkAssets.Count > 0; - - - // The files referenced by this file via the INCLUDE keyword - // We cache the paths of the files to be included for performance, giving us more freedom to refresh the actual includes list without needing to parse all the text. - public List localIncludePaths = new List(); - // The asset references for the included files. Unlike localIncludePaths this contains include files - public List includes = new List(); - // The InkFiles of the includes of this file - public List includesInkFiles { - get { - List _includesInkFiles = new List(); - foreach(var child in includes) { - if(child == null) { - Debug.LogError("Error compiling ink: Ink file include in "+filePath+" is null.", inkAsset); - continue; - } - _includesInkFiles.Add(InkLibrary.GetInkFileWithFile(child)); - } - return _includesInkFiles; - } - } - - - - - - public InkFile (DefaultAsset inkAsset) { - Debug.Assert(inkAsset != null); - this.inkAsset = inkAsset; - - ParseContent(); - // Should we run FindCompiledJSONAsset here? - } - - public void FindCompiledJSONAsset () { - Debug.Assert(inkAsset != null); - jsonAsset = AssetDatabase.LoadAssetAtPath(jsonPath); - } - - public void ClearAllHierarchyConnections() { - masterInkAssets.Clear(); - includes.Clear(); - } - - - - - - - - // Returns the contents of the .ink file. - public string GetFileContents () { - if(inkAsset == null) { - Debug.LogWarning("Ink file asset is null! Rebuild library using Assets > Rebuild Ink Library"); - return ""; - } - return File.ReadAllText(absoluteFilePath); - } - - // Parses the ink file and caches any information we may want to access without incurring a performance cost. - // Currently this only scans for includePaths, which are later used by InkLibrary.RebuildInkFileConnections. - public void ParseContent () { - localIncludePaths.Clear(); - localIncludePaths.AddRange(InkIncludeParser.ParseIncludes(GetFileContents())); - } + /// + /// Invoked by to initialize the ScriptableObject. This is not intended to be used elsewhere. + /// + /// + public void Initialize(string storyJson) + { + _storyJson = storyJson; + } public static class InkIncludeParser { static Regex _includeRegex; @@ -293,9 +126,8 @@ static IEnumerable FindIncludes(string str) { } } - public override string ToString () { - return $"[InkFile: filePath={filePath}]"; + return $"[InkFile: name={name}]"; } } } \ No newline at end of file diff --git a/Packages/Ink/Editor/Core/Ink Library/InkLibrary.cs b/Packages/Ink/Editor/Core/Ink Library/InkLibrary.cs deleted file mode 100644 index 9b5df09f..00000000 --- a/Packages/Ink/Editor/Core/Ink Library/InkLibrary.cs +++ /dev/null @@ -1,537 +0,0 @@ -using UnityEngine; -using UnityEditor; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using Debug = UnityEngine.Debug; - -/// -/// Holds a reference to an InkFile object for every .ink file detected in the Assets folder. -/// Provides helper functions to easily obtain these files. -/// -namespace Ink.UnityIntegration { - #if UNITY_2020_1_OR_NEWER - [FilePath("Library/asset", FilePathAttribute.Location.ProjectFolder)] - public class InkLibrary : ScriptableSingleton, IEnumerable { - #else - public class InkLibrary : ScriptableObject, IEnumerable { - #endif - // Ink version. This should really come from the core ink code. - public static System.Version inkVersionCurrent = new System.Version(1,2,0); - public static System.Version unityIntegrationVersionCurrent = new System.Version(1,2,1); - - static string absoluteSavePath { - get { - return System.IO.Path.GetFullPath(System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(),"Library","asset")); - } - } - - #if !UNITY_2020_1_OR_NEWER - public static bool created { - get { - // If it's null, there's no InkLibrary loaded - return (_instance != (Object) null); - } - } - private static InkLibrary _instance; - public static InkLibrary instance { - get { - if(!created) - LoadOrCreateInstance(); - return _instance; - } private set { - if(_instance == value) return; - _instance = value; - } - } - - - // This occurs on recompile, creation and load (note that data has not necessarily been loaded at this point!) - protected InkLibrary () { - if (created) - Debug.LogError((object) "ScriptableSingleton already exists. Did you query the singleton in a constructor?"); - else { - instance = this; - } - } - - public static void LoadOrCreateInstance () { - InternalEditorUtility.LoadSerializedFileAndForget(absoluteSavePath); - if(created) { - if(InkEditorUtils.isFirstCompile) { - Validate(); - } - } else { - instance = ScriptableObject.CreateInstance(); - instance.hideFlags = HideFlags.HideAndDontSave; - Rebuild(); - } - } - - public void Save (bool saveAsText) { - if(!created) return; - InternalEditorUtility.SaveToSerializedFileAndForget((Object[]) new InkLibrary[1] {instance}, absoluteSavePath, saveAsText); - } - - static void EnsureCreated () { - if(!created) LoadOrCreateInstance(); - } - #endif - - public class AssetSaver : UnityEditor.AssetModificationProcessor { - static string[] OnWillSaveAssets(string[] paths) { - instance.Save(true); - return paths; - } - } - - public List inkLibrary = new List(); - Dictionary inkLibraryDictionary = new Dictionary(); - - public int Count { - get { - return inkLibrary.Count; - } - } - public InkFile this[int key] { - get { - return inkLibrary[key]; - } set { - inkLibrary[key] = value; - } - } - IEnumerator IEnumerable.GetEnumerator() { - return inkLibrary.GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() { - return inkLibrary.GetEnumerator(); - } - - void OnValidate () { - BuildLookupDictionary(); - // This is experimental! I'd like to see if it fixes the issue where assets have not yet been imported. - EditorApplication.delayCall += () => { - Validate(); - }; - } - - static void BuildLookupDictionary () { - instance.inkLibraryDictionary.Clear(); - foreach(var inkFile in instance.inkLibrary) { - instance.inkLibraryDictionary.Add(inkFile.inkAsset, inkFile); - } - } - - /// - /// Checks if the library is corrupt and rebuilds if necessary. Returns true if the library was valid - /// - public static bool Validate () { - if(RequiresRebuild()) { - Rebuild(); - Debug.LogWarning("InkLibrary was invalid and has been rebuilt. This can occur if files are moved/deleted while the editor is closed. You can ignore this warning."); - return false; - } else { - return true; - } - } - - /// - /// Checks if the library is corrupt and requires a Rebuild. - /// This can happen when asset IDs change, causing the wrong file to be referenced. - /// This occassionally occurs from source control. - /// This is a fairly performant check. - /// - static bool RequiresRebuild () { - #if !UNITY_2020_1_OR_NEWER - EnsureCreated(); - #endif - foreach(var inkFile in instance.inkLibrary) { - if(inkFile == null) { - return true; - } - if(inkFile.inkAsset == null) { - // This can occur when the asset has not yet been imported! - return true; - } - if(!instance.inkLibraryDictionary.ContainsKey(inkFile.inkAsset)) { - return true; - } - foreach(var include in inkFile.includes) { - if(include == null) { - return true; - } - if(!instance.inkLibraryDictionary.ContainsKey(include)) { - return true; - } - } - } - return false; - } - - /// - /// Removes and null references in the library - /// - public static bool Clean () { - bool wasDirty = false; - for (int i = instance.Count - 1; i >= 0; i--) { - InkFile inkFile = instance[i]; - if (inkFile.inkAsset == null) { - RemoveAt(i); - wasDirty = true; - } - } - return wasDirty; - } - - static void Add (InkFile inkFile) { - instance.inkLibrary.Add(inkFile); - SortInkLibrary(); - instance.inkLibraryDictionary.Add(inkFile.inkAsset, inkFile); - } - public static void RemoveAt (int index) { - var inkFile = instance.inkLibrary[index]; - instance.inkLibrary.RemoveAt(index); - instance.inkLibraryDictionary.Remove(inkFile.inkAsset); - } - static void SortInkLibrary () { - instance.inkLibrary = instance.inkLibrary.OrderBy(x => x.filePath).ToList(); - } - - /// - /// Updates the ink library. Executed whenever an ink file is changed by InkToJSONPostProcessor - /// Can be called manually, but incurs a performance cost. - /// - public static void Rebuild () { - // Disable the asset post processor in case any assetdatabase functions called as a result of this would cause further operations. - InkPostProcessor.disabled = true; - - // Clear the old data - instance.inkLibrary.Clear(); - instance.inkLibraryDictionary.Clear(); - - // Reset the asset name - instance.name = "Ink Library "+unityIntegrationVersionCurrent.ToString(); - - // Add any new file connections (if any are found it replaces the old library entirely) - string[] inkFilePaths = GetAllInkFilePaths(); - bool inkLibraryChanged = false; - List newInkLibrary = new List(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(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(localAssetPath); - if(inkFileAsset == null) { - // If this occurs as a result assets not having been imported before OnValidate => Validate we should return immediately and set a flag to true. - // If an asset import is detected immediately after this via InkPostProcessor, then this rebuild may (will?) have been unnecessary anyway. - // At time of writing (11/05/21) I've not done this and am locally toying with EditorApplication.delayCall in OnValidate. - 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(); - } - BuildLookupDictionary(); - - RebuildInkFileConnections(); - - foreach (InkFile inkFile in instance.inkLibrary) inkFile.FindCompiledJSONAsset(); - - // if(InkSettings.instance.handleJSONFilesAutomatically) DeleteUnwantedCompiledJSONAssets(); - - instance.Save(true); - - // Re-enable the ink asset post processor - InkPostProcessor.disabled = false; - Debug.Log("Ink Library was rebuilt.\n"+instance.inkLibrary.Count+" ink files are currently tracked."); - } - - // To be used when adding .ink files. - // This process is typically handled by CreateOrReadUpdatedInkFiles, called from InkPostProcessor; but it may be desired to remove/disable the post processor. - // In those cases, this is the correct way to ensure the ink library correctly processes the file. - public static InkFile AddNewInkFile (DefaultAsset asset) { - Debug.Assert(asset != null); - // First, check if we've already got it in the library! - foreach(var _inkFile in instance) - if(_inkFile.inkAsset == asset) - return _inkFile; - // If not - var inkFile = new InkFile(asset); - inkFile.FindCompiledJSONAsset(); - Add(inkFile); - RebuildInkFileConnections(); - return inkFile; - } - - // This is called from InkPostProcessor after ink file(s) has been added/changed. - public static void CreateOrReadUpdatedInkFiles (List importedInkAssets) { - for (int i = 0; i < importedInkAssets.Count; i++) { - string importedAssetPath = importedInkAssets[i]; - InkFile inkFile = GetInkFileWithPath(importedAssetPath); - if(inkFile == null) { - DefaultAsset asset = AssetDatabase.LoadAssetAtPath(importedAssetPath); - if(asset == null) { - // This file wasn't found! This is a rare bug. We remove the file from the list in this case, preventing it from causing further bugs. - importedInkAssets.RemoveAt(i); - i--; - Debug.LogWarning("InkLibrary failed to load ink file at "+importedAssetPath+". It has been removed from the list of files. You can ignore this warning."); - } else { - // New file; create and add InkFile to represent it. Content is read in InkFile constructor. - inkFile = new InkFile(asset); - inkFile.FindCompiledJSONAsset(); - Add(inkFile); - } - } else { - // Read content - inkFile.ParseContent(); - } - } - // Now we've updated all the include paths for the ink library we can create master/child references between them. - RebuildInkFileConnections(); - } - - // Finds absolute file paths of all the ink files in Application.dataPath - private static string[] GetAllInkFilePaths () { - string[] inkFilePaths = Directory.GetFiles(Application.dataPath, "*.ink", SearchOption.AllDirectories); - for (int i = 0; i < inkFilePaths.Length; i++) { - inkFilePaths [i] = InkEditorUtils.SanitizePathString(inkFilePaths [i]); - } - return inkFilePaths; - } - - // All the master files - public static IEnumerable GetMasterInkFiles () { - if(instance.inkLibrary == null) yield break; - foreach (InkFile inkFile in instance.inkLibrary) { - if(inkFile.isMaster) - yield return inkFile; - } - } - - public static IEnumerable GetInkFilesMarkedToCompileAsMasterFiles () { - if(instance.inkLibrary == null) yield break; - foreach (InkFile inkFile in instance.inkLibrary) { - if(inkFile.isMaster) - yield return inkFile; - } - } - - // All the master files which are dirty and are set to compile - public static IEnumerable GetFilesRequiringRecompile () { - foreach(InkFile inkFile in GetInkFilesMarkedToCompileAsMasterFiles ()) { - if(InkSettings.instance.ShouldCompileInkFileAutomatically(inkFile) && inkFile.requiresCompile) - yield return inkFile; - } - } - - // All the master files which are set to compile - public static IEnumerable FilesCompiledByRecompileAll () { - foreach(InkFile inkFile in GetInkFilesMarkedToCompileAsMasterFiles ()) { - if(InkSettings.instance.ShouldCompileInkFileAutomatically(inkFile)) - yield return inkFile; - } - } - - /// - /// Gets the ink file from the .ink file reference. - /// - /// The ink file with path. - /// File asset. - /// Adds the file if missing from inkLibrary. - public static InkFile GetInkFileWithFile (DefaultAsset file, bool addIfMissing = false) { - if(instance.inkLibrary == null) return null; - - if (!file) { - Debug.LogError("Can't add null file."); - return null; - } - - if(instance.inkLibraryDictionary == null) { - Debug.LogWarning("GetInkFileWithFile: inkLibraryDictionary was null! This should never occur, but is handled following a user reported bug. If this has never been seen long after 12/08/2020, it can be safely removed"); - BuildLookupDictionary(); - } - foreach(InkFile inkFile in instance.inkLibrary) { - if(inkFile.inkAsset == file) { - return inkFile; - } - } - - var missingFileHasProperFileExtension = Path.GetExtension(AssetDatabase.GetAssetPath(file)) == InkEditorUtils.inkFileExtension; - if (addIfMissing) { - InkFile newFile = new InkFile(file); - instance.inkLibrary.Add(newFile); - if(missingFileHasProperFileExtension) Debug.Log(file + " missing from ink library. Adding it now."); - else Debug.LogWarning("File "+file + " is missing the .ink extension, but is believed to be an ink file. All ink files should use the .ink file extension! A common effect of this is forcing the InkLibrary to rebuild unexpectedly when the file is detected as an include of another file."); - return newFile; - } - - System.Text.StringBuilder listOfFiles = new System.Text.StringBuilder(); - foreach(InkFile inkFile in instance.inkLibrary) { - listOfFiles.AppendLine(inkFile.ToString()); - } - if(missingFileHasProperFileExtension) Debug.LogWarning (file + " missing from ink library. Please rebuild.\nFiles in Library:\n"+listOfFiles); - else Debug.LogWarning (file + " is missing from ink library. It is also missing the .ink file extension. All ink files should use the .ink file extension! \nFiles in Library:\n"+listOfFiles); - return null; - } - - /// - /// Gets the ink file with path relative to Assets folder, for example: "Assets/Ink/myStory.ink". - /// - /// The ink file with path. - /// Path. - public static InkFile GetInkFileWithPath (string path) { - if(instance.inkLibrary == null) return null; - foreach(InkFile inkFile in instance.inkLibrary) { - if(inkFile.filePath == path) { - return inkFile; - } - } - return null; - } - - /// - /// Gets the ink file with absolute path. - /// - /// The ink file with path. - /// Path. - public static InkFile GetInkFileWithAbsolutePath (string absolutePath) { - if(instance.inkLibrary == null) return null; - foreach(InkFile inkFile in instance.inkLibrary) { - if(inkFile.absoluteFilePath == absolutePath) { - return inkFile; - } - } - return null; - } - - public static InkFile GetInkFileWithJSONFile (TextAsset inkJSONAsset) { - if(instance.inkLibrary == null) return null; - foreach(InkFile inkFile in instance.inkLibrary) { - if(inkFile.jsonAsset == inkJSONAsset) { - return inkFile; - } - } - return null; - } - - /// - /// Rebuilds which files are master files and the connections between the files. - /// INCLUDE is always relative to the master file. This means that every file should be assumed to be a master file until proven otherwise. - /// - /// We might consider updating this to allow rebuilding connections for specific files, since the most common case this is called is when a single file changes. - /// The upside is that we wouldn't trigger warnings/errors that this function throws, for unrelated files. It's a bit risky so I've not done it yet. - public static void RebuildInkFileConnections () { - // Resets the connections between files - foreach (InkFile inkFile in instance.inkLibrary) { - inkFile.recursiveIncludeErrorPaths.Clear(); - inkFile.ClearAllHierarchyConnections(); - } - - - // A dictionary which contains a list of all the ink files that INCLUDE a given ink file. - // Once this is done we can determine which files are master files, and then assert that any INCLUDED files actually exist. - Dictionary> includedFileOwnerDictionary = new Dictionary>(); - Dictionary> recursiveIncludeLogs = new Dictionary>(); - // Traverses each file to any file paths referenced using INCLUDE, using the original file as the source path when dealing with nested INCLUDES. - // Since not all of the files are guaranteed to be master files, we don't assert that the files actually exist at this time. - foreach (InkFile inkFile in instance.inkLibrary) { - BuildIncludeHierarchyAsIfMasterFile(inkFile, inkFile, recursiveIncludeLogs); - // Recurse ink file includes for a (potential) master ink file, adding them to the file's list of includes if they exist - static void BuildIncludeHierarchyAsIfMasterFile(InkFile potentialMasterInkFile, InkFile currentInkFile, Dictionary> recursiveIncludeLogs) { - if(currentInkFile.localIncludePaths.Count == 0) - return; - foreach (var includePath in currentInkFile.localIncludePaths) { - var includedFile = FindIncludedFile(potentialMasterInkFile.filePath, includePath); - // Assets may not actually exist. - // A typical and expected example is when an included file in a subfolder from it's master file has an INCLUDE, since file paths are always relative to the master file. - if (includedFile != null) { - // We probably only need to show this error for files that are later proved to be master files - if (potentialMasterInkFile == includedFile || potentialMasterInkFile.includes.Contains(includedFile.inkAsset)) { - if(!recursiveIncludeLogs.ContainsKey(potentialMasterInkFile)) recursiveIncludeLogs.Add(potentialMasterInkFile, new List()); - recursiveIncludeLogs[potentialMasterInkFile].Add(currentInkFile); - continue; - } - Debug.Assert(includedFile.inkAsset != null); - potentialMasterInkFile.includes.Add(includedFile.inkAsset); - BuildIncludeHierarchyAsIfMasterFile(potentialMasterInkFile, includedFile, recursiveIncludeLogs); - } - } - - static InkFile FindIncludedFile(string masterFilePath, string includePath) { - string localIncludePath = InkEditorUtils.CombinePaths(Path.GetDirectoryName(masterFilePath), includePath); - // This enables parsing ..\ and the like. Can we use Path.GetFullPath instead? - var fullIncludePath = new FileInfo(localIncludePath).FullName; - localIncludePath = InkEditorUtils.AbsoluteToUnityRelativePath(fullIncludePath); - DefaultAsset includedInkFileAsset = AssetDatabase.LoadAssetAtPath(localIncludePath); - if(includedInkFileAsset != null) { - return GetInkFileWithFile(includedInkFileAsset); - } - return null; - } - } - - foreach (var includedFile in inkFile.includes) { - var includedInkFile = GetInkFileWithFile(includedFile); - if(!includedFileOwnerDictionary.ContainsKey(includedInkFile)) includedFileOwnerDictionary.Add(includedInkFile, new List()); - includedFileOwnerDictionary[includedInkFile].Add(inkFile); - } - } - - // Now we've established which files are INCLUDED we can tidy up by detecting and removing non-master files. - // It's not a master file then we remove all references to it as a master file in the includedFileOwnerDictionary. - // We don't clear the includes list for those files (even though referenced files may be null), because the user may mark isMarkedToCompileAsMasterFile true at a later date. - foreach (InkFile inkFile in instance.inkLibrary) { - var isMasterFile = !includedFileOwnerDictionary.ContainsKey(inkFile) || includedFileOwnerDictionary[inkFile].Count == 0 || inkFile.isMarkedToCompileAsMasterFile; - if (!isMasterFile) { - foreach (var includedFileOwners in includedFileOwnerDictionary) { - if(includedFileOwners.Key != inkFile) includedFileOwners.Value.Remove(inkFile); - } - } - } - - // Master ink files and includedFileOwnerDictionary are now valid collections denoting master files and their includes. The final step is to add the masters in any included files. - foreach (InkFile inkFile in instance.inkLibrary) { - if (!includedFileOwnerDictionary.ContainsKey(inkFile) || includedFileOwnerDictionary[inkFile].Count == 0 || inkFile.isMarkedToCompileAsMasterFile) { - foreach (var includedFile in inkFile.includes) { - var includedInkFile = GetInkFileWithFile(includedFile); - includedInkFile.masterInkAssets.Add(inkFile.inkAsset); - } - - } - } - - // Error logs for any master files that wanted to add recursive includes - foreach (var recursiveIncludeLog in recursiveIncludeLogs) { - if (recursiveIncludeLog.Key.isMaster) { - recursiveIncludeLog.Key.recursiveIncludeErrorPaths.AddRange(recursiveIncludeLog.Value.Select(x => x.filePath)); - var files = string.Join("\n", recursiveIncludeLog.Key.recursiveIncludeErrorPaths); - Debug.LogError("Recursive INCLUDE found in "+recursiveIncludeLog.Key.filePath+" at "+(recursiveIncludeLog.Value.Count == 1 ? "file:\n" : "files:\n")+files); - } - } - } - - // Deletes any JSON ink assets that aren't expected to exist because their ink files aren't expected to be compiled - public static void DeleteUnwantedCompiledJSONAssets() { - foreach (InkFile inkFile in instance.inkLibrary) { - if(!inkFile.isMaster && inkFile.jsonAsset != null) { - AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(inkFile.jsonAsset)); - inkFile.jsonAsset = null; - } - } - } - } -} \ No newline at end of file diff --git a/Packages/Ink/Editor/Core/Ink Library/InkLibrary.cs.meta b/Packages/Ink/Editor/Core/Ink Library/InkLibrary.cs.meta deleted file mode 100644 index cc246427..00000000 --- a/Packages/Ink/Editor/Core/Ink Library/InkLibrary.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: dc234ab28a32840f5adfb84a075bc023 -timeCreated: 1485516445 -licenseType: Pro -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Packages/Ink/Editor/Core/Ink Settings/InkSettings.cs b/Packages/Ink/Editor/Core/Ink Settings/InkSettings.cs index 81e532f5..b408c482 100644 --- a/Packages/Ink/Editor/Core/Ink Settings/InkSettings.cs +++ b/Packages/Ink/Editor/Core/Ink Settings/InkSettings.cs @@ -68,17 +68,6 @@ public string templateFilePath { else return AssetDatabase.GetAssetPath(templateFile); } } - - - public DefaultAsset defaultJsonAssetPath; - [UnityEngine.Serialization.FormerlySerializedAs("compileAutomatically")] - public bool compileAllFilesAutomatically = true; - public List includeFilesToCompileAsMasterFiles = new List(); - public List filesToCompileAutomatically = new List(); - public bool delayInPlayMode = true; - public bool handleJSONFilesAutomatically = true; - - public int compileTimeout = 30; public bool printInkLogsInConsoleOnCompile; @@ -96,30 +85,12 @@ public static SerializedObject GetSerializedSettings() { return new SerializedObject(instance); } #endif - - public bool ShouldCompileInkFileAutomatically (InkFile inkFile) { - return compileAllFilesAutomatically || (inkFile.isMaster && filesToCompileAutomatically.Contains(inkFile.inkAsset)); - } - void OnEnable () { // Oh gosh Unity never unloads ScriptableObjects once created! We destroy these objects before we recompile so there's only ever one in memory at once. AssemblyReloadEvents.beforeAssemblyReload += () => { DestroyImmediate(this); }; - // Validate the includeFilesToCompileAsMasterFiles list. - for (int i = includeFilesToCompileAsMasterFiles.Count - 1; i >= 0; i--) { - if(includeFilesToCompileAsMasterFiles[i] == null) { - includeFilesToCompileAsMasterFiles.RemoveAt(i); - Debug.LogError("REMOVE "+includeFilesToCompileAsMasterFiles.Count); - } - } - // Validate the filesToCompileAutomatically list. - for (int i = filesToCompileAutomatically.Count - 1; i >= 0; i--) { - if(filesToCompileAutomatically[i] == null) { - filesToCompileAutomatically.RemoveAt(i); - } - } } } } diff --git a/Packages/Ink/Editor/Core/Ink Settings/InkSettingsEditor.cs b/Packages/Ink/Editor/Core/Ink Settings/InkSettingsEditor.cs index 18e26f78..b7734d55 100644 --- a/Packages/Ink/Editor/Core/Ink Settings/InkSettingsEditor.cs +++ b/Packages/Ink/Editor/Core/Ink Settings/InkSettingsEditor.cs @@ -63,12 +63,7 @@ static void DrawSettings (InkSettings settings) { DrawTemplateMissingWarning(); settings.templateFile = (DefaultAsset)EditorGUILayout.ObjectField(new GUIContent("Ink Template", "Optional. The default content of files created via Assets > Create > Ink."), settings.templateFile, typeof(DefaultAsset)); - settings.defaultJsonAssetPath = (DefaultAsset)EditorGUILayout.ObjectField(new GUIContent("New JSON Path", "By default, story JSON files are placed next to the ink. Drag a folder here to place new JSON files there instead."), settings.defaultJsonAssetPath, typeof(DefaultAsset)); - settings.compileAllFilesAutomatically = EditorGUILayout.Toggle(new GUIContent("Compile All Ink Automatically", "When disabled, automatic compilation can be enabled on a per-story basis via the inspector for a master story file. This can be helpful when you have several stories in a single project."), settings.compileAllFilesAutomatically); - settings.delayInPlayMode = EditorGUILayout.Toggle(new GUIContent("Delay compilation if in Play Mode", "When enabled, ink compilation is delayed if in play mode. Files will be compiled on re-entering edit mode."), settings.delayInPlayMode); settings.printInkLogsInConsoleOnCompile = EditorGUILayout.Toggle(new GUIContent("Print ink TODOs in console on compile", "When enabled, ink lines starting with TODO are printed in the console."), settings.printInkLogsInConsoleOnCompile); - settings.handleJSONFilesAutomatically = EditorGUILayout.Toggle(new GUIContent("Handle JSON Automatically", "Whether JSON files are moved, renamed and deleted along with their ink files."), settings.handleJSONFilesAutomatically); - settings.compileTimeout = EditorGUILayout.IntField(new GUIContent("Compile Timeout", "The max time the compiler will attempt to compile for in case of unhanded errors. You may need to increase this for very large ink projects."), settings.compileTimeout); settings.suppressStartupWindow = EditorGUILayout.Toggle(new GUIContent("Suppress Startup Window", "Prevent the \"what's new\" (the one that appears if you click the \"Show changelog\" button above) appearing when the version of this plugin has changed and Unity is opened. This can be useful for CI/CD pipelines, where auto-launching editor windows can fail to load due to a Unity bug."), settings.suppressStartupWindow); settings.automaticallyAddDefineSymbols = EditorGUILayout.Toggle(new GUIContent("Add define symbols", "If true, automatically adds INK_EDITOR and INK_RUNTIME to the define symbols in the build settings. This is handy for conditional code."), settings.automaticallyAddDefineSymbols); //// DrawDefineManagerButtons(); @@ -128,8 +123,8 @@ static void DrawSettings (SerializedObject settings) { static void DrawVersions () { EditorGUILayout.LabelField(new GUIContent("Version Info"), EditorStyles.boldLabel); EditorGUI.BeginDisabledGroup(true); - EditorGUILayout.TextField(new GUIContent("Plugin version", "The version of the Ink Unity Integration package."), InkLibrary.unityIntegrationVersionCurrent.ToString()); - EditorGUILayout.TextField(new GUIContent("Ink version", "The version of ink that is included by the Unity package, used to compile and play ink files."), InkLibrary.inkVersionCurrent.ToString()); + EditorGUILayout.TextField(new GUIContent("Plugin version", "The version of the Ink Unity Integration package."), InkFile.unityIntegrationVersionCurrent.ToString()); + EditorGUILayout.TextField(new GUIContent("Ink version", "The version of ink that is included by the Unity package, used to compile and play ink files."), InkFile.inkVersionCurrent.ToString()); EditorGUILayout.TextField(new GUIContent("Ink story format version", "Significant changes to the Ink runtime are recorded by the story format version.\nCompatibility between different versions is limited; see comments at Ink.Runtime.Story.inkVersionCurrent for more details."), Ink.Runtime.Story.inkVersionCurrent.ToString()); EditorGUILayout.TextField(new GUIContent("Ink save format version", "Version of the ink save/load system.\nCompatibility between different versions is limited; see comments at Ink.Runtime.StoryState.kInkSaveStateVersion for more details."), Ink.Runtime.StoryState.kInkSaveStateVersion.ToString()); EditorGUI.EndDisabledGroup(); diff --git a/Packages/Ink/Editor/Core/InkEditorUtils.cs b/Packages/Ink/Editor/Core/InkEditorUtils.cs index 2da2d72b..5c0d1363 100644 --- a/Packages/Ink/Editor/Core/InkEditorUtils.cs +++ b/Packages/Ink/Editor/Core/InkEditorUtils.cs @@ -48,32 +48,6 @@ public static Texture2D inkLogoIcon { } } - [MenuItem("Assets/Rebuild Ink Library", false, 200)] - public static void RebuildLibrary() { - InkLibrary.Rebuild(); - } - - [MenuItem("Assets/Recompile Ink", false, 201)] - public static void RecompileAll() { - var filesToRecompile = InkLibrary.FilesCompiledByRecompileAll().ToArray(); - string logString = filesToRecompile.Any() ? - "Recompile All will compile "+string.Join(", ", filesToRecompile.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); - InkCompiler.CompileInk(filesToRecompile); - } - - public static void RecompileAllImmediately() { - var filesToRecompile = InkLibrary.FilesCompiledByRecompileAll().ToArray(); - string logString = filesToRecompile.Any() ? - "Recompile All Immediately will compile "+string.Join(", ", filesToRecompile.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); - InkCompiler.CompileInk(filesToRecompile, true, null); - } - - - [MenuItem("Assets/Create/Ink", false, 120)] public static void CreateNewInkFileAtSelectedPathWithTemplateAndStartNameEditing () { string fileName = "New Ink.ink"; @@ -187,6 +161,8 @@ public static bool CheckStoryIsValid (string storyJSON, out Exception exception) try { new Story(storyJSON); } catch (Exception ex) { + // log exception to unity console so we get a stack trace + Debug.LogException(ex); exception = ex; return false; } @@ -284,13 +260,6 @@ public static bool IsInkFile(string path) { string extension = Path.GetExtension(path); if (extension == InkEditorUtils.inkFileExtension) { return true; - } else if (String.IsNullOrEmpty(extension)) { - if (!File.Exists(path)) return false; - if (File.GetAttributes(path).HasFlag(FileAttributes.Directory)) return false; - // This check exists only in the case of ink files that lack the .ink extension. - // We support this mostly for legacy reasons - Inky didn't used to add .ink by default which made a this relatively common issue. - // This function needs to be speedy but getting all the ink file paths is a bit slow, so I'd like to remove support for missing extensions in the future. - return InkLibrary.instance.inkLibrary.Exists(f => f.filePath == path); } else return false; } @@ -303,7 +272,7 @@ public static bool IsInkFile(string path) { public static void OpenInEditor (InkFile inkFile, InkCompilerLog log) { var targetFilePath = log.GetAbsoluteFilePath(inkFile); // EditorUtility.OpenWithDefaultApp(targetFilePath); - AssetDatabase.OpenAsset(inkFile.inkAsset, log.lineNumber); + AssetDatabase.OpenAsset(inkFile, log.lineNumber); // Unity.CodeEditor.CodeEditor.OSOpenFile(); #if UNITY_2019_1_OR_NEWER diff --git a/Packages/Ink/Editor/Core/InkImporter.cs b/Packages/Ink/Editor/Core/InkImporter.cs new file mode 100644 index 00000000..13a48e74 --- /dev/null +++ b/Packages/Ink/Editor/Core/InkImporter.cs @@ -0,0 +1,64 @@ +using UnityEngine; +using UnityEditor.AssetImporters; +using System.IO; +using Ink.UnityIntegration; +using UnityEditor; +using Ink; + +/// +/// Automatically compiles .ink assets each time they are imported, and creates an InkFile asset. +/// +[ScriptedImporter(1, "ink")] +public class InkImporter : ScriptedImporter +{ + public override void OnImportAsset(AssetImportContext ctx) + { + var inkFile = ScriptableObject.CreateInstance(); + var absolutePath = InkEditorUtils.UnityRelativeToAbsolutePath(ctx.assetPath); + var inputString = File.ReadAllText(ctx.assetPath); + var compiler = new Compiler(inputString, new Compiler.Options + { + countAllVisits = true, + fileHandler = new UnityInkFileHandler(Path.GetDirectoryName(absolutePath)), + errorHandler = (string message, ErrorType type) => { + InkCompilerLog log; + if(InkCompilerLog.TryParse(message, out log)) { + if(string.IsNullOrEmpty(log.relativeFilePath)) log.relativeFilePath = Path.GetFileName(absolutePath); + switch (log.type) + { + case ErrorType.Error: + inkFile.errors.Add(log); + Debug.LogError("Ink "+log.type+" for "+Path.GetFileName(absolutePath)+": "+log.content + " (at "+log.relativeFilePath+":"+log.lineNumber+")", inkFile); + break; + case ErrorType.Warning: + inkFile.warnings.Add(log); + Debug.LogWarning("Ink "+log.type+" for "+Path.GetFileName(absolutePath)+": "+log.content + " (at "+log.relativeFilePath+" "+log.lineNumber+")", inkFile); + break; + case ErrorType.Author: + inkFile.todos.Add(log); + if (InkSettings.instance.printInkLogsInConsoleOnCompile) + { + Debug.Log("Ink Log for "+Path.GetFileName(absolutePath)+": "+log.content + " (at "+log.relativeFilePath+" "+log.lineNumber+")", inkFile); + } + break; + } + + } else { + Debug.LogWarning("Couldn't parse log "+message); + } + } + }); + + try { + var compiledStory = compiler.Compile(); + + if (compiledStory != null) + inkFile.Initialize(compiledStory.ToJson()); + } catch (System.SystemException e) { + Debug.LogException(e); + } + + ctx.AddObjectToAsset("InkFile", inkFile); + ctx.SetMainObject(inkFile); + } +} \ No newline at end of file diff --git a/Assets/Editor/InkLibraryEditorWindow.cs.meta b/Packages/Ink/Editor/Core/InkImporter.cs.meta similarity index 83% rename from Assets/Editor/InkLibraryEditorWindow.cs.meta rename to Packages/Ink/Editor/Core/InkImporter.cs.meta index 626048e7..5aba247f 100644 --- a/Assets/Editor/InkLibraryEditorWindow.cs.meta +++ b/Packages/Ink/Editor/Core/InkImporter.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 8b8ed05f30b81e3408103a91cffd2e30 +guid: 7dc164402b3932547b62cc35c116c770 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Packages/Ink/Editor/Tools/Build Validation.meta b/Packages/Ink/Editor/Tools/Build Validation.meta deleted file mode 100644 index 39e1ebbf..00000000 --- a/Packages/Ink/Editor/Tools/Build Validation.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 39ee3bcd699e5a748ae4bcc889c046e6 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Packages/Ink/Editor/Tools/Build Validation/InkPreBuildValidationCheck.cs b/Packages/Ink/Editor/Tools/Build Validation/InkPreBuildValidationCheck.cs deleted file mode 100644 index 30e0cf81..00000000 --- a/Packages/Ink/Editor/Tools/Build Validation/InkPreBuildValidationCheck.cs +++ /dev/null @@ -1,62 +0,0 @@ -using UnityEngine; -using UnityEditor; -using UnityEditor.Build; -using System.Text; -using Ink.UnityIntegration; -using System.Linq; -#if UNITY_2018_1_OR_NEWER -using UnityEditor.Build.Reporting; -#endif - -class InkPreBuildValidationCheck : -#if UNITY_2018_1_OR_NEWER -IPreprocessBuildWithReport -#else -IPreprocessBuild -#endif -{ - public int callbackOrder { get { return 0; } } - - #if UNITY_2018_1_OR_NEWER - public void OnPreprocessBuild(BuildReport report) { - PreprocessValidationStep(); - } - #else - public void OnPreprocessBuild(BuildTarget target, string path) { - PreprocessValidationStep(); - } - #endif - - static void PreprocessValidationStep () { - // If we're compiling, we've throw an error to cancel the build. Exit out immediately. - if(!AssertNotCompiling()) return; - EnsureInkIsCompiled(); - } - - // Prevent building if ink is currently compiling. - // Ideally we'd force it to complete instantly. - // It seems you can do this with WaitHandle.WaitAll but I'm out of my depth! - // Info here - https://stackoverflow.com/questions/540078/wait-for-pooled-threads-to-complete - static bool AssertNotCompiling () { - if(InkCompiler.executingCompilationStack) { - StringBuilder sb = new StringBuilder("Ink is currently compiling!"); - var errorString = sb.ToString(); - InkCompiler.SetBuildBlocked(); - if(UnityEditor.EditorUtility.DisplayDialog("Ink Build Error!", errorString, "Ok")) { - Debug.LogError(errorString); - } - return false; - } - return true; - } - - // Immediately compile any files that aren't compiled and should be. - static void EnsureInkIsCompiled () { - var filesToRecompile = InkLibrary.GetFilesRequiringRecompile(); - if(filesToRecompile.Any()) { - if(InkSettings.instance.compileAllFilesAutomatically) { - InkCompiler.CompileInk(filesToRecompile.ToArray(), true, null); - } - } - } -} \ No newline at end of file diff --git a/Packages/Ink/Editor/Tools/Build Validation/InkPreBuildValidationCheck.cs.meta b/Packages/Ink/Editor/Tools/Build Validation/InkPreBuildValidationCheck.cs.meta deleted file mode 100644 index 8be8a804..00000000 --- a/Packages/Ink/Editor/Tools/Build Validation/InkPreBuildValidationCheck.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 260430d96c5f0aa46a31363984dc9088 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Packages/Ink/Editor/Tools/File Icons/InkBrowserIcons.cs b/Packages/Ink/Editor/Tools/File Icons/InkBrowserIcons.cs index 9cfe82a0..032c2444 100644 --- a/Packages/Ink/Editor/Tools/File Icons/InkBrowserIcons.cs +++ b/Packages/Ink/Editor/Tools/File Icons/InkBrowserIcons.cs @@ -111,8 +111,8 @@ static InkBrowserIcons() { static void OnDrawProjectWindowItem(string guid, Rect rect) { string path = AssetDatabase.GUIDToAssetPath(guid); if (InkEditorUtils.IsInkFile(path)) { - DefaultAsset asset = AssetDatabase.LoadAssetAtPath(path); - DrawInkFile(InkLibrary.GetInkFileWithFile(asset), rect); + InkFile asset = AssetDatabase.LoadAssetAtPath(path); + DrawInkFile(asset, rect); } } @@ -149,9 +149,6 @@ static void DrawLarge (InkFile inkFile, Rect rect) { } else if(inkFile.hasTodos && todoIcon != null) { GUI.DrawTexture(miniRect, todoIcon); } - if(inkFile.isIncludeFile && childIcon != null) { - GUI.DrawTexture(new Rect(rect.x, rect.y, rect.width * 0.5f, rect.height * 0.5f), childIconLarge); - } } } @@ -164,25 +161,14 @@ static void DrawSmall (InkFile inkFile, Rect rect) { GUI.DrawTexture(new Rect(rect.x, rect.y, unknownFileIcon.width, unknownFileIcon.height), unknownFileIcon); } } else { - if (inkFile.isMaster) { - if (!InkSettings.instance.ShouldCompileInkFileAutomatically(inkFile)) { - GUI.DrawTexture(new Rect(rect.x, rect.y + rect.size.y * 0.5f, rect.size.x * 0.5f, rect.size.y * 0.5f), manualIcon); - - } - - Rect miniRect = new Rect(rect.center, rect.size * 0.5f); - if(inkFile.hasErrors && errorIcon != null) { - GUI.DrawTexture(miniRect, errorIcon); - } else if(inkFile.hasWarnings && warningIcon != null) { - GUI.DrawTexture(miniRect, warningIcon); - } else if(inkFile.hasTodos && todoIcon != null) { - GUI.DrawTexture(miniRect, todoIcon); - } - } - - if(inkFile.isIncludeFile && childIcon != null) { - GUI.DrawTexture(new Rect(rect.x, rect.y, childIcon.width, childIcon.height), childIcon); - } + Rect miniRect = new Rect(rect.center, rect.size * 0.5f); + if(inkFile.hasErrors && errorIcon != null) { + GUI.DrawTexture(miniRect, errorIcon); + } else if(inkFile.hasWarnings && warningIcon != null) { + GUI.DrawTexture(miniRect, warningIcon); + } else if(inkFile.hasTodos && todoIcon != null) { + GUI.DrawTexture(miniRect, todoIcon); + } } } } diff --git a/Packages/Ink/Editor/Tools/Ink Inspector/DefaultAssetEditor.cs b/Packages/Ink/Editor/Tools/Ink Inspector/DefaultAssetEditor.cs deleted file mode 100644 index 52892712..00000000 --- a/Packages/Ink/Editor/Tools/Ink Inspector/DefaultAssetEditor.cs +++ /dev/null @@ -1,60 +0,0 @@ -using UnityEngine; -using UnityEditor; -using System; -using System.Collections.Generic; -using System.Reflection; - -namespace Ink.UnityIntegration { - [CustomEditor(typeof(DefaultAsset), true)] - public class DefaultAssetEditor : Editor { - - private DefaultAssetInspector inspector; - - private void OnEnable () { - inspector = FindObjectInspector (); - if(inspector != null) { - inspector.editor = this; - inspector.serializedObject = serializedObject; - inspector.target = target; - inspector.OnEnable(); - } - } - - private void OnDisable () { - if(inspector != null) - inspector.OnDisable(); - } - - protected override void OnHeaderGUI () { - if(inspector != null) { - inspector.OnHeaderGUI(); - } - else - base.OnHeaderGUI(); - } - - public override void OnInspectorGUI () { - if(inspector != null) { - GUI.enabled = true; - inspector.OnInspectorGUI(); - } - else - base.OnInspectorGUI(); - } - - private DefaultAssetInspector FindObjectInspector () { - var assembly = Assembly.GetExecutingAssembly(); - var assetPath = AssetDatabase.GetAssetPath(target); - foreach(var type in assembly.GetTypes()) { - if(type.IsSubclassOf(typeof(DefaultAssetInspector))) { - DefaultAssetInspector objectInspector = (DefaultAssetInspector)Activator.CreateInstance(type); - if(objectInspector.IsValid(assetPath)) { - objectInspector.target = target; - return objectInspector; - } - } - } - return null; - } - } -} \ No newline at end of file diff --git a/Packages/Ink/Editor/Tools/Ink Inspector/DefaultAssetEditor.cs.meta b/Packages/Ink/Editor/Tools/Ink Inspector/DefaultAssetEditor.cs.meta deleted file mode 100644 index 58ab9c49..00000000 --- a/Packages/Ink/Editor/Tools/Ink Inspector/DefaultAssetEditor.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: fe3507ae5d970447197e131c39ac31b6 -timeCreated: 1464440328 -licenseType: Pro -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Packages/Ink/Editor/Tools/Ink Inspector/DefaultAssetInspector.cs b/Packages/Ink/Editor/Tools/Ink Inspector/DefaultAssetInspector.cs deleted file mode 100644 index 70816a0b..00000000 --- a/Packages/Ink/Editor/Tools/Ink Inspector/DefaultAssetInspector.cs +++ /dev/null @@ -1,19 +0,0 @@ -using UnityEngine; -using UnityEditor; - -namespace Ink.UnityIntegration { - public abstract class DefaultAssetInspector { - // Reference to the actual editor we draw to - public Editor editor; - // Shortcut to the target object - public Object target; - // Shortcut to the serializedObject - public SerializedObject serializedObject; - - public abstract bool IsValid(string assetPath); - public virtual void OnEnable () {} - public virtual void OnDisable () {} - public virtual void OnHeaderGUI () {} - public virtual void OnInspectorGUI() {} - } -} \ No newline at end of file diff --git a/Packages/Ink/Editor/Tools/Ink Inspector/DefaultAssetInspector.cs.meta b/Packages/Ink/Editor/Tools/Ink Inspector/DefaultAssetInspector.cs.meta deleted file mode 100644 index 7fd4ad0b..00000000 --- a/Packages/Ink/Editor/Tools/Ink Inspector/DefaultAssetInspector.cs.meta +++ /dev/null @@ -1,12 +0,0 @@ -fileFormatVersion: 2 -guid: 7fa6f007190b6408c8aebb32050a3bbe -timeCreated: 1470299519 -licenseType: Pro -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Packages/Ink/Editor/Tools/Ink Inspector/InkInspector.cs b/Packages/Ink/Editor/Tools/Ink Inspector/InkInspector.cs index b8f0a4d1..4cf74c03 100644 --- a/Packages/Ink/Editor/Tools/Ink Inspector/InkInspector.cs +++ b/Packages/Ink/Editor/Tools/Ink Inspector/InkInspector.cs @@ -8,22 +8,20 @@ using Object = UnityEngine.Object; namespace Ink.UnityIntegration { - public class InkInspector : DefaultAssetInspector { - + [CustomEditor(typeof(InkFile), true)] + public class InkInspector : Editor { private InkFile inkFile; - private ReorderableList includesFileList; - private ReorderableList mastersFileList; private ReorderableList errorList; private ReorderableList warningList; private ReorderableList todosList; private string cachedTrimmedFileContents; private const int maxCharacters = 16000; - public override bool IsValid(string assetPath) { + public bool IsValid(string assetPath) { return Path.GetExtension(assetPath) == InkEditorUtils.inkFileExtension; } - public override void OnHeaderGUI () { + protected override void OnHeaderGUI () { GUILayout.BeginHorizontal(); GUILayout.Space(38f); GUILayout.BeginVertical(); @@ -33,12 +31,12 @@ public override void OnHeaderGUI () { GUILayoutUtility.GetRect(10f, 10f, 16f, 35f, EditorStyles.layerMaskField); GUILayout.FlexibleSpace(); - EditorGUI.BeginDisabledGroup(inkFile == null); - if (GUILayout.Button("Open", EditorStyles.miniButton)) { - AssetDatabase.OpenAsset(inkFile.inkAsset, 3); - GUIUtility.ExitGUI(); - } - EditorGUI.EndDisabledGroup(); + // EditorGUI.BeginDisabledGroup(inkFile == null); + // if (GUILayout.Button("Open", EditorStyles.miniButton)) { + // AssetDatabase.OpenAsset(inkFile, 3); + // GUIUtility.ExitGUI(); + // } + // EditorGUI.EndDisabledGroup(); GUILayout.EndHorizontal(); GUILayout.EndVertical(); @@ -51,148 +49,36 @@ public override void OnHeaderGUI () { Rect childIconRect = new Rect(iconRect.x, iconRect.y, 16f, 16f); if(inkFile == null) { GUI.DrawTexture(childIconRect, InkBrowserIcons.unknownFileIcon, ScaleMode.ScaleToFit); - } else if(inkFile.isIncludeFile) { - GUI.DrawTexture(childIconRect, InkBrowserIcons.childIconLarge, ScaleMode.ScaleToFit); } Rect titleRect = new Rect(rect.x + 44f, rect.y + 6f, rect.width - 44f - 38f - 4f, 16f); titleRect.yMin -= 2f; titleRect.yMax += 2f; - GUI.Label(titleRect, editor.target.name, EditorStyles.largeLabel); - } - - public override void OnEnable () { - Rebuild(); - InkCompiler.OnCompileInk += OnCompileInk; - } - - public override void OnDisable () { - InkCompiler.OnCompileInk -= OnCompileInk; + GUI.Label(titleRect, target.name, EditorStyles.largeLabel); } - void OnCompileInk (InkFile[] inkFiles) { - // We could probably be smarter about when we rebuild - only rebuilding if the file that's shown in the inspector is in the list - but it's not frequent or expensive so it's not important! + public void OnEnable () { Rebuild(); } void Rebuild () { cachedTrimmedFileContents = ""; string assetPath = AssetDatabase.GetAssetPath(target); - inkFile = InkLibrary.GetInkFileWithPath(assetPath); + inkFile = AssetDatabase.LoadAssetAtPath(assetPath); if(inkFile == null) return; - if (inkFile.includes.Count > 0) CreateIncludeList (); - else includesFileList = null; - - if (inkFile.masterInkAssets.Count > 0) CreateMastersList (); - else mastersFileList = null; - errorList = CreateErrorList(); warningList = CreateWarningList(); todosList = CreateTodoList(); - cachedTrimmedFileContents = inkFile.GetFileContents(); + var absoluteFilePath = InkEditorUtils.UnityRelativeToAbsolutePath(assetPath); + cachedTrimmedFileContents = File.ReadAllText(absoluteFilePath); cachedTrimmedFileContents = cachedTrimmedFileContents.Substring(0, Mathf.Min(cachedTrimmedFileContents.Length, maxCharacters)); if(cachedTrimmedFileContents.Length >= maxCharacters) cachedTrimmedFileContents += "...\n\n<...etc...>"; } - void CreateIncludeList () { - List includeTextAssets = inkFile.includes; - includesFileList = new ReorderableList(includeTextAssets, typeof(DefaultAsset), false, true, false, false); - includesFileList.drawHeaderCallback = (Rect rect) => { - EditorGUI.LabelField(rect, "Included Files"); - }; - includesFileList.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) => { - DefaultAsset childAssetFile = ((List)includesFileList.list)[index]; - if(childAssetFile == null) { - Debug.LogError("Ink file in include list is null. This should never occur. Use Assets > Recompile Ink to fix this issue."); - EditorGUI.LabelField(rect, new GUIContent("Warning: Ink File in include list is null. Use Assets > Recompile Ink to fix this issue.")); - return; - } - InkFile childInkFile = InkLibrary.GetInkFileWithFile(childAssetFile); - if(childInkFile == null) { - Debug.LogError("Ink File for included file "+childAssetFile+" not found. This should never occur. Use Assets > Recompile Ink to fix this issue."); - EditorGUI.LabelField(rect, new GUIContent("Warning: Ink File for included file "+childAssetFile+" not found. Use Assets > Recompile Ink to fix this issue.")); - return; - } - Rect iconRect = new Rect(rect.x, rect.y, 0, 16); - if(childInkFile.hasErrors || childInkFile.hasWarnings) { - iconRect.width = 20; - } - Rect objectFieldRect = new Rect(iconRect.xMax, rect.y, rect.width - iconRect.width - 80, 16); - Rect selectRect = new Rect(objectFieldRect.xMax, rect.y, 80, 16); - if(childInkFile.hasErrors) { - EditorGUI.LabelField(iconRect, new GUIContent(InkBrowserIcons.errorIcon)); - } else if(childInkFile.hasWarnings) { - EditorGUI.LabelField(iconRect, new GUIContent(InkBrowserIcons.warningIcon)); - } - EditorGUI.BeginDisabledGroup(true); - EditorGUI.ObjectField(objectFieldRect, childAssetFile, typeof(Object), false); - EditorGUI.EndDisabledGroup(); - if(GUI.Button(selectRect, "Select")) { - Selection.activeObject = childAssetFile; - } - }; - } - - void CreateMastersList () { - List mastersTextAssets = inkFile.masterInkAssets; - mastersFileList = new ReorderableList(mastersTextAssets, typeof(DefaultAsset), false, true, false, false); - mastersFileList.drawHeaderCallback = (Rect rect) => { - EditorGUI.LabelField(rect, "Master Files"); - }; - mastersFileList.drawElementCallback = (Rect rect, int index, bool isActive, bool isFocused) => { - DefaultAsset masterAssetFile = ((List)mastersFileList.list)[index]; - if(masterAssetFile == null) { - Debug.LogError("Ink file in masters list is null. This should never occur. Use Assets > Recompile Ink to fix this issue."); - EditorGUI.LabelField(rect, new GUIContent("Warning: Ink File in masters list is null. Use Assets > Recompile Ink to fix this issue.")); - return; - } - InkFile masterInkFile = InkLibrary.GetInkFileWithFile(masterAssetFile); - if(masterInkFile == null) { - Debug.LogError("Ink File for master file "+masterAssetFile+" not found. This should never occur. Use Assets > Recompile Ink to fix this issue."); - EditorGUI.LabelField(rect, new GUIContent("Warning: Ink File for master file "+masterAssetFile+" not found. Use Assets > Recompile Ink to fix this issue.")); - return; - } - Rect iconRect = new Rect(rect.x, rect.y, 0, 16); - if(masterInkFile.hasErrors || masterInkFile.hasWarnings) { - iconRect.width = 20; - } - Rect objectFieldRect = new Rect(iconRect.xMax, rect.y, rect.width - iconRect.width - 80, 16); - Rect selectRect = new Rect(objectFieldRect.xMax, rect.y, 80, 16); - if(masterInkFile.hasErrors) { - EditorGUI.LabelField(iconRect, new GUIContent(InkBrowserIcons.errorIcon)); - } else if(masterInkFile.hasWarnings) { - EditorGUI.LabelField(iconRect, new GUIContent(InkBrowserIcons.warningIcon)); - } - EditorGUI.BeginDisabledGroup(true); - EditorGUI.ObjectField(objectFieldRect, masterAssetFile, typeof(Object), false); - EditorGUI.EndDisabledGroup(); - if(GUI.Button(selectRect, "Select")) { - Selection.activeObject = masterAssetFile; - } - - - // foreach(var masterInkFile in inkFile.masterInkFiles) { - // EditorGUILayout.BeginHorizontal(); - // if(masterInkFile.hasErrors) { - // GUILayout.Label(new GUIContent(InkBrowserIcons.errorIcon), GUILayout.Width(20)); - // } else if(masterInkFile.hasWarnings) { - // GUILayout.Label(new GUIContent(InkBrowserIcons.warningIcon), GUILayout.Width(20)); - // } - // EditorGUI.BeginDisabledGroup(true); - // EditorGUILayout.ObjectField("Master Ink File", masterInkFile.inkAsset, typeof(Object), false); - // EditorGUI.EndDisabledGroup(); - // if(GUILayout.Button("Select", GUILayout.Width(80))) { - // Selection.activeObject = masterInkFile.inkAsset; - // } - // EditorGUILayout.EndHorizontal(); - // } - }; - } - ReorderableList CreateErrorList () { var reorderableList = new ReorderableList(inkFile.errors, typeof(string), false, true, false, false); reorderableList.drawHeaderCallback = (Rect rect) => { @@ -251,87 +137,42 @@ public static void DrawLayoutInkLine (InkFile inkFile, int lineNumber, string la GUILayout.Label(label); string openLabel = "Open"+ (lineNumber == -1 ? "" : " ("+lineNumber+")"); if(GUILayout.Button(openLabel, GUILayout.Width(80))) { - InkEditorUtils.OpenInEditor(inkFile.filePath, null, lineNumber); + InkEditorUtils.OpenInEditor(AssetDatabase.GetAssetPath(inkFile), null, lineNumber); } GUILayout.EndHorizontal(); } public override void OnInspectorGUI () { - editor.Repaint(); + 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.isIncludeFile) { - EditorGUI.BeginChangeCheck(); - var newCompileAsIfMaster = EditorGUILayout.Toggle(new GUIContent("Should also be 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.isMaster) { - EditorGUILayout.BeginVertical(EditorStyles.helpBox); - DrawMasterFileHeader(); - - EditorGUILayout.Space(); - - // There's no point letting users compile when recursive INCLUDE files exist, so hide anything else while they exist! - if(inkFile.hasRecursiveIncludeErrorPaths) { - EditorGUILayout.HelpBox("A recursive INCLUDE connection exists in this ink file's INCLUDE hierarchy.\nThe offending INCLUDE(s) can be found at the following file(s):\n"+string.Join("\n", inkFile.recursiveIncludeErrorPaths.Select(x => "• "+x)), MessageType.Error); - } else { - 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(); - } - - DrawIncludedFiles(); - EditorGUILayout.EndVertical(); - - EditorGUILayout.Space(); - } - - if (inkFile.isIncludeFile) { - EditorGUILayout.BeginVertical(EditorStyles.helpBox); - EditorGUILayout.LabelField(new GUIContent("Include File", InkBrowserIcons.childIconLarge, "This file is included by at least one other file"), EditorStyles.boldLabel); - DrawListOfMasterFiles(); - EditorGUILayout.EndVertical(); - - EditorGUILayout.Space(); - } + GUI.enabled = true; + EditorGUILayout.BeginVertical(EditorStyles.helpBox); + DrawMasterFileHeader(); + + EditorGUILayout.Space(); + + // There's no point letting users compile when recursive INCLUDE files exist, so hide anything else while they exist! + if(inkFile.hasRecursiveIncludeErrorPaths) { + EditorGUILayout.HelpBox("A recursive INCLUDE connection exists in this ink file's INCLUDE hierarchy.\nThe offending INCLUDE(s) can be found at the following file(s):\n"+string.Join("\n", inkFile.recursiveIncludeErrorPaths.Select(x => "• "+x)), MessageType.Error); + } else { + 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); + } + + DrawCompileErrors(); + DrawErrors(); + DrawWarnings(); + DrawTODOList(); + } + + EditorGUILayout.EndVertical(); + + EditorGUILayout.Space(); DrawFileContents (); @@ -342,76 +183,20 @@ public override void OnInspectorGUI () { void DrawMasterFileHeader () { EditorGUILayout.LabelField(new GUIContent("Master File", "This file is a master file and can be compiled"), EditorStyles.boldLabel); - if(inkFile.jsonAsset != null && inkFile.errors.Count == 0 && GUILayout.Button("Play")) { - InkPlayerWindow.LoadAndPlay(inkFile.jsonAsset); + if(inkFile.errors.Count == 0 && GUILayout.Button("Play")) { + InkPlayerWindow.LoadAndPlay(inkFile); } EditorGUILayout.Space(); - EditorGUI.BeginDisabledGroup(true); - EditorGUILayout.ObjectField("JSON Asset", inkFile.jsonAsset, typeof(TextAsset), false); - EditorGUI.EndDisabledGroup(); DrawEditAndCompileDates(inkFile); - if(!InkSettings.instance.compileAllFilesAutomatically) { - EditorGUI.BeginChangeCheck(); - var newCompileAutomatically = EditorGUILayout.Toggle(new GUIContent("Compile Automatially", "If true, this file recompiles automatically when any changes are detected."), InkSettings.instance.ShouldCompileInkFileAutomatically(inkFile)); - if(EditorGUI.EndChangeCheck()) { - if(newCompileAutomatically) { - InkSettings.instance.filesToCompileAutomatically.Add(inkFile.inkAsset); - EditorUtility.SetDirty(InkSettings.instance); - } else { - InkSettings.instance.filesToCompileAutomatically.Remove(inkFile.inkAsset); - EditorUtility.SetDirty(InkSettings.instance); - } - } - EditorApplication.RepaintProjectWindow(); - } - -// if(!checkedStoryForErrors) { -// if(GUILayout.Button("Check for errors")) { -// GetStoryErrors(); -// } -// } else { -// if(exception != null) { -// EditorGUILayout.HelpBox("Story is invalid\n"+exception.ToString(), MessageType.Error); -// } else { -// EditorGUILayout.HelpBox("Story is valid", MessageType.Info); -// } -// } - } - - void DrawListOfMasterFiles() { - if(mastersFileList != null && mastersFileList.count > 0) { - mastersFileList.DoLayoutList(); - } } void DrawEditAndCompileDates (InkFile masterInkFile) { string editAndCompileDateString = ""; DateTime lastEditDate = inkFile.lastEditDate; editAndCompileDateString += "Last edit date "+lastEditDate.ToString(); - if(masterInkFile.jsonAsset != null) { - DateTime lastCompileDate = masterInkFile.lastCompileDate; - editAndCompileDateString += "\nLast compile date "+lastCompileDate.ToString(); - if(lastEditDate > lastCompileDate) { - if(EditorApplication.isPlaying && InkSettings.instance.delayInPlayMode) { - editAndCompileDateString += "\nWill compile on exiting play mode"; - EditorGUILayout.HelpBox(editAndCompileDateString, MessageType.Info); - } else { - EditorGUILayout.HelpBox(editAndCompileDateString, MessageType.Warning); - } - } else { - EditorGUILayout.HelpBox(editAndCompileDateString, MessageType.None); - } - } else { - EditorGUILayout.HelpBox(editAndCompileDateString, MessageType.None); - } - } - - void DrawIncludedFiles () { - if(includesFileList != null && includesFileList.count > 0) { - includesFileList.DoLayoutList(); - } + EditorGUILayout.HelpBox(editAndCompileDateString, MessageType.None); } void DrawCompileErrors () { diff --git a/Packages/Ink/Editor/Tools/Player Window/InkPlayerWindow.cs b/Packages/Ink/Editor/Tools/Player Window/InkPlayerWindow.cs index bc1a1522..06d6f5f7 100644 --- a/Packages/Ink/Editor/Tools/Player Window/InkPlayerWindow.cs +++ b/Packages/Ink/Editor/Tools/Player Window/InkPlayerWindow.cs @@ -63,27 +63,15 @@ public static InkPlayerWindow GetWindow (bool focus) { // Entry point for loading and playing a story. - public static void LoadAndPlay (TextAsset storyJSONTextAsset, bool focusWindow = true) { + public static void LoadAndPlay (InkFile inkFileAsset, bool focusWindow = true) { GetWindow(focusWindow); if(InkPlayerWindow.story != null) { if(EditorUtility.DisplayDialog("Story in progress", "The Ink Player Window is already playing a story. Would you like to stop it and load the new story?", "Stop and load", "Cancel")) { InkPlayerWindow.Stop(); - InkPlayerWindow.Play(storyJSONTextAsset); + InkPlayerWindow.Play(inkFileAsset); } } else { - InkPlayerWindow.Play(storyJSONTextAsset); - } - } - - public static void LoadAndPlay (string storyJSON, bool focusWindow = true) { - GetWindow(focusWindow); - if(InkPlayerWindow.story != null) { - if(EditorUtility.DisplayDialog("Story in progress", "The Ink Player Window is already playing a story. Would you like to stop it and load the new story?", "Stop and load", "Cancel")) { - InkPlayerWindow.Stop(); - InkPlayerWindow.Play(storyJSON); - } - } else { - InkPlayerWindow.Play(storyJSON); + InkPlayerWindow.Play(inkFileAsset); } } @@ -109,7 +97,7 @@ public static void Attach (Story story, InkPlayerParams inkPlayerParams) { InkPlayerWindow.story = story; // Clear the last loaded story setup on attaching stories. We don't NEED to do this but it's never really helpful and often seems like a bug. - InkPlayerWindowState.Instance.lastStoryJSONAssetPath = null; + InkPlayerWindowState.Instance.lastInkAssetPath = null; InkPlayerWindowState.Instance.lastStoryWasPlaying = false; // This allows reconstructing the story so it can be used after recompile. However, it can be expensive to run so there's a good argument for not running it on play! @@ -311,7 +299,7 @@ public static TextAsset storyStateTextAsset { return; _storyStateTextAsset = value; if(_storyStateTextAsset != null) - storyStateValid = InkEditorUtils.CheckStoryStateIsValid(storyJSONTextAsset.text, storyStateTextAsset.text); + storyStateValid = InkEditorUtils.CheckStoryStateIsValid(inkFile.storyJson, storyStateTextAsset.text); } } @@ -364,13 +352,13 @@ static void Load () { } } - public string lastStoryJSONAssetPath; + public string lastInkAssetPath; public bool lastStoryWasPlaying; - public TextAsset TryGetLastStoryJSONAsset () { - if(lastStoryJSONAssetPath == null) return null; - var asset = AssetDatabase.LoadAssetAtPath(lastStoryJSONAssetPath); + public InkFile TryGetLastInkAsset () { + if(lastInkAssetPath == null) return null; + var asset = AssetDatabase.LoadAssetAtPath(lastInkAssetPath); if(asset == null) { - lastStoryJSONAssetPath = null; + lastInkAssetPath = null; Save(); } return asset; @@ -394,19 +382,19 @@ public TextAsset TryGetLastStoryJSONAsset () { static bool attachedWhileInPlayMode {get; set;} - static TextAsset _storyJSONTextAsset; - static TextAsset storyJSONTextAsset { + static InkFile _inkFile; + static InkFile inkFile { get { - return _storyJSONTextAsset; + return _inkFile; } set { - if(_storyJSONTextAsset == value) return; - _storyJSONTextAsset = value; - if (_storyJSONTextAsset != null) { - InkPlayerWindowState.Instance.lastStoryJSONAssetPath = AssetDatabase.GetAssetPath(storyJSONTextAsset); - string fullJSONFilePath = InkEditorUtils.UnityRelativeToAbsolutePath(InkPlayerWindowState.Instance.lastStoryJSONAssetPath); + if(_inkFile == value) return; + _inkFile = value; + if (_inkFile != null) { + InkPlayerWindowState.Instance.lastInkAssetPath = AssetDatabase.GetAssetPath(inkFile); + string fullJSONFilePath = InkEditorUtils.UnityRelativeToAbsolutePath(InkPlayerWindowState.Instance.lastInkAssetPath); currentStoryJSONLastEditDateTime = File.GetLastWriteTime(fullJSONFilePath); } else { - InkPlayerWindowState.Instance.lastStoryJSONAssetPath = null; + InkPlayerWindowState.Instance.lastInkAssetPath = null; } InkPlayerWindowState.Save(); } @@ -653,7 +641,7 @@ void OnEnable () { EditorApplication.update += Update; if(story == null && !EditorApplication.isPlayingOrWillChangePlaymode) { - var lastLoadedStory = InkPlayerWindowState.Instance.TryGetLastStoryJSONAsset(); + var lastLoadedStory = InkPlayerWindowState.Instance.TryGetLastInkAsset(); if(lastLoadedStory != null) { if(InkPlayerWindowState.Instance.lastStoryWasPlaying) { LoadAndPlay(lastLoadedStory, false); @@ -824,45 +812,28 @@ static void DetachInstance () { } - static void Play (TextAsset storyJSONTextAsset) { - Play(storyJSONTextAsset, InkPlayerParams.Standard); + static void Play (InkFile inkFile) { + Play(inkFile, InkPlayerParams.Standard); } - static void Play (TextAsset storyJSONTextAsset, InkPlayerParams inkPlayerParams) { - if(TryPrepareInternal(storyJSONTextAsset)) { - InkPlayerWindow.playerParams = inkPlayerParams; - PlayInternal(); - } - } - static void Play (string storyJSON) { - Play(storyJSON, InkPlayerParams.Standard); - } - static void Play (string storyJSON, InkPlayerParams inkPlayerParams) { - if(TryPrepareInternal(storyJSON)) { + static void Play (InkFile inkFile, InkPlayerParams inkPlayerParams) { + if(TryPrepareInternal(inkFile)) { InkPlayerWindow.playerParams = inkPlayerParams; PlayInternal(); } } - static void PlayInternal () { story = new Story(storyJSON); } // Loads the story, ready to be played - static bool TryPrepareInternal (TextAsset newStoryJSONTextAsset) { + static bool TryPrepareInternal (InkFile newInkFile) { // This forces a refresh - storyJSONTextAsset = null; - storyJSONTextAsset = newStoryJSONTextAsset; - if(storyJSONTextAsset == null || !InkEditorUtils.CheckStoryIsValid(storyJSONTextAsset.text, out playStoryException)) - return false; - storyJSON = storyJSONTextAsset.text; - return true; - } - static bool TryPrepareInternal (string newStoryJSON) { - if(!InkEditorUtils.CheckStoryIsValid(storyJSON, out playStoryException)) + inkFile = null; + inkFile = newInkFile; + if(inkFile == null || !InkEditorUtils.CheckStoryIsValid(inkFile.storyJson, out playStoryException)) return false; - InkPlayerWindow.storyJSONTextAsset = null; - InkPlayerWindow.storyJSON = newStoryJSON; + storyJSON = inkFile.storyJson; return true; } @@ -966,16 +937,14 @@ static void Clear () { static void Restart () { Stop(); - if(storyJSONTextAsset != null) - Play(storyJSONTextAsset); - else if(storyJSON != null) - Play(storyJSON); + if(inkFile != null) + Play(inkFile); else Debug.LogError("Can't restart because no text asset or cached JSON exists"); } static bool CanRestart() { - return storyJSONTextAsset != null || storyJSON != null; + return inkFile != null; } static void ContinueStory () { @@ -1044,9 +1013,9 @@ static void SaveStoryState (string storyStateJSON) { // Text asset can be null if we attached to an existing story rather than loading our own string dirPath = string.Empty; string storyName = "story"; - if( storyJSONTextAsset != null ) { - dirPath = System.IO.Path.GetDirectoryName(AssetDatabase.GetAssetPath(storyJSONTextAsset)); - storyName = storyJSONTextAsset.name; + if( inkFile != null ) { + dirPath = System.IO.Path.GetDirectoryName(AssetDatabase.GetAssetPath(inkFile)); + storyName = inkFile.name; } var newStateAsset = InkEditorUtils.CreateStoryStateTextFile(storyStateJSON, dirPath, storyName+"_SaveState"); @@ -1175,17 +1144,17 @@ void DisplayHeader () { } else { EditorGUILayout.BeginVertical(); EditorGUI.BeginChangeCheck(); - storyJSONTextAsset = EditorGUILayout.ObjectField("Story JSON", storyJSONTextAsset, typeof(TextAsset), false) as TextAsset; + inkFile = EditorGUILayout.ObjectField("Ink File", inkFile, typeof(InkFile), false) as InkFile; if(EditorGUI.EndChangeCheck()) { - if(storyJSONTextAsset == null) { + if(inkFile == null) { story = null; } else { Stop(); - Play(storyJSONTextAsset); + Play(inkFile); } } if(CanRestart()) { - string fullJSONFilePath = InkEditorUtils.UnityRelativeToAbsolutePath(AssetDatabase.GetAssetPath(storyJSONTextAsset)); + string fullJSONFilePath = InkEditorUtils.UnityRelativeToAbsolutePath(AssetDatabase.GetAssetPath(inkFile)); var updatedStoryJSONLastEditDateTime = File.GetLastWriteTime(fullJSONFilePath); if (currentStoryJSONLastEditDateTime != updatedStoryJSONLastEditDateTime ) { EditorGUILayout.BeginHorizontal(); @@ -1193,7 +1162,7 @@ void DisplayHeader () { EditorGUILayout.BeginVertical(); if(GUILayout.Button(new GUIContent("Reload", restartIcon, "Reload and restart the current story, which has been updated."))) { var storyStateJSON = story.state.ToJson(); - Play(storyJSONTextAsset, InkPlayerWindow.playerParams); + Play(inkFile, InkPlayerWindow.playerParams); story.state.LoadJson(storyStateJSON); } if(GUILayout.Button(new GUIContent("Restart", restartIcon, "Restart the current story"))) { @@ -1215,11 +1184,11 @@ void DisplayStoryControlGroup () { EditorGUILayout.BeginHorizontal (EditorStyles.toolbar); if(story == null) { - EditorGUI.BeginDisabledGroup(storyJSONTextAsset == null); + EditorGUI.BeginDisabledGroup(inkFile == null); if(GUILayout.Button(new GUIContent("Start", playIcon, "Run the story"), EditorStyles.toolbarButton)) { var playerParams = InkPlayerParams.Standard; playerParams.profileOnStart = InkPlayerWindow.playerParams.profileOnStart; - Play(storyJSONTextAsset, playerParams); + Play(inkFile, playerParams); } EditorGUI.EndDisabledGroup(); } else { diff --git a/Packages/Ink/Editor/Tools/Startup Window/InkUnityIntegrationStartupWindow.cs b/Packages/Ink/Editor/Tools/Startup Window/InkUnityIntegrationStartupWindow.cs index 4e6eb6c6..42b8f377 100644 --- a/Packages/Ink/Editor/Tools/Startup Window/InkUnityIntegrationStartupWindow.cs +++ b/Packages/Ink/Editor/Tools/Startup Window/InkUnityIntegrationStartupWindow.cs @@ -27,7 +27,7 @@ static void TryCreateWindow() { } public static void ShowWindow () { - InkUnityIntegrationStartupWindow window = GetWindow(typeof(InkUnityIntegrationStartupWindow), true, "Ink Update "+InkLibrary.unityIntegrationVersionCurrent, true) as InkUnityIntegrationStartupWindow; + InkUnityIntegrationStartupWindow window = GetWindow(typeof(InkUnityIntegrationStartupWindow), true, "Ink Update "+InkFile.unityIntegrationVersionCurrent, true) as InkUnityIntegrationStartupWindow; window.minSize = new Vector2(200, 200); var size = new Vector2(520, 320); window.position = new Rect((Screen.currentResolution.width-size.x) * 0.5f, (Screen.currentResolution.height-size.y) * 0.5f, size.x, size.y); @@ -47,8 +47,8 @@ void OnGUI () EditorGUILayout.BeginVertical(); EditorGUILayout.LabelField(new GUIContent(InkEditorUtils.inkLogoIcon), GUILayout.Width(areaSize.x), GUILayout.Height(areaSize.x*((float)InkEditorUtils.inkLogoIcon.height/InkEditorUtils.inkLogoIcon.width))); GUILayout.Space(5); - EditorGUILayout.LabelField("Version "+InkLibrary.unityIntegrationVersionCurrent, EditorStyles.centeredGreyMiniLabel); - EditorGUILayout.LabelField("Ink version "+InkLibrary.inkVersionCurrent, EditorStyles.centeredGreyMiniLabel); + EditorGUILayout.LabelField("Version "+InkFile.unityIntegrationVersionCurrent, EditorStyles.centeredGreyMiniLabel); + EditorGUILayout.LabelField("Ink version "+InkFile.inkVersionCurrent, EditorStyles.centeredGreyMiniLabel); EditorGUILayout.EndVertical(); GUILayout.EndArea(); diff --git a/README.md b/README.md index 2b140fea..3a0113d6 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ This Unity package allows you to integrate inkle's [ink narrative scripting lang - **ink player**: Provides a powerful [Ink Player Window](https://github.com/inkle/ink-unity-integration/blob/master/Documentation/InkPlayerWindow.md) for playing and debugging stories. - - **Auto compilation**: Instantly creates and updates a JSON story file when a `.ink` is updated. + - **Auto compilation**: Instantly creates compiles story file when a `.ink` is updated. - **Inspector tools**: Provides an icon for ink files, and a custom inspector that provides information about a file. @@ -77,18 +77,8 @@ To keep up to date with the latest news about ink [sign up for the mailing list] ## Compilation -Ink files must be compiled to JSON before they can be used in-game. -**This package compiles all edited ink files automatically.** -By default, compiled files are created next to their ink file. - -### Editor Compilation -This package provides tools to automate this process when a .ink file is edited. - -**Disabling auto-compilation**: You might want to have manual control over ink compilation. If this is the case, you can disable "Compile ink automatically" in the InkSettings file or delete the InkPostProcessor class. - -**Manual compilation**: If you have disabled auto-compilation, you can manually compile all ink files using the **Assets > Recompile Ink** menu item, individually via the inspector of an ink file, or via code using InkCompiler.CompileInk(). - -**Play mode delay**: By default, ink does not compile while in play mode. This can be disabled in the InkSettings file. +Ink files must be compiled to JSON before they can be used in-game at runtime. +**This package compiles all edited ink files automatically via a [scripted importer](https://docs.unity3d.com/Manual/ScriptedImporters.html)**. The compiled JSON string is stored within the imported ink asset. ### In-game Compilation @@ -128,14 +118,6 @@ There's [unofficial support for PlayMaker here.](https://github.com/inkle/ink-un We'd love to see this supported more if you'd like to assist the effort! - -# Source control tips - -When you edit ink files, the compiler will also update the corresponding compiled .json file. If no compiled file existed before, Unity will also create a meta file for it. It is recommended that you always commit both ink and json files at the same time to avoid the file being re-compiled by your team members. - -Adding or removing ink files will also make changes to the InkLibrary file, and we could recommend authors also commit this file for the same reasons. - - # WebGL best practices WebGL builds should be as small as possible. The ink compiler is included in builds, but is typically only used in the editor.