summaryrefslogtreecommitdiff
path: root/modules/mono/editor
diff options
context:
space:
mode:
Diffstat (limited to 'modules/mono/editor')
-rw-r--r--modules/mono/editor/GodotSharpTools/Editor/MonoDevelopInstance.cs105
-rw-r--r--modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj1
-rw-r--r--modules/mono/editor/GodotSharpTools/GodotSharpTools.userprefs14
-rw-r--r--modules/mono/editor/GodotSharpTools/Utils/OS.cs62
-rw-r--r--modules/mono/editor/bindings_generator.cpp486
-rw-r--r--modules/mono/editor/bindings_generator.h21
-rw-r--r--modules/mono/editor/csharp_project.cpp4
-rw-r--r--modules/mono/editor/csharp_project.h2
-rw-r--r--modules/mono/editor/godotsharp_builds.cpp51
-rw-r--r--modules/mono/editor/godotsharp_builds.h5
-rw-r--r--modules/mono/editor/godotsharp_editor.cpp125
-rw-r--r--modules/mono/editor/godotsharp_editor.h19
-rw-r--r--modules/mono/editor/mono_bottom_panel.cpp6
-rw-r--r--modules/mono/editor/monodevelop_instance.cpp11
-rw-r--r--modules/mono/editor/monodevelop_instance.h9
-rw-r--r--modules/mono/editor/net_solution.cpp4
-rw-r--r--modules/mono/editor/net_solution.h4
17 files changed, 475 insertions, 454 deletions
diff --git a/modules/mono/editor/GodotSharpTools/Editor/MonoDevelopInstance.cs b/modules/mono/editor/GodotSharpTools/Editor/MonoDevelopInstance.cs
index 303be3b732..fba4a8f65c 100644
--- a/modules/mono/editor/GodotSharpTools/Editor/MonoDevelopInstance.cs
+++ b/modules/mono/editor/GodotSharpTools/Editor/MonoDevelopInstance.cs
@@ -2,13 +2,23 @@ using System;
using System.IO;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
namespace GodotSharpTools.Editor
{
public class MonoDevelopInstance
{
- private Process process;
- private string solutionFile;
+ public enum EditorId
+ {
+ MonoDevelop = 0,
+ VisualStudioForMac = 1
+ }
+
+ readonly string solutionFile;
+ readonly EditorId editorId;
+
+ Process process;
public void Execute(string[] files)
{
@@ -16,6 +26,35 @@ namespace GodotSharpTools.Editor
List<string> args = new List<string>();
+ string command;
+
+ if (Utils.OS.IsOSX())
+ {
+ string bundleId = codeEditorBundleIds[editorId];
+
+ if (IsApplicationBundleInstalled(bundleId))
+ {
+ command = "open";
+
+ args.Add("-b");
+ args.Add(bundleId);
+
+ // The 'open' process must wait until the application finishes
+ if (newWindow)
+ args.Add("--wait-apps");
+
+ args.Add("--args");
+ }
+ else
+ {
+ command = codeEditorPaths[editorId];
+ }
+ }
+ else
+ {
+ command = codeEditorPaths[editorId];
+ }
+
args.Add("--ipc-tcp");
if (newWindow)
@@ -33,25 +72,73 @@ namespace GodotSharpTools.Editor
if (newWindow)
{
- ProcessStartInfo startInfo = new ProcessStartInfo(MonoDevelopFile, string.Join(" ", args));
- process = Process.Start(startInfo);
+ process = Process.Start(new ProcessStartInfo()
+ {
+ FileName = command,
+ Arguments = string.Join(" ", args),
+ UseShellExecute = false
+ });
}
else
{
- Process.Start(MonoDevelopFile, string.Join(" ", args));
+ Process.Start(new ProcessStartInfo()
+ {
+ FileName = command,
+ Arguments = string.Join(" ", args),
+ UseShellExecute = false
+ });
}
}
- public MonoDevelopInstance(string solutionFile)
+ public MonoDevelopInstance(string solutionFile, EditorId editorId)
{
+ if (editorId == EditorId.VisualStudioForMac && !Utils.OS.IsOSX())
+ throw new InvalidOperationException($"{nameof(EditorId.VisualStudioForMac)} not supported on this platform");
+
this.solutionFile = solutionFile;
+ this.editorId = editorId;
}
- private static string MonoDevelopFile
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ private extern static bool IsApplicationBundleInstalled(string bundleId);
+
+ static readonly IReadOnlyDictionary<EditorId, string> codeEditorPaths;
+ static readonly IReadOnlyDictionary<EditorId, string> codeEditorBundleIds;
+
+ static MonoDevelopInstance()
{
- get
+ if (Utils.OS.IsOSX())
+ {
+ codeEditorPaths = new Dictionary<EditorId, string>
+ {
+ // Rely on PATH
+ { EditorId.MonoDevelop, "monodevelop" },
+ { EditorId.VisualStudioForMac, "VisualStudio" }
+ };
+ codeEditorBundleIds = new Dictionary<EditorId, string>
+ {
+ // TODO EditorId.MonoDevelop
+ { EditorId.VisualStudioForMac, "com.microsoft.visual-studio" }
+ };
+ }
+ else if (Utils.OS.IsWindows())
+ {
+ codeEditorPaths = new Dictionary<EditorId, string>
+ {
+ // XamarinStudio is no longer a thing, and the latest version is quite old
+ // MonoDevelop is available from source only on Windows. The recommendation
+ // is to use Visual Studio instead. Since there are no official builds, we
+ // will rely on custom MonoDevelop builds being added to PATH.
+ { EditorId.MonoDevelop, "MonoDevelop.exe" }
+ };
+ }
+ else if (Utils.OS.IsUnix())
{
- return "monodevelop";
+ codeEditorPaths = new Dictionary<EditorId, string>
+ {
+ // Rely on PATH
+ { EditorId.MonoDevelop, "monodevelop" }
+ };
}
}
}
diff --git a/modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj b/modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj
index 1c8714e31d..773e8196f7 100644
--- a/modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj
+++ b/modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj
@@ -40,6 +40,7 @@
<Compile Include="Project\ProjectGenerator.cs" />
<Compile Include="Project\ProjectUtils.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="Utils\OS.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project> \ No newline at end of file
diff --git a/modules/mono/editor/GodotSharpTools/GodotSharpTools.userprefs b/modules/mono/editor/GodotSharpTools/GodotSharpTools.userprefs
deleted file mode 100644
index 0cbafdc20d..0000000000
--- a/modules/mono/editor/GodotSharpTools/GodotSharpTools.userprefs
+++ /dev/null
@@ -1,14 +0,0 @@
-<Properties StartupItem="GodotSharpTools.csproj">
- <MonoDevelop.Ide.Workspace ActiveConfiguration="Debug" />
- <MonoDevelop.Ide.Workbench ActiveDocument="Build/BuildSystem.cs">
- <Files>
- <File FileName="Build/ProjectExtensions.cs" Line="1" Column="1" />
- <File FileName="Build/ProjectGenerator.cs" Line="1" Column="1" />
- <File FileName="Build/BuildSystem.cs" Line="37" Column="14" />
- </Files>
- </MonoDevelop.Ide.Workbench>
- <MonoDevelop.Ide.DebuggingService.Breakpoints>
- <BreakpointStore />
- </MonoDevelop.Ide.DebuggingService.Breakpoints>
- <MonoDevelop.Ide.DebuggingService.PinnedWatches />
-</Properties> \ No newline at end of file
diff --git a/modules/mono/editor/GodotSharpTools/Utils/OS.cs b/modules/mono/editor/GodotSharpTools/Utils/OS.cs
new file mode 100644
index 0000000000..148e954e77
--- /dev/null
+++ b/modules/mono/editor/GodotSharpTools/Utils/OS.cs
@@ -0,0 +1,62 @@
+using System;
+using System.Linq;
+using System.Runtime.CompilerServices;
+
+namespace GodotSharpTools.Utils
+{
+ public static class OS
+ {
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ extern static string GetPlatformName();
+
+ const string HaikuName = "Haiku";
+ const string OSXName = "OSX";
+ const string ServerName = "Server";
+ const string UWPName = "UWP";
+ const string WindowsName = "Windows";
+ const string X11Name = "X11";
+
+ public static bool IsHaiku()
+ {
+ return HaikuName.Equals(GetPlatformName(), StringComparison.OrdinalIgnoreCase);
+ }
+
+ public static bool IsOSX()
+ {
+ return OSXName.Equals(GetPlatformName(), StringComparison.OrdinalIgnoreCase);
+ }
+
+ public static bool IsServer()
+ {
+ return ServerName.Equals(GetPlatformName(), StringComparison.OrdinalIgnoreCase);
+ }
+
+ public static bool IsUWP()
+ {
+ return UWPName.Equals(GetPlatformName(), StringComparison.OrdinalIgnoreCase);
+ }
+
+ public static bool IsWindows()
+ {
+ return WindowsName.Equals(GetPlatformName(), StringComparison.OrdinalIgnoreCase);
+ }
+
+ public static bool IsX11()
+ {
+ return X11Name.Equals(GetPlatformName(), StringComparison.OrdinalIgnoreCase);
+ }
+
+ static bool? IsUnixCache = null;
+ static readonly string[] UnixPlatforms = new string[] { HaikuName, OSXName, ServerName, X11Name };
+
+ public static bool IsUnix()
+ {
+ if (IsUnixCache.HasValue)
+ return IsUnixCache.Value;
+
+ string osName = GetPlatformName();
+ IsUnixCache = UnixPlatforms.Any(p => p.Equals(osName, StringComparison.OrdinalIgnoreCase));
+ return IsUnixCache.Value;
+ }
+ }
+}
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index 4185f3407d..308c54ecb3 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -32,15 +32,16 @@
#ifdef DEBUG_METHODS_ENABLED
-#include "engine.h"
-#include "global_constants.h"
-#include "io/compression.h"
-#include "os/dir_access.h"
-#include "os/file_access.h"
-#include "os/os.h"
-#include "ucaps.h"
+#include "core/engine.h"
+#include "core/global_constants.h"
+#include "core/io/compression.h"
+#include "core/os/dir_access.h"
+#include "core/os/file_access.h"
+#include "core/os/os.h"
+#include "core/ucaps.h"
#include "../glue/cs_compressed.gen.h"
+#include "../glue/cs_glue_version.gen.h"
#include "../godotsharp_defs.h"
#include "../mono_gd/gd_mono_marshal.h"
#include "../utils/path_utils.h"
@@ -48,7 +49,7 @@
#include "csharp_project.h"
#include "net_solution.h"
-#define CS_INDENT " "
+#define CS_INDENT " " // 4 whitespaces
#define INDENT1 CS_INDENT
#define INDENT2 INDENT1 INDENT1
@@ -68,23 +69,18 @@
#define CLOSE_BLOCK_L3 INDENT3 CLOSE_BLOCK
#define CLOSE_BLOCK_L4 INDENT4 CLOSE_BLOCK
-#define LOCAL_RET "ret"
-
#define CS_FIELD_MEMORYOWN "memoryOwn"
#define CS_PARAM_METHODBIND "method"
#define CS_PARAM_INSTANCE "ptr"
#define CS_SMETHOD_GETINSTANCE "GetPtr"
-#define CS_FIELD_SINGLETON "instance"
-#define CS_PROP_SINGLETON "Instance"
-#define CS_CLASS_SIGNALAWAITER "SignalAwaiter"
#define CS_METHOD_CALL "Call"
#define GLUE_HEADER_FILE "glue_header.h"
#define ICALL_PREFIX "godot_icall_"
#define SINGLETON_ICALL_SUFFIX "_get_singleton"
-#define ICALL_GET_METHODBIND ICALL_PREFIX "ClassDB_get_method"
-#define ICALL_CONNECT_SIGNAL_AWAITER ICALL_PREFIX "Object_connect_signal_awaiter"
-#define ICALL_OBJECT_DTOR ICALL_PREFIX "Object_Dtor"
+#define ICALL_GET_METHODBIND ICALL_PREFIX "Object_ClassDB_get_method"
+
+#define C_LOCAL_RET "ret"
#define C_LOCAL_PTRCALL_ARGS "call_args"
#define C_MACRO_OBJECT_CONSTRUCT "GODOTSHARP_INSTANCE_OBJECT"
@@ -101,7 +97,7 @@
#define C_METHOD_MONOARRAY_TO(m_type) C_NS_MONOMARSHAL "::mono_array_to_" #m_type
#define C_METHOD_MONOARRAY_FROM(m_type) C_NS_MONOMARSHAL "::" #m_type "_to_mono_array"
-#define BINDINGS_GENERATOR_VERSION UINT32_C(2)
+#define BINDINGS_GENERATOR_VERSION UINT32_C(3)
const char *BindingsGenerator::TypeInterface::DEFAULT_VARARG_C_IN = "\t%0 %1_in = %1;\n";
@@ -196,48 +192,6 @@ String BindingsGenerator::_determine_enum_prefix(const EnumInterface &p_ienum) {
return front->get().name.substr(0, candidate_len);
}
-void BindingsGenerator::_generate_header_icalls() {
-
- core_custom_icalls.clear();
-
- core_custom_icalls.push_back(InternalCall(ICALL_GET_METHODBIND, "IntPtr", "string type, string method"));
- core_custom_icalls.push_back(InternalCall(ICALL_OBJECT_DTOR, "void", "object obj, IntPtr ptr"));
-
- core_custom_icalls.push_back(InternalCall(ICALL_CONNECT_SIGNAL_AWAITER, "Error",
- "IntPtr source, string signal, IntPtr target, " CS_CLASS_SIGNALAWAITER " awaiter"));
-
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "NodePath_Ctor", "IntPtr", "string path"));
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "NodePath_Dtor", "void", "IntPtr ptr"));
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "NodePath_operator_String", "string", "IntPtr ptr"));
-
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "RID_Ctor", "IntPtr", "IntPtr from"));
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "RID_Dtor", "void", "IntPtr ptr"));
-
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "String_md5_buffer", "byte[]", "string str"));
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "String_md5_text", "string", "string str"));
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "String_rfind", "int", "string str, string what, int from"));
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "String_rfindn", "int", "string str, string what, int from"));
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "String_sha256_buffer", "byte[]", "string str"));
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "String_sha256_text", "string", "string str"));
-
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_bytes2var", "object", "byte[] bytes"));
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_convert", "object", "object what, int type"));
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_hash", "int", "object var"));
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_instance_from_id", "Object", "int instance_id"));
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_print", "void", "object[] what"));
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_printerr", "void", "object[] what"));
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_printraw", "void", "object[] what"));
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_prints", "void", "object[] what"));
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_printt", "void", "object[] what"));
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_seed", "void", "int seed"));
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_str", "string", "object[] what"));
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_str2var", "object", "string str"));
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_type_exists", "bool", "string type"));
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_var2bytes", "byte[]", "object what"));
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_var2str", "string", "object var"));
- core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_weakref", "WeakRef", "IntPtr obj"));
-}
-
void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) {
for (const List<MethodInterface>::Element *E = p_itype.methods.front(); E; E = E->next()) {
@@ -248,13 +202,8 @@ void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) {
const TypeInterface *return_type = _get_type_or_placeholder(imethod.return_type);
- String im_sig;
- String im_unique_sig;
-
- if (p_itype.is_object_type) {
- im_sig += "IntPtr " CS_PARAM_METHODBIND ", ";
- im_unique_sig += imethod.return_type.cname.operator String() + ",IntPtr,IntPtr";
- }
+ String im_sig = "IntPtr " CS_PARAM_METHODBIND ", ";
+ String im_unique_sig = imethod.return_type.cname.operator String() + ",IntPtr,IntPtr";
im_sig += "IntPtr " CS_PARAM_INSTANCE;
@@ -268,37 +217,28 @@ void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) {
im_sig += " arg";
im_sig += itos(i + 1);
- if (p_itype.is_object_type) {
- im_unique_sig += ",";
- im_unique_sig += get_unique_sig(*arg_type);
- }
+ im_unique_sig += ",";
+ im_unique_sig += get_unique_sig(*arg_type);
i++;
}
+ // godot_icall_{argc}_{icallcount}
String icall_method = ICALL_PREFIX;
-
- if (p_itype.is_object_type) {
- icall_method += itos(imethod.arguments.size()) + "_" + itos(method_icalls.size()); // godot_icall_{argc}_{icallcount}
- } else {
- icall_method += p_itype.name + "_" + imethod.name; // godot_icall_{Type}_{method}
- }
+ icall_method += itos(imethod.arguments.size());
+ icall_method += "_";
+ icall_method += itos(method_icalls.size());
InternalCall im_icall = InternalCall(p_itype.api_type, icall_method, return_type->im_type_out, im_sig, im_unique_sig);
- if (p_itype.is_object_type) {
- List<InternalCall>::Element *match = method_icalls.find(im_icall);
+ List<InternalCall>::Element *match = method_icalls.find(im_icall);
- if (match) {
- if (p_itype.api_type != ClassDB::API_EDITOR)
- match->get().editor_only = false;
- method_icalls_map.insert(&E->get(), &match->get());
- } else {
- List<InternalCall>::Element *added = method_icalls.push_back(im_icall);
- method_icalls_map.insert(&E->get(), &added->get());
- }
+ if (match) {
+ if (p_itype.api_type != ClassDB::API_EDITOR)
+ match->get().editor_only = false;
+ method_icalls_map.insert(&E->get(), &match->get());
} else {
- List<InternalCall>::Element *added = builtin_method_icalls.push_back(im_icall);
+ List<InternalCall>::Element *added = method_icalls.push_back(im_icall);
method_icalls_map.insert(&E->get(), &added->get());
}
}
@@ -483,20 +423,6 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bo
compile_items.push_back(output_file);
}
-#define GENERATE_BUILTIN_TYPE(m_name) \
- { \
- String output_file = path_join(core_dir, #m_name ".cs"); \
- Error err = _generate_cs_type(builtin_types[#m_name], output_file); \
- if (err != OK) \
- return err; \
- compile_items.push_back(output_file); \
- }
-
- GENERATE_BUILTIN_TYPE(NodePath);
- GENERATE_BUILTIN_TYPE(RID);
-
-#undef GENERATE_BUILTIN_TYPE
-
// Generate sources from compressed files
Map<String, CompressedFile> compressed_files;
@@ -533,34 +459,30 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bo
cs_icalls_content.push_back("using System;\n"
"using System.Runtime.CompilerServices;\n"
- "using " BINDINGS_NAMESPACE_COLLECTIONS ";\n"
"\n");
cs_icalls_content.push_back("namespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK);
cs_icalls_content.push_back(INDENT1 "internal static class " BINDINGS_CLASS_NATIVECALLS "\n" INDENT1 OPEN_BLOCK);
- cs_icalls_content.push_back(INDENT2 "internal static ulong godot_api_hash = ");
+ cs_icalls_content.push_back(MEMBER_BEGIN "internal static ulong godot_api_hash = ");
cs_icalls_content.push_back(String::num_uint64(GDMono::get_singleton()->get_api_core_hash()) + ";\n");
- cs_icalls_content.push_back(INDENT2 "internal static uint bindings_version = ");
+ cs_icalls_content.push_back(MEMBER_BEGIN "internal static uint bindings_version = ");
cs_icalls_content.push_back(String::num_uint64(BINDINGS_GENERATOR_VERSION) + ";\n");
- cs_icalls_content.push_back(INDENT2 "internal static uint cs_glue_version = ");
+ cs_icalls_content.push_back(MEMBER_BEGIN "internal static uint cs_glue_version = ");
cs_icalls_content.push_back(String::num_uint64(CS_GLUE_VERSION) + ";\n");
- cs_icalls_content.push_back("\n");
-#define ADD_INTERNAL_CALL(m_icall) \
- if (!m_icall.editor_only) { \
- cs_icalls_content.push_back(INDENT2 "[MethodImpl(MethodImplOptions.InternalCall)]\n"); \
- cs_icalls_content.push_back(INDENT2 "internal extern static "); \
- cs_icalls_content.push_back(m_icall.im_type_out + " "); \
- cs_icalls_content.push_back(m_icall.name + "("); \
- cs_icalls_content.push_back(m_icall.im_sig + ");\n"); \
+#define ADD_INTERNAL_CALL(m_icall) \
+ if (!m_icall.editor_only) { \
+ cs_icalls_content.push_back(MEMBER_BEGIN "[MethodImpl(MethodImplOptions.InternalCall)]\n"); \
+ cs_icalls_content.push_back(INDENT2 "internal extern static "); \
+ cs_icalls_content.push_back(m_icall.im_type_out + " "); \
+ cs_icalls_content.push_back(m_icall.name + "("); \
+ cs_icalls_content.push_back(m_icall.im_sig + ");\n"); \
}
for (const List<InternalCall>::Element *E = core_custom_icalls.front(); E; E = E->next())
ADD_INTERNAL_CALL(E->get());
for (const List<InternalCall>::Element *E = method_icalls.front(); E; E = E->next())
ADD_INTERNAL_CALL(E->get());
- for (const List<InternalCall>::Element *E = builtin_method_icalls.front(); E; E = E->next())
- ADD_INTERNAL_CALL(E->get());
#undef ADD_INTERNAL_CALL
@@ -638,7 +560,6 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_output_dir,
cs_icalls_content.push_back("using System;\n"
"using System.Runtime.CompilerServices;\n"
- "using " BINDINGS_NAMESPACE_COLLECTIONS ";\n"
"\n");
cs_icalls_content.push_back("namespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK);
cs_icalls_content.push_back(INDENT1 "internal static class " BINDINGS_CLASS_NATIVECALLS_EDITOR "\n" INDENT1 OPEN_BLOCK);
@@ -660,8 +581,6 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_output_dir,
cs_icalls_content.push_back(m_icall.im_sig + ");\n"); \
}
- // No need to add builtin_method_icalls. Builtin types are core only
-
for (const List<InternalCall>::Element *E = editor_custom_icalls.front(); E; E = E->next())
ADD_INTERNAL_CALL(E->get());
for (const List<InternalCall>::Element *E = method_icalls.front(); E; E = E->next())
@@ -695,26 +614,40 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_output_dir,
return OK;
}
-// TODO: there are constants that hide inherited members. must explicitly use `new` to avoid warnings
-// e.g.: warning CS0108: 'SpriteBase3D.FLAG_MAX' hides inherited member 'GeometryInstance.FLAG_MAX'. Use the new keyword if hiding was intended.
+// FIXME: There are some members that hide other inherited members.
+// - In the case of both members being the same kind, the new one must be declared
+// explicitly as `new` to avoid the warning (and we must print a message about it).
+// - In the case of both members being of a different kind, then the new one must
+// be renamed to avoid the name collision (and we must print a warning about it).
+// - Csc warning e.g.:
+// ObjectType/LineEdit.cs(140,38): warning CS0108: 'LineEdit.FocusMode' hides inherited member 'Control.FocusMode'. Use the new keyword if hiding was intended.
Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const String &p_output_file) {
+ CRASH_COND(!itype.is_object_type);
+
bool is_derived_type = itype.base_name != StringName();
+ if (!is_derived_type) {
+ // Some Godot.Object assertions
+ CRASH_COND(itype.cname != name_cache.type_Object);
+ CRASH_COND(!itype.is_instantiable);
+ CRASH_COND(itype.api_type != ClassDB::API_CORE);
+ CRASH_COND(itype.is_reference);
+ CRASH_COND(itype.is_singleton);
+ }
+
List<InternalCall> &custom_icalls = itype.api_type == ClassDB::API_EDITOR ? editor_custom_icalls : core_custom_icalls;
if (verbose_output)
OS::get_singleton()->print(String("Generating " + itype.proxy_name + ".cs...\n").utf8());
- String ctor_method(ICALL_PREFIX + itype.proxy_name + "_Ctor");
+ String ctor_method(ICALL_PREFIX + itype.proxy_name + "_Ctor"); // Used only for derived types
List<String> output;
output.push_back("using System;\n"); // IntPtr
-
- if (itype.requires_collections)
- output.push_back("using " BINDINGS_NAMESPACE_COLLECTIONS ";\n"); // Dictionary
-
+ output.push_back("\n#pragma warning disable CS1591 // Disable warning: "
+ "'Missing XML comment for publicly visible type or member'\n");
output.push_back("\nnamespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK);
const DocData::ClassDoc *class_doc = itype.class_doc;
@@ -737,21 +670,24 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
}
output.push_back(INDENT1 "public ");
- bool is_abstract = itype.is_object_type && !ClassDB::can_instance(itype.name) && ClassDB::is_class_enabled(itype.name); // can_instance returns true if there's a constructor and the class is not 'disabled'
- output.push_back(itype.is_singleton ? "static partial class " : (is_abstract ? "abstract partial class " : "partial class "));
+ if (itype.is_singleton) {
+ output.push_back("static partial class ");
+ } else {
+ output.push_back(itype.is_instantiable ? "partial class " : "abstract partial class ");
+ }
output.push_back(itype.proxy_name);
if (itype.is_singleton) {
output.push_back("\n");
- } else if (!is_derived_type || !itype.is_object_type /* assuming only object types inherit */) {
- output.push_back(" : IDisposable\n");
- } else if (obj_types.has(itype.base_name)) {
- output.push_back(" : ");
- output.push_back(obj_types[itype.base_name].proxy_name);
- output.push_back("\n");
- } else {
- ERR_PRINTS("Base type '" + itype.base_name.operator String() + "' does not exist, for class " + itype.name);
- return ERR_INVALID_DATA;
+ } else if (is_derived_type) {
+ if (obj_types.has(itype.base_name)) {
+ output.push_back(" : ");
+ output.push_back(obj_types[itype.base_name].proxy_name);
+ output.push_back("\n");
+ } else {
+ ERR_PRINTS("Base type '" + itype.base_name.operator String() + "' does not exist, for class " + itype.name);
+ return ERR_INVALID_DATA;
+ }
}
output.push_back(INDENT1 "{");
@@ -848,9 +784,6 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
output.push_back(INDENT2 CLOSE_BLOCK);
}
- if (itype.enums.size())
- output.push_back("\n");
-
// Add properties
for (const List<PropertyInterface>::Element *E = itype.properties.front(); E; E = E->next()) {
@@ -862,43 +795,9 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
ERR_FAIL_V(prop_err);
}
}
-
- if (class_doc->properties.size())
- output.push_back("\n");
}
- if (!itype.is_object_type) {
- output.push_back(MEMBER_BEGIN "private const string " BINDINGS_NATIVE_NAME_FIELD " = \"" + itype.name + "\";\n");
- output.push_back(MEMBER_BEGIN "private bool disposed = false;\n");
- output.push_back(MEMBER_BEGIN "internal IntPtr " BINDINGS_PTR_FIELD ";\n");
-
- output.push_back(MEMBER_BEGIN "internal static IntPtr " CS_SMETHOD_GETINSTANCE "(");
- output.push_back(itype.proxy_name);
- output.push_back(" instance)\n" OPEN_BLOCK_L2 "return instance == null ? IntPtr.Zero : instance." BINDINGS_PTR_FIELD ";\n" CLOSE_BLOCK_L2);
-
- // Add Destructor
- output.push_back(MEMBER_BEGIN "~");
- output.push_back(itype.proxy_name);
- output.push_back("()\n" OPEN_BLOCK_L2 "Dispose(false);\n" CLOSE_BLOCK_L2);
-
- // Add the Dispose from IDisposable
- output.push_back(MEMBER_BEGIN "public void Dispose()\n" OPEN_BLOCK_L2 "Dispose(true);\n" INDENT3 "GC.SuppressFinalize(this);\n" CLOSE_BLOCK_L2);
-
- // Add the virtual Dispose
- output.push_back(MEMBER_BEGIN "protected virtual void Dispose(bool disposing)\n" OPEN_BLOCK_L2
- "if (disposed) return;\n" INDENT3
- "if (" BINDINGS_PTR_FIELD " != IntPtr.Zero)\n" OPEN_BLOCK_L3 "NativeCalls.godot_icall_");
- output.push_back(itype.proxy_name);
- output.push_back("_Dtor(" BINDINGS_PTR_FIELD ");\n" INDENT5 BINDINGS_PTR_FIELD " = IntPtr.Zero;\n" CLOSE_BLOCK_L3 INDENT3
- "GC.SuppressFinalize(this);\n" INDENT3 "disposed = true;\n" CLOSE_BLOCK_L2);
-
- output.push_back(MEMBER_BEGIN "internal ");
- output.push_back(itype.proxy_name);
- output.push_back("(IntPtr " BINDINGS_PTR_FIELD ")\n" OPEN_BLOCK_L2 "this." BINDINGS_PTR_FIELD " = " BINDINGS_PTR_FIELD ";\n" CLOSE_BLOCK_L2);
-
- output.push_back(MEMBER_BEGIN "public IntPtr NativeInstance\n" OPEN_BLOCK_L2
- "get { return " BINDINGS_PTR_FIELD "; }\n" CLOSE_BLOCK_L2);
- } else if (itype.is_singleton) {
+ if (itype.is_singleton) {
// Add the type name and the singleton pointer as static fields
output.push_back(MEMBER_BEGIN "private const string " BINDINGS_NATIVE_NAME_FIELD " = \"");
@@ -910,21 +809,13 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
output.push_back("." ICALL_PREFIX);
output.push_back(itype.name);
output.push_back(SINGLETON_ICALL_SUFFIX "();\n");
- } else {
+ } else if (is_derived_type) {
// Add member fields
output.push_back(MEMBER_BEGIN "private const string " BINDINGS_NATIVE_NAME_FIELD " = \"");
output.push_back(itype.name);
output.push_back("\";\n");
- // Only the base class stores the pointer to the native object
- // This pointer is expected to be and must be of type Object*
- if (!is_derived_type) {
- output.push_back(MEMBER_BEGIN "private bool disposed = false;\n");
- output.push_back(INDENT2 "internal IntPtr " BINDINGS_PTR_FIELD ";\n");
- output.push_back(INDENT2 "internal bool " CS_FIELD_MEMORYOWN ";\n");
- }
-
// Add default constructor
if (itype.is_instantiable) {
output.push_back(MEMBER_BEGIN "public ");
@@ -949,67 +840,9 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
// Add.. em.. trick constructor. Sort of.
output.push_back(MEMBER_BEGIN "internal ");
output.push_back(itype.proxy_name);
- if (is_derived_type) {
- output.push_back("(bool " CS_FIELD_MEMORYOWN ") : base(" CS_FIELD_MEMORYOWN ") {}\n");
- } else {
- output.push_back("(bool " CS_FIELD_MEMORYOWN ")\n" OPEN_BLOCK_L2
- "this." CS_FIELD_MEMORYOWN " = " CS_FIELD_MEMORYOWN ";\n" CLOSE_BLOCK_L2);
- }
-
- // Add methods
-
- if (!is_derived_type) {
- output.push_back(MEMBER_BEGIN "public IntPtr NativeInstance\n" OPEN_BLOCK_L2
- "get { return " BINDINGS_PTR_FIELD "; }\n" CLOSE_BLOCK_L2);
-
- output.push_back(MEMBER_BEGIN "internal static IntPtr " CS_SMETHOD_GETINSTANCE "(Object instance)\n" OPEN_BLOCK_L2
- "return instance == null ? IntPtr.Zero : instance." BINDINGS_PTR_FIELD ";\n" CLOSE_BLOCK_L2);
- }
-
- if (!is_derived_type) {
- // Add destructor
- output.push_back(MEMBER_BEGIN "~");
- output.push_back(itype.proxy_name);
- output.push_back("()\n" OPEN_BLOCK_L2 "Dispose(false);\n" CLOSE_BLOCK_L2);
-
- // Add the Dispose from IDisposable
- output.push_back(MEMBER_BEGIN "public void Dispose()\n" OPEN_BLOCK_L2 "Dispose(true);\n" INDENT3 "GC.SuppressFinalize(this);\n" CLOSE_BLOCK_L2);
-
- // Add the virtual Dispose
- output.push_back(MEMBER_BEGIN "protected virtual void Dispose(bool disposing)\n" OPEN_BLOCK_L2
- "if (disposed) return;\n" INDENT3
- "if (" BINDINGS_PTR_FIELD " != IntPtr.Zero)\n" OPEN_BLOCK_L3
- "if (" CS_FIELD_MEMORYOWN ")\n" OPEN_BLOCK_L4 CS_FIELD_MEMORYOWN
- " = false;\n" INDENT5 BINDINGS_CLASS_NATIVECALLS "." ICALL_OBJECT_DTOR
- "(this, " BINDINGS_PTR_FIELD ");\n" CLOSE_BLOCK_L4 CLOSE_BLOCK_L3 INDENT3
- "this." BINDINGS_PTR_FIELD " = IntPtr.Zero;\n" INDENT3
- "GC.SuppressFinalize(this);\n" INDENT3 "disposed = true;\n" CLOSE_BLOCK_L2);
-
- Map<StringName, TypeInterface>::Element *array_itype = builtin_types.find(name_cache.type_Array);
-
- if (!array_itype) {
- ERR_PRINT("BUG: Array type interface not found!");
- return ERR_BUG;
- }
-
- OrderedHashMap<StringName, TypeInterface>::Element object_itype = obj_types.find("Object");
-
- if (!object_itype) {
- ERR_PRINT("BUG: Object type interface not found!");
- return ERR_BUG;
- }
-
- output.push_back(MEMBER_BEGIN "public " CS_CLASS_SIGNALAWAITER " ToSignal(");
- output.push_back(object_itype.get().cs_type);
- output.push_back(" source, string signal)\n" OPEN_BLOCK_L2
- "return new " CS_CLASS_SIGNALAWAITER "(source, signal, this);\n" CLOSE_BLOCK_L2);
- }
+ output.push_back("(bool " CS_FIELD_MEMORYOWN ") : base(" CS_FIELD_MEMORYOWN ") {}\n");
}
- Map<StringName, String>::Element *extra_member = extra_members.find(itype.cname);
- if (extra_member)
- output.push_back(extra_member->get());
-
int method_bind_count = 0;
for (const List<MethodInterface>::Element *E = itype.methods.front(); E; E = E->next()) {
const MethodInterface &imethod = E->get();
@@ -1027,14 +860,17 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
custom_icalls.push_back(singleton_icall);
}
- if (itype.is_instantiable) {
+ if (is_derived_type && itype.is_instantiable) {
InternalCall ctor_icall = InternalCall(itype.api_type, ctor_method, "IntPtr", itype.proxy_name + " obj");
if (!find_icall_by_name(ctor_icall.name, custom_icalls))
custom_icalls.push_back(ctor_icall);
}
- output.push_back(INDENT1 CLOSE_BLOCK CLOSE_BLOCK);
+ output.push_back(INDENT1 CLOSE_BLOCK /* class */
+ CLOSE_BLOCK /* namespace */);
+
+ output.push_back("\n#pragma warning restore CS1591\n");
return _save_file(p_output_file, output);
}
@@ -1172,9 +1008,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
String arguments_sig;
String cs_in_statements;
- String icall_params;
- if (p_itype.is_object_type)
- icall_params += method_bind_field + ", ";
+ String icall_params = method_bind_field + ", ";
icall_params += sformat(p_itype.cs_in, "this");
List<String> default_args_doc;
@@ -1251,9 +1085,9 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
// Generate method
{
- if (p_itype.is_object_type && !p_imethod.is_virtual && !p_imethod.requires_object_call) {
+ if (!p_imethod.is_virtual && !p_imethod.requires_object_call) {
p_output.push_back(MEMBER_BEGIN "private static IntPtr ");
- p_output.push_back(method_bind_field + " = " BINDINGS_CLASS_NATIVECALLS "." ICALL_GET_METHODBIND "(" BINDINGS_NATIVE_NAME_FIELD ", \"");
+ p_output.push_back(method_bind_field + " = Object." ICALL_GET_METHODBIND "(" BINDINGS_NATIVE_NAME_FIELD ", \"");
p_output.push_back(p_imethod.name);
p_output.push_back("\");\n");
}
@@ -1366,19 +1200,31 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
List<String> output;
- output.push_back("#include \"" GLUE_HEADER_FILE "\"\n"
- "\n");
+ output.push_back("/* THIS FILE IS GENERATED DO NOT EDIT */\n");
+ output.push_back("#include \"" GLUE_HEADER_FILE "\"\n");
+ output.push_back("\n#ifdef MONO_GLUE_ENABLED\n");
generated_icall_funcs.clear();
for (OrderedHashMap<StringName, TypeInterface>::Element type_elem = obj_types.front(); type_elem; type_elem = type_elem.next()) {
const TypeInterface &itype = type_elem.get();
+ bool is_derived_type = itype.base_name != StringName();
+
+ if (!is_derived_type) {
+ // Some Object assertions
+ CRASH_COND(itype.cname != name_cache.type_Object);
+ CRASH_COND(!itype.is_instantiable);
+ CRASH_COND(itype.api_type != ClassDB::API_CORE);
+ CRASH_COND(itype.is_reference);
+ CRASH_COND(itype.is_singleton);
+ }
+
List<InternalCall> &custom_icalls = itype.api_type == ClassDB::API_EDITOR ? editor_custom_icalls : core_custom_icalls;
OS::get_singleton()->print(String("Generating " + itype.name + "...\n").utf8());
- String ctor_method(ICALL_PREFIX + itype.proxy_name + "_Ctor");
+ String ctor_method(ICALL_PREFIX + itype.proxy_name + "_Ctor"); // Used only for derived types
for (const List<MethodInterface>::Element *E = itype.methods.front(); E; E = E->next()) {
const MethodInterface &imethod = E->get();
@@ -1403,7 +1249,7 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
output.push_back("\");\n" CLOSE_BLOCK "\n");
}
- if (itype.is_instantiable) {
+ if (is_derived_type && itype.is_instantiable) {
InternalCall ctor_icall = InternalCall(itype.api_type, ctor_method, "IntPtr", itype.proxy_name + " obj");
if (!find_icall_by_name(ctor_icall.name, custom_icalls))
@@ -1420,7 +1266,7 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
}
}
- output.push_back("namespace GodotSharpBindings\n" OPEN_BLOCK);
+ output.push_back("namespace GodotSharpBindings\n" OPEN_BLOCK "\n");
output.push_back("uint64_t get_core_api_hash() { return ");
output.push_back(String::num_uint64(GDMono::get_singleton()->get_api_core_hash()) + "; }\n");
@@ -1432,11 +1278,9 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
output.push_back("uint32_t get_bindings_version() { return ");
output.push_back(String::num_uint64(BINDINGS_GENERATOR_VERSION) + "; }\n");
- output.push_back("uint32_t get_cs_glue_version() { return ");
- output.push_back(String::num_uint64(CS_GLUE_VERSION) + "; }\n");
- output.push_back("void register_generated_icalls() " OPEN_BLOCK);
- output.push_back("\tgodot_register_header_icalls();");
+ output.push_back("\nvoid register_generated_icalls() " OPEN_BLOCK);
+ output.push_back("\tgodot_register_glue_header_icalls();\n");
#define ADD_INTERNAL_CALL_REGISTRATION(m_icall) \
{ \
@@ -1499,12 +1343,11 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
output.push_back("#endif\n");
}
- for (const List<InternalCall>::Element *E = builtin_method_icalls.front(); E; E = E->next())
- ADD_INTERNAL_CALL_REGISTRATION(E->get());
-
#undef ADD_INTERNAL_CALL_REGISTRATION
- output.push_back(CLOSE_BLOCK "}\n");
+ output.push_back(CLOSE_BLOCK "\n} // namespace GodotSharpBindings\n");
+
+ output.push_back("\n#endif // MONO_GLUE_ENABLED\n");
Error save_err = _save_file(path_join(p_output_dir, "mono_glue.gen.cpp"), output);
if (save_err != OK)
@@ -1519,10 +1362,6 @@ uint32_t BindingsGenerator::get_version() {
return BINDINGS_GENERATOR_VERSION;
}
-uint32_t BindingsGenerator::get_cs_glue_version() {
- return CS_GLUE_VERSION;
-}
-
Error BindingsGenerator::_save_file(const String &p_path, const List<String> &p_content) {
FileAccessRef file = FileAccess::open(p_path, FileAccess::WRITE);
@@ -1585,9 +1424,6 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte
i++;
}
- if (!p_itype.is_object_type)
- return OK; // no auto-generated icall functions for builtin types
-
const Map<const MethodInterface *, const InternalCall *>::Element *match = method_icalls_map.find(&p_imethod);
ERR_FAIL_NULL_V(match, ERR_BUG);
@@ -1622,7 +1458,7 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte
}
p_output.push_back("\t" + ptrcall_return_type);
- p_output.push_back(" " LOCAL_RET);
+ p_output.push_back(" " C_LOCAL_RET);
p_output.push_back(initialization + ";\n");
p_output.push_back("\tERR_FAIL_NULL_V(" CS_PARAM_INSTANCE);
p_output.push_back(fail_ret);
@@ -1672,7 +1508,7 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte
p_output.push_back("\tVariant::CallError vcall_error;\n\t");
if (!ret_void)
- p_output.push_back(LOCAL_RET " = ");
+ p_output.push_back(C_LOCAL_RET " = ");
p_output.push_back(CS_PARAM_METHODBIND "->call(" CS_PARAM_INSTANCE ", ");
p_output.push_back(p_imethod.arguments.size() ? "(const Variant**)" C_LOCAL_PTRCALL_ARGS ".ptr()" : "NULL");
@@ -1680,14 +1516,14 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte
} else {
p_output.push_back("\t" CS_PARAM_METHODBIND "->ptrcall(" CS_PARAM_INSTANCE ", ");
p_output.push_back(p_imethod.arguments.size() ? C_LOCAL_PTRCALL_ARGS ", " : "NULL, ");
- p_output.push_back(!ret_void ? "&" LOCAL_RET ");\n" : "NULL);\n");
+ p_output.push_back(!ret_void ? "&" C_LOCAL_RET ");\n" : "NULL);\n");
}
if (!ret_void) {
if (return_type->c_out.empty())
- p_output.push_back("\treturn " LOCAL_RET ";\n");
+ p_output.push_back("\treturn " C_LOCAL_RET ";\n");
else
- p_output.push_back(sformat(return_type->c_out, return_type->c_type_out, LOCAL_RET, return_type->name));
+ p_output.push_back(sformat(return_type->c_out, return_type->c_type_out, C_LOCAL_RET, return_type->name));
}
p_output.push_back(CLOSE_BLOCK "\n");
@@ -1746,9 +1582,6 @@ const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_or_placehol
return &placeholder_types.insert(placeholder.cname, placeholder)->get();
}
-static void _create_constant_interface_from(const StringName &p_constant, const DocData::ClassDoc &p_classdoc) {
-}
-
void BindingsGenerator::_populate_object_type_interfaces() {
obj_types.clear();
@@ -1883,9 +1716,6 @@ void BindingsGenerator::_populate_object_type_interfaces() {
if (virtual_method_list.find(method_info)) {
// A virtual method without the virtual flag. This is a special case.
- // This type of method can only be found in Object derived types.
- ERR_FAIL_COND(!itype.is_object_type);
-
// There is no method bind, so let's fallback to Godot's object.Call(string, params)
imethod.requires_object_call = true;
@@ -1922,9 +1752,6 @@ void BindingsGenerator::_populate_object_type_interfaces() {
imethod.return_type.cname = Variant::get_type_name(return_info.type);
}
- if (!itype.requires_collections && imethod.return_type.cname == name_cache.type_Dictionary || imethod.return_type.cname == name_cache.type_Array)
- itype.requires_collections = true;
-
for (int i = 0; i < argc; i++) {
PropertyInfo arginfo = method_info.arguments[i];
@@ -1946,9 +1773,6 @@ void BindingsGenerator::_populate_object_type_interfaces() {
iarg.name = escape_csharp_keyword(snake_to_camel_case(iarg.name));
- if (!itype.requires_collections && iarg.type.cname == name_cache.type_Dictionary || imethod.return_type.cname == name_cache.type_Array)
- itype.requires_collections = true;
-
if (m && m->has_default_argument(i)) {
_default_argument_from_variant(m->get_default_argument(i), iarg);
}
@@ -2273,13 +2097,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.cs_out = "return new %1(%0);";
itype.im_type_in = "IntPtr";
itype.im_type_out = "IntPtr";
- _populate_builtin_type(itype, Variant::NODE_PATH);
- extra_members.insert(itype.cname, MEMBER_BEGIN "public NodePath() : this(string.Empty) {}\n" MEMBER_BEGIN "public NodePath(string path)\n" OPEN_BLOCK_L2
- "this." BINDINGS_PTR_FIELD " = NativeCalls.godot_icall_NodePath_Ctor(path);\n" CLOSE_BLOCK_L2
- MEMBER_BEGIN "public static implicit operator NodePath(string from)\n" OPEN_BLOCK_L2 "return new NodePath(from);\n" CLOSE_BLOCK_L2
- MEMBER_BEGIN "public static implicit operator string(NodePath from)\n" OPEN_BLOCK_L2
- "return NativeCalls." ICALL_PREFIX "NodePath_operator_String(NodePath." CS_SMETHOD_GETINSTANCE "(from));\n" CLOSE_BLOCK_L2
- MEMBER_BEGIN "public override string ToString()\n" OPEN_BLOCK_L2 "return (string)this;\n" CLOSE_BLOCK_L2);
builtin_types.insert(itype.cname, itype);
// RID
@@ -2296,9 +2113,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.cs_out = "return new %1(%0);";
itype.im_type_in = "IntPtr";
itype.im_type_out = "IntPtr";
- _populate_builtin_type(itype, Variant::_RID);
- extra_members.insert(itype.cname, MEMBER_BEGIN "internal RID()\n" OPEN_BLOCK_L2
- "this." BINDINGS_PTR_FIELD " = IntPtr.Zero;\n" CLOSE_BLOCK_L2);
builtin_types.insert(itype.cname, itype);
// Variant
@@ -2371,14 +2185,14 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype = TypeInterface();
itype.name = "Array";
itype.cname = itype.name;
- itype.proxy_name = "Collections.Array";
+ itype.proxy_name = itype.name;
itype.c_out = "\treturn memnew(Array(%1));\n";
itype.c_type = itype.name;
itype.c_type_in = itype.c_type + "*";
itype.c_type_out = itype.c_type + "*";
- itype.cs_type = itype.proxy_name;
+ itype.cs_type = BINDINGS_NAMESPACE_COLLECTIONS "." + itype.proxy_name;
itype.cs_in = "%0." CS_SMETHOD_GETINSTANCE "()";
- itype.cs_out = "return new Collections.Array(%0);";
+ itype.cs_out = "return new " + itype.cs_type + "(%0);";
itype.im_type_in = "IntPtr";
itype.im_type_out = "IntPtr";
builtin_types.insert(itype.cname, itype);
@@ -2387,14 +2201,14 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype = TypeInterface();
itype.name = "Dictionary";
itype.cname = itype.name;
- itype.proxy_name = "Collections.Dictionary";
+ itype.proxy_name = itype.name;
itype.c_out = "\treturn memnew(Dictionary(%1));\n";
itype.c_type = itype.name;
itype.c_type_in = itype.c_type + "*";
itype.c_type_out = itype.c_type + "*";
- itype.cs_type = itype.proxy_name;
+ itype.cs_type = BINDINGS_NAMESPACE_COLLECTIONS "." + itype.proxy_name;
itype.cs_in = "%0." CS_SMETHOD_GETINSTANCE "()";
- itype.cs_out = "return new Collections.Dictionary(%0);";
+ itype.cs_out = "return new " + itype.cs_type + "(%0);";
itype.im_type_in = "IntPtr";
itype.im_type_out = "IntPtr";
builtin_types.insert(itype.cname, itype);
@@ -2413,66 +2227,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
builtin_types.insert(itype.cname, itype);
}
-void BindingsGenerator::_populate_builtin_type(TypeInterface &r_itype, Variant::Type vtype) {
-
- Variant::CallError cerror;
- Variant v = Variant::construct(vtype, NULL, 0, cerror);
-
- List<MethodInfo> method_list;
- v.get_method_list(&method_list);
- method_list.sort();
-
- for (List<MethodInfo>::Element *E = method_list.front(); E; E = E->next()) {
- MethodInfo &mi = E->get();
- MethodInterface imethod;
-
- imethod.name = mi.name;
- imethod.cname = imethod.name;
- imethod.proxy_name = escape_csharp_keyword(snake_to_pascal_case(mi.name));
-
- for (int i = 0; i < mi.arguments.size(); i++) {
- ArgumentInterface iarg;
- PropertyInfo pi = mi.arguments[i];
-
- iarg.name = pi.name;
-
- if (pi.type == Variant::NIL)
- iarg.type.cname = name_cache.type_Variant;
- else
- iarg.type.cname = Variant::get_type_name(pi.type);
-
- if (!r_itype.requires_collections && iarg.type.cname == name_cache.type_Dictionary || imethod.return_type.cname == name_cache.type_Array)
- r_itype.requires_collections = true;
-
- if ((mi.default_arguments.size() - mi.arguments.size() + i) >= 0)
- _default_argument_from_variant(Variant::construct(pi.type, NULL, 0, cerror), iarg);
-
- imethod.add_argument(iarg);
- }
-
- if (mi.return_val.type == Variant::NIL) {
- if (mi.return_val.name != "")
- imethod.return_type.cname = name_cache.type_Variant;
- } else {
- imethod.return_type.cname = Variant::get_type_name(mi.return_val.type);
- }
-
- if (!r_itype.requires_collections && imethod.return_type.cname == name_cache.type_Dictionary || imethod.return_type.cname == name_cache.type_Array)
- r_itype.requires_collections = true;
-
- if (r_itype.class_doc) {
- for (int i = 0; i < r_itype.class_doc->methods.size(); i++) {
- if (r_itype.class_doc->methods[i].name == imethod.name) {
- imethod.method_doc = &r_itype.class_doc->methods[i];
- break;
- }
- }
- }
-
- r_itype.methods.push_back(imethod);
- }
-}
-
void BindingsGenerator::_populate_global_constants() {
int global_constants_count = GlobalConstants::get_global_constant_count();
@@ -2570,15 +2324,13 @@ void BindingsGenerator::initialize() {
_populate_global_constants();
- // Populate internal calls (after populating type interfaces and global constants)
+ // Generate internal calls (after populating type interfaces and global constants)
- _generate_header_icalls();
+ core_custom_icalls.clear();
+ editor_custom_icalls.clear();
for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next())
_generate_method_icalls(E.get());
-
- _generate_method_icalls(builtin_types["NodePath"]);
- _generate_method_icalls(builtin_types["RID"]);
}
void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) {
diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h
index 5b33a0e53f..ad89255ba5 100644
--- a/modules/mono/editor/bindings_generator.h
+++ b/modules/mono/editor/bindings_generator.h
@@ -31,13 +31,13 @@
#ifndef BINDINGS_GENERATOR_H
#define BINDINGS_GENERATOR_H
-#include "class_db.h"
+#include "core/class_db.h"
#include "editor/doc/doc_data.h"
#include "editor/editor_help.h"
#ifdef DEBUG_METHODS_ENABLED
-#include "ustring.h"
+#include "core/ustring.h"
class BindingsGenerator {
@@ -192,7 +192,7 @@ class BindingsGenerator {
/**
* Used only by Object-derived types.
- * Determines if this type is not virtual (incomplete).
+ * Determines if this type is not abstract (incomplete).
* e.g.: CanvasItem cannot be instantiated.
*/
bool is_instantiable;
@@ -204,12 +204,6 @@ class BindingsGenerator {
*/
bool memory_own;
- /**
- * Determines if the file must have a using directive for System.Collections.Generic
- * e.g.: When the generated class makes use of Dictionary
- */
- bool requires_collections;
-
// !! The comments of the following fields make reference to other fields via square brackets, e.g.: [field_name]
// !! When renaming those fields, make sure to rename their references in the comments
@@ -295,7 +289,7 @@ class BindingsGenerator {
/**
* Type used for method signatures, both for parameters and the return type.
- * Same as [proxy_name] except for variable arguments (VarArg).
+ * Same as [proxy_name] except for variable arguments (VarArg) and collections (which include the namespace).
*/
String cs_type;
@@ -414,7 +408,6 @@ class BindingsGenerator {
is_instantiable = false;
memory_own = false;
- requires_collections = false;
c_arg_in = "%s";
@@ -463,10 +456,7 @@ class BindingsGenerator {
List<EnumInterface> global_enums;
List<ConstantInterface> global_constants;
- Map<StringName, String> extra_members;
-
List<InternalCall> method_icalls;
- List<InternalCall> builtin_method_icalls;
Map<const MethodInterface *, const InternalCall *> method_icalls_map;
List<const InternalCall *> generated_icall_funcs;
@@ -525,14 +515,12 @@ class BindingsGenerator {
String _determine_enum_prefix(const EnumInterface &p_ienum);
- void _generate_header_icalls();
void _generate_method_icalls(const TypeInterface &p_itype);
const TypeInterface *_get_type_or_null(const TypeReference &p_typeref);
const TypeInterface *_get_type_or_placeholder(const TypeReference &p_typeref);
void _default_argument_from_variant(const Variant &p_val, ArgumentInterface &r_iarg);
- void _populate_builtin_type(TypeInterface &r_itype, Variant::Type vtype);
void _populate_object_type_interfaces();
void _populate_builtin_type_interfaces();
@@ -564,7 +552,6 @@ public:
Error generate_glue(const String &p_output_dir);
static uint32_t get_version();
- static uint32_t get_cs_glue_version();
void initialize();
diff --git a/modules/mono/editor/csharp_project.cpp b/modules/mono/editor/csharp_project.cpp
index bc95607743..4764cbe941 100644
--- a/modules/mono/editor/csharp_project.cpp
+++ b/modules/mono/editor/csharp_project.cpp
@@ -30,8 +30,8 @@
#include "csharp_project.h"
-#include "os/os.h"
-#include "project_settings.h"
+#include "core/os/os.h"
+#include "core/project_settings.h"
#include "../mono_gd/gd_mono_class.h"
#include "../mono_gd/gd_mono_marshal.h"
diff --git a/modules/mono/editor/csharp_project.h b/modules/mono/editor/csharp_project.h
index 381dd17e02..d852139de0 100644
--- a/modules/mono/editor/csharp_project.h
+++ b/modules/mono/editor/csharp_project.h
@@ -31,7 +31,7 @@
#ifndef CSHARP_PROJECT_H
#define CSHARP_PROJECT_H
-#include "ustring.h"
+#include "core/ustring.h"
namespace CSharpProject {
diff --git a/modules/mono/editor/godotsharp_builds.cpp b/modules/mono/editor/godotsharp_builds.cpp
index 2faab1718d..d397814fa7 100644
--- a/modules/mono/editor/godotsharp_builds.cpp
+++ b/modules/mono/editor/godotsharp_builds.cpp
@@ -30,8 +30,10 @@
#include "godotsharp_builds.h"
+#include "core/vector.h"
#include "main/main.h"
+#include "../glue/cs_glue_version.gen.h"
#include "../godotsharp_dirs.h"
#include "../mono_gd/gd_mono_class.h"
#include "../mono_gd/gd_mono_marshal.h"
@@ -50,6 +52,16 @@ void godot_icall_BuildInstance_ExitCallback(MonoString *p_solution, MonoString *
GodotSharpBuilds::get_singleton()->build_exit_callback(MonoBuildInfo(solution, config), p_exit_code);
}
+static Vector<const char *> _get_msbuild_hint_dirs() {
+ Vector<const char *> ret;
+#ifdef OSX_ENABLED
+ ret.push_back("/Library/Frameworks/Mono.framework/Versions/Current/bin/");
+ ret.push_back("/usr/local/var/homebrew/linked/mono/bin/");
+#endif
+ ret.push_back("/opt/novell/mono/bin/");
+ return ret;
+}
+
#ifdef UNIX_ENABLED
String _find_build_engine_on_unix(const String &p_name) {
String ret = path_which(p_name);
@@ -61,15 +73,9 @@ String _find_build_engine_on_unix(const String &p_name) {
if (ret_fallback.length())
return ret_fallback;
- const char *locations[] = {
-#ifdef OSX_ENABLED
- "/Library/Frameworks/Mono.framework/Versions/Current/bin/",
- "/usr/local/var/homebrew/linked/mono/bin/",
-#endif
- "/opt/novell/mono/bin/"
- };
+ static Vector<const char *> locations = _get_msbuild_hint_dirs();
- for (int i = 0; i < sizeof(locations) / sizeof(const char *); i++) {
+ for (int i = 0; i < locations.size(); i++) {
String hint_path = locations[i] + p_name;
if (FileAccess::exists(hint_path)) {
@@ -88,7 +94,12 @@ MonoString *godot_icall_BuildInstance_get_MSBuildPath() {
#if defined(WINDOWS_ENABLED)
switch (build_tool) {
case GodotSharpBuilds::MSBUILD_VS: {
- static String msbuild_tools_path = MonoRegUtils::find_msbuild_tools_path();
+ static String msbuild_tools_path;
+
+ if (msbuild_tools_path.empty() || !FileAccess::exists(msbuild_tools_path)) {
+ // Try to search it again if it wasn't found last time or if it was removed from its location
+ msbuild_tools_path = MonoRegUtils::find_msbuild_tools_path();
+ }
if (msbuild_tools_path.length()) {
if (!msbuild_tools_path.ends_with("\\"))
@@ -122,15 +133,25 @@ MonoString *godot_icall_BuildInstance_get_MSBuildPath() {
CRASH_NOW();
}
#elif defined(UNIX_ENABLED)
- static String msbuild_path = _find_build_engine_on_unix("msbuild");
- static String xbuild_path = _find_build_engine_on_unix("xbuild");
+ static String msbuild_path;
+ static String xbuild_path;
if (build_tool == GodotSharpBuilds::XBUILD) {
+ if (xbuild_path.empty() || !FileAccess::exists(xbuild_path)) {
+ // Try to search it again if it wasn't found last time or if it was removed from its location
+ xbuild_path = _find_build_engine_on_unix("msbuild");
+ }
+
if (xbuild_path.empty()) {
WARN_PRINT("Cannot find binary for '" PROP_NAME_XBUILD "'");
return NULL;
}
} else {
+ if (msbuild_path.empty() || !FileAccess::exists(msbuild_path)) {
+ // Try to search it again if it wasn't found last time or if it was removed from its location
+ msbuild_path = _find_build_engine_on_unix("msbuild");
+ }
+
if (msbuild_path.empty()) {
WARN_PRINT("Cannot find binary for '" PROP_NAME_MSBUILD_MONO "'");
return NULL;
@@ -186,7 +207,11 @@ MonoBoolean godot_icall_BuildInstance_get_UsingMonoMSBuildOnWindows() {
#endif
}
-void GodotSharpBuilds::_register_internal_calls() {
+void GodotSharpBuilds::register_internal_calls() {
+
+ static bool registered = false;
+ ERR_FAIL_COND(registered);
+ registered = true;
mono_add_internal_call("GodotSharpTools.Build.BuildSystem::godot_icall_BuildInstance_ExitCallback", (void *)godot_icall_BuildInstance_ExitCallback);
mono_add_internal_call("GodotSharpTools.Build.BuildInstance::godot_icall_BuildInstance_get_MSBuildPath", (void *)godot_icall_BuildInstance_get_MSBuildPath);
@@ -263,7 +288,7 @@ String GodotSharpBuilds::_api_folder_name(APIAssembly::Type p_api_type) {
GDMono::get_singleton()->get_api_editor_hash();
return String::num_uint64(api_hash) +
"_" + String::num_uint64(BindingsGenerator::get_version()) +
- "_" + String::num_uint64(BindingsGenerator::get_cs_glue_version());
+ "_" + String::num_uint64(CS_GLUE_VERSION);
}
bool GodotSharpBuilds::make_api_sln(APIAssembly::Type p_api_type) {
diff --git a/modules/mono/editor/godotsharp_builds.h b/modules/mono/editor/godotsharp_builds.h
index 4afc284d45..c6dc6b6236 100644
--- a/modules/mono/editor/godotsharp_builds.h
+++ b/modules/mono/editor/godotsharp_builds.h
@@ -61,9 +61,6 @@ private:
static GodotSharpBuilds *singleton;
- friend class GDMono;
- static void _register_internal_calls();
-
public:
enum BuildTool {
MSBUILD_MONO,
@@ -75,6 +72,8 @@ public:
_FORCE_INLINE_ static GodotSharpBuilds *get_singleton() { return singleton; }
+ static void register_internal_calls();
+
static void show_build_error_dialog(const String &p_message);
void build_exit_callback(const MonoBuildInfo &p_build_info, int p_exit_code);
diff --git a/modules/mono/editor/godotsharp_editor.cpp b/modules/mono/editor/godotsharp_editor.cpp
index faeb58e5a7..3ee38515bf 100644
--- a/modules/mono/editor/godotsharp_editor.cpp
+++ b/modules/mono/editor/godotsharp_editor.cpp
@@ -38,12 +38,17 @@
#include "../csharp_script.h"
#include "../godotsharp_dirs.h"
#include "../mono_gd/gd_mono.h"
+#include "../mono_gd/gd_mono_marshal.h"
#include "../utils/path_utils.h"
#include "bindings_generator.h"
#include "csharp_project.h"
#include "godotsharp_export.h"
#include "net_solution.h"
+#ifdef OSX_ENABLED
+#include "../utils/osx_utils.h"
+#endif
+
#ifdef WINDOWS_ENABLED
#include "../utils/mono_reg_utils.h"
#endif
@@ -169,6 +174,31 @@ void GodotSharpEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_menu_option_pressed", "id"), &GodotSharpEditor::_menu_option_pressed);
}
+MonoBoolean godot_icall_MonoDevelopInstance_IsApplicationBundleInstalled(MonoString *p_bundle_id) {
+#ifdef OSX_ENABLED
+ return (MonoBoolean)osx_is_app_bundle_installed(GDMonoMarshal::mono_string_to_godot(p_bundle_id));
+#else
+ (void)p_bundle_id; // UNUSED
+ ERR_FAIL_V(false);
+#endif
+}
+
+MonoString *godot_icall_Utils_OS_GetPlatformName() {
+ return GDMonoMarshal::mono_string_from_godot(OS::get_singleton()->get_name());
+}
+
+void GodotSharpEditor::register_internal_calls() {
+
+ static bool registered = false;
+ ERR_FAIL_COND(registered);
+ registered = true;
+
+ mono_add_internal_call("GodotSharpTools.Editor.MonoDevelopInstance::IsApplicationBundleInstalled", (void *)godot_icall_MonoDevelopInstance_IsApplicationBundleInstalled);
+ mono_add_internal_call("GodotSharpTools.Utils.OS::GetPlatformName", (void *)godot_icall_Utils_OS_GetPlatformName);
+
+ GodotSharpBuilds::register_internal_calls();
+}
+
void GodotSharpEditor::show_error_dialog(const String &p_message, const String &p_title) {
error_dialog->set_title(p_title);
@@ -181,8 +211,36 @@ Error GodotSharpEditor::open_in_external_editor(const Ref<Script> &p_script, int
ExternalEditor editor = ExternalEditor(int(EditorSettings::get_singleton()->get("mono/editor/external_editor")));
switch (editor) {
- case EDITOR_CODE: {
+ case EDITOR_VSCODE: {
+ static String vscode_path;
+
+ if (vscode_path.empty() || !FileAccess::exists(vscode_path)) {
+ // Try to search it again if it wasn't found last time or if it was removed from its location
+ vscode_path = path_which("code");
+ }
+
List<String> args;
+
+#ifdef OSX_ENABLED
+ // The package path is '/Applications/Visual Studio Code.app'
+ static const String vscode_bundle_id = "com.microsoft.VSCode";
+ static bool osx_app_bundle_installed = osx_is_app_bundle_installed(vscode_bundle_id);
+
+ if (osx_app_bundle_installed) {
+ args.push_back("-b");
+ args.push_back(vscode_bundle_id);
+
+ // The reusing of existing windows made by the 'open' command might not choose a wubdiw that is
+ // editing our folder. It's better to ask for a new window and let VSCode do the window management.
+ args.push_back("-n");
+
+ // The open process must wait until the application finishes (which is instant in VSCode's case)
+ args.push_back("--wait-apps");
+
+ args.push_back("--args");
+ }
+#endif
+
args.push_back(ProjectSettings::get_singleton()->get_resource_path());
String script_path = ProjectSettings::get_singleton()->globalize_path(p_script->get_path());
@@ -194,18 +252,47 @@ Error GodotSharpEditor::open_in_external_editor(const Ref<Script> &p_script, int
args.push_back(script_path);
}
- static String program = path_which("code");
+#ifdef OSX_ENABLED
+ ERR_EXPLAIN("Cannot find code editor: VSCode");
+ ERR_FAIL_COND_V(!osx_app_bundle_installed && vscode_path.empty(), ERR_FILE_NOT_FOUND);
- Error err = OS::get_singleton()->execute(program.length() ? program : "code", args, false);
+ String command = osx_app_bundle_installed ? "/usr/bin/open" : vscode_path;
+#else
+ ERR_EXPLAIN("Cannot find code editor: VSCode");
+ ERR_FAIL_COND_V(vscode_path.empty(), ERR_FILE_NOT_FOUND);
+
+ String command = vscode_path;
+#endif
+
+ Error err = OS::get_singleton()->execute(command, args, false);
if (err != OK) {
- ERR_PRINT("GodotSharp: Could not execute external editor");
+ ERR_PRINT("Error when trying to execute code editor: VSCode");
return err;
}
} break;
+#ifdef OSX_ENABLED
+ case EDITOR_VISUALSTUDIO_MAC:
+ // [[fallthrough]];
+#endif
case EDITOR_MONODEVELOP: {
- if (!monodevel_instance)
- monodevel_instance = memnew(MonoDevelopInstance(GodotSharpDirs::get_project_sln_path()));
+#ifdef OSX_ENABLED
+ bool is_visualstudio = editor == EDITOR_VISUALSTUDIO_MAC;
+
+ MonoDevelopInstance **instance = is_visualstudio ?
+ &visualstudio_mac_instance :
+ &monodevelop_instance;
+
+ MonoDevelopInstance::EditorId editor_id = is_visualstudio ?
+ MonoDevelopInstance::VISUALSTUDIO_FOR_MAC :
+ MonoDevelopInstance::MONODEVELOP;
+#else
+ MonoDevelopInstance **instance = &monodevelop_instance;
+ MonoDevelopInstance::EditorId editor_id = MonoDevelopInstance::MONODEVELOP;
+#endif
+
+ if (!*instance)
+ *instance = memnew(MonoDevelopInstance(GodotSharpDirs::get_project_sln_path(), editor_id));
String script_path = ProjectSettings::get_singleton()->globalize_path(p_script->get_path());
@@ -213,7 +300,7 @@ Error GodotSharpEditor::open_in_external_editor(const Ref<Script> &p_script, int
script_path += ";" + itos(p_line + 1) + ";" + itos(p_col);
}
- monodevel_instance->execute(script_path);
+ (*instance)->execute(script_path);
} break;
default:
return ERR_UNAVAILABLE;
@@ -231,7 +318,10 @@ GodotSharpEditor::GodotSharpEditor(EditorNode *p_editor) {
singleton = this;
- monodevel_instance = NULL;
+ monodevelop_instance = NULL;
+#ifdef OSX_ENABLED
+ visualstudio_mac_instance = NULL;
+#endif
editor = p_editor;
@@ -314,7 +404,18 @@ GodotSharpEditor::GodotSharpEditor(EditorNode *p_editor) {
// External editor settings
EditorSettings *ed_settings = EditorSettings::get_singleton();
EDITOR_DEF("mono/editor/external_editor", EDITOR_NONE);
- ed_settings->add_property_hint(PropertyInfo(Variant::INT, "mono/editor/external_editor", PROPERTY_HINT_ENUM, "None,MonoDevelop,Visual Studio Code"));
+
+ String settings_hint_str = "None";
+
+#ifdef WINDOWS_ENABLED
+ settings_hint_str += ",MonoDevelop,Visual Studio Code";
+#elif OSX_ENABLED
+ settings_hint_str += ",Visual Studio,MonoDevelop,Visual Studio Code";
+#elif UNIX_ENABLED
+ settings_hint_str += ",MonoDevelop,Visual Studio Code";
+#endif
+
+ ed_settings->add_property_hint(PropertyInfo(Variant::INT, "mono/editor/external_editor", PROPERTY_HINT_ENUM, settings_hint_str));
// Export plugin
Ref<GodotSharpExport> godotsharp_export;
@@ -328,9 +429,9 @@ GodotSharpEditor::~GodotSharpEditor() {
memdelete(godotsharp_builds);
- if (monodevel_instance) {
- memdelete(monodevel_instance);
- monodevel_instance = NULL;
+ if (monodevelop_instance) {
+ memdelete(monodevelop_instance);
+ monodevelop_instance = NULL;
}
}
diff --git a/modules/mono/editor/godotsharp_editor.h b/modules/mono/editor/godotsharp_editor.h
index 66da814c8b..46b6bd5ebf 100644
--- a/modules/mono/editor/godotsharp_editor.h
+++ b/modules/mono/editor/godotsharp_editor.h
@@ -50,7 +50,10 @@ class GodotSharpEditor : public Node {
GodotSharpBuilds *godotsharp_builds;
- MonoDevelopInstance *monodevel_instance;
+ MonoDevelopInstance *monodevelop_instance;
+#ifdef OSX_ENABLED
+ MonoDevelopInstance *visualstudio_mac_instance;
+#endif
bool _create_project_solution();
@@ -74,12 +77,24 @@ public:
enum ExternalEditor {
EDITOR_NONE,
+#ifdef WINDOWS_ENABLED
+ //EDITOR_VISUALSTUDIO, // TODO
EDITOR_MONODEVELOP,
- EDITOR_CODE,
+ EDITOR_VSCODE
+#elif OSX_ENABLED
+ EDITOR_VISUALSTUDIO_MAC,
+ EDITOR_MONODEVELOP,
+ EDITOR_VSCODE
+#elif UNIX_ENABLED
+ EDITOR_MONODEVELOP,
+ EDITOR_VSCODE
+#endif
};
_FORCE_INLINE_ static GodotSharpEditor *get_singleton() { return singleton; }
+ static void register_internal_calls();
+
void show_error_dialog(const String &p_message, const String &p_title = "Error");
Error open_in_external_editor(const Ref<Script> &p_script, int p_line, int p_col);
diff --git a/modules/mono/editor/mono_bottom_panel.cpp b/modules/mono/editor/mono_bottom_panel.cpp
index 9317550d28..ecc3e4c59e 100644
--- a/modules/mono/editor/mono_bottom_panel.cpp
+++ b/modules/mono/editor/mono_bottom_panel.cpp
@@ -53,9 +53,9 @@ void MonoBottomPanel::_update_build_tabs_list() {
build_tabs_list->add_item(item_name, tab->get_icon_texture());
- String item_tooltip = String("Solution: ") + tab->build_info.solution;
- item_tooltip += String("\nConfiguration: ") + tab->build_info.configuration;
- item_tooltip += String("\nStatus: ");
+ String item_tooltip = "Solution: " + tab->build_info.solution;
+ item_tooltip += "\nConfiguration: " + tab->build_info.configuration;
+ item_tooltip += "\nStatus: ";
if (tab->build_exited) {
item_tooltip += tab->build_result == MonoBuildTab::RESULT_SUCCESS ? "Succeeded" : "Errored";
diff --git a/modules/mono/editor/monodevelop_instance.cpp b/modules/mono/editor/monodevelop_instance.cpp
index 9f05711fd6..1d858d80bf 100644
--- a/modules/mono/editor/monodevelop_instance.cpp
+++ b/modules/mono/editor/monodevelop_instance.cpp
@@ -47,7 +47,7 @@ void MonoDevelopInstance::execute(const Vector<String> &p_files) {
execute_method->invoke(gc_handle->get_target(), args, &exc);
if (exc) {
- GDMonoUtils::debug_unhandled_exception(exc);
+ GDMonoUtils::debug_print_unhandled_exception(exc);
ERR_FAIL();
}
}
@@ -59,7 +59,7 @@ void MonoDevelopInstance::execute(const String &p_file) {
execute(files);
}
-MonoDevelopInstance::MonoDevelopInstance(const String &p_solution) {
+MonoDevelopInstance::MonoDevelopInstance(const String &p_solution, EditorId p_editor_id) {
_GDMONO_SCOPE_DOMAIN_(TOOLS_DOMAIN)
@@ -67,15 +67,16 @@ MonoDevelopInstance::MonoDevelopInstance(const String &p_solution) {
MonoObject *obj = mono_object_new(TOOLS_DOMAIN, klass->get_mono_ptr());
- GDMonoMethod *ctor = klass->get_method(".ctor", 1);
+ GDMonoMethod *ctor = klass->get_method(".ctor", 2);
MonoException *exc = NULL;
Variant solution = p_solution;
- const Variant *args[1] = { &solution };
+ Variant editor_id = p_editor_id;
+ const Variant *args[2] = { &solution, &editor_id };
ctor->invoke(obj, args, &exc);
if (exc) {
- GDMonoUtils::debug_unhandled_exception(exc);
+ GDMonoUtils::debug_print_unhandled_exception(exc);
ERR_FAIL();
}
diff --git a/modules/mono/editor/monodevelop_instance.h b/modules/mono/editor/monodevelop_instance.h
index 552c10a61d..29de4a4735 100644
--- a/modules/mono/editor/monodevelop_instance.h
+++ b/modules/mono/editor/monodevelop_instance.h
@@ -31,7 +31,7 @@
#ifndef MONODEVELOP_INSTANCE_H
#define MONODEVELOP_INSTANCE_H
-#include "reference.h"
+#include "core/reference.h"
#include "../mono_gc_handle.h"
#include "../mono_gd/gd_mono_method.h"
@@ -42,10 +42,15 @@ class MonoDevelopInstance {
GDMonoMethod *execute_method;
public:
+ enum EditorId {
+ MONODEVELOP = 0,
+ VISUALSTUDIO_FOR_MAC = 1
+ };
+
void execute(const Vector<String> &p_files);
void execute(const String &p_file);
- MonoDevelopInstance(const String &p_solution);
+ MonoDevelopInstance(const String &p_solution, EditorId p_editor_id);
};
#endif // MONODEVELOP_INSTANCE_H
diff --git a/modules/mono/editor/net_solution.cpp b/modules/mono/editor/net_solution.cpp
index dab96e44e9..8bbd376c9a 100644
--- a/modules/mono/editor/net_solution.cpp
+++ b/modules/mono/editor/net_solution.cpp
@@ -30,8 +30,8 @@
#include "net_solution.h"
-#include "os/dir_access.h"
-#include "os/file_access.h"
+#include "core/os/dir_access.h"
+#include "core/os/file_access.h"
#include "../utils/path_utils.h"
#include "../utils/string_utils.h"
diff --git a/modules/mono/editor/net_solution.h b/modules/mono/editor/net_solution.h
index 293e86917a..bdff24af0b 100644
--- a/modules/mono/editor/net_solution.h
+++ b/modules/mono/editor/net_solution.h
@@ -31,8 +31,8 @@
#ifndef NET_SOLUTION_H
#define NET_SOLUTION_H
-#include "map.h"
-#include "ustring.h"
+#include "core/map.h"
+#include "core/ustring.h"
struct NETSolution {
String name;