C#: Use custom project setting for C# project files name

The setting is initially assigned the name of the Godot project,
but it's kept freezed to prevent issues when renaming the Godot
project.

The user can always rename the C# project and solution manually and
change the setting to the new name.
This commit is contained in:
Ignacio Roldán Etcheverry 2022-07-28 17:41:51 +02:00
parent 0c30c678f0
commit 1bf4397e5b
10 changed files with 114 additions and 103 deletions

View file

@ -65,17 +65,8 @@
#ifdef TOOLS_ENABLED #ifdef TOOLS_ENABLED
static bool _create_project_solution_if_needed() { static bool _create_project_solution_if_needed() {
String sln_path = GodotSharpDirs::get_project_sln_path(); CRASH_COND(CSharpLanguage::get_singleton()->get_godotsharp_editor() == nullptr);
String csproj_path = GodotSharpDirs::get_project_csproj_path(); return CSharpLanguage::get_singleton()->get_godotsharp_editor()->call("CreateProjectSolutionIfNeeded");
if (!FileAccess::exists(sln_path) || !FileAccess::exists(csproj_path)) {
// A solution does not yet exist, create a new one
CRASH_COND(CSharpLanguage::get_singleton()->get_godotsharp_editor() == nullptr);
return CSharpLanguage::get_singleton()->get_godotsharp_editor()->call("CreateProjectSolution");
}
return true;
} }
#endif #endif
@ -107,7 +98,7 @@ Error CSharpLanguage::execute_file(const String &p_path) {
extern void *godotsharp_pinvoke_funcs[186]; extern void *godotsharp_pinvoke_funcs[186];
[[maybe_unused]] volatile void **do_not_strip_godotsharp_pinvoke_funcs; [[maybe_unused]] volatile void **do_not_strip_godotsharp_pinvoke_funcs;
#ifdef TOOLS_ENABLED #ifdef TOOLS_ENABLED
extern void *godotsharp_editor_pinvoke_funcs[30]; extern void *godotsharp_editor_pinvoke_funcs[28];
[[maybe_unused]] volatile void **do_not_strip_godotsharp_editor_pinvoke_funcs; [[maybe_unused]] volatile void **do_not_strip_godotsharp_editor_pinvoke_funcs;
#endif #endif
@ -709,10 +700,14 @@ bool CSharpLanguage::is_assembly_reloading_needed() {
return false; // Already up to date return false; // Already up to date
} }
} else { } else {
String appname_safe = ProjectSettings::get_singleton()->get_safe_project_name(); String assembly_name = ProjectSettings::get_singleton()->get_setting("dotnet/project/assembly_name");
if (assembly_name.is_empty()) {
assembly_name = ProjectSettings::get_singleton()->get_safe_project_name();
}
assembly_path = GodotSharpDirs::get_res_temp_assemblies_dir() assembly_path = GodotSharpDirs::get_res_temp_assemblies_dir()
.plus_file(appname_safe + ".dll"); .plus_file(assembly_name + ".dll");
assembly_path = ProjectSettings::get_singleton()->globalize_path(assembly_path); assembly_path = ProjectSettings::get_singleton()->globalize_path(assembly_path);
if (!FileAccess::exists(assembly_path)) { if (!FileAccess::exists(assembly_path)) {

View file

@ -289,7 +289,7 @@ MONO_AOT_MODE_LAST = 1000,
// Archive the AOT object files into a static library // Archive the AOT object files into a static library
var arFilePathsForAllArchs = new List<string>(); var arFilePathsForAllArchs = new List<string>();
string projectAssemblyName = GodotSharpEditor.ProjectAssemblyName; string projectAssemblyName = GodotSharpDirs.ProjectAssemblyName;
foreach (var archPathsPair in objFilePathsForiOSArch) foreach (var archPathsPair in objFilePathsForiOSArch)
{ {

View file

@ -141,9 +141,9 @@ namespace GodotTools.Export
_ => "so" _ => "so"
}; };
if (!File.Exists(Path.Combine(publishOutputTempDir, $"{GodotSharpEditor.ProjectAssemblyName}.dll")) if (!File.Exists(Path.Combine(publishOutputTempDir, $"{GodotSharpDirs.ProjectAssemblyName}.dll"))
// NativeAOT shared library output // NativeAOT shared library output
&& !File.Exists(Path.Combine(publishOutputTempDir, $"{GodotSharpEditor.ProjectAssemblyName}.{soExt}"))) && !File.Exists(Path.Combine(publishOutputTempDir, $"{GodotSharpDirs.ProjectAssemblyName}.{soExt}")))
{ {
throw new NotSupportedException( throw new NotSupportedException(
"Publish succeeded but project assembly not found in the output directory"); "Publish succeeded but project assembly not found in the output directory");

View file

@ -40,19 +40,17 @@ namespace GodotTools
public bool SkipBuildBeforePlaying { get; set; } = false; public bool SkipBuildBeforePlaying { get; set; } = false;
public static string ProjectAssemblyName [UsedImplicitly]
private bool CreateProjectSolutionIfNeeded()
{ {
get if (!File.Exists(GodotSharpDirs.ProjectSlnPath) || !File.Exists(GodotSharpDirs.ProjectCsProjPath))
{ {
string projectAssemblyName = (string)ProjectSettings.GetSetting("application/config/name"); return CreateProjectSolution();
projectAssemblyName = projectAssemblyName.ToSafeDirName();
if (string.IsNullOrEmpty(projectAssemblyName))
projectAssemblyName = "UnnamedProject";
return projectAssemblyName;
} }
return true;
} }
[UsedImplicitly]
private bool CreateProjectSolution() private bool CreateProjectSolution()
{ {
using (var pr = new EditorProgress("create_csharp_solution", "Generating solution...".TTR(), 2)) using (var pr = new EditorProgress("create_csharp_solution", "Generating solution...".TTR(), 2))
@ -62,7 +60,7 @@ namespace GodotTools
string resourceDir = ProjectSettings.GlobalizePath("res://"); string resourceDir = ProjectSettings.GlobalizePath("res://");
string path = resourceDir; string path = resourceDir;
string name = ProjectAssemblyName; string name = GodotSharpDirs.ProjectAssemblyName;
string guid = CsProjOperations.GenerateGameProject(path, name); string guid = CsProjOperations.GenerateGameProject(path, name);
@ -327,7 +325,8 @@ namespace GodotTools
[UsedImplicitly] [UsedImplicitly]
public bool OverridesExternalEditor() public bool OverridesExternalEditor()
{ {
return (ExternalEditorId)(int)_editorSettings.GetSetting("mono/editor/external_editor") != ExternalEditorId.None; return (ExternalEditorId)(int)_editorSettings.GetSetting("mono/editor/external_editor") !=
ExternalEditorId.None;
} }
public override bool _Build() public override bool _Build()
@ -348,7 +347,7 @@ namespace GodotTools
// NOTE: The order in which changes are made to the project is important // NOTE: The order in which changes are made to the project is important
// Migrate to MSBuild project Sdks style if using the old style // Migrate to MSBuild project Sdks style if using the old style
ProjectUtils.MigrateToProjectSdksStyle(msbuildProject, ProjectAssemblyName); ProjectUtils.MigrateToProjectSdksStyle(msbuildProject, GodotSharpDirs.ProjectAssemblyName);
ProjectUtils.EnsureGodotSdkIsUpToDate(msbuildProject); ProjectUtils.EnsureGodotSdkIsUpToDate(msbuildProject);
@ -412,6 +411,8 @@ namespace GodotTools
_editorSettings = editorInterface.GetEditorSettings(); _editorSettings = editorInterface.GetEditorSettings();
GodotSharpDirs.RegisterProjectSettings();
_errorDialog = new AcceptDialog(); _errorDialog = new AcceptDialog();
editorBaseControl.AddChild(_errorDialog); editorBaseControl.AddChild(_errorDialog);

View file

@ -1,4 +1,8 @@
using System.IO;
using Godot;
using Godot.NativeInterop; using Godot.NativeInterop;
using GodotTools.Core;
using static GodotTools.Internals.Globals;
namespace GodotTools.Internals namespace GodotTools.Internals
{ {
@ -34,26 +38,6 @@ namespace GodotTools.Internals
} }
} }
public static string ProjectSlnPath
{
get
{
Internal.godot_icall_GodotSharpDirs_ProjectSlnPath(out godot_string dest);
using (dest)
return Marshaling.ConvertStringToManaged(dest);
}
}
public static string ProjectCsProjPath
{
get
{
Internal.godot_icall_GodotSharpDirs_ProjectCsProjPath(out godot_string dest);
using (dest)
return Marshaling.ConvertStringToManaged(dest);
}
}
public static string DataEditorToolsDir public static string DataEditorToolsDir
{ {
get get
@ -63,5 +47,79 @@ namespace GodotTools.Internals
return Marshaling.ConvertStringToManaged(dest); return Marshaling.ConvertStringToManaged(dest);
} }
} }
public static void RegisterProjectSettings()
{
GlobalDef("dotnet/project/assembly_name", "");
GlobalDef("dotnet/project/solution_directory", "");
GlobalDef("dotnet/project/c#_project_directory", "");
}
private static void DetermineProjectLocation()
{
static string DetermineProjectName()
{
string projectAssemblyName = (string)ProjectSettings.GetSetting("application/config/name");
projectAssemblyName = projectAssemblyName.ToSafeDirName();
if (string.IsNullOrEmpty(projectAssemblyName))
projectAssemblyName = "UnnamedProject";
return projectAssemblyName;
}
_projectAssemblyName = (string)ProjectSettings.GetSetting("dotnet/project/assembly_name");
if (string.IsNullOrEmpty(_projectAssemblyName))
{
_projectAssemblyName = DetermineProjectName();
ProjectSettings.SetSetting("dotnet/project/assembly_name", _projectAssemblyName);
}
string slnParentDir = (string)ProjectSettings.GetSetting("dotnet/project/solution_directory");
if (string.IsNullOrEmpty(slnParentDir))
slnParentDir = "res://";
string csprojParentDir = (string)ProjectSettings.GetSetting("dotnet/project/c#_project_directory");
if (string.IsNullOrEmpty(csprojParentDir))
csprojParentDir = "res://";
_projectSlnPath = Path.Combine(ProjectSettings.GlobalizePath(slnParentDir),
string.Concat(_projectAssemblyName, ".sln"));
_projectCsProjPath = Path.Combine(ProjectSettings.GlobalizePath(csprojParentDir),
string.Concat(_projectAssemblyName, ".csproj"));
}
private static string _projectAssemblyName;
private static string _projectSlnPath;
private static string _projectCsProjPath;
public static string ProjectAssemblyName
{
get
{
if (_projectAssemblyName == null)
DetermineProjectLocation();
return _projectAssemblyName;
}
}
public static string ProjectSlnPath
{
get
{
if (_projectSlnPath == null)
DetermineProjectLocation();
return _projectSlnPath;
}
}
public static string ProjectCsProjPath
{
get
{
if (_projectCsProjPath == null)
DetermineProjectLocation();
return _projectCsProjPath;
}
}
} }
} }

View file

@ -75,12 +75,6 @@ namespace GodotTools.Internals
[DllImport(GodotDllName)] [DllImport(GodotDllName)]
public static extern void godot_icall_GodotSharpDirs_BuildLogsDirs(out godot_string r_dest); public static extern void godot_icall_GodotSharpDirs_BuildLogsDirs(out godot_string r_dest);
[DllImport(GodotDllName)]
public static extern void godot_icall_GodotSharpDirs_ProjectSlnPath(out godot_string r_dest);
[DllImport(GodotDllName)]
public static extern void godot_icall_GodotSharpDirs_ProjectCsProjPath(out godot_string r_dest);
[DllImport(GodotDllName)] [DllImport(GodotDllName)]
public static extern void godot_icall_GodotSharpDirs_DataEditorToolsDir(out godot_string r_dest); public static extern void godot_icall_GodotSharpDirs_DataEditorToolsDir(out godot_string r_dest);

View file

@ -86,22 +86,6 @@ GD_PINVOKE_EXPORT void godot_icall_GodotSharpDirs_BuildLogsDirs(godot_string *r_
#endif #endif
} }
GD_PINVOKE_EXPORT void godot_icall_GodotSharpDirs_ProjectSlnPath(godot_string *r_dest) {
#ifdef TOOLS_ENABLED
memnew_placement(r_dest, String(GodotSharpDirs::get_project_sln_path()));
#else
return nullptr;
#endif
}
GD_PINVOKE_EXPORT void godot_icall_GodotSharpDirs_ProjectCsProjPath(godot_string *r_dest) {
#ifdef TOOLS_ENABLED
memnew_placement(r_dest, String(GodotSharpDirs::get_project_csproj_path()));
#else
return nullptr;
#endif
}
GD_PINVOKE_EXPORT void godot_icall_GodotSharpDirs_DataEditorToolsDir(godot_string *r_dest) { GD_PINVOKE_EXPORT void godot_icall_GodotSharpDirs_DataEditorToolsDir(godot_string *r_dest) {
#ifdef TOOLS_ENABLED #ifdef TOOLS_ENABLED
memnew_placement(r_dest, String(GodotSharpDirs::get_data_editor_tools_dir())); memnew_placement(r_dest, String(GodotSharpDirs::get_data_editor_tools_dir()));
@ -253,12 +237,10 @@ GD_PINVOKE_EXPORT bool godot_icall_Utils_OS_UnixFileHasExecutableAccess(const go
} }
#endif #endif
void *godotsharp_editor_pinvoke_funcs[30] = { void *godotsharp_editor_pinvoke_funcs[28] = {
(void *)godot_icall_GodotSharpDirs_ResMetadataDir, (void *)godot_icall_GodotSharpDirs_ResMetadataDir,
(void *)godot_icall_GodotSharpDirs_MonoUserDir, (void *)godot_icall_GodotSharpDirs_MonoUserDir,
(void *)godot_icall_GodotSharpDirs_BuildLogsDirs, (void *)godot_icall_GodotSharpDirs_BuildLogsDirs,
(void *)godot_icall_GodotSharpDirs_ProjectSlnPath,
(void *)godot_icall_GodotSharpDirs_ProjectCsProjPath,
(void *)godot_icall_GodotSharpDirs_DataEditorToolsDir, (void *)godot_icall_GodotSharpDirs_DataEditorToolsDir,
(void *)godot_icall_EditorProgress_Create, (void *)godot_icall_EditorProgress_Create,
(void *)godot_icall_EditorProgress_Dispose, (void *)godot_icall_EditorProgress_Dispose,

View file

@ -110,9 +110,6 @@ public:
String mono_solutions_dir; String mono_solutions_dir;
String build_logs_dir; String build_logs_dir;
String sln_filepath;
String csproj_filepath;
String data_editor_tools_dir; String data_editor_tools_dir;
#else #else
// Equivalent of res_assemblies_dir, but in the data directory rather than in 'res://'. // Equivalent of res_assemblies_dir, but in the data directory rather than in 'res://'.
@ -151,16 +148,7 @@ private:
mono_solutions_dir = mono_user_dir.plus_file("solutions"); mono_solutions_dir = mono_user_dir.plus_file("solutions");
build_logs_dir = mono_user_dir.plus_file("build_logs"); build_logs_dir = mono_user_dir.plus_file("build_logs");
String appname = ProjectSettings::get_singleton()->get("application/config/name");
String appname_safe = OS::get_singleton()->get_safe_dir_name(appname);
if (appname_safe.is_empty()) {
appname_safe = "UnnamedProject";
}
String base_path = ProjectSettings::get_singleton()->globalize_path("res://"); String base_path = ProjectSettings::get_singleton()->globalize_path("res://");
sln_filepath = base_path.plus_file(appname_safe + ".sln");
csproj_filepath = base_path.plus_file(appname_safe + ".csproj");
#endif #endif
String exe_dir = OS::get_singleton()->get_executable_path().get_base_dir(); String exe_dir = OS::get_singleton()->get_executable_path().get_base_dir();
@ -298,14 +286,6 @@ String get_build_logs_dir() {
return _GodotSharpDirs::get_singleton().build_logs_dir; return _GodotSharpDirs::get_singleton().build_logs_dir;
} }
String get_project_sln_path() {
return _GodotSharpDirs::get_singleton().sln_filepath;
}
String get_project_csproj_path() {
return _GodotSharpDirs::get_singleton().csproj_filepath;
}
String get_data_editor_tools_dir() { String get_data_editor_tools_dir() {
return _GodotSharpDirs::get_singleton().data_editor_tools_dir; return _GodotSharpDirs::get_singleton().data_editor_tools_dir;
} }

View file

@ -52,9 +52,6 @@ String get_mono_logs_dir();
String get_mono_solutions_dir(); String get_mono_solutions_dir();
String get_build_logs_dir(); String get_build_logs_dir();
String get_project_sln_path();
String get_project_csproj_path();
String get_data_editor_tools_dir(); String get_data_editor_tools_dir();
#else #else
String get_data_game_assemblies_dir(); String get_data_game_assemblies_dir();

View file

@ -329,13 +329,13 @@ godot_plugins_initialize_fn initialize_hostfxr_and_godot_plugins(bool &r_runtime
} }
#else #else
static String get_assembly_name() { static String get_assembly_name() {
String appname = ProjectSettings::get_singleton()->get("application/config/name"); String assembly_name = ProjectSettings::get_singleton()->get_setting("dotnet/project/assembly_name");
String appname_safe = OS::get_singleton()->get_safe_dir_name(appname);
if (appname_safe.is_empty()) { if (assembly_name.is_empty()) {
appname_safe = "UnnamedProject"; assembly_name = ProjectSettings::get_singleton()->get_safe_project_name();
} }
return appname_safe; return assembly_name;
} }
godot_plugins_initialize_fn initialize_hostfxr_and_godot_plugins(bool &r_runtime_initialized) { godot_plugins_initialize_fn initialize_hostfxr_and_godot_plugins(bool &r_runtime_initialized) {
@ -501,10 +501,14 @@ void GDMono::_init_godot_api_hashes() {
#ifdef TOOLS_ENABLED #ifdef TOOLS_ENABLED
bool GDMono::_load_project_assembly() { bool GDMono::_load_project_assembly() {
String appname_safe = ProjectSettings::get_singleton()->get_safe_project_name(); String assembly_name = ProjectSettings::get_singleton()->get_setting("dotnet/project/assembly_name");
if (assembly_name.is_empty()) {
assembly_name = ProjectSettings::get_singleton()->get_safe_project_name();
}
String assembly_path = GodotSharpDirs::get_res_temp_assemblies_dir() String assembly_path = GodotSharpDirs::get_res_temp_assemblies_dir()
.plus_file(appname_safe + ".dll"); .plus_file(assembly_name + ".dll");
assembly_path = ProjectSettings::get_singleton()->globalize_path(assembly_path); assembly_path = ProjectSettings::get_singleton()->globalize_path(assembly_path);
String loaded_assembly_path; String loaded_assembly_path;