public void YarnProjectUtility_OnGeneratingLinesFile_CreatesFile() { // Arrange: // Set up a project with a Yarn file filled with tagged lines. var project = SetUpProject(TestYarnScriptSource); var importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(project)) as YarnProjectImporter; var destinationStringsFilePath = "Assets/" + Path.GetRandomFileName() + ".csv"; // Act: // Create a .CSV File, and add it to the Yarn project. YarnProjectUtility.WriteStringsFile(destinationStringsFilePath, importer); createdFilePaths.Add(destinationStringsFilePath); AssetDatabase.Refresh(); var stringsAsset = AssetDatabase.LoadAssetAtPath <TextAsset>(destinationStringsFilePath); importer.languagesToSourceAssets.Add(new YarnProjectImporter.LanguageToSourceAsset { languageID = "test", stringsFile = stringsAsset }); EditorUtility.SetDirty(importer); importer.SaveAndReimport(); // Assert: // A new localization, based on the .csv file we just created, // should be present. Assert.IsNotNull(project.baseLocalization); Assert.IsNotEmpty(project.localizations); Assert.AreEqual("test", project.localizations[0].LocaleCode); CollectionAssert.AreEquivalent(project.localizations[0].GetLineIDs(), ExpectedStrings.Select(l => l.ID)); }
public void YarnImporterUtility_CanUpdateLocalizedCSVs_WhenBaseScriptChanges() { // Arrange: // Set up a project with a Yarn file filled with tagged lines. var project = SetUpProject(TestYarnScriptSource); var importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(project)) as YarnProjectImporter; var scriptPath = AssetDatabase.GetAssetPath(importer.sourceScripts[0]); var destinationStringsFilePath = "Assets/" + Path.GetRandomFileName() + ".csv"; // Act: // Create a .CSV File, and add it to the Yarn project. YarnProjectUtility.WriteStringsFile(destinationStringsFilePath, importer); createdFilePaths.Add(destinationStringsFilePath); AssetDatabase.Refresh(); var stringsAsset = AssetDatabase.LoadAssetAtPath <TextAsset>(destinationStringsFilePath); importer.languagesToSourceAssets.Add(new YarnProjectImporter.LanguageToSourceAsset { languageID = "test", stringsFile = stringsAsset }); EditorUtility.SetDirty(importer); importer.SaveAndReimport(); // Capture the strings tables. We'll use them later. var unmodifiedBaseStringsTable = importer.GenerateStringsTable(); var unmodifiedLocalizedStringsTable = StringTableEntry.ParseFromCSV(File.ReadAllText(destinationStringsFilePath)); // Next, modify the original source script. File.WriteAllText(scriptPath, TestYarnScriptSourceModified); AssetDatabase.Refresh(); // Finally, update the CSV. LogAssert.Expect(LogType.Log, $"Updated the following files: {destinationStringsFilePath}"); YarnProjectUtility.UpdateLocalizationCSVs(importer); AssetDatabase.Refresh(); // Doing it again should result in a no-op. LogAssert.Expect(LogType.Log, "No files needed updating."); YarnProjectUtility.UpdateLocalizationCSVs(importer); // Capture the updated strings tables, so we can compare them. var modifiedBaseStringsTable = importer.GenerateStringsTable(); var modifiedLocalizedStringsTable = StringTableEntry.ParseFromCSV(File.ReadAllText(destinationStringsFilePath)); // Assert: verify the base language string table contains the // string table entries we expect, verify the localized string // table contains the string table entries we expect System.Func <StringTableEntry, string> CompareIDs = t => t.ID; System.Func <StringTableEntry, string> CompareLocks = t => t.Lock; var tests = new[] {
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 (string.IsNullOrEmpty(compilationErrorMessageProperty.stringValue) == false) { if (serializedObject.isEditingMultipleObjects) { EditorGUILayout.HelpBox("Some of the selected scripts have errors.", MessageType.Error); } else { EditorGUILayout.HelpBox(compilationErrorMessageProperty.stringValue, MessageType.Error); } } else if (string.IsNullOrEmpty(DestinationProjectError) == false) { EditorGUILayout.HelpBox(DestinationProjectError, MessageType.Error); } if (destinationYarnProject == null) { EditorGUILayout.HelpBox("This script is not currently part of a Yarn Project. Create a new Yarn Project, and add this script to it.", MessageType.Info); if (GUILayout.Button("Create New Yarn Project")) { YarnProjectUtility.CreateYarnProject(target as YarnImporter); UpdateDestinationProgram(); } } else { using (new EditorGUI.DisabledGroupScope(true)) { EditorGUILayout.ObjectField("Program", destinationYarnProject, typeof(YarnProjectImporter), false); } } 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 }