Пример #1
0
        /// <summary>
        /// Creates a new .yarnproject asset in the same directory as the
        /// Yarn script represented by serializedObject, and configures the
        /// script's importer to use the new Yarn Project.
        /// </summary>
        /// <param name="serializedObject">A serialized object that
        /// represents a <see cref="YarnImporter"/>.</param>
        /// <returns>The path to the created asset.</returns>
        internal static string CreateYarnProject(YarnImporter initialSourceAsset)
        {
            // Figure out where on disk this asset is
            var path      = initialSourceAsset.assetPath;
            var directory = Path.GetDirectoryName(path);

            // Figure out a new, unique path for the localization we're
            // creating
            var databaseFileName = $"Project.yarnproject";

            var destinationPath = Path.Combine(directory, databaseFileName);

            destinationPath = AssetDatabase.GenerateUniqueAssetPath(destinationPath);

            // Create the program
            YarnEditorUtility.CreateYarnAsset(destinationPath);

            AssetDatabase.ImportAsset(destinationPath);
            AssetDatabase.SaveAssets();

            var programImporter = AssetImporter.GetAtPath(destinationPath) as YarnProjectImporter;

            programImporter.sourceScripts.Add(AssetDatabase.LoadAssetAtPath <TextAsset>(path));

            EditorUtility.SetDirty(programImporter);

            // Reimport the program to make it generate its default string
            // table, if needed
            programImporter.SaveAndReimport();

            return(destinationPath);
        }
Пример #2
0
        private void ImportCompiledYarn(AssetImportContext ctx)
        {
            var bytes = File.ReadAllBytes(ctx.assetPath);

            try
            {
                // Validate that this can be parsed as a Program protobuf
                var _ = Program.Parser.ParseFrom(bytes);
            }
            catch (Google.Protobuf.InvalidProtocolBufferException)
            {
                ctx.LogImportError("Invalid compiled yarn file. Please re-compile the source code.");
                return;
            }

            isSuccessfullyParsed = true;

            // Create a container for storing the bytes
            var programContainer = new TextAsset("<pre-compiled Yarn script>");

            // Add this container to the imported asset; it will be what
            // the user interacts with in Unity
            ctx.AddObjectToAsset("Program", programContainer, YarnEditorUtility.GetYarnDocumentIconTexture());
            ctx.SetMainObject(programContainer);
        }
Пример #3
0
        private void ImportYarn(AssetImportContext ctx)
        {
            var    sourceText = File.ReadAllText(ctx.assetPath);
            string fileName   = System.IO.Path.GetFileNameWithoutExtension(ctx.assetPath);

            var text = new TextAsset(File.ReadAllText(ctx.assetPath));

            // Add this container to the imported asset; it will be what
            // the user interacts with in Unity
            ctx.AddObjectToAsset("Program", text, YarnEditorUtility.GetYarnDocumentIconTexture());
            ctx.SetMainObject(text);

            Yarn.Program compiledProgram = null;
            IDictionary <string, Yarn.Compiler.StringInfo> stringTable = null;

            parseErrorMessage = null;

            try
            {
                // Compile the source code into a compiled Yarn program (or
                // generate a parse error)
                var compilationJob = CompilationJob.CreateFromString(fileName, sourceText, null);
                compilationJob.CompilationType = CompilationJob.Type.StringsOnly;

                var result = Yarn.Compiler.Compiler.Compile(compilationJob);

                LastImportHadImplicitStringIDs = result.ContainsImplicitStringTags;
                LastImportHadAnyStrings        = result.StringTable.Count > 0;

                stringTable          = result.StringTable;
                compiledProgram      = result.Program;
                isSuccessfullyParsed = true;
                parseErrorMessage    = string.Empty;
            }
            catch (Yarn.Compiler.ParseException e)
            {
                isSuccessfullyParsed = false;
                parseErrorMessage    = e.Message;
                ctx.LogImportError($"Error importing {ctx.assetPath}: {e.Message}");
                return;
            }
        }
        // Sets up a YarnProject, and as many yarn scripts as there are
        // parameters. All files will have random filenames.
        public YarnProject SetUpProject(params string[] yarnScriptText)
        {
            // Disable errors causing failures, in case the yarn script
            // text contains deliberately invalid code
            var wasIgnoringFailingMessages = LogAssert.ignoreFailingMessages;

            LogAssert.ignoreFailingMessages = true;

            string yarnProjectName = Path.GetRandomFileName();
            string yarnProjectPath = $"Assets/{yarnProjectName}.yarnproject";

            createdFilePaths.Add(yarnProjectPath);

            var project             = YarnEditorUtility.CreateYarnProject(yarnProjectPath) as YarnProject;
            var yarnProjectImporter = AssetImporter.GetAtPath(yarnProjectPath) as YarnProjectImporter;

            var pathsToAdd = new List <string>();

            foreach (var scriptText in yarnScriptText)
            {
                string yarnScriptName = Path.GetRandomFileName();
                string yarnScriptPath = $"Assets/{yarnScriptName}.yarn";
                createdFilePaths.Add(yarnScriptPath);
                pathsToAdd.Add(yarnScriptPath);

                string textToWrite;

                if (string.IsNullOrEmpty(scriptText))
                {
                    textToWrite = $"title: {yarnScriptName.Replace(".", "_")}\n---\n===\n";
                }
                else
                {
                    textToWrite = scriptText;
                }

                File.WriteAllText(yarnScriptPath, textToWrite);
            }

            // Import all these files
            AssetDatabase.Refresh();

            foreach (var path in pathsToAdd)
            {
                var textAsset = AssetDatabase.LoadAssetAtPath <TextAsset>(path);

                // We should have a text asset, imported by a YarnImporter
                Assert.IsNotNull(textAsset);
                Assert.IsInstanceOf <YarnImporter>(AssetImporter.GetAtPath(path));

                // Make the yarn project use this script
                yarnProjectImporter.sourceScripts.Add(textAsset);
            }

            // Reimport the project to make it set up the links
            EditorUtility.SetDirty(yarnProjectImporter);
            yarnProjectImporter.SaveAndReimport();

            foreach (var path in pathsToAdd)
            {
                var scriptImporter = AssetImporter.GetAtPath(path) as YarnImporter;

                Assert.AreSame(project, scriptImporter.DestinationProject);
            }

            // As a final check, make sure the project is referencing the
            // right number of scripts
            Assert.AreEqual(yarnScriptText.Length, yarnProjectImporter.sourceScripts.Count);

            LogAssert.ignoreFailingMessages = wasIgnoringFailingMessages;

            return(project);
        }
Пример #5
0
    private void ImportYarn(AssetImportContext ctx)
    {
        var    sourceText = File.ReadAllText(ctx.assetPath);
        string fileName   = System.IO.Path.GetFileNameWithoutExtension(ctx.assetPath);

        try
        {
            // Compile the source code into a compiled Yarn program (or
            // generate a parse error)
            compilationStatus = Compiler.CompileString(sourceText, fileName, out var compiledProgram, out var stringTable);

            // Create a container for storing the bytes
            var programContainer = ScriptableObject.CreateInstance <YarnProgram>();

            using (var memoryStream = new MemoryStream())
                using (var outputStream = new Google.Protobuf.CodedOutputStream(memoryStream))
                {
                    // Serialize the compiled program to memory
                    compiledProgram.WriteTo(outputStream);
                    outputStream.Flush();

                    byte[] compiledBytes = memoryStream.ToArray();

                    programContainer.compiledProgram = compiledBytes;

                    // Add this container to the imported asset; it will be
                    // what the user interacts with in Unity
                    ctx.AddObjectToAsset("Program", programContainer, YarnEditorUtility.GetYarnDocumentIconTexture());
                    ctx.SetMainObject(programContainer);

                    isSuccesfullyCompiled = true;

                    // var outPath = Path.ChangeExtension(ctx.assetPath, ".yarnc");
                    // File.WriteAllBytes(outPath, compiledBytes);
                }

            if (stringTable.Count > 0)
            {
                using (var memoryStream = new MemoryStream())
                    using (var textWriter = new StreamWriter(memoryStream)) {
                        // Generate the localised .csv file

                        // Use the invariant culture when writing the CSV
                        var configuration = new CsvHelper.Configuration.Configuration(
                            System.Globalization.CultureInfo.InvariantCulture
                            );

                        var csv = new CsvHelper.CsvWriter(
                            textWriter,   // write into this stream
                            configuration // use this configuration
                            );

                        var lines = stringTable.Select(x => new {
                            id         = x.Key,
                            text       = x.Value.text,
                            file       = x.Value.fileName,
                            node       = x.Value.nodeName,
                            lineNumber = x.Value.lineNumber
                        });

                        csv.WriteRecords(lines);

                        textWriter.Flush();

                        memoryStream.Position = 0;

                        using (var reader = new StreamReader(memoryStream)) {
                            var textAsset = new TextAsset(reader.ReadToEnd());
                            textAsset.name = $"{fileName} ({baseLanguageID})";

                            ctx.AddObjectToAsset("Strings", textAsset);

                            programContainer.baseLocalisationStringTable = textAsset;
                            baseLanguage = textAsset;
                            programContainer.localizations = localizations;
                        }

                        stringIDs = lines.Select(l => l.id).ToArray();
                    }
            }
        }
        catch (Yarn.Compiler.ParseException e)
        {
            isSuccesfullyCompiled   = false;
            compilationErrorMessage = e.Message;
            var message = FormatError(sourceText, compilationErrorMessage);
            Debug.LogError(message);
            return;
        }
    }
Пример #6
0
 public void YarnEditorUtility_HasValidEditorResources()
 {
     // Test that YarnEditorUtility can locate the editor assets
     Assert.IsNotNull(YarnEditorUtility.GetYarnDocumentIconTexture());
     Assert.IsNotNull(YarnEditorUtility.GetTemplateYarnScriptPath());
 }
Пример #7
0
        private void ImportYarn(AssetImportContext ctx)
        {
            var    sourceText = File.ReadAllText(ctx.assetPath);
            string fileName   = System.IO.Path.GetFileNameWithoutExtension(ctx.assetPath);

            Yarn.Program compiledProgram = null;
            IDictionary <string, Yarn.Compiler.StringInfo> stringTable = null;

            compilationErrorMessage = null;

            try
            {
                // Compile the source code into a compiled Yarn program (or
                // generate a parse error)
                compilationStatus       = Yarn.Compiler.Compiler.CompileString(sourceText, fileName, out compiledProgram, out stringTable);
                isSuccesfullyCompiled   = true;
                compilationErrorMessage = string.Empty;
            }
            catch (Yarn.Compiler.ParseException e)
            {
                isSuccesfullyCompiled   = false;
                compilationErrorMessage = e.Message;
                ctx.LogImportError(e.Message);
            }

            // Create a container for storing the bytes
            if (programContainer == null)
            {
                programContainer = ScriptableObject.CreateInstance <YarnProgram>();
            }

            byte[] compiledBytes = null;

            if (compiledProgram != null)
            {
                using (var memoryStream = new MemoryStream())
                    using (var outputStream = new Google.Protobuf.CodedOutputStream(memoryStream))
                    {
                        // Serialize the compiled program to memory
                        compiledProgram.WriteTo(outputStream);
                        outputStream.Flush();

                        compiledBytes = memoryStream.ToArray();
                    }
            }


            programContainer.compiledProgram = compiledBytes;

            // Add this container to the imported asset; it will be
            // what the user interacts with in Unity
            ctx.AddObjectToAsset("Program", programContainer, YarnEditorUtility.GetYarnDocumentIconTexture());
            ctx.SetMainObject(programContainer);

            if (stringTable?.Count > 0)
            {
                var lines = stringTable.Select(x => new StringTableEntry
                {
                    ID         = x.Key,
                    Language   = baseLanguageID,
                    Text       = x.Value.text,
                    File       = x.Value.fileName,
                    Node       = x.Value.nodeName,
                    LineNumber = x.Value.lineNumber.ToString(),
                    Lock       = GetHashString(x.Value.text, 8),
                }).OrderBy(entry => int.Parse(entry.LineNumber));

                var stringTableCSV = StringTableEntry.CreateCSV(lines);

                var textAsset = new TextAsset(stringTableCSV);
                textAsset.name = $"{fileName} ({baseLanguageID})";

                ctx.AddObjectToAsset("Strings", textAsset);

                programContainer.baseLocalizationId = baseLanguageID;
                baseLanguage = textAsset;
                programContainer.localizations      = localizations.Append(new YarnProgram.YarnTranslation(baseLanguageID, textAsset)).ToArray();
                programContainer.baseLocalizationId = baseLanguageID;

                stringIDs = lines.Select(l => l.ID).ToArray();
            }
        }