summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/csg/doc_classes/CSGBox.xml2
-rw-r--r--modules/csg/doc_classes/CSGCylinder.xml2
-rw-r--r--modules/csg/doc_classes/CSGMesh.xml4
-rw-r--r--modules/csg/doc_classes/CSGPolygon.xml2
-rw-r--r--modules/csg/doc_classes/CSGSphere.xml2
-rw-r--r--modules/csg/doc_classes/CSGTorus.xml2
-rw-r--r--modules/gdnative/doc_classes/GDNative.xml2
-rw-r--r--modules/gdnative/doc_classes/NativeScript.xml2
-rw-r--r--modules/gdscript/gdscript_editor.cpp4
-rw-r--r--modules/gdscript/gdscript_parser.cpp21
-rw-r--r--modules/gridmap/doc_classes/GridMap.xml2
-rw-r--r--modules/mono/csharp_script.cpp21
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/CSharpProject.cs4
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/GodotSharpBuilds.cs131
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs110
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj1
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/HotReloadAssemblyWatcher.cs3
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Internals/Globals.cs33
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs34
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/MonoBottomPanel.cs13
-rw-r--r--modules/mono/editor/editor_internal_calls.cpp44
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp504
-rw-r--r--modules/mono/mono_gd/gd_mono.h15
-rw-r--r--modules/opensimplex/doc_classes/NoiseTexture.xml2
-rw-r--r--modules/regex/doc_classes/RegExMatch.xml4
-rw-r--r--modules/visual_script/doc_classes/VisualScriptPreload.xml2
26 files changed, 362 insertions, 604 deletions
diff --git a/modules/csg/doc_classes/CSGBox.xml b/modules/csg/doc_classes/CSGBox.xml
index d100c01205..14f5a1952e 100644
--- a/modules/csg/doc_classes/CSGBox.xml
+++ b/modules/csg/doc_classes/CSGBox.xml
@@ -17,7 +17,7 @@
<member name="height" type="float" setter="set_height" getter="get_height" default="2.0">
Height of the box measured from the center of the box.
</member>
- <member name="material" type="Material" setter="set_material" getter="get_material" default="null">
+ <member name="material" type="Material" setter="set_material" getter="get_material">
The material used to render the box.
</member>
<member name="width" type="float" setter="set_width" getter="get_width" default="2.0">
diff --git a/modules/csg/doc_classes/CSGCylinder.xml b/modules/csg/doc_classes/CSGCylinder.xml
index 643eb7c7f4..9fc0281887 100644
--- a/modules/csg/doc_classes/CSGCylinder.xml
+++ b/modules/csg/doc_classes/CSGCylinder.xml
@@ -17,7 +17,7 @@
<member name="height" type="float" setter="set_height" getter="get_height" default="1.0">
The height of the cylinder.
</member>
- <member name="material" type="Material" setter="set_material" getter="get_material" default="null">
+ <member name="material" type="Material" setter="set_material" getter="get_material">
The material used to render the cylinder.
</member>
<member name="radius" type="float" setter="set_radius" getter="get_radius" default="1.0">
diff --git a/modules/csg/doc_classes/CSGMesh.xml b/modules/csg/doc_classes/CSGMesh.xml
index daa08decb6..afe0bc262d 100644
--- a/modules/csg/doc_classes/CSGMesh.xml
+++ b/modules/csg/doc_classes/CSGMesh.xml
@@ -11,9 +11,9 @@
<methods>
</methods>
<members>
- <member name="material" type="Material" setter="set_material" getter="get_material" default="null">
+ <member name="material" type="Material" setter="set_material" getter="get_material">
</member>
- <member name="mesh" type="Mesh" setter="set_mesh" getter="get_mesh" default="null">
+ <member name="mesh" type="Mesh" setter="set_mesh" getter="get_mesh">
The mesh resource to use as a CSG shape.
</member>
</members>
diff --git a/modules/csg/doc_classes/CSGPolygon.xml b/modules/csg/doc_classes/CSGPolygon.xml
index 48f5d730cc..0ecee92cd5 100644
--- a/modules/csg/doc_classes/CSGPolygon.xml
+++ b/modules/csg/doc_classes/CSGPolygon.xml
@@ -14,7 +14,7 @@
<member name="depth" type="float" setter="set_depth" getter="get_depth" default="1.0">
Extrusion depth when [member mode] is [constant MODE_DEPTH].
</member>
- <member name="material" type="Material" setter="set_material" getter="get_material" default="null">
+ <member name="material" type="Material" setter="set_material" getter="get_material">
Material to use for the resulting mesh.
</member>
<member name="mode" type="int" setter="set_mode" getter="get_mode" enum="CSGPolygon.Mode" default="0">
diff --git a/modules/csg/doc_classes/CSGSphere.xml b/modules/csg/doc_classes/CSGSphere.xml
index 0a62644179..714e725acb 100644
--- a/modules/csg/doc_classes/CSGSphere.xml
+++ b/modules/csg/doc_classes/CSGSphere.xml
@@ -11,7 +11,7 @@
<methods>
</methods>
<members>
- <member name="material" type="Material" setter="set_material" getter="get_material" default="null">
+ <member name="material" type="Material" setter="set_material" getter="get_material">
The material used to render the sphere.
</member>
<member name="radial_segments" type="int" setter="set_radial_segments" getter="get_radial_segments" default="12">
diff --git a/modules/csg/doc_classes/CSGTorus.xml b/modules/csg/doc_classes/CSGTorus.xml
index 156fb185e7..5dc6bb8380 100644
--- a/modules/csg/doc_classes/CSGTorus.xml
+++ b/modules/csg/doc_classes/CSGTorus.xml
@@ -14,7 +14,7 @@
<member name="inner_radius" type="float" setter="set_inner_radius" getter="get_inner_radius" default="2.0">
The inner radius of the torus.
</member>
- <member name="material" type="Material" setter="set_material" getter="get_material" default="null">
+ <member name="material" type="Material" setter="set_material" getter="get_material">
The material used to render the torus.
</member>
<member name="outer_radius" type="float" setter="set_outer_radius" getter="get_outer_radius" default="3.0">
diff --git a/modules/gdnative/doc_classes/GDNative.xml b/modules/gdnative/doc_classes/GDNative.xml
index 95ed1fc048..8750ddc56d 100644
--- a/modules/gdnative/doc_classes/GDNative.xml
+++ b/modules/gdnative/doc_classes/GDNative.xml
@@ -33,7 +33,7 @@
</method>
</methods>
<members>
- <member name="library" type="GDNativeLibrary" setter="set_library" getter="get_library" default="null">
+ <member name="library" type="GDNativeLibrary" setter="set_library" getter="get_library">
</member>
</members>
<constants>
diff --git a/modules/gdnative/doc_classes/NativeScript.xml b/modules/gdnative/doc_classes/NativeScript.xml
index 460471386d..e34e209374 100644
--- a/modules/gdnative/doc_classes/NativeScript.xml
+++ b/modules/gdnative/doc_classes/NativeScript.xml
@@ -53,7 +53,7 @@
<members>
<member name="class_name" type="String" setter="set_class_name" getter="get_class_name" default="&quot;&quot;">
</member>
- <member name="library" type="GDNativeLibrary" setter="set_library" getter="get_library" default="null">
+ <member name="library" type="GDNativeLibrary" setter="set_library" getter="get_library">
</member>
<member name="script_class_icon_path" type="String" setter="set_script_class_icon_path" getter="get_script_class_icon_path" default="&quot;&quot;">
</member>
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index 78a1bfc99b..c4937f023b 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -161,6 +161,10 @@ bool GDScriptLanguage::validate(const String &p_script, int &r_line_error, int &
funcs[cl->subclasses[i]->functions[j]->line] = String(cl->subclasses[i]->name) + "." + String(cl->subclasses[i]->functions[j]->name);
}
+ for (int j = 0; j < cl->subclasses[i]->static_functions.size(); j++) {
+
+ funcs[cl->subclasses[i]->static_functions[j]->line] = String(cl->subclasses[i]->name) + "." + String(cl->subclasses[i]->static_functions[j]->name);
+ }
}
for (Map<int, String>::Element *E = funcs.front(); E; E = E->next()) {
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index 80da606967..fa430b5364 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -2211,6 +2211,8 @@ void GDScriptParser::_parse_pattern_block(BlockNode *p_block, Vector<PatternBran
p_block->has_return = true;
+ bool catch_all_appeared = false;
+
while (true) {
while (tokenizer->get_token() == GDScriptTokenizer::TK_NEWLINE && _parse_newline())
@@ -2221,7 +2223,7 @@ void GDScriptParser::_parse_pattern_block(BlockNode *p_block, Vector<PatternBran
return;
if (indent_level > tab_level.back()->get()) {
- return; // go back a level
+ break; // go back a level
}
if (pending_newline != -1) {
@@ -2236,12 +2238,20 @@ void GDScriptParser::_parse_pattern_block(BlockNode *p_block, Vector<PatternBran
branch->patterns.push_back(_parse_pattern(p_static));
if (!branch->patterns[0]) {
- return;
+ break;
}
bool has_binding = branch->patterns[0]->pt_type == PatternNode::PT_BIND;
bool catch_all = has_binding || branch->patterns[0]->pt_type == PatternNode::PT_WILDCARD;
+#ifdef DEBUG_ENABLED
+ // Branches after a wildcard or binding are unreachable
+ if (catch_all_appeared && !current_function->has_unreachable_code) {
+ _add_warning(GDScriptWarning::UNREACHABLE_CODE, -1, current_function->name.operator String());
+ current_function->has_unreachable_code = true;
+ }
+#endif
+
while (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
tokenizer->advance();
branch->patterns.push_back(_parse_pattern(p_static));
@@ -2259,6 +2269,8 @@ void GDScriptParser::_parse_pattern_block(BlockNode *p_block, Vector<PatternBran
catch_all = catch_all || pt == PatternNode::PT_WILDCARD;
}
+ catch_all_appeared = catch_all_appeared || catch_all;
+
if (!_enter_indent_block()) {
_set_error("Expected block in pattern branch");
return;
@@ -2274,6 +2286,11 @@ void GDScriptParser::_parse_pattern_block(BlockNode *p_block, Vector<PatternBran
p_branches.push_back(branch);
}
+
+ // Even if all branches return, there is possibility of default fallthrough
+ if (!catch_all_appeared) {
+ p_block->has_return = false;
+ }
}
void GDScriptParser::_generate_pattern(PatternNode *p_pattern, Node *p_node_to_match, Node *&p_resulting_node, Map<StringName, Node *> &p_bindings) {
diff --git a/modules/gridmap/doc_classes/GridMap.xml b/modules/gridmap/doc_classes/GridMap.xml
index 325432579f..1bd3d72066 100644
--- a/modules/gridmap/doc_classes/GridMap.xml
+++ b/modules/gridmap/doc_classes/GridMap.xml
@@ -210,7 +210,7 @@
</member>
<member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="1">
</member>
- <member name="mesh_library" type="MeshLibrary" setter="set_mesh_library" getter="get_mesh_library" default="null">
+ <member name="mesh_library" type="MeshLibrary" setter="set_mesh_library" getter="get_mesh_library">
The assigned [MeshLibrary].
</member>
<member name="theme" type="MeshLibrary" setter="set_theme" getter="get_theme">
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 1add697997..078a490b22 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -114,15 +114,20 @@ void CSharpLanguage::init() {
gdmono = memnew(GDMono);
gdmono->initialize();
-#ifndef MONO_GLUE_ENABLED
- WARN_PRINT("This binary is built with `mono_glue=no` and cannot be used for scripting");
-#endif
-
#if defined(TOOLS_ENABLED) && defined(DEBUG_METHODS_ENABLED)
+ // Generate bindings here, before loading assemblies. `initialize_load_assemblies` aborts
+ // the applications if the api assemblies or the main tools assembly is missing, but this
+ // is not a problem for BindingsGenerator as it only needs the tools project editor assembly.
List<String> cmdline_args = OS::get_singleton()->get_cmdline_args();
BindingsGenerator::handle_cmdline_args(cmdline_args);
#endif
+#ifndef MONO_GLUE_ENABLED
+ print_line("Run this binary with `--generate-mono-glue path/to/modules/mono/glue`");
+#endif
+
+ gdmono->initialize_load_assemblies();
+
#ifdef TOOLS_ENABLED
EditorNode::add_init_callback(&_editor_init_callback);
@@ -710,14 +715,6 @@ bool CSharpLanguage::is_assembly_reloading_needed() {
return false; // No assembly to load
}
-#ifdef TOOLS_ENABLED
- if (!gdmono->get_core_api_assembly() && gdmono->metadata_is_api_assembly_invalidated(APIAssembly::API_CORE))
- return false; // The core API assembly to load is invalidated
-
- if (!gdmono->get_editor_api_assembly() && gdmono->metadata_is_api_assembly_invalidated(APIAssembly::API_EDITOR))
- return false; // The editor API assembly to load is invalidated
-#endif
-
return true;
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/CSharpProject.cs b/modules/mono/editor/GodotTools/GodotTools/CSharpProject.cs
index e216d30462..4535ed7247 100644
--- a/modules/mono/editor/GodotTools/GodotTools/CSharpProject.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/CSharpProject.cs
@@ -1,9 +1,9 @@
using Godot;
using System;
-using System.Collections.Generic;
using Godot.Collections;
using GodotTools.Internals;
using GodotTools.ProjectEditor;
+using static GodotTools.Internals.Globals;
using File = GodotTools.Utils.File;
using Directory = GodotTools.Utils.Directory;
@@ -26,7 +26,7 @@ namespace GodotTools
public static void AddItem(string projectPath, string itemType, string include)
{
- if (!(bool) Internal.GlobalDef("mono/project/auto_update_project", true))
+ if (!(bool) GlobalDef("mono/project/auto_update_project", true))
return;
ProjectUtils.AddItemToProjectChecked(projectPath, itemType, include);
diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpBuilds.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpBuilds.cs
index 433a931941..a884b0ead0 100644
--- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpBuilds.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpBuilds.cs
@@ -5,6 +5,7 @@ using System.Threading.Tasks;
using GodotTools.Build;
using GodotTools.Internals;
using GodotTools.Utils;
+using static GodotTools.Internals.Globals;
using Error = Godot.Error;
using File = GodotTools.Utils.File;
using Directory = GodotTools.Utils.Directory;
@@ -192,134 +193,14 @@ namespace GodotTools
return false;
}
- private static bool CopyApiAssembly(string srcDir, string dstDir, string assemblyName, ApiAssemblyType apiType)
- {
- // Create destination directory if needed
- if (!Directory.Exists(dstDir))
- {
- try
- {
- Directory.CreateDirectory(dstDir);
- }
- catch (IOException e)
- {
- ShowBuildErrorDialog($"Failed to create destination directory for the API assemblies. Exception message: {e.Message}");
- return false;
- }
- }
-
- string assemblyFile = assemblyName + ".dll";
- string assemblySrc = Path.Combine(srcDir, assemblyFile);
- string assemblyDst = Path.Combine(dstDir, assemblyFile);
-
- if (!File.Exists(assemblyDst) || File.GetLastWriteTime(assemblySrc) > File.GetLastWriteTime(assemblyDst) ||
- Internal.MetadataIsApiAssemblyInvalidated(apiType))
- {
- string xmlFile = $"{assemblyName}.xml";
- string pdbFile = $"{assemblyName}.pdb";
-
- try
- {
- File.Copy(Path.Combine(srcDir, xmlFile), Path.Combine(dstDir, xmlFile));
- }
- catch (IOException e)
- {
- Godot.GD.PushWarning(e.ToString());
- }
-
- try
- {
- File.Copy(Path.Combine(srcDir, pdbFile), Path.Combine(dstDir, pdbFile));
- }
- catch (IOException e)
- {
- Godot.GD.PushWarning(e.ToString());
- }
-
- try
- {
- File.Copy(assemblySrc, assemblyDst);
- }
- catch (IOException e)
- {
- ShowBuildErrorDialog($"Failed to copy {assemblyFile}. Exception message: {e.Message}");
- return false;
- }
-
- Internal.MetadataSetApiAssemblyInvalidated(apiType, false);
- }
-
- return true;
- }
-
- public static bool MakeApiAssembly(ApiAssemblyType apiType, string config)
- {
- string apiName = apiType == ApiAssemblyType.Core ? ApiAssemblyNames.Core : ApiAssemblyNames.Editor;
-
- string editorPrebuiltApiDir = Path.Combine(GodotSharpDirs.DataEditorPrebuiltApiDir, config);
- string resAssembliesDir = Path.Combine(GodotSharpDirs.ResAssembliesBaseDir, config);
-
- if (File.Exists(Path.Combine(editorPrebuiltApiDir, $"{apiName}.dll")))
- {
- using (var copyProgress = new EditorProgress("mono_copy_prebuilt_api_assembly", $"Copying prebuilt {apiName} assembly...", 1))
- {
- copyProgress.Step($"Copying {apiName} assembly", 0);
- return CopyApiAssembly(editorPrebuiltApiDir, resAssembliesDir, apiName, apiType);
- }
- }
-
- const string apiSolutionName = ApiAssemblyNames.SolutionName;
-
- using (var pr = new EditorProgress($"mono_build_release_{apiSolutionName}", $"Building {apiSolutionName} solution...", 3))
- {
- pr.Step($"Generating {apiSolutionName} solution", 0);
-
- string apiSlnDir = Path.Combine(GodotSharpDirs.MonoSolutionsDir, _ApiFolderName(ApiAssemblyType.Core));
- string apiSlnFile = Path.Combine(apiSlnDir, $"{apiSolutionName}.sln");
-
- if (!Directory.Exists(apiSlnDir) || !File.Exists(apiSlnFile))
- {
- var bindingsGenerator = new BindingsGenerator();
-
- if (!Godot.OS.IsStdoutVerbose())
- bindingsGenerator.LogPrintEnabled = false;
-
- Error err = bindingsGenerator.GenerateCsApi(apiSlnDir);
- if (err != Error.Ok)
- {
- ShowBuildErrorDialog($"Failed to generate {apiSolutionName} solution. Error: {err}");
- return false;
- }
- }
-
- pr.Step($"Building {apiSolutionName} solution", 1);
-
- if (!BuildApiSolution(apiSlnDir, config))
- return false;
-
- pr.Step($"Copying {apiName} assembly", 2);
-
- // Copy the built assembly to the assemblies directory
- string apiAssemblyDir = Path.Combine(apiSlnDir, apiName, "bin", config);
- if (!CopyApiAssembly(apiAssemblyDir, resAssembliesDir, apiName, apiType))
- return false;
- }
-
- return true;
- }
-
public static bool BuildProjectBlocking(string config, IEnumerable<string> godotDefines)
{
if (!File.Exists(GodotSharpDirs.ProjectSlnPath))
return true; // No solution to build
- string apiConfig = config == "Release" ? "Release" : "Debug";
-
- if (!MakeApiAssembly(ApiAssemblyType.Core, apiConfig))
- return false;
-
- if (!MakeApiAssembly(ApiAssemblyType.Editor, apiConfig))
- return false;
+ // Make sure to update the API assemblies if they happen to be missing. Just in
+ // case the user decided to delete them at some point after they were loaded.
+ Internal.UpdateApiAssembliesFromPrebuilt();
using (var pr = new EditorProgress("mono_project_debug_build", "Building project solution...", 1))
{
@@ -376,7 +257,7 @@ namespace GodotTools
{
// Build tool settings
- Internal.EditorDef("mono/builds/build_tool", OS.IsWindows() ? BuildTool.MsBuildVs : BuildTool.MsBuildMono);
+ EditorDef("mono/builds/build_tool", OS.IsWindows() ? BuildTool.MsBuildVs : BuildTool.MsBuildMono);
var editorSettings = GodotSharpEditor.Instance.GetEditorInterface().GetEditorSettings();
@@ -390,7 +271,7 @@ namespace GodotTools
$"{PropNameMsbuildMono},{PropNameXbuild}"
});
- Internal.EditorDef("mono/builds/print_build_output", false);
+ EditorDef("mono/builds/print_build_output", false);
}
}
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
index da439b8d6f..90dec43412 100644
--- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
@@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.IO;
using GodotTools.Internals;
using GodotTools.ProjectEditor;
+using static GodotTools.Internals.Globals;
using File = GodotTools.Utils.File;
using Path = System.IO.Path;
using OS = GodotTools.Utils.OS;
@@ -26,15 +27,15 @@ namespace GodotTools
private MonoDevelopInstance monoDevelopInstance;
private MonoDevelopInstance visualStudioForMacInstance;
- private WeakReference<GodotSharpExport> exportPluginWeak;
+ private WeakRef exportPluginWeak; // TODO Use WeakReference once we have proper serialization
public MonoBottomPanel MonoBottomPanel { get; private set; }
private bool CreateProjectSolution()
{
- using (var pr = new EditorProgress("create_csharp_solution", "Generating solution...", 2)) // TTR("Generating solution...")
+ using (var pr = new EditorProgress("create_csharp_solution", "Generating solution...".TTR(), 2))
{
- pr.Step("Generating C# project..."); // TTR("Generating C# project...")
+ pr.Step("Generating C# project...".TTR());
string resourceDir = ProjectSettings.GlobalizePath("res://");
@@ -67,96 +68,28 @@ namespace GodotTools
}
catch (IOException e)
{
- ShowErrorDialog($"Failed to save solution. Exception message: {e.Message}"); // TTR
+ ShowErrorDialog("Failed to save solution. Exception message: ".TTR() + e.Message);
return false;
}
- string apiConfig = "Debug";
+ // Make sure to update the API assemblies if they happen to be missing. Just in
+ // case the user decided to delete them at some point after they were loaded.
+ Internal.UpdateApiAssembliesFromPrebuilt();
- if (!GodotSharpBuilds.MakeApiAssembly(ApiAssemblyType.Core, apiConfig))
- return false;
-
- if (!GodotSharpBuilds.MakeApiAssembly(ApiAssemblyType.Editor, apiConfig))
- return false;
-
- pr.Step("Done"); // TTR("Done")
+ pr.Step("Done".TTR());
// Here, after all calls to progress_task_step
CallDeferred(nameof(_RemoveCreateSlnMenuOption));
}
else
{
- ShowErrorDialog("Failed to create C# project."); // TTR
+ ShowErrorDialog("Failed to create C# project.".TTR());
}
return true;
}
}
- private static int _makeApiSolutionsAttempts = 100;
- private static bool _makeApiSolutionsRecursionGuard = false;
-
- private void _MakeApiSolutionsIfNeeded()
- {
- // I'm sick entirely of ProgressDialog
-
- if (Internal.IsMessageQueueFlushing() || Engine.GetMainLoop() == null)
- {
- if (_makeApiSolutionsAttempts == 0) // This better never happen or I swear...
- throw new TimeoutException();
-
- if (Engine.GetMainLoop() != null)
- {
- if (!Engine.GetMainLoop().IsConnected("idle_frame", this, nameof(_MakeApiSolutionsIfNeeded)))
- Engine.GetMainLoop().Connect("idle_frame", this, nameof(_MakeApiSolutionsIfNeeded));
- }
- else
- {
- CallDeferred(nameof(_MakeApiSolutionsIfNeededImpl));
- }
-
- _makeApiSolutionsAttempts--;
- return;
- }
-
- // Recursion guard needed because signals don't play well with ProgressDialog either, but unlike
- // the message queue, with signals the collateral damage should be minimal in the worst case.
- if (!_makeApiSolutionsRecursionGuard)
- {
- _makeApiSolutionsRecursionGuard = true;
-
- // Oneshot signals don't play well with ProgressDialog either, so we do it this way instead
- if (Engine.GetMainLoop().IsConnected("idle_frame", this, nameof(_MakeApiSolutionsIfNeeded)))
- Engine.GetMainLoop().Disconnect("idle_frame", this, nameof(_MakeApiSolutionsIfNeeded));
-
- _MakeApiSolutionsIfNeededImpl();
-
- _makeApiSolutionsRecursionGuard = false;
- }
- }
-
- private void _MakeApiSolutionsIfNeededImpl()
- {
- // If the project has a solution and C# project make sure the API assemblies are present and up to date
-
- string api_config = "Debug";
- string resAssembliesDir = Path.Combine(GodotSharpDirs.ResAssembliesBaseDir, api_config);
-
- if (!File.Exists(Path.Combine(resAssembliesDir, $"{ApiAssemblyNames.Core}.dll")) ||
- Internal.MetadataIsApiAssemblyInvalidated(ApiAssemblyType.Core))
- {
- if (!GodotSharpBuilds.MakeApiAssembly(ApiAssemblyType.Core, api_config))
- return;
- }
-
- if (!File.Exists(Path.Combine(resAssembliesDir, $"{ApiAssemblyNames.Editor}.dll")) ||
- Internal.MetadataIsApiAssemblyInvalidated(ApiAssemblyType.Editor))
- {
- if (!GodotSharpBuilds.MakeApiAssembly(ApiAssemblyType.Editor, api_config))
- return; // Redundant? I don't think so!
- }
- }
-
private void _RemoveCreateSlnMenuOption()
{
menuPopup.RemoveItem(menuPopup.GetItemIndex((int) MenuOptions.CreateSln));
@@ -407,7 +340,7 @@ namespace GodotTools
MonoBottomPanel = new MonoBottomPanel();
- bottomPanelBtn = AddControlToBottomPanel(MonoBottomPanel, "Mono"); // TTR("Mono")
+ bottomPanelBtn = AddControlToBottomPanel(MonoBottomPanel, "Mono".TTR());
AddChild(new HotReloadAssemblyWatcher {Name = "HotReloadAssemblyWatcher"});
@@ -419,7 +352,7 @@ namespace GodotTools
// TODO: Remove or edit this info dialog once Mono support is no longer in alpha
{
- menuPopup.AddItem("About C# support", (int) MenuOptions.AboutCSharp); // TTR("About C# support")
+ menuPopup.AddItem("About C# support".TTR(), (int) MenuOptions.AboutCSharp);
aboutDialog = new AcceptDialog();
editorBaseControl.AddChild(aboutDialog);
aboutDialog.WindowTitle = "Important: C# support is not feature-complete";
@@ -441,7 +374,7 @@ namespace GodotTools
var aboutLabel = new Label();
aboutHBox.AddChild(aboutLabel);
- aboutLabel.RectMinSize = new Vector2(600, 150) * Internal.EditorScale;
+ aboutLabel.RectMinSize = new Vector2(600, 150) * EditorScale;
aboutLabel.SizeFlagsVertical = (int) Control.SizeFlags.ExpandFill;
aboutLabel.Autowrap = true;
aboutLabel.Text =
@@ -454,7 +387,7 @@ namespace GodotTools
" https://github.com/godotengine/godot/issues\n\n" +
"Your critical feedback at this stage will play a great role in shaping the C# support in future releases, so thank you!";
- Internal.EditorDef("mono/editor/show_info_on_start", true);
+ EditorDef("mono/editor/show_info_on_start", true);
// CheckBox in main container
aboutDialogCheckBox = new CheckBox {Text = "Show this warning when starting the editor"};
@@ -464,16 +397,13 @@ namespace GodotTools
if (File.Exists(GodotSharpDirs.ProjectSlnPath) && File.Exists(GodotSharpDirs.ProjectCsProjPath))
{
- // Defer this task because EditorProgress calls Main::iterarion() and the main loop is not yet initialized.
- CallDeferred(nameof(_MakeApiSolutionsIfNeeded));
-
// Make sure the existing project has Api assembly references configured correctly
CSharpProject.FixApiHintPath(GodotSharpDirs.ProjectCsProjPath);
}
else
{
bottomPanelBtn.Hide();
- menuPopup.AddItem("Create C# solution", (int) MenuOptions.CreateSln); // TTR("Create C# solution")
+ menuPopup.AddItem("Create C# solution".TTR(), (int) MenuOptions.CreateSln);
}
menuPopup.Connect("id_pressed", this, nameof(_MenuOptionPressed));
@@ -488,7 +418,7 @@ namespace GodotTools
AddControlToContainer(CustomControlContainer.Toolbar, buildButton);
// External editor settings
- Internal.EditorDef("mono/editor/external_editor", ExternalEditor.None);
+ EditorDef("mono/editor/external_editor", ExternalEditor.None);
string settingsHintStr = "Disabled";
@@ -520,7 +450,7 @@ namespace GodotTools
// Export plugin
var exportPlugin = new GodotSharpExport();
AddExportPlugin(exportPlugin);
- exportPluginWeak = new WeakReference<GodotSharpExport>(exportPlugin);
+ exportPluginWeak = WeakRef(exportPlugin);
GodotSharpBuilds.Initialize();
}
@@ -529,13 +459,15 @@ namespace GodotTools
{
base.Dispose(disposing);
- if (exportPluginWeak.TryGetTarget(out var exportPlugin))
+ if (exportPluginWeak != null)
{
// We need to dispose our export plugin before the editor destroys EditorSettings.
// Otherwise, if the GC disposes it at a later time, EditorExportPlatformAndroid
// will be freed after EditorSettings already was, and its device polling thread
// will try to access the EditorSettings singleton, resulting in null dereferencing.
- exportPlugin.Dispose();
+ (exportPluginWeak.GetRef() as GodotSharpExport)?.Dispose();
+
+ exportPluginWeak.Dispose();
}
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj
index a0ff8a0df1..01e8c87d14 100644
--- a/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj
+++ b/modules/mono/editor/GodotTools/GodotTools/GodotTools.csproj
@@ -44,6 +44,7 @@
<Compile Include="Internals\GodotSharpDirs.cs" />
<Compile Include="Internals\Internal.cs" />
<Compile Include="Internals\ScriptClassParser.cs" />
+ <Compile Include="Internals\Globals.cs" />
<Compile Include="MonoDevelopInstance.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Build\BuildSystem.cs" />
diff --git a/modules/mono/editor/GodotTools/GodotTools/HotReloadAssemblyWatcher.cs b/modules/mono/editor/GodotTools/GodotTools/HotReloadAssemblyWatcher.cs
index aa52079cf4..0f6f5ffadc 100644
--- a/modules/mono/editor/GodotTools/GodotTools/HotReloadAssemblyWatcher.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/HotReloadAssemblyWatcher.cs
@@ -1,5 +1,6 @@
using Godot;
using GodotTools.Internals;
+using static GodotTools.Internals.Globals;
namespace GodotTools
{
@@ -37,7 +38,7 @@ namespace GodotTools
watchTimer = new Timer
{
OneShot = false,
- WaitTime = (float) Internal.EditorDef("mono/assembly_watch_interval_sec", 0.5)
+ WaitTime = (float) EditorDef("mono/assembly_watch_interval_sec", 0.5)
};
watchTimer.Connect("timeout", this, nameof(TimerTimeout));
AddChild(watchTimer);
diff --git a/modules/mono/editor/GodotTools/GodotTools/Internals/Globals.cs b/modules/mono/editor/GodotTools/GodotTools/Internals/Globals.cs
new file mode 100644
index 0000000000..793f84fd77
--- /dev/null
+++ b/modules/mono/editor/GodotTools/GodotTools/Internals/Globals.cs
@@ -0,0 +1,33 @@
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
+
+namespace GodotTools.Internals
+{
+ public static class Globals
+ {
+ public static float EditorScale => internal_EditorScale();
+
+ public static object GlobalDef(string setting, object defaultValue, bool restartIfChanged = false) =>
+ internal_GlobalDef(setting, defaultValue, restartIfChanged);
+
+ public static object EditorDef(string setting, object defaultValue, bool restartIfChanged = false) =>
+ internal_EditorDef(setting, defaultValue, restartIfChanged);
+
+ [SuppressMessage("ReSharper", "InconsistentNaming")]
+ public static string TTR(this string text) => internal_TTR(text);
+
+ // Internal Calls
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ private static extern float internal_EditorScale();
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ private static extern object internal_GlobalDef(string setting, object defaultValue, bool restartIfChanged);
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ private static extern object internal_EditorDef(string setting, object defaultValue, bool restartIfChanged);
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ private static extern string internal_TTR(string text);
+ }
+}
diff --git a/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs b/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs
index 5c7ce832cd..9526dd3c6f 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Internals/Internal.cs
@@ -10,13 +10,8 @@ namespace GodotTools.Internals
public const string CSharpLanguageType = "CSharpScript";
public const string CSharpLanguageExtension = "cs";
- public static float EditorScale => internal_EditorScale();
-
- public static object GlobalDef(string setting, object defaultValue, bool restartIfChanged = false) =>
- internal_GlobalDef(setting, defaultValue, restartIfChanged);
-
- public static object EditorDef(string setting, object defaultValue, bool restartIfChanged = false) =>
- internal_EditorDef(setting, defaultValue, restartIfChanged);
+ public static string UpdateApiAssembliesFromPrebuilt() =>
+ internal_UpdateApiAssembliesFromPrebuilt();
public static string FullTemplatesDir =>
internal_FullTemplatesDir();
@@ -25,14 +20,6 @@ namespace GodotTools.Internals
public static bool IsOsxAppBundleInstalled(string bundleId) => internal_IsOsxAppBundleInstalled(bundleId);
- public static bool MetadataIsApiAssemblyInvalidated(ApiAssemblyType apiType) =>
- internal_MetadataIsApiAssemblyInvalidated(apiType);
-
- public static void MetadataSetApiAssemblyInvalidated(ApiAssemblyType apiType, bool invalidated) =>
- internal_MetadataSetApiAssemblyInvalidated(apiType, invalidated);
-
- public static bool IsMessageQueueFlushing() => internal_IsMessageQueueFlushing();
-
public static bool GodotIs32Bits() => internal_GodotIs32Bits();
public static bool GodotIsRealTDouble() => internal_GodotIsRealTDouble();
@@ -62,13 +49,7 @@ namespace GodotTools.Internals
// Internal Calls
[MethodImpl(MethodImplOptions.InternalCall)]
- private static extern float internal_EditorScale();
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- private static extern object internal_GlobalDef(string setting, object defaultValue, bool restartIfChanged);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- private static extern object internal_EditorDef(string setting, object defaultValue, bool restartIfChanged);
+ private static extern string internal_UpdateApiAssembliesFromPrebuilt();
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern string internal_FullTemplatesDir();
@@ -80,15 +61,6 @@ namespace GodotTools.Internals
private static extern bool internal_IsOsxAppBundleInstalled(string bundleId);
[MethodImpl(MethodImplOptions.InternalCall)]
- private static extern bool internal_MetadataIsApiAssemblyInvalidated(ApiAssemblyType apiType);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- private static extern void internal_MetadataSetApiAssemblyInvalidated(ApiAssemblyType apiType, bool invalidated);
-
- [MethodImpl(MethodImplOptions.InternalCall)]
- private static extern bool internal_IsMessageQueueFlushing();
-
- [MethodImpl(MethodImplOptions.InternalCall)]
private static extern bool internal_GodotIs32Bits();
[MethodImpl(MethodImplOptions.InternalCall)]
diff --git a/modules/mono/editor/GodotTools/GodotTools/MonoBottomPanel.cs b/modules/mono/editor/GodotTools/GodotTools/MonoBottomPanel.cs
index 300cf7fcb9..53ff0891d5 100644
--- a/modules/mono/editor/GodotTools/GodotTools/MonoBottomPanel.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/MonoBottomPanel.cs
@@ -3,6 +3,7 @@ using System;
using System.IO;
using Godot.Collections;
using GodotTools.Internals;
+using static GodotTools.Internals.Globals;
using File = GodotTools.Utils.File;
using Path = System.IO.Path;
@@ -254,7 +255,7 @@ namespace GodotTools
panelTabs = new TabContainer
{
TabAlign = TabContainer.TabAlignEnum.Left,
- RectMinSize = new Vector2(0, 228) * Internal.EditorScale,
+ RectMinSize = new Vector2(0, 228) * EditorScale,
SizeFlagsVertical = (int) SizeFlags.ExpandFill
};
panelTabs.AddStyleboxOverride("panel", editorBaseControl.GetStylebox("DebuggerPanel", "EditorStyles"));
@@ -266,7 +267,7 @@ namespace GodotTools
// Builds tab
panelBuildsTab = new VBoxContainer
{
- Name = "Builds", // TTR
+ Name = "Builds".TTR(),
SizeFlagsHorizontal = (int) SizeFlags.ExpandFill
};
panelTabs.AddChild(panelBuildsTab);
@@ -276,7 +277,7 @@ namespace GodotTools
var buildProjectBtn = new Button
{
- Text = "Build Project", // TTR
+ Text = "Build Project".TTR(),
FocusMode = FocusModeEnum.None
};
buildProjectBtn.Connect("pressed", this, nameof(BuildProjectPressed));
@@ -286,7 +287,7 @@ namespace GodotTools
warningsBtn = new ToolButton
{
- Text = "Warnings", // TTR
+ Text = "Warnings".TTR(),
ToggleMode = true,
Pressed = true,
Visible = false,
@@ -297,7 +298,7 @@ namespace GodotTools
errorsBtn = new ToolButton
{
- Text = "Errors", // TTR
+ Text = "Errors".TTR(),
ToggleMode = true,
Pressed = true,
Visible = false,
@@ -310,7 +311,7 @@ namespace GodotTools
viewLogBtn = new Button
{
- Text = "View log", // TTR
+ Text = "View log".TTR(),
FocusMode = FocusModeEnum.None,
Visible = false
};
diff --git a/modules/mono/editor/editor_internal_calls.cpp b/modules/mono/editor/editor_internal_calls.cpp
index a3b5b450ef..0014aaca70 100644
--- a/modules/mono/editor/editor_internal_calls.cpp
+++ b/modules/mono/editor/editor_internal_calls.cpp
@@ -30,7 +30,6 @@
#include "editor_internal_calls.h"
-#include "core/message_queue.h"
#include "core/os/os.h"
#include "core/version.h"
#include "editor/editor_node.h"
@@ -231,24 +230,34 @@ uint32_t godot_icall_GodotSharpExport_GetExportedAssemblyDependencies(MonoString
return GodotSharpExport::get_exported_assembly_dependencies(project_dll_name, project_dll_src_path, build_config, custom_lib_dir, dependencies);
}
-float godot_icall_Internal_EditorScale() {
+float godot_icall_Globals_EditorScale() {
return EDSCALE;
}
-MonoObject *godot_icall_Internal_GlobalDef(MonoString *p_setting, MonoObject *p_default_value, MonoBoolean p_restart_if_changed) {
+MonoObject *godot_icall_Globals_GlobalDef(MonoString *p_setting, MonoObject *p_default_value, MonoBoolean p_restart_if_changed) {
String setting = GDMonoMarshal::mono_string_to_godot(p_setting);
Variant default_value = GDMonoMarshal::mono_object_to_variant(p_default_value);
Variant result = _GLOBAL_DEF(setting, default_value, (bool)p_restart_if_changed);
return GDMonoMarshal::variant_to_mono_object(result);
}
-MonoObject *godot_icall_Internal_EditorDef(MonoString *p_setting, MonoObject *p_default_value, MonoBoolean p_restart_if_changed) {
+MonoObject *godot_icall_Globals_EditorDef(MonoString *p_setting, MonoObject *p_default_value, MonoBoolean p_restart_if_changed) {
String setting = GDMonoMarshal::mono_string_to_godot(p_setting);
Variant default_value = GDMonoMarshal::mono_object_to_variant(p_default_value);
- Variant result = _GLOBAL_DEF(setting, default_value, (bool)p_restart_if_changed);
+ Variant result = _EDITOR_DEF(setting, default_value, (bool)p_restart_if_changed);
return GDMonoMarshal::variant_to_mono_object(result);
}
+MonoString *godot_icall_Globals_TTR(MonoString *p_text) {
+ String text = GDMonoMarshal::mono_string_to_godot(p_text);
+ return GDMonoMarshal::mono_string_from_godot(TTR(text));
+}
+
+MonoString *godot_icall_Internal_UpdateApiAssembliesFromPrebuilt() {
+ String error_str = GDMono::get_singleton()->update_api_assemblies_from_prebuilt();
+ return GDMonoMarshal::mono_string_from_godot(error_str);
+}
+
MonoString *godot_icall_Internal_FullTemplatesDir() {
String full_templates_dir = EditorSettings::get_singleton()->get_templates_dir().plus_file(VERSION_FULL_CONFIG);
return GDMonoMarshal::mono_string_from_godot(full_templates_dir);
@@ -269,18 +278,6 @@ MonoBoolean godot_icall_Internal_IsOsxAppBundleInstalled(MonoString *p_bundle_id
#endif
}
-MonoBoolean godot_icall_Internal_MetadataIsApiAssemblyInvalidated(int32_t p_api_type) {
- return GDMono::get_singleton()->metadata_is_api_assembly_invalidated((APIAssembly::Type)p_api_type);
-}
-
-void godot_icall_Internal_MetadataSetApiAssemblyInvalidated(int32_t p_api_type, MonoBoolean p_invalidated) {
- GDMono::get_singleton()->metadata_set_api_assembly_invalidated((APIAssembly::Type)p_api_type, (bool)p_invalidated);
-}
-
-MonoBoolean godot_icall_Internal_IsMessageQueueFlushing() {
- return (MonoBoolean)MessageQueue::get_singleton()->is_flushing();
-}
-
MonoBoolean godot_icall_Internal_GodotIs32Bits() {
return sizeof(void *) == 4;
}
@@ -402,15 +399,10 @@ void register_editor_internal_calls() {
mono_add_internal_call("GodotTools.GodotSharpExport::internal_GetExportedAssemblyDependencies", (void *)godot_icall_GodotSharpExport_GetExportedAssemblyDependencies);
// Internals
- mono_add_internal_call("GodotTools.Internals.Internal::internal_EditorScale", (void *)godot_icall_Internal_EditorScale);
- mono_add_internal_call("GodotTools.Internals.Internal::internal_GlobalDef", (void *)godot_icall_Internal_GlobalDef);
- mono_add_internal_call("GodotTools.Internals.Internal::internal_EditorDef", (void *)godot_icall_Internal_EditorDef);
+ mono_add_internal_call("GodotTools.Internals.Internal::internal_UpdateApiAssembliesFromPrebuilt", (void *)godot_icall_Internal_UpdateApiAssembliesFromPrebuilt);
mono_add_internal_call("GodotTools.Internals.Internal::internal_FullTemplatesDir", (void *)godot_icall_Internal_FullTemplatesDir);
mono_add_internal_call("GodotTools.Internals.Internal::internal_SimplifyGodotPath", (void *)godot_icall_Internal_SimplifyGodotPath);
mono_add_internal_call("GodotTools.Internals.Internal::internal_IsOsxAppBundleInstalled", (void *)godot_icall_Internal_IsOsxAppBundleInstalled);
- mono_add_internal_call("GodotTools.Internals.Internal::internal_MetadataIsApiAssemblyInvalidated", (void *)godot_icall_Internal_MetadataIsApiAssemblyInvalidated);
- mono_add_internal_call("GodotTools.Internals.Internal::internal_MetadataSetApiAssemblyInvalidated", (void *)godot_icall_Internal_MetadataSetApiAssemblyInvalidated);
- mono_add_internal_call("GodotTools.Internals.Internal::internal_IsMessageQueueFlushing", (void *)godot_icall_Internal_IsMessageQueueFlushing);
mono_add_internal_call("GodotTools.Internals.Internal::internal_GodotIs32Bits", (void *)godot_icall_Internal_GodotIs32Bits);
mono_add_internal_call("GodotTools.Internals.Internal::internal_GodotIsRealTDouble", (void *)godot_icall_Internal_GodotIsRealTDouble);
mono_add_internal_call("GodotTools.Internals.Internal::internal_GodotMainIteration", (void *)godot_icall_Internal_GodotMainIteration);
@@ -424,6 +416,12 @@ void register_editor_internal_calls() {
mono_add_internal_call("GodotTools.Internals.Internal::internal_GetScriptsMetadataOrNothing", (void *)godot_icall_Internal_GetScriptsMetadataOrNothing);
mono_add_internal_call("GodotTools.Internals.Internal::internal_MonoWindowsInstallRoot", (void *)godot_icall_Internal_MonoWindowsInstallRoot);
+ // Globals
+ mono_add_internal_call("GodotTools.Internals.Globals::internal_EditorScale", (void *)godot_icall_Globals_EditorScale);
+ mono_add_internal_call("GodotTools.Internals.Globals::internal_GlobalDef", (void *)godot_icall_Globals_GlobalDef);
+ mono_add_internal_call("GodotTools.Internals.Globals::internal_EditorDef", (void *)godot_icall_Globals_EditorDef);
+ mono_add_internal_call("GodotTools.Internals.Globals::internal_TTR", (void *)godot_icall_Globals_TTR);
+
// Utils.OS
mono_add_internal_call("GodotTools.Utils.OS::GetPlatformName", (void *)godot_icall_Utils_OS_GetPlatformName);
}
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index 06fbae019c..096ad0f5e3 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -59,10 +59,6 @@
#include "android_mono_config.gen.h"
#endif
-#define OUT_OF_SYNC_ERR_MESSAGE(m_assembly_name) "The assembly '" m_assembly_name "' is out of sync. " \
- "This error is expected if you just upgraded to a newer Godot version. " \
- "Building the project will update the assembly to the correct version."
-
GDMono *GDMono::singleton = NULL;
namespace {
@@ -304,26 +300,9 @@ void GDMono::initialize() {
mono_install_unhandled_exception_hook(&unhandled_exception_hook, NULL);
#ifndef TOOLS_ENABLED
- if (!DirAccess::exists("res://.mono")) {
- // 'res://.mono/' is missing so there is nothing to load. We don't need to initialize mono, but
- // we still do so unless mscorlib is missing (which is the case for projects that don't use C#).
-
- String mscorlib_fname("mscorlib.dll");
-
- Vector<String> search_dirs;
- GDMonoAssembly::fill_search_dirs(search_dirs);
-
- bool found = false;
- for (int i = 0; i < search_dirs.size(); i++) {
- if (FileAccess::exists(search_dirs[i].plus_file(mscorlib_fname))) {
- found = true;
- break;
- }
- }
-
- if (!found)
- return; // mscorlib is missing, do not initialize mono
- }
+ // Export templates only load the Mono runtime if the project uses it
+ if (!DirAccess::exists("res://.mono"))
+ return;
#endif
root_domain = mono_jit_init_version("GodotEngine.RootDomain", "v4.0.30319");
@@ -354,63 +333,48 @@ void GDMono::initialize() {
_register_internal_calls();
- // The following assemblies are not required at initialization
-#ifdef MONO_GLUE_ENABLED
- if (_load_api_assemblies()) {
- // Everything is fine with the api assemblies, load the tools and project assemblies
-
-#if defined(TOOLS_ENABLED)
- ERR_EXPLAIN("Mono: Failed to load GodotTools assemblies");
- ERR_FAIL_COND(!_load_tools_assemblies());
-#endif
+ print_verbose("Mono: INITIALIZED");
+}
- _load_project_assembly();
+void GDMono::initialize_load_assemblies() {
- } else {
- if ((core_api_assembly && (core_api_assembly_out_of_sync || !GDMonoUtils::mono_cache.godot_api_cache_updated))
-#ifdef TOOLS_ENABLED
- || (editor_api_assembly && editor_api_assembly_out_of_sync)
+#ifndef MONO_GLUE_ENABLED
+ ERR_EXPLAIN("Mono: This binary was built with `mono_glue=no`; cannot load assemblies");
+ CRASH_NOW();
#endif
- ) {
-#ifdef TOOLS_ENABLED
- // The assembly was successfully loaded, but the full api could not be cached.
- // This is most likely an outdated assembly loaded because of an invalid version in the
- // metadata, so we invalidate the version in the metadata and unload the script domain.
-
- if (core_api_assembly_out_of_sync) {
- ERR_PRINT(OUT_OF_SYNC_ERR_MESSAGE(CORE_API_ASSEMBLY_NAME));
- metadata_set_api_assembly_invalidated(APIAssembly::API_CORE, true);
- } else if (!GDMonoUtils::mono_cache.godot_api_cache_updated) {
- ERR_PRINT("The loaded assembly '" CORE_API_ASSEMBLY_NAME "' is in sync, but the cache update failed");
- metadata_set_api_assembly_invalidated(APIAssembly::API_CORE, true);
- }
- if (editor_api_assembly_out_of_sync) {
- ERR_PRINT(OUT_OF_SYNC_ERR_MESSAGE(EDITOR_API_ASSEMBLY_NAME));
- metadata_set_api_assembly_invalidated(APIAssembly::API_EDITOR, true);
- }
+ // Load assemblies. The API and tools assemblies are required,
+ // the application is aborted if these assemblies cannot be loaded.
- print_line("Mono: Proceeding to unload scripts domain because of invalid API assemblies.");
+ _load_api_assemblies();
- Error err = _unload_scripts_domain();
- if (err != OK) {
- WARN_PRINT("Mono: Failed to unload scripts domain");
- }
-#else
- ERR_PRINT("The loaded API assembly is invalid");
- CRASH_NOW();
-#endif // TOOLS_ENABLED
- }
+#if defined(TOOLS_ENABLED)
+ if (!_load_tools_assemblies()) {
+ ERR_EXPLAIN("Mono: Failed to load GodotTools assemblies");
+ CRASH_NOW();
}
-#else
- print_verbose("Mono: Glue disabled, ignoring script assemblies.");
-#endif // MONO_GLUE_ENABLED
+#endif
- print_verbose("Mono: INITIALIZED");
+ // Load the project's main assembly. This doesn't necessarily need to succeed.
+ // The game may not be using .NET at all, or if the project does use .NET and
+ // we're running in the editor, it may just happen to be it wasn't built yet.
+ if (!_load_project_assembly()) {
+ if (OS::get_singleton()->is_stdout_verbose())
+ print_error("Mono: Failed to load project assembly");
+ }
+}
+
+bool GDMono::_are_api_assemblies_out_of_sync() {
+ bool out_of_sync = core_api_assembly && (core_api_assembly_out_of_sync || !GDMonoUtils::mono_cache.godot_api_cache_updated);
+#ifdef TOOLS_ENABLED
+ if (!out_of_sync)
+ out_of_sync = editor_api_assembly && editor_api_assembly_out_of_sync;
+#endif
+ return out_of_sync;
}
-#ifdef MONO_GLUE_ENABLED
namespace GodotSharpBindings {
+#ifdef MONO_GLUE_ENABLED
uint64_t get_core_api_hash();
#ifdef TOOLS_ENABLED
@@ -419,13 +383,33 @@ uint64_t get_editor_api_hash();
uint32_t get_bindings_version();
void register_generated_icalls();
-} // namespace GodotSharpBindings
+
+#else
+
+uint64_t get_core_api_hash() {
+ CRASH_NOW();
+ GD_UNREACHABLE();
+}
+#ifdef TOOLS_ENABLED
+uint64_t get_editor_api_hash() {
+ CRASH_NOW();
+ GD_UNREACHABLE();
+}
#endif
+uint32_t get_bindings_version() {
+ CRASH_NOW();
+ GD_UNREACHABLE();
+}
+
+void register_generated_icalls() {
+ /* Fine, just do nothing */
+}
+
+#endif // MONO_GLUE_ENABLED
+} // namespace GodotSharpBindings
void GDMono::_register_internal_calls() {
-#ifdef MONO_GLUE_ENABLED
GodotSharpBindings::register_generated_icalls();
-#endif
}
void GDMono::_initialize_and_check_api_hashes() {
@@ -565,12 +549,21 @@ bool GDMono::_load_corlib_assembly() {
}
#ifdef TOOLS_ENABLED
-static bool copy_api_assembly(const String &p_src_dir, const String &p_dst_dir, const String &p_assembly_name, APIAssembly::Type p_api_type) {
+bool GDMono::copy_prebuilt_api_assembly(APIAssembly::Type p_api_type) {
+
+ bool &api_assembly_out_of_sync = (p_api_type == APIAssembly::API_CORE) ?
+ GDMono::get_singleton()->core_api_assembly_out_of_sync :
+ GDMono::get_singleton()->editor_api_assembly_out_of_sync;
+
+ String src_dir = GodotSharpDirs::get_data_editor_prebuilt_api_dir().plus_file("Debug");
+ String dst_dir = GodotSharpDirs::get_res_assemblies_dir();
+
+ String assembly_name = p_api_type == APIAssembly::API_CORE ? CORE_API_ASSEMBLY_NAME : EDITOR_API_ASSEMBLY_NAME;
// Create destination directory if needed
- if (!DirAccess::exists(p_dst_dir)) {
- DirAccess *da = DirAccess::create_for_path(p_dst_dir);
- Error err = da->make_dir_recursive(p_dst_dir);
+ if (!DirAccess::exists(dst_dir)) {
+ DirAccess *da = DirAccess::create_for_path(dst_dir);
+ Error err = da->make_dir_recursive(dst_dir);
memdelete(da);
if (err != OK) {
@@ -579,21 +572,19 @@ static bool copy_api_assembly(const String &p_src_dir, const String &p_dst_dir,
}
}
- String assembly_file = p_assembly_name + ".dll";
- String assembly_src = p_src_dir.plus_file(assembly_file);
- String assembly_dst = p_dst_dir.plus_file(assembly_file);
+ String assembly_file = assembly_name + ".dll";
+ String assembly_src = src_dir.plus_file(assembly_file);
+ String assembly_dst = dst_dir.plus_file(assembly_file);
- if (!FileAccess::exists(assembly_dst) ||
- FileAccess::get_modified_time(assembly_src) > FileAccess::get_modified_time(assembly_dst) ||
- GDMono::get_singleton()->metadata_is_api_assembly_invalidated(p_api_type)) {
+ if (!FileAccess::exists(assembly_dst) || api_assembly_out_of_sync) {
DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- String xml_file = p_assembly_name + ".xml";
- if (da->copy(p_src_dir.plus_file(xml_file), p_dst_dir.plus_file(xml_file)) != OK)
+ String xml_file = assembly_name + ".xml";
+ if (da->copy(src_dir.plus_file(xml_file), dst_dir.plus_file(xml_file)) != OK)
WARN_PRINTS("Failed to copy " + xml_file);
- String pdb_file = p_assembly_name + ".pdb";
- if (da->copy(p_src_dir.plus_file(pdb_file), p_dst_dir.plus_file(pdb_file)) != OK)
+ String pdb_file = assembly_name + ".pdb";
+ if (da->copy(src_dir.plus_file(pdb_file), dst_dir.plus_file(pdb_file)) != OK)
WARN_PRINTS("Failed to copy " + pdb_file);
Error err = da->copy(assembly_src, assembly_dst);
@@ -603,11 +594,46 @@ static bool copy_api_assembly(const String &p_src_dir, const String &p_dst_dir,
return false;
}
- GDMono::get_singleton()->metadata_set_api_assembly_invalidated(p_api_type, false);
+ api_assembly_out_of_sync = false;
}
return true;
}
+
+String GDMono::update_api_assemblies_from_prebuilt() {
+
+#define FAIL_REASON(m_out_of_sync, m_prebuilt_exist) \
+ ( \
+ (m_out_of_sync ? \
+ String("The assembly is invalidated") : \
+ String("The assembly was not found")) + \
+ (m_prebuilt_exist ? \
+ String(" and the prebuilt assemblies are missing") : \
+ String(" and we failed to copy the prebuilt assemblies")))
+
+ bool api_assembly_out_of_sync = core_api_assembly_out_of_sync || editor_api_assembly_out_of_sync;
+
+ String core_assembly_path = GodotSharpDirs::get_res_assemblies_dir().plus_file(CORE_API_ASSEMBLY_NAME ".dll");
+ String editor_assembly_path = GodotSharpDirs::get_res_assemblies_dir().plus_file(EDITOR_API_ASSEMBLY_NAME ".dll");
+
+ if (!api_assembly_out_of_sync && FileAccess::exists(core_assembly_path) && FileAccess::exists(editor_assembly_path))
+ return String(); // No update needed
+
+ String prebuilt_api_dir = GodotSharpDirs::get_data_editor_prebuilt_api_dir().plus_file("Debug");
+ String prebuilt_core_dll_path = prebuilt_api_dir.plus_file(CORE_API_ASSEMBLY_NAME ".dll");
+ String prebuilt_editor_dll_path = prebuilt_api_dir.plus_file(EDITOR_API_ASSEMBLY_NAME ".dll");
+
+ if (!FileAccess::exists(prebuilt_core_dll_path) || !FileAccess::exists(prebuilt_editor_dll_path))
+ return FAIL_REASON(api_assembly_out_of_sync, /* prebuilt_exist: */ false);
+
+ // Copy the prebuilt Api
+ if (!copy_prebuilt_api_assembly(APIAssembly::API_CORE) || !copy_prebuilt_api_assembly(APIAssembly::API_EDITOR))
+ return FAIL_REASON(api_assembly_out_of_sync, /* prebuilt_exist: */ true);
+
+ return String(); // Updated successfully
+
+#undef FAIL_REASON
+}
#endif
bool GDMono::_load_core_api_assembly() {
@@ -616,35 +642,15 @@ bool GDMono::_load_core_api_assembly() {
return true;
#ifdef TOOLS_ENABLED
- if (metadata_is_api_assembly_invalidated(APIAssembly::API_CORE)) {
- String prebuilt_api_dir = GodotSharpDirs::get_data_editor_prebuilt_api_dir().plus_file("Debug");
- String prebuilt_dll_path = prebuilt_api_dir.plus_file(CORE_API_ASSEMBLY_NAME ".dll");
- String invalidated_dll_path = get_invalidated_api_assembly_path(APIAssembly::API_CORE);
-
- if (!FileAccess::exists(prebuilt_dll_path) ||
- FileAccess::get_modified_time(invalidated_dll_path) == FileAccess::get_modified_time(prebuilt_dll_path)) {
- print_verbose("Mono: Skipping loading of Core API assembly because it was invalidated");
- return false;
- } else {
- // Copy the prebuilt Api
- String res_assemblies_dir = GodotSharpDirs::get_res_assemblies_dir();
- if (!copy_api_assembly(prebuilt_api_dir, res_assemblies_dir, CORE_API_ASSEMBLY_NAME, APIAssembly::API_CORE) ||
- !copy_api_assembly(prebuilt_api_dir, res_assemblies_dir, EDITOR_API_ASSEMBLY_NAME, APIAssembly::API_EDITOR)) {
- print_verbose("Mono: Failed to copy prebuilt API. Skipping loading of Core API assembly because it was invalidated");
- return false;
- }
- }
- }
-#endif
-
+ // For the editor and the editor player we want to load it from a specific path to make sure we can keep it up to date
String assembly_path = GodotSharpDirs::get_res_assemblies_dir().plus_file(CORE_API_ASSEMBLY_NAME ".dll");
-
- bool success = (FileAccess::exists(assembly_path) &&
- load_assembly_from(CORE_API_ASSEMBLY_NAME, assembly_path, &core_api_assembly)) ||
- load_assembly(CORE_API_ASSEMBLY_NAME, &core_api_assembly);
+ bool success = FileAccess::exists(assembly_path) &&
+ load_assembly_from(CORE_API_ASSEMBLY_NAME, assembly_path, &core_api_assembly);
+#else
+ bool success = load_assembly(CORE_API_ASSEMBLY_NAME, &core_api_assembly);
+#endif
if (success) {
-#ifdef MONO_GLUE_ENABLED
APIAssembly::Version api_assembly_ver = APIAssembly::Version::get_from_loaded_assembly(core_api_assembly, APIAssembly::API_CORE);
core_api_assembly_out_of_sync = GodotSharpBindings::get_core_api_hash() != api_assembly_ver.godot_api_hash ||
GodotSharpBindings::get_bindings_version() != api_assembly_ver.bindings_version ||
@@ -654,9 +660,8 @@ bool GDMono::_load_core_api_assembly() {
_install_trace_listener();
}
-#else
- GDMonoUtils::update_godot_api_cache();
-#endif
+ } else {
+ core_api_assembly_out_of_sync = false;
}
return success;
@@ -668,44 +673,100 @@ bool GDMono::_load_editor_api_assembly() {
if (editor_api_assembly)
return true;
- if (metadata_is_api_assembly_invalidated(APIAssembly::API_EDITOR)) {
- String prebuilt_api_dir = GodotSharpDirs::get_data_editor_prebuilt_api_dir().plus_file("Debug");
- String prebuilt_dll_path = prebuilt_api_dir.plus_file(EDITOR_API_ASSEMBLY_NAME ".dll");
- String invalidated_dll_path = get_invalidated_api_assembly_path(APIAssembly::API_EDITOR);
-
- if (!FileAccess::exists(prebuilt_dll_path) ||
- FileAccess::get_modified_time(invalidated_dll_path) == FileAccess::get_modified_time(prebuilt_dll_path)) {
- print_verbose("Mono: Skipping loading of Editor API assembly because it was invalidated");
- return false;
- } else {
- // Copy the prebuilt editor Api (no need to copy the core api if we got to this point)
- String res_assemblies_dir = GodotSharpDirs::get_res_assemblies_dir();
- if (!copy_api_assembly(prebuilt_api_dir, res_assemblies_dir, EDITOR_API_ASSEMBLY_NAME, APIAssembly::API_EDITOR)) {
- print_verbose("Mono: Failed to copy prebuilt API. Skipping loading of Editor API assembly because it was invalidated");
- return false;
- }
- }
- }
-
+ // For the editor and the editor player we want to load it from a specific path to make sure we can keep it up to date
String assembly_path = GodotSharpDirs::get_res_assemblies_dir().plus_file(EDITOR_API_ASSEMBLY_NAME ".dll");
-
- bool success = (FileAccess::exists(assembly_path) &&
- load_assembly_from(EDITOR_API_ASSEMBLY_NAME, assembly_path, &editor_api_assembly)) ||
- load_assembly(EDITOR_API_ASSEMBLY_NAME, &editor_api_assembly);
+ bool success = FileAccess::exists(assembly_path) &&
+ load_assembly_from(EDITOR_API_ASSEMBLY_NAME, assembly_path, &editor_api_assembly);
if (success) {
-#ifdef MONO_GLUE_ENABLED
APIAssembly::Version api_assembly_ver = APIAssembly::Version::get_from_loaded_assembly(editor_api_assembly, APIAssembly::API_EDITOR);
editor_api_assembly_out_of_sync = GodotSharpBindings::get_editor_api_hash() != api_assembly_ver.godot_api_hash ||
GodotSharpBindings::get_bindings_version() != api_assembly_ver.bindings_version ||
CS_GLUE_VERSION != api_assembly_ver.cs_glue_version;
-#endif
+ } else {
+ editor_api_assembly_out_of_sync = false;
}
return success;
}
#endif
+bool GDMono::_try_load_api_assemblies() {
+
+ if (!_load_core_api_assembly()) {
+ if (OS::get_singleton()->is_stdout_verbose())
+ print_error("Mono: Failed to load Core API assembly");
+ return false;
+ }
+
+ if (core_api_assembly_out_of_sync || !GDMonoUtils::mono_cache.godot_api_cache_updated)
+ return false;
+
+#ifdef TOOLS_ENABLED
+ if (!_load_editor_api_assembly()) {
+ if (OS::get_singleton()->is_stdout_verbose())
+ print_error("Mono: Failed to load Editor API assembly");
+ return false;
+ }
+
+ if (editor_api_assembly_out_of_sync)
+ return false;
+#endif
+
+ return true;
+}
+
+void GDMono::_load_api_assemblies() {
+
+ if (!_try_load_api_assemblies()) {
+ // The API assemblies are out of sync. Fine, try one more time, but this time
+ // update them from the prebuilt assemblies directory before trying to load them.
+
+ // 1. Unload the scripts domain
+ if (_unload_scripts_domain() != OK) {
+ ERR_EXPLAIN("Mono: Failed to unload scripts domain");
+ CRASH_NOW();
+ }
+
+ // 2. Update the API assemblies
+ String update_error = update_api_assemblies_from_prebuilt();
+ if (!update_error.empty()) {
+ ERR_EXPLAIN(update_error);
+ CRASH_NOW();
+ }
+
+ // 3. Load the scripts domain again
+ if (_load_scripts_domain() != OK) {
+ ERR_EXPLAIN("Mono: Failed to load scripts domain");
+ CRASH_NOW();
+ }
+
+ // 4. Try loading the updated assemblies
+ if (!_try_load_api_assemblies()) {
+ // welp... too bad
+
+ if (_are_api_assemblies_out_of_sync()) {
+ if (core_api_assembly_out_of_sync) {
+ ERR_PRINT("The assembly '" CORE_API_ASSEMBLY_NAME "' is out of sync");
+ } else if (!GDMonoUtils::mono_cache.godot_api_cache_updated) {
+ ERR_PRINT("The loaded assembly '" CORE_API_ASSEMBLY_NAME "' is in sync, but the cache update failed");
+ }
+
+#ifdef TOOLS_ENABLED
+ if (editor_api_assembly_out_of_sync) {
+ ERR_PRINT("The assembly '" EDITOR_API_ASSEMBLY_NAME "' is out of sync");
+ }
+#endif
+
+ CRASH_NOW();
+ } else {
+ ERR_EXPLAIN("Failed to load one of the API assemblies");
+ CRASH_NOW();
+ }
+ }
+ }
+}
+
#ifdef TOOLS_ENABLED
bool GDMono::_load_tools_assemblies() {
@@ -734,39 +795,11 @@ bool GDMono::_load_project_assembly() {
if (success) {
mono_assembly_set_main(project_assembly->get_assembly());
- } else {
- if (OS::get_singleton()->is_stdout_verbose())
- print_error("Mono: Failed to load project assembly");
}
return success;
}
-bool GDMono::_load_api_assemblies() {
-
- if (!_load_core_api_assembly()) {
- if (OS::get_singleton()->is_stdout_verbose())
- print_error("Mono: Failed to load Core API assembly");
- return false;
- }
-
- if (core_api_assembly_out_of_sync || !GDMonoUtils::mono_cache.godot_api_cache_updated)
- return false;
-
-#ifdef TOOLS_ENABLED
- if (!_load_editor_api_assembly()) {
- if (OS::get_singleton()->is_stdout_verbose())
- print_error("Mono: Failed to load Editor API assembly");
- return false;
- }
-
- if (editor_api_assembly_out_of_sync)
- return false;
-#endif
-
- return true;
-}
-
void GDMono::_install_trace_listener() {
#ifdef DEBUG_ENABLED
@@ -784,78 +817,6 @@ void GDMono::_install_trace_listener() {
#endif
}
-#ifdef TOOLS_ENABLED
-String GDMono::_get_api_assembly_metadata_path() {
-
- return GodotSharpDirs::get_res_metadata_dir().plus_file("api_assemblies.cfg");
-}
-
-void GDMono::metadata_set_api_assembly_invalidated(APIAssembly::Type p_api_type, bool p_invalidated) {
-
- String section = APIAssembly::to_string(p_api_type);
- String path = _get_api_assembly_metadata_path();
-
- Ref<ConfigFile> metadata;
- metadata.instance();
- metadata->load(path);
-
- metadata->set_value(section, "invalidated", p_invalidated);
-
- String assembly_path = GodotSharpDirs::get_res_assemblies_dir()
- .plus_file(p_api_type == APIAssembly::API_CORE ?
- CORE_API_ASSEMBLY_NAME ".dll" :
- EDITOR_API_ASSEMBLY_NAME ".dll");
-
- ERR_FAIL_COND(!FileAccess::exists(assembly_path));
-
- uint64_t modified_time = FileAccess::get_modified_time(assembly_path);
-
- metadata->set_value(section, "invalidated_asm_modified_time", String::num_uint64(modified_time));
-
- String dir = path.get_base_dir();
- if (!DirAccess::exists(dir)) {
- DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- ERR_FAIL_COND(!da);
- Error err = da->make_dir_recursive(ProjectSettings::get_singleton()->globalize_path(dir));
- ERR_FAIL_COND(err != OK);
- }
-
- Error save_err = metadata->save(path);
- ERR_FAIL_COND(save_err != OK);
-}
-
-bool GDMono::metadata_is_api_assembly_invalidated(APIAssembly::Type p_api_type) {
-
- String section = APIAssembly::to_string(p_api_type);
-
- Ref<ConfigFile> metadata;
- metadata.instance();
- metadata->load(_get_api_assembly_metadata_path());
-
- String assembly_path = GodotSharpDirs::get_res_assemblies_dir()
- .plus_file(p_api_type == APIAssembly::API_CORE ?
- CORE_API_ASSEMBLY_NAME ".dll" :
- EDITOR_API_ASSEMBLY_NAME ".dll");
-
- if (!FileAccess::exists(assembly_path))
- return false;
-
- uint64_t modified_time = FileAccess::get_modified_time(assembly_path);
-
- uint64_t stored_modified_time = metadata->get_value(section, "invalidated_asm_modified_time", 0);
-
- return metadata->get_value(section, "invalidated", false) && modified_time <= stored_modified_time;
-}
-
-String GDMono::get_invalidated_api_assembly_path(APIAssembly::Type p_api_type) {
-
- return GodotSharpDirs::get_res_assemblies_dir()
- .plus_file(p_api_type == APIAssembly::API_CORE ?
- CORE_API_ASSEMBLY_NAME ".dll" :
- EDITOR_API_ASSEMBLY_NAME ".dll");
-}
-#endif
-
Error GDMono::_load_scripts_domain() {
ERR_FAIL_COND_V(scripts_domain != NULL, ERR_BUG);
@@ -903,11 +864,6 @@ Error GDMono::_unload_scripts_domain() {
tools_project_editor_assembly = NULL;
#endif
- core_api_assembly_out_of_sync = false;
-#ifdef TOOLS_ENABLED
- editor_api_assembly_out_of_sync = false;
-#endif
-
MonoDomain *domain = scripts_domain;
scripts_domain = NULL;
@@ -944,57 +900,25 @@ Error GDMono::reload_scripts_domain() {
return err;
}
-#ifdef MONO_GLUE_ENABLED
- if (!_load_api_assemblies()) {
- if ((core_api_assembly && (core_api_assembly_out_of_sync || !GDMonoUtils::mono_cache.godot_api_cache_updated))
-#ifdef TOOLS_ENABLED
- || (editor_api_assembly && editor_api_assembly_out_of_sync)
-#endif
- ) {
-#ifdef TOOLS_ENABLED
- // The assembly was successfully loaded, but the full api could not be cached.
- // This is most likely an outdated assembly loaded because of an invalid version in the
- // metadata, so we invalidate the version in the metadata and unload the script domain.
-
- if (core_api_assembly_out_of_sync) {
- ERR_PRINT(OUT_OF_SYNC_ERR_MESSAGE(CORE_API_ASSEMBLY_NAME));
- metadata_set_api_assembly_invalidated(APIAssembly::API_CORE, true);
- } else if (!GDMonoUtils::mono_cache.godot_api_cache_updated) {
- ERR_PRINT("The loaded Core API assembly is in sync, but the cache update failed");
- metadata_set_api_assembly_invalidated(APIAssembly::API_CORE, true);
- }
-
- if (editor_api_assembly_out_of_sync) {
- ERR_PRINT(OUT_OF_SYNC_ERR_MESSAGE(EDITOR_API_ASSEMBLY_NAME));
- metadata_set_api_assembly_invalidated(APIAssembly::API_EDITOR, true);
- }
+ // Load assemblies. The API and tools assemblies are required,
+ // the application is aborted if these assemblies cannot be loaded.
- err = _unload_scripts_domain();
- if (err != OK) {
- WARN_PRINT("Mono: Failed to unload scripts domain");
- }
+ _load_api_assemblies();
- return ERR_CANT_RESOLVE;
-#else
- ERR_PRINT("The loaded API assembly is invalid");
- CRASH_NOW();
-#endif
- } else {
- return ERR_CANT_OPEN;
- }
+#if defined(TOOLS_ENABLED)
+ if (!_load_tools_assemblies()) {
+ ERR_EXPLAIN("Mono: Failed to load GodotTools assemblies");
+ CRASH_NOW();
}
-
-#ifdef TOOLS_ENABLED
- ERR_EXPLAIN("Mono: Failed to load GodotTools assemblies");
- ERR_FAIL_COND_V(!_load_tools_assemblies(), ERR_CANT_OPEN);
#endif
+ // Load the project's main assembly. Here, during hot-reloading, we do
+ // consider failing to load the project's main assembly to be an error.
+ // However, unlike the API and tools assemblies, the application can continue working.
if (!_load_project_assembly()) {
+ print_error("Mono: Failed to load project assembly");
return ERR_CANT_OPEN;
}
-#else
- print_verbose("Mono: Glue disabled, ignoring script assemblies.");
-#endif // MONO_GLUE_ENABLED
return OK;
}
diff --git a/modules/mono/mono_gd/gd_mono.h b/modules/mono/mono_gd/gd_mono.h
index a926bf4126..deebe5fd50 100644
--- a/modules/mono/mono_gd/gd_mono.h
+++ b/modules/mono/mono_gd/gd_mono.h
@@ -104,6 +104,8 @@ class GDMono {
void _domain_assemblies_cleanup(uint32_t p_domain_id);
+ bool _are_api_assemblies_out_of_sync();
+
bool _load_corlib_assembly();
bool _load_core_api_assembly();
#ifdef TOOLS_ENABLED
@@ -112,11 +114,8 @@ class GDMono {
#endif
bool _load_project_assembly();
- bool _load_api_assemblies();
-
-#ifdef TOOLS_ENABLED
- String _get_api_assembly_metadata_path();
-#endif
+ bool _try_load_api_assemblies();
+ void _load_api_assemblies();
void _install_trace_listener();
@@ -157,9 +156,8 @@ public:
#endif
#ifdef TOOLS_ENABLED
- void metadata_set_api_assembly_invalidated(APIAssembly::Type p_api_type, bool p_invalidated);
- bool metadata_is_api_assembly_invalidated(APIAssembly::Type p_api_type);
- String get_invalidated_api_assembly_path(APIAssembly::Type p_api_type);
+ bool copy_prebuilt_api_assembly(APIAssembly::Type p_api_type);
+ String update_api_assemblies_from_prebuilt();
#endif
static GDMono *get_singleton() { return singleton; }
@@ -203,6 +201,7 @@ public:
Error finalize_and_unload_domain(MonoDomain *p_domain);
void initialize();
+ void initialize_load_assemblies();
GDMono();
~GDMono();
diff --git a/modules/opensimplex/doc_classes/NoiseTexture.xml b/modules/opensimplex/doc_classes/NoiseTexture.xml
index 4826b6cd2a..4b59a380f5 100644
--- a/modules/opensimplex/doc_classes/NoiseTexture.xml
+++ b/modules/opensimplex/doc_classes/NoiseTexture.xml
@@ -20,7 +20,7 @@
<member name="height" type="int" setter="set_height" getter="get_height" default="512">
Height of the generated texture.
</member>
- <member name="noise" type="OpenSimplexNoise" setter="set_noise" getter="get_noise" default="null">
+ <member name="noise" type="OpenSimplexNoise" setter="set_noise" getter="get_noise">
The [OpenSimplexNoise] instance used to generate the noise.
</member>
<member name="seamless" type="bool" setter="set_seamless" getter="get_seamless" default="false">
diff --git a/modules/regex/doc_classes/RegExMatch.xml b/modules/regex/doc_classes/RegExMatch.xml
index e279607d13..6dec9fc516 100644
--- a/modules/regex/doc_classes/RegExMatch.xml
+++ b/modules/regex/doc_classes/RegExMatch.xml
@@ -48,9 +48,7 @@
</method>
</methods>
<members>
- <member name="names" type="Dictionary" setter="" getter="get_names" default="{
-
-}">
+ <member name="names" type="Dictionary" setter="" getter="get_names" default="{}">
A dictionary of named groups and its corresponding group number. Only groups with that were matched are included. If multiple groups have the same name, that name would refer to the first matching one.
</member>
<member name="strings" type="Array" setter="" getter="get_strings" default="[ ]">
diff --git a/modules/visual_script/doc_classes/VisualScriptPreload.xml b/modules/visual_script/doc_classes/VisualScriptPreload.xml
index 05ed0ad1e5..b3b39691c9 100644
--- a/modules/visual_script/doc_classes/VisualScriptPreload.xml
+++ b/modules/visual_script/doc_classes/VisualScriptPreload.xml
@@ -15,7 +15,7 @@
<methods>
</methods>
<members>
- <member name="resource" type="Resource" setter="set_preload" getter="get_preload" default="null">
+ <member name="resource" type="Resource" setter="set_preload" getter="get_preload">
The [Resource] to load.
</member>
</members>