From 5f5427e046b1fe214cdf532f8bc3d3f70cf1ef13 Mon Sep 17 00:00:00 2001 From: dogboydog Date: Sat, 2 Dec 2023 00:04:55 -0500 Subject: [PATCH] export samples in CI. call yarn project compilation synchronously in more locations --- .github/workflows/continuous_build_check.yaml | 50 +++- .../Palette-dialogue.yarn.import | 2 +- .../MarkupPalette/Palette.yarnproject.import | 2 +- .../PauseDialogue.yarn.import | 2 +- .../PauseProj.yarnproject.import | 2 +- .../RoundedViews/Rounded.yarnproject.import | 2 +- .../RoundedViews/RoundedDialogue.yarn.import | 2 +- .../Editor/YarnProjectEditorUtility.cs | 257 +++++++++--------- .../Editor/YarnProjectImporter.cs | 7 - .../Editor/YarnProjectInspectorPlugin.cs | 3 +- 10 files changed, 174 insertions(+), 155 deletions(-) diff --git a/.github/workflows/continuous_build_check.yaml b/.github/workflows/continuous_build_check.yaml index ba84379..3056d33 100644 --- a/.github/workflows/continuous_build_check.yaml +++ b/.github/workflows/continuous_build_check.yaml @@ -9,7 +9,9 @@ on: - '**/*.md' - 'docs/**' env: - GODOT_CLI: ./godot/godot.x86_64 + DOTNET_CLI_TELEMETRY_OPTOUT: true + DOTNET_NOLOGO: true + defaults: run: shell: bash @@ -20,7 +22,7 @@ jobs: strategy: fail-fast: false matrix: - godotDownload: ["https://downloads.tuxfamily.org/godotengine/4.1.3/mono/Godot_v4.1.3-stable_mono_linux_x86_64.zip", "https://downloads.tuxfamily.org/godotengine/4.2/mono/Godot_v4.2-stable_mono_linux_x86_64.zip"] + godotVersion: ["4.1.3", "4.2.0"] targetFramework: ["net6.0", "net7.0"] name: Build runs-on: ubuntu-latest @@ -36,20 +38,42 @@ jobs: - name: Set Target Framework ${{ matrix.targetFramework }} run: | sed -i 's|.*<|'${{ matrix.targetFramework }}'<|g' YarnSpinner-Godot.csproj - - - name: Download Godot - id: downloadGodot + + - uses: chickensoft-games/setup-godot@v1 + name: 🤖 Setup Godot + with: + version: ${{ matrix.godotVersion}} + # Use .NET-enabled version of Godot (the default is also true). + use-dotnet: true + + - name: 🔬 Verify Setup run: | - wget -O godot.zip ${{ matrix.godotDownload }} - unzip godot.zip - mv ./Godot_v4* ./godot - touch ./godot/.gdignore - mv ./godot/*.x86_64 $GODOT_CLI + dotnet --version + godot --version - name: Build solution id: buildSolution run: | - $GODOT_CLI --headless --path . --verbose -q -e --build-solutions --quit - # sometimes --build-solutions still exits with code 0, so double check + godot --headless --path . --verbose -e --build-solutions --quit dotnet build - timeout-minutes: 2 \ No newline at end of file + timeout-minutes: 2 + + - name: Export samples + id: exportSamples + run: | + + exportPath=./build/linux64_debug/YarnSpinner-GodotSamples.x86_64 + mkdir -p "$(dirname $exportPath)" + godot --headless --path . --verbose --export-debug linux_x86_64 "$exportPath" --quit + if ! test -f "$exportPath"; then + echo "::error::Failed to export the debug samples to $exportPath" + exit 1 + fi + exportPath=./build/linux64/YarnSpinner-GodotSamples.x86_64 + mkdir -p "$(dirname $exportPath)" + godot --headless --path . --verbose --export-release linux_x86_64 "$exportPath" --quit + if ! test -f "$exportPath"; then + echo "::error::Failed to export the release samples to $exportPath" + exit 1 + fi + timeout-minutes: 6 \ No newline at end of file diff --git a/Samples/MarkupPalette/Palette-dialogue.yarn.import b/Samples/MarkupPalette/Palette-dialogue.yarn.import index 2d24d4f..697e191 100644 --- a/Samples/MarkupPalette/Palette-dialogue.yarn.import +++ b/Samples/MarkupPalette/Palette-dialogue.yarn.import @@ -2,7 +2,7 @@ importer="yarnscript" type="Resource" -uid="uid://dwascvkaa7nmf" +uid="uid://cxb41xoif5iib" path="res://.godot/imported/Palette-dialogue.yarn-caa39b62f3fe47a6c11e168523b4ecdb.tres" [deps] diff --git a/Samples/MarkupPalette/Palette.yarnproject.import b/Samples/MarkupPalette/Palette.yarnproject.import index c5be9b6..0ae4f33 100644 --- a/Samples/MarkupPalette/Palette.yarnproject.import +++ b/Samples/MarkupPalette/Palette.yarnproject.import @@ -2,7 +2,7 @@ importer="yarnproject" type="Resource" -uid="uid://b1abkyu12dnfd" +uid="uid://rr8xlqj5fkjd" path="res://.godot/imported/Palette.yarnproject-2c1612daef56a2c0f2be9d1a92c0c8b9.tres" [deps] diff --git a/Samples/PausingTypewriter/PauseDialogue.yarn.import b/Samples/PausingTypewriter/PauseDialogue.yarn.import index bc25f22..4578746 100644 --- a/Samples/PausingTypewriter/PauseDialogue.yarn.import +++ b/Samples/PausingTypewriter/PauseDialogue.yarn.import @@ -2,7 +2,7 @@ importer="yarnscript" type="Resource" -uid="uid://dgw4ojltf2hn6" +uid="uid://hjgqmuramr6p" path="res://.godot/imported/PauseDialogue.yarn-926959666337d027238a2c8dd345367d.tres" [deps] diff --git a/Samples/PausingTypewriter/PauseProj.yarnproject.import b/Samples/PausingTypewriter/PauseProj.yarnproject.import index 9e5da90..af56e54 100644 --- a/Samples/PausingTypewriter/PauseProj.yarnproject.import +++ b/Samples/PausingTypewriter/PauseProj.yarnproject.import @@ -2,7 +2,7 @@ importer="yarnproject" type="Resource" -uid="uid://833nti2rn1c0" +uid="uid://21gon4fidoq8" path="res://.godot/imported/PauseProj.yarnproject-744c25107925e6d1f7a2789f0626afa3.tres" [deps] diff --git a/Samples/RoundedViews/Rounded.yarnproject.import b/Samples/RoundedViews/Rounded.yarnproject.import index ce89ff0..a0c4d74 100644 --- a/Samples/RoundedViews/Rounded.yarnproject.import +++ b/Samples/RoundedViews/Rounded.yarnproject.import @@ -2,7 +2,7 @@ importer="yarnproject" type="Resource" -uid="uid://60ierya2lso6" +uid="uid://i6tlrqbg4dbf" path="res://.godot/imported/Rounded.yarnproject-f4f7cd79583437b6fbb15d97bcf58422.tres" [deps] diff --git a/Samples/RoundedViews/RoundedDialogue.yarn.import b/Samples/RoundedViews/RoundedDialogue.yarn.import index d6f99ee..6755d61 100644 --- a/Samples/RoundedViews/RoundedDialogue.yarn.import +++ b/Samples/RoundedViews/RoundedDialogue.yarn.import @@ -2,7 +2,7 @@ importer="yarnscript" type="Resource" -uid="uid://7ukn607q8q87" +uid="uid://4k86j6pstse4" path="res://.godot/imported/RoundedDialogue.yarn-782e62627649fc50f7a31dbc32e16966.tres" [deps] diff --git a/addons/YarnSpinner-Godot/Editor/YarnProjectEditorUtility.cs b/addons/YarnSpinner-Godot/Editor/YarnProjectEditorUtility.cs index 99a3d67..7119dee 100644 --- a/addons/YarnSpinner-Godot/Editor/YarnProjectEditorUtility.cs +++ b/addons/YarnSpinner-Godot/Editor/YarnProjectEditorUtility.cs @@ -82,23 +82,32 @@ private static IEnumerable FindAllYarnProjects() private static object _lastUpdateLock = new object(); /// - /// Re-compile scripts in a yarn project, add all associated data to the project, - /// and save it back to disk in the same .tres file. + /// Queue up a re-compile of scripts in a yarn project, add all associated data to the project, + /// and save it back to disk in the same .tres file. This will wait for + /// before updating the project, resetting the timeout each time it is called for a given YarnProject. + /// Call this method when you want to avoid repeated updates of the same project. /// - /// + /// The yarn project to re-compile scripts for public static void UpdateYarnProject(YarnProject project) { - if (project == null) return; - if (string.IsNullOrEmpty(project.ResourcePath)) return; + if (project == null) + { + return; + } + + ; + if (string.IsNullOrEmpty(project.ResourcePath)) + { + return; + } + lock (_lastUpdateLock) { _projectPathToLastUpdateTime[project.ResourcePath] = DateTime.Now; - if (_projectPathToUpdateTask.ContainsKey(project.ResourcePath)) + if (!_projectPathToUpdateTask.ContainsKey(project.ResourcePath)) { - return; + _projectPathToUpdateTask[project.ResourcePath] = UpdateYarnProjectTask(project); } - - _projectPathToUpdateTask[project.ResourcePath] = UpdateYarnProjectTask(project); } } @@ -122,54 +131,43 @@ TimeSpan getTimeDiff() { CompileAllScripts(project); SaveYarnProject(project); - lock (_lastUpdateLock) - { - _projectPathToUpdateTask.Remove(project.ResourcePath); - } } catch (Exception e) + { + GD.PushError( + $"Error updating {nameof(YarnProject)} '{project.ResourcePath}': {e.Message}{e.StackTrace}"); + } + finally { lock (_lastUpdateLock) { _projectPathToUpdateTask.Remove(project.ResourcePath); } - - GD.PushError( - $"Error updating {nameof(YarnProject)} '{project.ResourcePath}': {e.Message}{e.StackTrace}"); } } - public static void WriteBaseLanguageStringsCSV(YarnProject project, string path) { UpdateLocalizationFile(project.baseLocalization.GetStringTableEntries(), project.JSONProject.BaseLanguage, path); } - public static async void UpdateLocalizationCSVs(YarnProject project) + + public static void UpdateLocalizationCSVs(YarnProject project) { if (project.JSONProject.Localisation.Count > 0) { var modifiedFiles = new List(); if (project.baseLocalization == null) { - // build the base language string table if we went straight into the localization - // update without compiling. - if (!_projectPathToUpdateTask.ContainsKey(project.ResourcePath)) - { - UpdateYarnProject(project); - } - - if (_projectPathToUpdateTask.TryGetValue(project.ResourcePath, out var updateTask)) - { - await updateTask; - } + CompileAllScripts(project); } foreach (var loc in project.JSONProject.Localisation) { if (string.IsNullOrEmpty(loc.Value.Strings)) { - GD.PrintErr($"Can't update localization for {loc.Key} because it doesn't have a Strings file."); + GD.PrintErr( + $"Can't update localization for {loc.Key} because it doesn't have a Strings file."); continue; } @@ -399,126 +397,129 @@ public static void SaveYarnProject(YarnProject project) public static void CompileAllScripts(YarnProject project) { - List newFunctionList = new List(); - var assetPath = project.ResourcePath; - GD.Print($"Compiling all scripts in {assetPath}"); - - project.ResourceName = Path.GetFileNameWithoutExtension(assetPath); - var sourceScripts = project.JSONProject.SourceFiles.ToList(); - if (!sourceScripts.Any()) + lock (project) { - GD.Print( - $"No .yarn files found matching the {nameof(project.JSONProject.SourceFilePatterns)} in {project.JSONProjectPath}"); - return; - } + List newFunctionList = new List(); + var assetPath = project.ResourcePath; + GD.Print($"Compiling all scripts in {assetPath}"); - var library = new Library(); + project.ResourceName = Path.GetFileNameWithoutExtension(assetPath); + var sourceScripts = project.JSONProject.SourceFiles.ToList(); + if (!sourceScripts.Any()) + { + GD.Print( + $"No .yarn files found matching the {nameof(project.JSONProject.SourceFilePatterns)} in {project.JSONProjectPath}"); + return; + } - IEnumerable errors; - project.ProjectErrors = Array.Empty(); + var library = new Library(); - // We now now compile! - var scriptAbsolutePaths = sourceScripts.ToList().Where(s => s != null) - .Select(ProjectSettings.GlobalizePath).ToList(); - // Store the compiled program - byte[] compiledBytes = null; - CompilationResult? compilationResult = new CompilationResult?(); - if (scriptAbsolutePaths.Count > 0) - { - var job = CompilationJob.CreateFromFiles(scriptAbsolutePaths); - // job.VariableDeclarations = localDeclarations; - job.CompilationType = CompilationJob.Type.FullCompilation; - job.Library = library; - compilationResult = Yarn.Compiler.Compiler.Compile(job); - - errors = compilationResult.Value.Diagnostics.Where(d => - d.Severity == Diagnostic.DiagnosticSeverity.Error); - - if (errors.Count() > 0) + IEnumerable errors; + project.ProjectErrors = Array.Empty(); + + // We now now compile! + var scriptAbsolutePaths = sourceScripts.ToList().Where(s => s != null) + .Select(ProjectSettings.GlobalizePath).ToList(); + // Store the compiled program + byte[] compiledBytes = null; + CompilationResult? compilationResult = new CompilationResult?(); + if (scriptAbsolutePaths.Count > 0) { - var errorGroups = errors.GroupBy(e => e.FileName); - foreach (var errorGroup in errorGroups) - { - var errorMessages = errorGroup.Select(e => e.ToString()); + var job = CompilationJob.CreateFromFiles(scriptAbsolutePaths); + // job.VariableDeclarations = localDeclarations; + job.CompilationType = CompilationJob.Type.FullCompilation; + job.Library = library; + compilationResult = Yarn.Compiler.Compiler.Compile(job); + + errors = compilationResult.Value.Diagnostics.Where(d => + d.Severity == Diagnostic.DiagnosticSeverity.Error); - foreach (var message in errorMessages) + if (errors.Count() > 0) + { + var errorGroups = errors.GroupBy(e => e.FileName); + foreach (var errorGroup in errorGroups) { - GD.PushError($"Error compiling: {message}"); + var errorMessages = errorGroup.Select(e => e.ToString()); + + foreach (var message in errorMessages) + { + GD.PushError($"Error compiling: {message}"); + } } - } - var projectErrors = errors.ToList().ConvertAll(e => - new YarnProjectError - { - Context = e.Context, - Message = e.Message, - FileName = ProjectSettings.LocalizePath(e.FileName) - }); - project.ProjectErrors = projectErrors.ToArray(); - return; - } + var projectErrors = errors.ToList().ConvertAll(e => + new YarnProjectError + { + Context = e.Context, + Message = e.Message, + FileName = ProjectSettings.LocalizePath(e.FileName) + }); + project.ProjectErrors = projectErrors.ToArray(); + return; + } - if (compilationResult.Value.Program == null) - { - GD.PushError( - "public error: Failed to compile: resulting program was null, but compiler did not report errors."); - return; - } + if (compilationResult.Value.Program == null) + { + GD.PushError( + "public error: Failed to compile: resulting program was null, but compiler did not report errors."); + return; + } - // Store _all_ declarations - both the ones in this - // .yarnproject file, and the ones inside the .yarn files. + // Store _all_ declarations - both the ones in this + // .yarnproject file, and the ones inside the .yarn files. - // While we're here, filter out any declarations that begin with our - // Yarn public prefix. These are synthesized variables that are - // generated as a result of the compilation, and are not declared by - // the user. + // While we're here, filter out any declarations that begin with our + // Yarn public prefix. These are synthesized variables that are + // generated as a result of the compilation, and are not declared by + // the user. - var newDeclarations = new List() //localDeclarations - .Concat(compilationResult.Value.Declarations) - .Where(decl => !decl.Name.StartsWith("$Yarn.Internal.")) - .Where(decl => !(decl.Type is FunctionType)) - .Select(decl => - { - SerializedDeclaration existingDeclaration = null; - // try to re-use a declaration if one exists to avoid changing the .tres file so much - foreach (var existing in project.SerializedDeclarations) + var newDeclarations = new List() //localDeclarations + .Concat(compilationResult.Value.Declarations) + .Where(decl => !decl.Name.StartsWith("$Yarn.Internal.")) + .Where(decl => !(decl.Type is FunctionType)) + .Select(decl => { - if (existing.name == decl.Name) + SerializedDeclaration existingDeclaration = null; + // try to re-use a declaration if one exists to avoid changing the .tres file so much + foreach (var existing in project.SerializedDeclarations) { - existingDeclaration = existing; - break; + if (existing.name == decl.Name) + { + existingDeclaration = existing; + break; + } } - } - var serialized = existingDeclaration ?? new SerializedDeclaration(); - serialized.SetDeclaration(decl); - return serialized; - }).ToArray(); - project.SerializedDeclarations = newDeclarations; - // Clear error messages from all scripts - they've all passed - // compilation - project.ProjectErrors = Array.Empty(); + var serialized = existingDeclaration ?? new SerializedDeclaration(); + serialized.SetDeclaration(decl); + return serialized; + }).ToArray(); + project.SerializedDeclarations = newDeclarations; + // Clear error messages from all scripts - they've all passed + // compilation + project.ProjectErrors = Array.Empty(); - CreateYarnInternalLocalizationAssets(project, compilationResult.Value); + CreateYarnInternalLocalizationAssets(project, compilationResult.Value); - using (var memoryStream = new MemoryStream()) - using (var outputStream = new CodedOutputStream(memoryStream)) - { - // Serialize the compiled program to memory - compilationResult.Value.Program.WriteTo(outputStream); - outputStream.Flush(); + using (var memoryStream = new MemoryStream()) + using (var outputStream = new CodedOutputStream(memoryStream)) + { + // Serialize the compiled program to memory + compilationResult.Value.Program.WriteTo(outputStream); + outputStream.Flush(); - compiledBytes = memoryStream.ToArray(); + compiledBytes = memoryStream.ToArray(); + } } - } - project.ListOfFunctions = newFunctionList.ToArray(); - project.CompiledYarnProgramBase64 = compiledBytes == null ? "" : Convert.ToBase64String(compiledBytes); - var saveErr = ResourceSaver.Save(project, project.ImportPath, - ResourceSaver.SaverFlags.ReplaceSubresourcePaths); - if (saveErr != Error.Ok) - { - GD.PushError($"Failed to save updated {nameof(YarnProject)}: {saveErr}"); + project.ListOfFunctions = newFunctionList.ToArray(); + project.CompiledYarnProgramBase64 = compiledBytes == null ? "" : Convert.ToBase64String(compiledBytes); + var saveErr = ResourceSaver.Save(project, project.ImportPath, + ResourceSaver.SaverFlags.ReplaceSubresourcePaths); + if (saveErr != Error.Ok) + { + GD.PushError($"Failed to save updated {nameof(YarnProject)}: {saveErr}"); + } } } diff --git a/addons/YarnSpinner-Godot/Editor/YarnProjectImporter.cs b/addons/YarnSpinner-Godot/Editor/YarnProjectImporter.cs index 422e03d..7619e04 100644 --- a/addons/YarnSpinner-Godot/Editor/YarnProjectImporter.cs +++ b/addons/YarnSpinner-Godot/Editor/YarnProjectImporter.cs @@ -86,13 +86,6 @@ public override Error _Import( } YarnProjectEditorUtility.UpdateYarnProject(godotProject); - YarnProjectEditorUtility.UpdateLocalizationCSVs(godotProject); - saveErr = ResourceSaver.Save(godotProject, godotProject.ImportPath); - if (saveErr != Error.Ok) - { - GD.PrintErr($"Error saving .yarnproject file import: {saveErr.ToString()}"); - } - return (int) Error.Ok; } } diff --git a/addons/YarnSpinner-Godot/Editor/YarnProjectInspectorPlugin.cs b/addons/YarnSpinner-Godot/Editor/YarnProjectInspectorPlugin.cs index 675db2b..7ff308c 100644 --- a/addons/YarnSpinner-Godot/Editor/YarnProjectInspectorPlugin.cs +++ b/addons/YarnSpinner-Godot/Editor/YarnProjectInspectorPlugin.cs @@ -419,7 +419,8 @@ private void OnUpdateLocalizationsClicked() private void OnRecompileClicked(YarnProject project) { - YarnProjectEditorUtility.UpdateYarnProject(project); + YarnProjectEditorUtility.CompileAllScripts(project); + YarnProjectEditorUtility.SaveYarnProject(project); _compileErrorsPropertyEditor.Refresh(); project.NotifyPropertyListChanged(); }