public override void OnInspectorGUI() { serializedObject.Update(); YarnProjectImporter yarnProjectImporter = serializedObject.targetObject as YarnProjectImporter; EditorGUILayout.Space(); if (sourceScriptsProperty.arraySize == 0) { EditorGUILayout.HelpBox("This Yarn Project has no content. Add Yarn Scripts to it.", MessageType.Warning); } EditorGUILayout.PropertyField(sourceScriptsProperty, true); EditorGUILayout.Space(); bool hasCompileError = compileErrorsProperty.arraySize > 0; if (hasCompileError) { foreach (SerializedProperty compileError in compileErrorsProperty) { EditorGUILayout.HelpBox(compileError.stringValue, MessageType.Error); } } serializedDeclarationsList.DrawLayout(); // The 'Convert Implicit Declarations' feature has been // temporarily removed in v2.0.0-beta5. #if false // If any of the serialized declarations are implicit, add a // button that lets you generate explicit declarations for them var anyImplicitDeclarations = false; foreach (SerializedProperty declProp in serializedDeclarationsProperty) { anyImplicitDeclarations |= declProp.FindPropertyRelative("isImplicit").boolValue; } if (hasCompileError == false && anyImplicitDeclarations) { if (GUILayout.Button("Convert Implicit Declarations")) { // add explicit variable declarations to the file YarnProjectUtility.ConvertImplicitVariableDeclarationsToExplicit(yarnProjectImporter); // Return here becuase this method call will cause the // YarnProgram contents to change, which confuses the // SerializedObject when we're in the middle of a GUI // draw call. So, stop here, and let Unity re-draw the // Inspector (which it will do on the next editor tick // because the item we're inspecting got re-imported.) return; } } #endif EditorGUILayout.PropertyField(defaultLanguageProperty, new GUIContent("Base Language")); CurrentProjectDefaultLanguageProperty = defaultLanguageProperty; EditorGUILayout.PropertyField(languagesToSourceAssetsProperty, new GUIContent("Localisations")); CurrentProjectDefaultLanguageProperty = null; // Ask the project importer if it can generate a strings table. // This involves querying several assets, which means various // exceptions might get thrown, which we'll catch and log (if // we're in debug mode). bool canGenerateStringsTable; try { canGenerateStringsTable = yarnProjectImporter.CanGenerateStringsTable; } catch (System.Exception e) { #if YARNSPINNER_DEBUG Debug.LogWarning($"Encountered in error when checking to see if Yarn Project Importer could generate a strings table: {e}", this); #else // Ignore the 'variable e is unused' warning var _ = e; #endif canGenerateStringsTable = false; } // The following controls only do something useful if all of // the lines in the project have tags, which means the project // can generate a string table. using (new EditorGUI.DisabledScope(canGenerateStringsTable == false)) { #if USE_ADDRESSABLES // If the addressable assets package is available, show a // checkbox for using it. var hasAnySourceAssetFolders = yarnProjectImporter.languagesToSourceAssets.Any(l => l.assetsFolder != null); if (hasAnySourceAssetFolders == false) { // Disable this checkbox if there are no assets // available. using (new EditorGUI.DisabledScope(true)) { EditorGUILayout.Toggle(useAddressableAssetsProperty.displayName, false); } } else { EditorGUILayout.PropertyField(useAddressableAssetsProperty); // Show a warning if we've requested addressables but // haven't set it up. if (useAddressableAssetsProperty.boolValue && AddressableAssetSettingsDefaultObject.SettingsExists == false) { EditorGUILayout.HelpBox("Please set up Addressable Assets in this project.", MessageType.Warning); } } // Add a button for updating asset addresses, if any asset // source folders exist if (useAddressableAssetsProperty.boolValue && AddressableAssetSettingsDefaultObject.SettingsExists) { using (new EditorGUI.DisabledScope(hasAnySourceAssetFolders == false)) { if (GUILayout.Button($"Update Asset Addresses")) { YarnProjectUtility.UpdateAssetAddresses(yarnProjectImporter); } } } #endif } EditorGUILayout.Space(); EditorGUILayout.LabelField("Commands and Functions", EditorStyles.boldLabel); var searchAllAssembliesLabel = new GUIContent("Search All Assemblies", "Search all assembly definitions for commands and functions, as well as code that's not in a folder with an assembly definition"); EditorGUILayout.PropertyField(searchAllAssembliesProperty, searchAllAssembliesLabel); if (searchAllAssembliesProperty.boolValue == false) { EditorGUI.indentLevel += 1; EditorGUILayout.PropertyField(assembliesToSearchProperty); EditorGUI.indentLevel -= 1; } using (new EditorGUI.DisabledGroupScope(canGenerateStringsTable == false)) { if (GUILayout.Button("Export Strings as CSV")) { var currentPath = AssetDatabase.GetAssetPath(serializedObject.targetObject); var currentFileName = Path.GetFileNameWithoutExtension(currentPath); var currentDirectory = Path.GetDirectoryName(currentPath); var destinationPath = EditorUtility.SaveFilePanel("Export Strings CSV", currentDirectory, $"{currentFileName}.csv", "csv"); if (string.IsNullOrEmpty(destinationPath) == false) { // Generate the file on disk YarnProjectUtility.WriteStringsFile(destinationPath, yarnProjectImporter); // destinationPath may have been inside our Assets // directory, so refresh the asset database AssetDatabase.Refresh(); } } if (yarnProjectImporter.languagesToSourceAssets.Count > 0) { if (GUILayout.Button("Update Existing Strings Files")) { YarnProjectUtility.UpdateLocalizationCSVs(yarnProjectImporter); } } } // Does this project's source scripts list contain any actual // assets? (It can have a count of >0 and still have no assets // when, for example, you've just clicked the + button but // haven't dragged an asset in yet.) var hasAnyTextAssets = yarnProjectImporter.sourceScripts.Where(s => s != null).Count() > 0; // Disable this button if 1. all lines already have tags or 2. // no actual source files exist using (new EditorGUI.DisabledScope(canGenerateStringsTable == true || hasAnyTextAssets == false)) { if (GUILayout.Button("Add Line Tags to Scripts")) { YarnProjectUtility.AddLineTagsToFilesInYarnProject(yarnProjectImporter); } } var hadChanges = serializedObject.ApplyModifiedProperties(); #if UNITY_2018 // Unity 2018's ApplyRevertGUI is buggy, and doesn't // automatically detect changes to the importer's // serializedObject. This means that we'd need to track the // state of the importer, and don't have a way to present a // Revert button. // // Rather than offer a broken experience, on Unity 2018 we // immediately reimport the changes. This is slow (we're // serializing and writing the asset to disk on every property // change!) but ensures that the writes are done. if (hadChanges) { // Manually perform the same tasks as the 'Apply' button // would ApplyAndImport(); } #endif #if UNITY_2019_1_OR_NEWER // On Unity 2019 and newer, we can use an ApplyRevertGUI that // works identically to the built-in importer inspectors. ApplyRevertGUI(); #endif }
public override void OnInspectorGUI() { serializedObject.Update(); EditorGUILayout.Space(); // If there's a parse error in any of the selected objects, // show an error. If the selected objects have the same // destination program, and there's a compile error in it, show // that. if (parseErrorMessagesProperty.arraySize > 0) { if (serializedObject.isEditingMultipleObjects) { EditorGUILayout.HelpBox("Some of the selected scripts have errors.", MessageType.Error); } else { foreach (SerializedProperty errorProperty in parseErrorMessagesProperty) { EditorGUILayout.HelpBox(errorProperty.stringValue, MessageType.Error); } } } else if (DestinationProjectError.Count() > 0) { var displayMessage = string.Join("\n", DestinationProjectError); EditorGUILayout.HelpBox(displayMessage, MessageType.Error); } if (destinationYarnProject == null) { EditorGUILayout.HelpBox("This script is not currently part of a Yarn Project, so it can't be compiled or loaded into a Dialogue Runner. Either click Create New Yarn Project, or add a Yarn project to the field below.", MessageType.Info); if (GUILayout.Button("Create New Yarn Project...")) { YarnProjectUtility.CreateYarnProject(target as YarnImporter); UpdateDestinationProject(); } } using (var change = new EditorGUI.ChangeCheckScope()) { var project = EditorGUILayout.ObjectField("Project", destinationYarnProject, typeof(YarnProject), false); if (change.changed) { string programPath = null; if (project != null) { programPath = AssetDatabase.GetAssetPath(project); } YarnProjectUtility.AssignScriptToProject((target as YarnImporter).assetPath, programPath); UpdateDestinationProject(); } } EditorGUILayout.Space(); var hadChanges = serializedObject.ApplyModifiedProperties(); #if UNITY_2018 // Unity 2018's ApplyRevertGUI is buggy, and doesn't automatically // detect changes to the importer's serializedObject. This means // that we'd need to track the state of the importer, and don't // have a way to present a Revert button. // // Rather than offer a broken experience, on Unity 2018 we // immediately reimport the changes. This is slow (we're // serializing and writing the asset to disk on every property // change!) but ensures that the writes are done. if (hadChanges) { // Manually perform the same tasks as the 'Apply' button would ApplyAndImport(); } #endif #if UNITY_2019_1_OR_NEWER // On Unity 2019 and newer, we can use an ApplyRevertGUI that // works identically to the built-in importer inspectors. ApplyRevertGUI(); #endif }