summaryrefslogtreecommitdiff
path: root/modules/mono/editor
diff options
context:
space:
mode:
Diffstat (limited to 'modules/mono/editor')
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.Core/FileUtils.cs27
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj1
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs5
-rw-r--r--modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs62
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs54
-rw-r--r--modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs21
-rw-r--r--modules/mono/editor/bindings_generator.cpp2
-rw-r--r--modules/mono/editor/editor_internal_calls.cpp10
-rw-r--r--modules/mono/editor/godotsharp_export.cpp18
-rw-r--r--modules/mono/editor/godotsharp_export.h4
10 files changed, 135 insertions, 69 deletions
diff --git a/modules/mono/editor/GodotTools/GodotTools.Core/FileUtils.cs b/modules/mono/editor/GodotTools/GodotTools.Core/FileUtils.cs
new file mode 100644
index 0000000000..85760a3705
--- /dev/null
+++ b/modules/mono/editor/GodotTools/GodotTools.Core/FileUtils.cs
@@ -0,0 +1,27 @@
+using System.IO;
+
+namespace GodotTools.Core
+{
+ public static class FileUtils
+ {
+ public static void SaveBackupCopy(string filePath)
+ {
+ string backupPathBase = filePath + ".old";
+ string backupPath = backupPathBase;
+
+ const int maxAttempts = 5;
+ int attempt = 1;
+
+ while (File.Exists(backupPath) && attempt <= maxAttempts)
+ {
+ backupPath = backupPathBase + "." + (attempt);
+ attempt++;
+ }
+
+ if (attempt > maxAttempts + 1)
+ return;
+
+ File.Copy(filePath, backupPath, overwrite: true);
+ }
+ }
+}
diff --git a/modules/mono/editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj b/modules/mono/editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj
index 2c35ef540a..c9ea7d3a2c 100644
--- a/modules/mono/editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj
+++ b/modules/mono/editor/GodotTools/GodotTools.Core/GodotTools.Core.csproj
@@ -31,6 +31,7 @@
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="FileUtils.cs" />
<Compile Include="ProcessExtensions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="StringExtensions.cs" />
diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs
index 9afd9adeb1..6f318aab4a 100644
--- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs
+++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/DotNetSolution.cs
@@ -153,7 +153,12 @@ EndProject";
var result = regex.Replace(input,m => dict[m.Value]);
if (result != input)
+ {
+ // Save a copy of the solution before replacing it
+ FileUtils.SaveBackupCopy(slnPath);
+
File.WriteAllText(slnPath, result);
+ }
}
}
}
diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs
index 1776b46e6a..f2ebef1a7d 100644
--- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs
+++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/ProjectUtils.cs
@@ -9,8 +9,28 @@ using Microsoft.Build.Construction;
namespace GodotTools.ProjectEditor
{
+ public sealed class MSBuildProject
+ {
+ public ProjectRootElement Root { get; }
+
+ public bool HasUnsavedChanges { get; set; }
+
+ public void Save() => Root.Save();
+
+ public MSBuildProject(ProjectRootElement root)
+ {
+ Root = root;
+ }
+ }
+
public static class ProjectUtils
{
+ public static MSBuildProject Open(string path)
+ {
+ var root = ProjectRootElement.Open(path);
+ return root != null ? new MSBuildProject(root) : null;
+ }
+
public static void AddItemToProjectChecked(string projectPath, string itemType, string include)
{
var dir = Directory.GetParent(projectPath).FullName;
@@ -43,7 +63,6 @@ namespace GodotTools.ProjectEditor
public static void RemoveItemFromProjectChecked(string projectPath, string itemType, string include)
{
- var dir = Directory.GetParent(projectPath).FullName;
var root = ProjectRootElement.Open(projectPath);
Debug.Assert(root != null);
@@ -150,12 +169,9 @@ namespace GodotTools.ProjectEditor
}
/// Simple function to make sure the Api assembly references are configured correctly
- public static void FixApiHintPath(string projectPath)
+ public static void FixApiHintPath(MSBuildProject project)
{
- var root = ProjectRootElement.Open(projectPath);
- Debug.Assert(root != null);
-
- bool dirty = false;
+ var root = project.Root;
void AddPropertyIfNotPresent(string name, string condition, string value)
{
@@ -170,7 +186,7 @@ namespace GodotTools.ProjectEditor
}
root.AddProperty(name, value).Condition = " " + condition + " ";
- dirty = true;
+ project.HasUnsavedChanges = true;
}
AddPropertyIfNotPresent(name: "ApiConfiguration",
@@ -212,7 +228,7 @@ namespace GodotTools.ProjectEditor
}
referenceWithHintPath.AddMetadata("HintPath", hintPath);
- dirty = true;
+ project.HasUnsavedChanges = true;
return;
}
@@ -221,14 +237,14 @@ namespace GodotTools.ProjectEditor
{
// Found a Reference item without a HintPath
referenceWithoutHintPath.AddMetadata("HintPath", hintPath);
- dirty = true;
+ project.HasUnsavedChanges = true;
return;
}
}
// Found no Reference item at all. Add it.
root.AddItem("Reference", referenceName).Condition = " " + condition + " ";
- dirty = true;
+ project.HasUnsavedChanges = true;
}
const string coreProjectName = "GodotSharp";
@@ -242,17 +258,11 @@ namespace GodotTools.ProjectEditor
SetReferenceHintPath(coreProjectName, coreCondition, coreHintPath);
SetReferenceHintPath(editorProjectName, editorCondition, editorHintPath);
-
- if (dirty)
- root.Save();
}
- public static void MigrateFromOldConfigNames(string projectPath)
+ public static void MigrateFromOldConfigNames(MSBuildProject project)
{
- var root = ProjectRootElement.Open(projectPath);
- Debug.Assert(root != null);
-
- bool dirty = false;
+ var root = project.Root;
bool hasGodotProjectGeneratorVersion = false;
bool foundOldConfiguration = false;
@@ -267,7 +277,7 @@ namespace GodotTools.ProjectEditor
{
configItem.Value = "Debug";
foundOldConfiguration = true;
- dirty = true;
+ project.HasUnsavedChanges = true;
}
}
@@ -275,7 +285,7 @@ namespace GodotTools.ProjectEditor
{
root.PropertyGroups.First(g => g.Condition == string.Empty)?
.AddProperty("GodotProjectGeneratorVersion", Assembly.GetExecutingAssembly().GetName().Version.ToString());
- dirty = true;
+ project.HasUnsavedChanges = true;
}
if (!foundOldConfiguration)
@@ -301,7 +311,7 @@ namespace GodotTools.ProjectEditor
foreach (var propertyGroup in root.PropertyGroups.Where(g => g.Condition.Trim() == oldCondition))
{
propertyGroup.Condition = " " + newCondition + " ";
- dirty = true;
+ project.HasUnsavedChanges = true;
}
foreach (var propertyGroup in root.PropertyGroups)
@@ -309,14 +319,14 @@ namespace GodotTools.ProjectEditor
foreach (var prop in propertyGroup.Properties.Where(p => p.Condition.Trim() == oldCondition))
{
prop.Condition = " " + newCondition + " ";
- dirty = true;
+ project.HasUnsavedChanges = true;
}
}
foreach (var itemGroup in root.ItemGroups.Where(g => g.Condition.Trim() == oldCondition))
{
itemGroup.Condition = " " + newCondition + " ";
- dirty = true;
+ project.HasUnsavedChanges = true;
}
foreach (var itemGroup in root.ItemGroups)
@@ -324,7 +334,7 @@ namespace GodotTools.ProjectEditor
foreach (var item in itemGroup.Items.Where(item => item.Condition.Trim() == oldCondition))
{
item.Condition = " " + newCondition + " ";
- dirty = true;
+ project.HasUnsavedChanges = true;
}
}
}
@@ -340,10 +350,6 @@ namespace GodotTools.ProjectEditor
MigrateConfigurationConditions("Release", "ExportRelease");
MigrateConfigurationConditions("Tools", "Debug"); // Must be last
}
-
-
- if (dirty)
- root.Save();
}
}
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs
index d782d4e61b..2ceb4888a2 100644
--- a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs
@@ -168,13 +168,13 @@ namespace GodotTools.Export
// Add dependency assemblies
- var dependencies = new Godot.Collections.Dictionary<string, string>();
+ var assemblies = new Godot.Collections.Dictionary<string, string>();
string projectDllName = GodotSharpEditor.ProjectAssemblyName;
string projectDllSrcDir = Path.Combine(GodotSharpDirs.ResTempAssembliesBaseDir, buildConfig);
string projectDllSrcPath = Path.Combine(projectDllSrcDir, $"{projectDllName}.dll");
- dependencies[projectDllName] = projectDllSrcPath;
+ assemblies[projectDllName] = projectDllSrcPath;
if (platform == OS.Platforms.Android)
{
@@ -184,15 +184,15 @@ namespace GodotTools.Export
if (!File.Exists(monoAndroidAssemblyPath))
throw new FileNotFoundException("Assembly not found: 'Mono.Android'", monoAndroidAssemblyPath);
- dependencies["Mono.Android"] = monoAndroidAssemblyPath;
+ assemblies["Mono.Android"] = monoAndroidAssemblyPath;
}
string bclDir = DeterminePlatformBclDir(platform);
- var initialDependencies = dependencies.Duplicate();
- internal_GetExportedAssemblyDependencies(initialDependencies, buildConfig, bclDir, dependencies);
+ var initialAssemblies = assemblies.Duplicate();
+ internal_GetExportedAssemblyDependencies(initialAssemblies, buildConfig, bclDir, assemblies);
- AddI18NAssemblies(dependencies, bclDir);
+ AddI18NAssemblies(assemblies, bclDir);
string outputDataDir = null;
@@ -211,20 +211,32 @@ namespace GodotTools.Export
Directory.CreateDirectory(outputDataGameAssembliesDir);
}
- foreach (var dependency in dependencies)
+ foreach (var assembly in assemblies)
{
- string dependSrcPath = dependency.Value;
-
- if (assembliesInsidePck)
- {
- string dependDstPath = Path.Combine(resAssembliesDir, dependSrcPath.GetFile());
- AddFile(dependSrcPath, dependDstPath);
- }
- else
+ void AddToAssembliesDir(string fileSrcPath)
{
- string dependDstPath = Path.Combine(outputDataDir, "Assemblies", dependSrcPath.GetFile());
- File.Copy(dependSrcPath, dependDstPath);
+ if (assembliesInsidePck)
+ {
+ string fileDstPath = Path.Combine(resAssembliesDir, fileSrcPath.GetFile());
+ AddFile(fileSrcPath, fileDstPath);
+ }
+ else
+ {
+ Debug.Assert(outputDataDir != null);
+ string fileDstPath = Path.Combine(outputDataDir, "Assemblies", fileSrcPath.GetFile());
+ File.Copy(fileSrcPath, fileDstPath);
+ }
}
+
+ string assemblySrcPath = assembly.Value;
+
+ string assemblyPathWithoutExtension = Path.ChangeExtension(assemblySrcPath, null);
+ string pdbSrcPath = assemblyPathWithoutExtension + ".pdb";
+
+ AddToAssembliesDir(assemblySrcPath);
+
+ if (File.Exists(pdbSrcPath))
+ AddToAssembliesDir(pdbSrcPath);
}
// AOT compilation
@@ -254,7 +266,7 @@ namespace GodotTools.Export
ToolchainPath = aotToolchainPath
};
- AotBuilder.CompileAssemblies(this, aotOpts, features, platform, isDebug, bclDir, outputDir, outputDataDir, dependencies);
+ AotBuilder.CompileAssemblies(this, aotOpts, features, platform, isDebug, bclDir, outputDir, outputDataDir, assemblies);
}
}
@@ -366,7 +378,7 @@ namespace GodotTools.Export
if (PlatformRequiresCustomBcl(platform))
throw new FileNotFoundException($"Missing BCL (Base Class Library) for platform: {platform}");
- platformBclDir = typeof(object).Assembly.Location; // Use the one we're running on
+ platformBclDir = typeof(object).Assembly.Location.GetBaseDir(); // Use the one we're running on
}
}
@@ -425,7 +437,7 @@ namespace GodotTools.Export
}
[MethodImpl(MethodImplOptions.InternalCall)]
- private static extern void internal_GetExportedAssemblyDependencies(Godot.Collections.Dictionary<string, string> initialDependencies,
- string buildConfig, string customBclDir, Godot.Collections.Dictionary<string, string> dependencies);
+ private static extern void internal_GetExportedAssemblyDependencies(Godot.Collections.Dictionary<string, string> initialAssemblies,
+ string buildConfig, string customBclDir, Godot.Collections.Dictionary<string, string> dependencyAssemblies);
}
}
diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
index c9d7dd26f8..c070cb16d9 100644
--- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
+++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs
@@ -1,4 +1,5 @@
using Godot;
+using GodotTools.Core;
using GodotTools.Export;
using GodotTools.Utils;
using System;
@@ -442,13 +443,27 @@ namespace GodotTools
{
// Migrate solution from old configuration names to: Debug, ExportDebug and ExportRelease
DotNetSolution.MigrateFromOldConfigNames(GodotSharpDirs.ProjectSlnPath);
+
+ var msbuildProject = ProjectUtils.Open(GodotSharpDirs.ProjectCsProjPath)
+ ?? throw new Exception("Cannot open C# project");
+
+ // NOTE: The order in which changes are made to the project is important
+
// Migrate csproj from old configuration names to: Debug, ExportDebug and ExportRelease
- ProjectUtils.MigrateFromOldConfigNames(GodotSharpDirs.ProjectCsProjPath);
+ ProjectUtils.MigrateFromOldConfigNames(msbuildProject);
- // Apply the other fixes after configurations are migrated
+ // Apply the other fixes only after configurations have been migrated
// Make sure the existing project has Api assembly references configured correctly
- ProjectUtils.FixApiHintPath(GodotSharpDirs.ProjectCsProjPath);
+ ProjectUtils.FixApiHintPath(msbuildProject);
+
+ if (msbuildProject.HasUnsavedChanges)
+ {
+ // Save a copy of the project before replacing it
+ FileUtils.SaveBackupCopy(GodotSharpDirs.ProjectCsProjPath);
+
+ msbuildProject.Save();
+ }
}
catch (Exception e)
{
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index 71bb8ff851..ee92a6234a 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -2383,7 +2383,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
for (const List<PropertyInfo>::Element *E = property_list.front(); E; E = E->next()) {
const PropertyInfo &property = E->get();
- if (property.usage & PROPERTY_USAGE_GROUP || property.usage & PROPERTY_USAGE_CATEGORY)
+ if (property.usage & PROPERTY_USAGE_GROUP || property.usage & PROPERTY_USAGE_SUBGROUP || property.usage & PROPERTY_USAGE_CATEGORY)
continue;
PropertyInterface iprop;
diff --git a/modules/mono/editor/editor_internal_calls.cpp b/modules/mono/editor/editor_internal_calls.cpp
index 283d4beb8e..c3e7e67ae9 100644
--- a/modules/mono/editor/editor_internal_calls.cpp
+++ b/modules/mono/editor/editor_internal_calls.cpp
@@ -231,14 +231,14 @@ int32_t godot_icall_ScriptClassParser_ParseFile(MonoString *p_filepath, MonoObje
return err;
}
-uint32_t godot_icall_ExportPlugin_GetExportedAssemblyDependencies(MonoObject *p_initial_dependencies,
- MonoString *p_build_config, MonoString *p_custom_bcl_dir, MonoObject *r_dependencies) {
- Dictionary initial_dependencies = GDMonoMarshal::mono_object_to_variant(p_initial_dependencies);
+uint32_t godot_icall_ExportPlugin_GetExportedAssemblyDependencies(MonoObject *p_initial_assemblies,
+ MonoString *p_build_config, MonoString *p_custom_bcl_dir, MonoObject *r_assembly_dependencies) {
+ Dictionary initial_dependencies = GDMonoMarshal::mono_object_to_variant(p_initial_assemblies);
String build_config = GDMonoMarshal::mono_string_to_godot(p_build_config);
String custom_bcl_dir = GDMonoMarshal::mono_string_to_godot(p_custom_bcl_dir);
- Dictionary dependencies = GDMonoMarshal::mono_object_to_variant(r_dependencies);
+ Dictionary assembly_dependencies = GDMonoMarshal::mono_object_to_variant(r_assembly_dependencies);
- return GodotSharpExport::get_exported_assembly_dependencies(initial_dependencies, build_config, custom_bcl_dir, dependencies);
+ return GodotSharpExport::get_exported_assembly_dependencies(initial_dependencies, build_config, custom_bcl_dir, assembly_dependencies);
}
MonoString *godot_icall_Internal_UpdateApiAssembliesFromPrebuilt(MonoString *p_config) {
diff --git a/modules/mono/editor/godotsharp_export.cpp b/modules/mono/editor/godotsharp_export.cpp
index 324013e5e2..4126da16be 100644
--- a/modules/mono/editor/godotsharp_export.cpp
+++ b/modules/mono/editor/godotsharp_export.cpp
@@ -50,13 +50,13 @@ String get_assemblyref_name(MonoImage *p_image, int index) {
return String::utf8(mono_metadata_string_heap(p_image, cols[MONO_ASSEMBLYREF_NAME]));
}
-Error get_assembly_dependencies(GDMonoAssembly *p_assembly, const Vector<String> &p_search_dirs, Dictionary &r_dependencies) {
+Error get_assembly_dependencies(GDMonoAssembly *p_assembly, const Vector<String> &p_search_dirs, Dictionary &r_assembly_dependencies) {
MonoImage *image = p_assembly->get_image();
for (int i = 0; i < mono_image_get_table_rows(image, MONO_TABLE_ASSEMBLYREF); i++) {
String ref_name = get_assemblyref_name(image, i);
- if (r_dependencies.has(ref_name))
+ if (r_assembly_dependencies.has(ref_name))
continue;
GDMonoAssembly *ref_assembly = nullptr;
@@ -93,17 +93,17 @@ Error get_assembly_dependencies(GDMonoAssembly *p_assembly, const Vector<String>
ERR_FAIL_COND_V_MSG(!ref_assembly, ERR_CANT_RESOLVE, "Cannot load assembly (refonly): '" + ref_name + "'.");
// Use the path we got from the search. Don't try to get the path from the loaded assembly as we can't trust it will be from the selected BCL dir.
- r_dependencies[ref_name] = path;
+ r_assembly_dependencies[ref_name] = path;
- Error err = get_assembly_dependencies(ref_assembly, p_search_dirs, r_dependencies);
+ Error err = get_assembly_dependencies(ref_assembly, p_search_dirs, r_assembly_dependencies);
ERR_FAIL_COND_V_MSG(err != OK, err, "Cannot load one of the dependencies for the assembly: '" + ref_name + "'.");
}
return OK;
}
-Error get_exported_assembly_dependencies(const Dictionary &p_initial_dependencies,
- const String &p_build_config, const String &p_custom_bcl_dir, Dictionary &r_dependencies) {
+Error get_exported_assembly_dependencies(const Dictionary &p_initial_assemblies,
+ const String &p_build_config, const String &p_custom_bcl_dir, Dictionary &r_assembly_dependencies) {
MonoDomain *export_domain = GDMonoUtils::create_domain("GodotEngine.Domain.ProjectExport");
ERR_FAIL_NULL_V(export_domain, FAILED);
_GDMONO_SCOPE_EXIT_DOMAIN_UNLOAD_(export_domain);
@@ -113,16 +113,16 @@ Error get_exported_assembly_dependencies(const Dictionary &p_initial_dependencie
Vector<String> search_dirs;
GDMonoAssembly::fill_search_dirs(search_dirs, p_build_config, p_custom_bcl_dir);
- for (const Variant *key = p_initial_dependencies.next(); key; key = p_initial_dependencies.next(key)) {
+ for (const Variant *key = p_initial_assemblies.next(); key; key = p_initial_assemblies.next(key)) {
String assembly_name = *key;
- String assembly_path = p_initial_dependencies[*key];
+ String assembly_path = p_initial_assemblies[*key];
GDMonoAssembly *assembly = nullptr;
bool load_success = GDMono::get_singleton()->load_assembly_from(assembly_name, assembly_path, &assembly, /* refonly: */ true);
ERR_FAIL_COND_V_MSG(!load_success, ERR_CANT_RESOLVE, "Cannot load assembly (refonly): '" + assembly_name + "'.");
- Error err = get_assembly_dependencies(assembly, search_dirs, r_dependencies);
+ Error err = get_assembly_dependencies(assembly, search_dirs, r_assembly_dependencies);
if (err != OK)
return err;
}
diff --git a/modules/mono/editor/godotsharp_export.h b/modules/mono/editor/godotsharp_export.h
index 36138f81b7..9ab57755de 100644
--- a/modules/mono/editor/godotsharp_export.h
+++ b/modules/mono/editor/godotsharp_export.h
@@ -41,8 +41,8 @@ namespace GodotSharpExport {
Error get_assembly_dependencies(GDMonoAssembly *p_assembly, const Vector<String> &p_search_dirs, Dictionary &r_dependencies);
-Error get_exported_assembly_dependencies(const Dictionary &p_initial_dependencies,
- const String &p_build_config, const String &p_custom_lib_dir, Dictionary &r_dependencies);
+Error get_exported_assembly_dependencies(const Dictionary &p_initial_assemblies,
+ const String &p_build_config, const String &p_custom_lib_dir, Dictionary &r_assembly_dependencies);
} // namespace GodotSharpExport