summaryrefslogtreecommitdiff
path: root/modules/mono
diff options
context:
space:
mode:
Diffstat (limited to 'modules/mono')
-rw-r--r--modules/mono/SCsub5
-rw-r--r--modules/mono/csharp_script.cpp146
-rw-r--r--modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs12
-rw-r--r--modules/mono/editor/GodotSharpTools/Project/ProjectExtensions.cs5
-rw-r--r--modules/mono/editor/GodotSharpTools/Project/ProjectUtils.cs4
-rw-r--r--modules/mono/editor/bindings_generator.cpp21
-rw-r--r--modules/mono/editor/godotsharp_builds.cpp62
-rw-r--r--modules/mono/editor/godotsharp_editor.cpp4
-rw-r--r--modules/mono/glue/cs_files/Basis.cs77
-rw-r--r--modules/mono/glue/cs_files/Quat.cs4
-rw-r--r--modules/mono/glue/cs_files/Transform.cs8
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp38
-rw-r--r--modules/mono/mono_gd/gd_mono.h2
-rw-r--r--modules/mono/mono_gd/gd_mono_assembly.cpp97
-rw-r--r--modules/mono/mono_gd/gd_mono_assembly.h8
-rw-r--r--modules/mono/mono_gd/gd_mono_field.cpp4
-rw-r--r--modules/mono/mono_gd/gd_mono_marshal.cpp73
-rw-r--r--modules/mono/mono_gd/gd_mono_marshal.h19
-rw-r--r--modules/mono/mono_reg_utils.py6
-rw-r--r--modules/mono/register_types.cpp1
20 files changed, 390 insertions, 206 deletions
diff --git a/modules/mono/SCsub b/modules/mono/SCsub
index 0af2056c5c..caf4fdb3ca 100644
--- a/modules/mono/SCsub
+++ b/modules/mono/SCsub
@@ -2,9 +2,10 @@
Import('env')
+from compat import byte_to_str
def make_cs_files_header(src, dst):
- with open(dst, 'wb') as header:
+ with open(dst, 'w') as header:
header.write('/* This is an automatically generated file; DO NOT EDIT! OK THX */\n')
header.write('#ifndef _CS_FILES_DATA_H\n')
header.write('#define _CS_FILES_DATA_H\n\n')
@@ -26,7 +27,7 @@ def make_cs_files_header(src, dst):
for i, buf_idx in enumerate(range(len(buf))):
if i > 0:
header.write(', ')
- header.write(str(ord(buf[buf_idx])))
+ header.write(byte_to_str(buf[buf_idx]))
inserted_files += '\tr_files.insert(\"' + file + '\", ' \
'CompressedFile(_cs_' + name + '_compressed_size, ' \
'_cs_' + name + '_uncompressed_size, ' \
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
index 67b4e67e2b..b475782729 100644
--- a/modules/mono/csharp_script.cpp
+++ b/modules/mono/csharp_script.cpp
@@ -50,6 +50,21 @@
#define CACHED_STRING_NAME(m_var) (CSharpLanguage::get_singleton()->string_names.m_var)
+static bool _create_project_solution_if_needed() {
+
+ String sln_path = GodotSharpDirs::get_project_sln_path();
+ String csproj_path = GodotSharpDirs::get_project_csproj_path();
+
+ if (!FileAccess::exists(sln_path) || !FileAccess::exists(csproj_path)) {
+ // A solution does not yet exist, create a new one
+
+ CRASH_COND(GodotSharpEditor::get_singleton() == NULL);
+ return GodotSharpEditor::get_singleton()->call("_create_project_solution");
+ }
+
+ return true;
+}
+
CSharpLanguage *CSharpLanguage::singleton = NULL;
String CSharpLanguage::get_name() const {
@@ -639,6 +654,13 @@ void *CSharpLanguage::alloc_instance_binding_data(Object *p_object) {
StringName type_name = p_object->get_class_name();
+ // ¯\_(ツ)_/¯
+ const ClassDB::ClassInfo *classinfo = ClassDB::classes.getptr(type_name);
+ while (classinfo && !classinfo->exposed)
+ classinfo = classinfo->inherits_ptr;
+ ERR_FAIL_NULL_V(classinfo, NULL);
+ type_name = classinfo->name;
+
GDMonoClass *type_class = GDMonoUtils::type_get_proxy_class(type_name);
ERR_FAIL_NULL_V(type_class, NULL);
@@ -767,7 +789,7 @@ bool CSharpInstance::set(const StringName &p_name, const Variant &p_value) {
if (method) {
MonoObject *ret = method->invoke(mono_object, args);
- if (ret && UNBOX_BOOLEAN(ret))
+ if (ret && GDMonoMarshal::unbox<MonoBoolean>(ret) == true)
return true;
}
@@ -1186,8 +1208,6 @@ bool CSharpScript::_update_exports() {
exported_members_cache.clear();
exported_members_defval_cache.clear();
- const Vector<GDMonoField *> &fields = script_class->get_all_fields();
-
// We are creating a temporary new instance of the class here to get the default value
// TODO Workaround. Should be replaced with IL opcodes analysis
@@ -1211,36 +1231,47 @@ bool CSharpScript::_update_exports() {
return false;
}
- for (int i = 0; i < fields.size(); i++) {
- GDMonoField *field = fields[i];
+ GDMonoClass *top = script_class;
- if (field->is_static() || field->get_visibility() != GDMono::PUBLIC)
- continue;
+ while (top && top != native) {
+ const Vector<GDMonoField *> &fields = top->get_all_fields();
- String name = field->get_name();
- StringName cname = name;
+ for (int i = 0; i < fields.size(); i++) {
+ GDMonoField *field = fields[i];
- Variant::Type type = GDMonoMarshal::managed_to_variant_type(field->get_type());
+ if (field->is_static() || field->get_visibility() != GDMono::PUBLIC)
+ continue;
- if (field->has_attribute(CACHED_CLASS(ExportAttribute))) {
- MonoObject *attr = field->get_attribute(CACHED_CLASS(ExportAttribute));
+ String name = field->get_name();
+ StringName cname = name;
- // Field has Export attribute
- int hint = CACHED_FIELD(ExportAttribute, hint)->get_int_value(attr);
- String hint_string = CACHED_FIELD(ExportAttribute, hint_string)->get_string_value(attr);
- int usage = CACHED_FIELD(ExportAttribute, usage)->get_int_value(attr);
+ if (member_info.has(cname))
+ continue;
- PropertyInfo prop_info = PropertyInfo(type, name, PropertyHint(hint), hint_string, PropertyUsageFlags(usage));
+ Variant::Type type = GDMonoMarshal::managed_to_variant_type(field->get_type());
- member_info[cname] = prop_info;
- exported_members_cache.push_back(prop_info);
+ if (field->has_attribute(CACHED_CLASS(ExportAttribute))) {
+ MonoObject *attr = field->get_attribute(CACHED_CLASS(ExportAttribute));
- if (tmp_object) {
- exported_members_defval_cache[cname] = GDMonoMarshal::mono_object_to_variant(field->get_value(tmp_object));
+ // Field has Export attribute
+ int hint = CACHED_FIELD(ExportAttribute, hint)->get_int_value(attr);
+ String hint_string = CACHED_FIELD(ExportAttribute, hint_string)->get_string_value(attr);
+ int usage = CACHED_FIELD(ExportAttribute, usage)->get_int_value(attr);
+
+ PropertyInfo prop_info = PropertyInfo(type, name, PropertyHint(hint), hint_string, PropertyUsageFlags(usage));
+
+ member_info[cname] = prop_info;
+ exported_members_cache.push_back(prop_info);
+
+ if (tmp_object) {
+ exported_members_defval_cache[cname] = GDMonoMarshal::mono_object_to_variant(field->get_value(tmp_object));
+ }
+ } else {
+ member_info[cname] = PropertyInfo(type, name, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_SCRIPT_VARIABLE);
}
- } else {
- member_info[cname] = PropertyInfo(type, name, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_SCRIPT_VARIABLE);
}
+
+ top = top->get_parent_class();
}
}
@@ -1359,7 +1390,18 @@ Ref<CSharpScript> CSharpScript::create_for_managed_type(GDMonoClass *p_class) {
bool CSharpScript::can_instance() const {
- // TODO does the second condition even make sense?
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint()) {
+ if (_create_project_solution_if_needed()) {
+ CSharpProject::add_item(GodotSharpDirs::get_project_csproj_path(),
+ "Compile",
+ ProjectSettings::get_singleton()->globalize_path(get_path()));
+ } else {
+ ERR_PRINTS("Cannot add " + get_path() + " to the C# project because it could not be created.");
+ }
+ }
+#endif
+
return valid || (!tool && !ScriptServer::is_scripting_enabled());
}
@@ -1545,6 +1587,18 @@ Error CSharpScript::reload(bool p_keep_state) {
if (project_assembly) {
script_class = project_assembly->get_object_derived_class(name);
+
+ if (!script_class) {
+ ERR_PRINTS("Cannot find class " + name + " for script " + get_path());
+ }
+#ifdef DEBUG_ENABLED
+ else if (OS::get_singleton()->is_stdout_verbose()) {
+ OS::get_singleton()->print(String("Found class " + script_class->get_namespace() + "." +
+ script_class->get_name() + " for script " + get_path() + "\n")
+ .utf8());
+ }
+#endif
+
valid = script_class != NULL;
if (script_class) {
@@ -1757,6 +1811,31 @@ RES ResourceFormatLoaderCSharpScript::load(const String &p_path, const String &p
#endif
script->set_path(p_original_path);
+
+#ifndef TOOLS_ENABLED
+
+#ifdef DEBUG_ENABLED
+ // User is responsible for thread attach/detach
+ ERR_EXPLAIN("Thread is not attached");
+ CRASH_COND(mono_domain_get() == NULL);
+#endif
+
+#else
+ if (Engine::get_singleton()->is_editor_hint() && mono_domain_get() == NULL) {
+
+ CRASH_COND(Thread::get_caller_id() == Thread::get_main_id());
+
+ // Thread is not attached, but we will make an exception in this case
+ // because this may be called by one of the editor's worker threads.
+ // Attach this thread temporarily to reload the script.
+
+ MonoThread *mono_thread = mono_thread_attach(SCRIPTS_DOMAIN);
+ CRASH_COND(mono_thread == NULL);
+ script->reload();
+ mono_thread_detach(mono_thread);
+
+ } else // just reload it normally
+#endif
script->reload();
if (r_error)
@@ -1791,21 +1870,12 @@ Error ResourceFormatSaverCSharpScript::save(const String &p_path, const RES &p_r
if (!FileAccess::exists(p_path)) {
// The file does not yet exists, let's assume the user just created this script
- String sln_path = GodotSharpDirs::get_project_sln_path();
- String csproj_path = GodotSharpDirs::get_project_csproj_path();
-
- if (!FileAccess::exists(sln_path) || !FileAccess::exists(csproj_path)) {
- // A solution does not yet exist, create a new one
-
- CRASH_COND(GodotSharpEditor::get_singleton() == NULL);
- GodotSharpEditor::get_singleton()->call("_create_project_solution");
- }
-
- // Add the file to the C# project
- if (FileAccess::exists(csproj_path)) {
- CSharpProject::add_item(csproj_path, "Compile", ProjectSettings::get_singleton()->globalize_path(p_path));
+ if (_create_project_solution_if_needed()) {
+ CSharpProject::add_item(GodotSharpDirs::get_project_csproj_path(),
+ "Compile",
+ ProjectSettings::get_singleton()->globalize_path(p_path));
} else {
- ERR_PRINT("C# project not found!");
+ ERR_PRINTS("Cannot add " + p_path + " to the C# project because it could not be created.");
}
}
#endif
diff --git a/modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs b/modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs
index 256e64ddde..5544233eb7 100644
--- a/modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs
+++ b/modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs
@@ -19,7 +19,15 @@ namespace GodotSharpTools.Build
private static string MSBuildPath
{
- get { return godot_icall_BuildInstance_get_MSBuildPath(); }
+ get
+ {
+ string ret = godot_icall_BuildInstance_get_MSBuildPath();
+
+ if (ret == null)
+ throw new FileNotFoundException("Cannot find the MSBuild executable.");
+
+ return ret;
+ }
}
private string solution;
@@ -98,7 +106,7 @@ namespace GodotSharpTools.Build
private string BuildArguments(string loggerAssemblyPath, string loggerOutputDir, string[] customProperties)
{
- string arguments = string.Format("{0} /v:normal /t:Build /p:{1} /l:{2},{3};{4}",
+ string arguments = string.Format(@"""{0}"" /v:normal /t:Build ""/p:{1}"" ""/l:{2},{3};{4}""",
solution,
"Configuration=" + config,
typeof(GodotBuildLogger).FullName,
diff --git a/modules/mono/editor/GodotSharpTools/Project/ProjectExtensions.cs b/modules/mono/editor/GodotSharpTools/Project/ProjectExtensions.cs
index 6a97731539..f00ec5a2ad 100644
--- a/modules/mono/editor/GodotSharpTools/Project/ProjectExtensions.cs
+++ b/modules/mono/editor/GodotSharpTools/Project/ProjectExtensions.cs
@@ -27,12 +27,15 @@ namespace GodotSharpTools.Project
return false;
}
- public static void AddItemChecked(this ProjectRootElement root, string itemType, string include)
+ public static bool AddItemChecked(this ProjectRootElement root, string itemType, string include)
{
if (!root.HasItem(itemType, include))
{
root.AddItem(itemType, include);
+ return true;
}
+
+ return false;
}
public static Guid GetGuid(this ProjectRootElement root)
diff --git a/modules/mono/editor/GodotSharpTools/Project/ProjectUtils.cs b/modules/mono/editor/GodotSharpTools/Project/ProjectUtils.cs
index a50b4fb064..6889ea715f 100644
--- a/modules/mono/editor/GodotSharpTools/Project/ProjectUtils.cs
+++ b/modules/mono/editor/GodotSharpTools/Project/ProjectUtils.cs
@@ -10,8 +10,8 @@ namespace GodotSharpTools.Project
{
var dir = Directory.GetParent(projectPath).FullName;
var root = ProjectRootElement.Open(projectPath);
- root.AddItemChecked(itemType, include.RelativeToPath(dir).Replace("/", "\\"));
- root.Save();
+ if (root.AddItemChecked(itemType, include.RelativeToPath(dir).Replace("/", "\\")))
+ root.Save();
}
}
}
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
index 123f00ea10..704910c5b9 100644
--- a/modules/mono/editor/bindings_generator.cpp
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -133,12 +133,6 @@ static bool is_csharp_keyword(const String &p_name) {
p_name == "virtual" || p_name == "volatile" || p_name == "void" || p_name == "while";
}
-static bool is_singleton_black_listed(const String &p_type) {
-
- return p_type == "IP_Unix" || p_type == "InputDefault" || p_type == "AudioServerSW" || p_type == "PhysicsServerSW" ||
- p_type == "Physics2DServerSW" || p_type == "SpatialSoundServerSW" || p_type == "SpatialSound2DServerSW";
-}
-
inline static String escape_csharp_keyword(const String &p_name) {
return is_csharp_keyword(p_name) ? "@" + p_name : p_name;
@@ -247,9 +241,6 @@ void BindingsGenerator::_generate_header_icalls() {
void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) {
- if (p_itype.base_name.length() && obj_types[p_itype.base_name].is_singleton && is_singleton_black_listed(p_itype.name))
- return;
-
for (const List<MethodInterface>::Element *E = p_itype.methods.front(); E; E = E->next()) {
const MethodInterface &imethod = E->get();
@@ -580,9 +571,6 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str
bool is_derived_type = itype.base_name.length();
- if (is_derived_type && obj_types[itype.base_name].is_singleton && is_singleton_black_listed(itype.name))
- return ERR_SKIP;
-
List<InternalCall> &custom_icalls = itype.api_type == ClassDB::API_EDITOR ? editor_custom_icalls : core_custom_icalls;
if (verbose_output)
@@ -1167,9 +1155,6 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) {
for (Map<String, TypeInterface>::Element *type_elem = obj_types.front(); type_elem; type_elem = type_elem->next()) {
const TypeInterface &itype = type_elem->get();
- if (itype.base_name.length() && obj_types[itype.base_name].is_singleton && is_singleton_black_listed(itype.name))
- continue;
-
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());
@@ -1519,6 +1504,12 @@ void BindingsGenerator::_populate_object_type_interfaces() {
itype.is_reference = ClassDB::is_parent_class(type_cname, refclass_name);
itype.memory_own = itype.is_reference;
+ if (!ClassDB::is_class_exposed(type_cname)) {
+ WARN_PRINTS("Ignoring type " + String(type_cname) + " because it's not exposed");
+ class_list.pop_front();
+ continue;
+ }
+
itype.c_out = "\treturn ";
itype.c_out += C_METHOD_UNMANAGED_GET_MANAGED;
itype.c_out += itype.is_reference ? "(%1.ptr());\n" : "(%1);\n";
diff --git a/modules/mono/editor/godotsharp_builds.cpp b/modules/mono/editor/godotsharp_builds.cpp
index e7d9c83421..1bad8a3f85 100644
--- a/modules/mono/editor/godotsharp_builds.cpp
+++ b/modules/mono/editor/godotsharp_builds.cpp
@@ -29,13 +29,14 @@
/*************************************************************************/
#include "godotsharp_builds.h"
+#include "main/main.h"
+
#include "../godotsharp_dirs.h"
#include "../mono_gd/gd_mono_class.h"
#include "../mono_gd/gd_mono_marshal.h"
#include "../utils/path_utils.h"
#include "bindings_generator.h"
#include "godotsharp_editor.h"
-#include "main/main.h"
void godot_icall_BuildInstance_ExitCallback(MonoString *p_solution, MonoString *p_config, int p_exit_code) {
@@ -44,11 +45,37 @@ void godot_icall_BuildInstance_ExitCallback(MonoString *p_solution, MonoString *
GodotSharpBuilds::get_singleton()->build_exit_callback(MonoBuildInfo(solution, config), p_exit_code);
}
+#ifdef UNIX_ENABLED
+String _find_build_engine_on_unix(const String &p_name) {
+ String ret = path_which(p_name);
+
+ if (ret.length())
+ return ret;
+
+ const char *locations[] = {
+#ifdef OSX_ENABLED
+ "/Library/Frameworks/Mono.framework/Versions/Current/bin/",
+#endif
+ "/opt/novell/mono/bin/"
+ };
+
+ for (int i = 0; i < sizeof(locations) / sizeof(const char *); i++) {
+ String location = locations[i];
+
+ if (FileAccess::exists(location + p_name)) {
+ return location;
+ }
+ }
+
+ return String();
+}
+#endif
+
MonoString *godot_icall_BuildInstance_get_MSBuildPath() {
GodotSharpBuilds::BuildTool build_tool = GodotSharpBuilds::BuildTool(int(EditorSettings::get_singleton()->get("mono/builds/build_tool")));
-#ifdef WINDOWS_ENABLED
+#if defined(WINDOWS_ENABLED)
switch (build_tool) {
case GodotSharpBuilds::MSBUILD: {
static String msbuild_tools_path = MonoRegUtils::find_msbuild_tools_path();
@@ -84,14 +111,25 @@ MonoString *godot_icall_BuildInstance_get_MSBuildPath() {
ERR_EXPLAIN("You don't deserve to live");
CRASH_NOW();
}
-#else
- static bool msbuild_found = path_which("msbuild").length();
-
- if (build_tool != GodotSharpBuilds::XBUILD && !msbuild_found) {
- WARN_PRINT("Cannot find msbuild ('mono/builds/build_tool').");
+#elif defined(UNIX_ENABLED)
+ static String msbuild_path = _find_build_engine_on_unix("msbuild");
+ static String xbuild_path = _find_build_engine_on_unix("xbuild");
+
+ if (build_tool != GodotSharpBuilds::XBUILD) {
+ if (msbuild_path.empty()) {
+ WARN_PRINT("Cannot find msbuild ('mono/builds/build_tool').");
+ return NULL;
+ }
+ } else {
+ if (xbuild_path.empty()) {
+ WARN_PRINT("Cannot find xbuild ('mono/builds/build_tool').");
+ return NULL;
+ }
}
- return GDMonoMarshal::mono_string_from_godot(build_tool != GodotSharpBuilds::XBUILD ? "msbuild" : "xbuild");
+ return GDMonoMarshal::mono_string_from_godot(build_tool != GodotSharpBuilds::XBUILD ? msbuild_path : xbuild_path);
+#else
+ return NULL;
#endif
}
@@ -314,8 +352,8 @@ GodotSharpBuilds::GodotSharpBuilds() {
// Build tool settings
EditorSettings *ed_settings = EditorSettings::get_singleton();
- if (!ed_settings->has("mono/builds/build_tool")) {
- ed_settings->set("mono/builds/build_tool", MSBUILD);
+ if (!ed_settings->has_setting("mono/builds/build_tool")) {
+ ed_settings->set_setting("mono/builds/build_tool", MSBUILD);
}
ed_settings->add_property_hint(PropertyInfo(Variant::INT, "mono/builds/build_tool", PROPERTY_HINT_ENUM, "MSBuild (System),MSBuild (Mono),xbuild"));
}
@@ -423,6 +461,10 @@ void GodotSharpBuilds::BuildProcess::start(bool p_blocking) {
if (p_blocking) {
exited = true;
exit_code = klass->get_field("exitCode")->get_int_value(mono_object);
+
+ if (exit_code != 0 && OS::get_singleton()->is_stdout_verbose())
+ OS::get_singleton()->print(String("MSBuild finished with exit code " + itos(exit_code) + "\n").utf8());
+
build_tab->on_build_exit(exit_code == 0 ? MonoBuildTab::RESULT_SUCCESS : MonoBuildTab::RESULT_ERROR);
} else {
build_instance = MonoGCHandle::create_strong(mono_object);
diff --git a/modules/mono/editor/godotsharp_editor.cpp b/modules/mono/editor/godotsharp_editor.cpp
index 5aaf029495..30e7653256 100644
--- a/modules/mono/editor/godotsharp_editor.cpp
+++ b/modules/mono/editor/godotsharp_editor.cpp
@@ -237,8 +237,8 @@ GodotSharpEditor::GodotSharpEditor(EditorNode *p_editor) {
// External editor settings
EditorSettings *ed_settings = EditorSettings::get_singleton();
- if (!ed_settings->has("mono/editor/external_editor")) {
- ed_settings->set("mono/editor/external_editor", EDITOR_NONE);
+ if (!ed_settings->has_setting("mono/editor/external_editor")) {
+ ed_settings->set_setting("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,Visual Studio Code"));
}
diff --git a/modules/mono/glue/cs_files/Basis.cs b/modules/mono/glue/cs_files/Basis.cs
index 6a73ebd554..c50e783349 100644
--- a/modules/mono/glue/cs_files/Basis.cs
+++ b/modules/mono/glue/cs_files/Basis.cs
@@ -160,26 +160,29 @@ namespace Godot
Basis m = this.orthonormalized();
Vector3 euler;
+ euler.z = 0.0f;
- euler.y = Mathf.asin(m.x[2]);
+ float mxy = m.y[2];
- if (euler.y < Mathf.PI * 0.5f)
+
+ if (mxy < 1.0f)
{
- if (euler.y > -Mathf.PI * 0.5f)
+ if (mxy > -1.0f)
{
- euler.x = Mathf.atan2(-m.y[2], m.z[2]);
- euler.z = Mathf.atan2(-m.x[1], m.x[0]);
+ euler.x = Mathf.asin(-mxy);
+ euler.y = Mathf.atan2(m.x[2], m.z[2]);
+ euler.z = Mathf.atan2(m.y[0], m.y[1]);
}
else
{
- euler.z = 0.0f;
- euler.x = euler.z - Mathf.atan2(m.y[0], m.y[1]);
+ euler.x = Mathf.PI * 0.5f;
+ euler.y = -Mathf.atan2(-m.x[1], m.x[0]);
}
}
else
{
- euler.z = 0f;
- euler.x = Mathf.atan2(m.x[1], m.y[1]) - euler.z;
+ euler.x = -Mathf.PI * 0.5f;
+ euler.y = -Mathf.atan2(m.x[1], m.x[0]);
}
return euler;
@@ -273,7 +276,7 @@ namespace Godot
public Basis rotated(Vector3 axis, float phi)
{
- return this * new Basis(axis, phi);
+ return new Basis(axis, phi) * this;
}
public Basis scaled(Vector3 scale)
@@ -281,13 +284,13 @@ namespace Godot
Basis m = this;
m[0, 0] *= scale.x;
- m[1, 0] *= scale.x;
- m[2, 0] *= scale.x;
- m[0, 1] *= scale.y;
+ m[0, 1] *= scale.x;
+ m[0, 2] *= scale.x;
+ m[1, 0] *= scale.y;
m[1, 1] *= scale.y;
- m[2, 1] *= scale.y;
- m[0, 2] *= scale.z;
- m[1, 2] *= scale.z;
+ m[1, 2] *= scale.y;
+ m[2, 0] *= scale.z;
+ m[2, 1] *= scale.z;
m[2, 2] *= scale.z;
return m;
@@ -347,6 +350,48 @@ namespace Godot
);
}
+ public Quat Quat() {
+ float trace = x[0] + y[1] + z[2];
+
+ if (trace > 0.0f) {
+ float s = Mathf.sqrt(trace + 1.0f) * 2f;
+ float inv_s = 1f / s;
+ return new Quat(
+ (z[1] - y[2]) * inv_s,
+ (x[2] - z[0]) * inv_s,
+ (y[0] - x[1]) * inv_s,
+ s * 0.25f
+ );
+ } else if (x[0] > y[1] && x[0] > z[2]) {
+ float s = Mathf.sqrt(x[0] - y[1] - z[2] + 1.0f) * 2f;
+ float inv_s = 1f / s;
+ return new Quat(
+ s * 0.25f,
+ (x[1] + y[0]) * inv_s,
+ (x[2] + z[0]) * inv_s,
+ (z[1] - y[2]) * inv_s
+ );
+ } else if (y[1] > z[2]) {
+ float s = Mathf.sqrt(-x[0] + y[1] - z[2] + 1.0f) * 2f;
+ float inv_s = 1f / s;
+ return new Quat(
+ (x[1] + y[0]) * inv_s,
+ s * 0.25f,
+ (y[2] + z[1]) * inv_s,
+ (x[2] - z[0]) * inv_s
+ );
+ } else {
+ float s = Mathf.sqrt(-x[0] - y[1] + z[2] + 1.0f) * 2f;
+ float inv_s = 1f / s;
+ return new Quat(
+ (x[2] + z[0]) * inv_s,
+ (y[2] + z[1]) * inv_s,
+ s * 0.25f,
+ (y[0] - x[1]) * inv_s
+ );
+ }
+ }
+
public Basis(Quat quat)
{
float s = 2.0f / quat.length_squared();
diff --git a/modules/mono/glue/cs_files/Quat.cs b/modules/mono/glue/cs_files/Quat.cs
index 6345239f47..9b4b7fb297 100644
--- a/modules/mono/glue/cs_files/Quat.cs
+++ b/modules/mono/glue/cs_files/Quat.cs
@@ -201,12 +201,12 @@ namespace Godot
}
else
{
- float s = Mathf.sin(-angle * 0.5f) / d;
+ float s = Mathf.sin(angle * 0.5f) / d;
x = axis.x * s;
y = axis.y * s;
z = axis.z * s;
- w = Mathf.cos(-angle * 0.5f);
+ w = Mathf.cos(angle * 0.5f);
}
}
diff --git a/modules/mono/glue/cs_files/Transform.cs b/modules/mono/glue/cs_files/Transform.cs
index 2010f0b3af..74271e758b 100644
--- a/modules/mono/glue/cs_files/Transform.cs
+++ b/modules/mono/glue/cs_files/Transform.cs
@@ -35,7 +35,7 @@ namespace Godot
public Transform rotated(Vector3 axis, float phi)
{
- return this * new Transform(new Basis(axis, phi), new Vector3());
+ return new Transform(new Basis(axis, phi), new Vector3()) * this;
}
public Transform scaled(Vector3 scale)
@@ -104,6 +104,12 @@ namespace Godot
this.origin = origin;
}
+ public Transform(Quat quat, Vector3 origin)
+ {
+ this.basis = new Basis(quat);
+ this.origin = origin;
+ }
+
public Transform(Basis basis, Vector3 origin)
{
this.basis = basis;
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index 77f01842bb..98b57adc50 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -31,6 +31,7 @@
#include <mono/metadata/mono-config.h>
#include <mono/metadata/mono-debug.h>
+#include <mono/metadata/mono-gc.h>
#include "os/dir_access.h"
#include "os/file_access.h"
@@ -265,6 +266,13 @@ void GDMono::add_assembly(uint32_t p_domain_id, GDMonoAssembly *p_assembly) {
assemblies[p_domain_id][p_assembly->get_name()] = p_assembly;
}
+GDMonoAssembly **GDMono::get_loaded_assembly(const String &p_name) {
+
+ MonoDomain *domain = mono_domain_get();
+ uint32_t domain_id = domain ? mono_domain_get_id(domain) : 0;
+ return assemblies[domain_id].getptr(p_name);
+}
+
bool GDMono::_load_assembly(const String &p_name, GDMonoAssembly **r_assembly) {
CRASH_COND(!r_assembly);
@@ -272,7 +280,7 @@ bool GDMono::_load_assembly(const String &p_name, GDMonoAssembly **r_assembly) {
if (OS::get_singleton()->is_stdout_verbose())
OS::get_singleton()->print((String() + "Mono: Loading assembly " + p_name + "...\n").utf8());
- MonoImageOpenStatus status;
+ MonoImageOpenStatus status = MONO_IMAGE_OK;
MonoAssemblyName *aname = mono_assembly_name_new(p_name.utf8());
MonoAssembly *assembly = mono_assembly_load_full(aname, NULL, &status, false);
mono_assembly_name_free(aname);
@@ -284,27 +292,11 @@ bool GDMono::_load_assembly(const String &p_name, GDMonoAssembly **r_assembly) {
GDMonoAssembly **stored_assembly = assemblies[domain_id].getptr(p_name);
- if (stored_assembly) {
- // Loaded by our preload hook (status is not initialized when returning from a preload hook)
- ERR_FAIL_COND_V((*stored_assembly)->get_assembly() != assembly, false);
- *r_assembly = *stored_assembly;
- } else {
- ERR_FAIL_COND_V(status != MONO_IMAGE_OK, false);
-
- MonoImage *assembly_image = mono_assembly_get_image(assembly);
- ERR_FAIL_NULL_V(assembly_image, false);
-
- const char *path = mono_image_get_filename(assembly_image);
+ ERR_FAIL_COND_V(status != MONO_IMAGE_OK, false);
+ ERR_FAIL_COND_V(stored_assembly == NULL, false);
- *r_assembly = memnew(GDMonoAssembly(p_name, path));
- Error error = (*r_assembly)->wrapper_for_image(assembly_image);
-
- if (error != OK) {
- memdelete(*r_assembly);
- *r_assembly = NULL;
- ERR_FAIL_V(false);
- }
- }
+ ERR_FAIL_COND_V((*stored_assembly)->get_assembly() != assembly, false);
+ *r_assembly = *stored_assembly;
if (OS::get_singleton()->is_stdout_verbose())
OS::get_singleton()->print(String("Mono: Assembly " + p_name + " loaded from path: " + (*r_assembly)->get_path() + "\n").utf8());
@@ -438,10 +430,14 @@ Error GDMono::_unload_scripts_domain() {
if (mono_domain_get() != root_domain)
mono_domain_set(root_domain, true);
+ mono_gc_collect(mono_gc_max_generation());
+
finalizing_scripts_domain = true;
mono_domain_finalize(scripts_domain, 2000);
finalizing_scripts_domain = false;
+ mono_gc_collect(mono_gc_max_generation());
+
_domain_assemblies_cleanup(mono_domain_get_id(scripts_domain));
api_assembly = NULL;
diff --git a/modules/mono/mono_gd/gd_mono.h b/modules/mono/mono_gd/gd_mono.h
index ab96d575e6..b188c0730a 100644
--- a/modules/mono/mono_gd/gd_mono.h
+++ b/modules/mono/mono_gd/gd_mono.h
@@ -122,7 +122,9 @@ public:
static GDMono *get_singleton() { return singleton; }
+ // Do not use these, unless you know what you're doing
void add_assembly(uint32_t p_domain_id, GDMonoAssembly *p_assembly);
+ GDMonoAssembly **get_loaded_assembly(const String &p_name);
_FORCE_INLINE_ bool is_runtime_initialized() const { return runtime_initialized; }
_FORCE_INLINE_ bool is_finalizing_scripts_domain() const { return finalizing_scripts_domain; }
diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp
index a98537b9e1..4b370295f3 100644
--- a/modules/mono/mono_gd/gd_mono_assembly.cpp
+++ b/modules/mono/mono_gd/gd_mono_assembly.cpp
@@ -39,28 +39,60 @@
#include "../godotsharp_dirs.h"
#include "gd_mono_class.h"
-MonoAssembly *gdmono_load_assembly_from(const String &p_name, const String &p_path) {
+bool GDMonoAssembly::no_search = false;
+Vector<String> GDMonoAssembly::search_dirs;
- MonoDomain *domain = mono_domain_get();
+MonoAssembly *GDMonoAssembly::_search_hook(MonoAssemblyName *aname, void *user_data) {
- GDMonoAssembly *assembly = memnew(GDMonoAssembly(p_name, p_path));
- Error err = assembly->load(domain);
- ERR_FAIL_COND_V(err != OK, NULL);
+ (void)user_data; // UNUSED
- GDMono::get_singleton()->add_assembly(mono_domain_get_id(domain), assembly);
+ String name = mono_assembly_name_get_name(aname);
+ bool has_extension = name.ends_with(".dll") || name.ends_with(".exe");
- return assembly->get_assembly();
-}
+ if (no_search)
+ return NULL;
-MonoAssembly *gdmono_MonoAssemblyPreLoad(MonoAssemblyName *aname, char **assemblies_path, void *user_data) {
+ GDMonoAssembly **loaded_asm = GDMono::get_singleton()->get_loaded_assembly(has_extension ? name.get_basename() : name);
+ if (loaded_asm)
+ return (*loaded_asm)->get_assembly();
- (void)user_data; // UNUSED
+ no_search = true; // Avoid the recursion madness
+
+ String path;
+ MonoAssembly *res = NULL;
+
+ for (int i = 0; i < search_dirs.size(); i++) {
+ const String &search_dir = search_dirs[i];
- MonoAssembly *assembly_loaded = mono_assembly_loaded(aname);
- if (assembly_loaded) // Already loaded
- return assembly_loaded;
+ if (has_extension) {
+ path = search_dir.plus_file(name);
+ if (FileAccess::exists(path)) {
+ res = _load_assembly_from(name.get_basename(), path);
+ break;
+ }
+ } else {
+ path = search_dir.plus_file(name + ".dll");
+ if (FileAccess::exists(path)) {
+ res = _load_assembly_from(name, path);
+ break;
+ }
+
+ path = search_dir.plus_file(name + ".exe");
+ if (FileAccess::exists(path)) {
+ res = _load_assembly_from(name, path);
+ break;
+ }
+ }
+ }
- static Vector<String> search_dirs;
+ no_search = false;
+
+ return res;
+}
+
+MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data) {
+
+ (void)user_data; // UNUSED
if (search_dirs.empty()) {
search_dirs.push_back(GodotSharpDirs::get_res_temp_assemblies_dir());
@@ -80,35 +112,32 @@ MonoAssembly *gdmono_MonoAssemblyPreLoad(MonoAssemblyName *aname, char **assembl
}
}
- String name = mono_assembly_name_get_name(aname);
- bool has_extension = name.ends_with(".dll") || name.ends_with(".exe");
+ return NULL;
+}
- String path;
+MonoAssembly *GDMonoAssembly::_load_assembly_from(const String &p_name, const String &p_path) {
- for (int i = 0; i < search_dirs.size(); i++) {
- const String &search_dir = search_dirs[i];
+ GDMonoAssembly *assembly = memnew(GDMonoAssembly(p_name, p_path));
- if (has_extension) {
- path = search_dir.plus_file(name);
- if (FileAccess::exists(path))
- return gdmono_load_assembly_from(name.get_basename(), path);
- } else {
- path = search_dir.plus_file(name + ".dll");
- if (FileAccess::exists(path))
- return gdmono_load_assembly_from(name, path);
+ MonoDomain *domain = mono_domain_get();
- path = search_dir.plus_file(name + ".exe");
- if (FileAccess::exists(path))
- return gdmono_load_assembly_from(name, path);
- }
+ Error err = assembly->load(domain);
+
+ if (err != OK) {
+ memdelete(assembly);
+ ERR_FAIL_V(NULL);
}
- return NULL;
+ GDMono::get_singleton()->add_assembly(domain ? mono_domain_get_id(domain) : 0, assembly);
+
+ return assembly->get_assembly();
}
void GDMonoAssembly::initialize() {
- mono_install_assembly_preload_hook(&gdmono_MonoAssemblyPreLoad, NULL);
+ // TODO refonly as well?
+ mono_install_assembly_preload_hook(&GDMonoAssembly::_preload_hook, NULL);
+ mono_install_assembly_search_hook(&GDMonoAssembly::_search_hook, NULL);
}
Error GDMonoAssembly::load(MonoDomain *p_domain) {
@@ -153,7 +182,7 @@ no_pdb:
ERR_FAIL_COND_V(status != MONO_IMAGE_OK || assembly == NULL, ERR_FILE_CANT_OPEN);
- if (mono_image_get_entry_point(image)) {
+ if (p_domain && mono_image_get_entry_point(image)) {
// TODO should this be removed? do we want to call main? what other effects does this have?
mono_jit_exec(p_domain, assembly, 0, NULL);
}
diff --git a/modules/mono/mono_gd/gd_mono_assembly.h b/modules/mono/mono_gd/gd_mono_assembly.h
index 89e091549c..710b674622 100644
--- a/modules/mono/mono_gd/gd_mono_assembly.h
+++ b/modules/mono/mono_gd/gd_mono_assembly.h
@@ -86,6 +86,14 @@ class GDMonoAssembly {
Vector<uint8_t> pdb_data;
#endif
+ static bool no_search;
+ static Vector<String> search_dirs;
+
+ static MonoAssembly *_search_hook(MonoAssemblyName *aname, void *user_data);
+ static MonoAssembly *_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data);
+
+ static MonoAssembly *_load_assembly_from(const String &p_name, const String &p_path);
+
friend class GDMono;
static void initialize();
diff --git a/modules/mono/mono_gd/gd_mono_field.cpp b/modules/mono/mono_gd/gd_mono_field.cpp
index 0c64380e31..c2d8eeaa32 100644
--- a/modules/mono/mono_gd/gd_mono_field.cpp
+++ b/modules/mono/mono_gd/gd_mono_field.cpp
@@ -279,11 +279,11 @@ void GDMonoField::set_value(MonoObject *p_object, const Variant &p_value) {
}
bool GDMonoField::get_bool_value(MonoObject *p_object) {
- return UNBOX_BOOLEAN(get_value(p_object));
+ return (bool)GDMonoMarshal::unbox<MonoBoolean>(get_value(p_object));
}
int GDMonoField::get_int_value(MonoObject *p_object) {
- return UNBOX_INT32(get_value(p_object));
+ return GDMonoMarshal::unbox<int32_t>(get_value(p_object));
}
String GDMonoField::get_string_value(MonoObject *p_object) {
diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp
index b5419952de..9a6c8f0cd6 100644
--- a/modules/mono/mono_gd/gd_mono_marshal.cpp
+++ b/modules/mono/mono_gd/gd_mono_marshal.cpp
@@ -41,11 +41,11 @@ namespace GDMonoMarshal {
return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(m_t), raw); \
}
-#define RETURN_UNBOXED_STRUCT(m_t, m_var_in) \
- { \
- float *raw = UNBOX_FLOAT_PTR(m_var_in); \
- MARSHALLED_IN(m_t, raw, ret); \
- return ret; \
+#define RETURN_UNBOXED_STRUCT(m_t, m_var_in) \
+ { \
+ float *raw = (float *)mono_object_unbox(m_var_in); \
+ MARSHALLED_IN(m_t, raw, ret); \
+ return ret; \
}
Variant::Type managed_to_variant_type(const ManagedType &p_type) {
@@ -453,30 +453,30 @@ Variant mono_object_to_variant(MonoObject *p_obj) {
Variant mono_object_to_variant(MonoObject *p_obj, const ManagedType &p_type) {
switch (p_type.type_encoding) {
case MONO_TYPE_BOOLEAN:
- return (bool)UNBOX_BOOLEAN(p_obj);
+ return (bool)unbox<MonoBoolean>(p_obj);
case MONO_TYPE_I1:
- return UNBOX_INT8(p_obj);
+ return unbox<int8_t>(p_obj);
case MONO_TYPE_I2:
- return UNBOX_INT16(p_obj);
+ return unbox<int16_t>(p_obj);
case MONO_TYPE_I4:
- return UNBOX_INT32(p_obj);
+ return unbox<int32_t>(p_obj);
case MONO_TYPE_I8:
- return UNBOX_INT64(p_obj);
+ return unbox<int64_t>(p_obj);
case MONO_TYPE_U1:
- return UNBOX_UINT8(p_obj);
+ return unbox<uint8_t>(p_obj);
case MONO_TYPE_U2:
- return UNBOX_UINT16(p_obj);
+ return unbox<uint16_t>(p_obj);
case MONO_TYPE_U4:
- return UNBOX_UINT32(p_obj);
+ return unbox<uint32_t>(p_obj);
case MONO_TYPE_U8:
- return UNBOX_UINT64(p_obj);
+ return unbox<uint64_t>(p_obj);
case MONO_TYPE_R4:
- return UNBOX_FLOAT(p_obj);
+ return unbox<float>(p_obj);
case MONO_TYPE_R8:
- return UNBOX_DOUBLE(p_obj);
+ return unbox<double>(p_obj);
case MONO_TYPE_STRING: {
String str = mono_string_to_godot((MonoString *)p_obj);
@@ -554,29 +554,18 @@ Variant mono_object_to_variant(MonoObject *p_obj, const ManagedType &p_type) {
// GodotObject
if (CACHED_CLASS(GodotObject)->is_assignable_from(type_class)) {
- GDMonoField *ptr_field = CACHED_FIELD(GodotObject, ptr);
-
- ERR_FAIL_NULL_V(ptr_field, Variant());
-
- void *ptr_to_unmanaged = UNBOX_PTR(ptr_field->get_value(p_obj));
-
- if (!ptr_to_unmanaged) // IntPtr.Zero
- return Variant();
-
- Object *object_ptr = static_cast<Object *>(ptr_to_unmanaged);
-
- if (!object_ptr)
- return Variant();
-
- return object_ptr;
+ Object *ptr = unbox<Object *>(CACHED_FIELD(GodotObject, ptr)->get_value(p_obj));
+ return ptr ? Variant(ptr) : Variant();
}
if (CACHED_CLASS(NodePath) == type_class) {
- return UNBOX_PTR(CACHED_FIELD(NodePath, ptr)->get_value(p_obj));
+ NodePath *ptr = unbox<NodePath *>(CACHED_FIELD(NodePath, ptr)->get_value(p_obj));
+ return ptr ? Variant(*ptr) : Variant();
}
if (CACHED_CLASS(RID) == type_class) {
- return UNBOX_PTR(CACHED_FIELD(RID, ptr)->get_value(p_obj));
+ RID *ptr = unbox<RID *>(CACHED_FIELD(RID, ptr)->get_value(p_obj));
+ return ptr ? Variant(*ptr) : Variant();
}
} break;
@@ -716,9 +705,9 @@ MonoArray *PoolColorArray_to_mono_array(const PoolColorArray &p_array) {
real_t *raw = (real_t *)mono_array_addr_with_size(ret, sizeof(real_t) * 4, i);
const Color &elem = p_array[i];
raw[0] = elem.r;
- raw[4] = elem.g;
- raw[8] = elem.b;
- raw[12] = elem.a;
+ raw[1] = elem.g;
+ raw[2] = elem.b;
+ raw[3] = elem.a;
#endif
}
@@ -730,7 +719,7 @@ PoolColorArray mono_array_to_PoolColorArray(MonoArray *p_array) {
int length = mono_array_length(p_array);
for (int i = 0; i < length; i++) {
- real_t *raw_elem = mono_array_get(p_array, real_t *, i);
+ real_t *raw_elem = (real_t *)mono_array_addr_with_size(p_array, sizeof(real_t) * 4, i);
MARSHALLED_IN(Color, raw_elem, elem);
ret.push_back(elem);
}
@@ -748,7 +737,7 @@ MonoArray *PoolVector2Array_to_mono_array(const PoolVector2Array &p_array) {
real_t *raw = (real_t *)mono_array_addr_with_size(ret, sizeof(real_t) * 2, i);
const Vector2 &elem = p_array[i];
raw[0] = elem.x;
- raw[4] = elem.y;
+ raw[1] = elem.y;
#endif
}
@@ -760,7 +749,7 @@ PoolVector2Array mono_array_to_PoolVector2Array(MonoArray *p_array) {
int length = mono_array_length(p_array);
for (int i = 0; i < length; i++) {
- real_t *raw_elem = mono_array_get(p_array, real_t *, i);
+ real_t *raw_elem = (real_t *)mono_array_addr_with_size(p_array, sizeof(real_t) * 2, i);
MARSHALLED_IN(Vector2, raw_elem, elem);
ret.push_back(elem);
}
@@ -778,8 +767,8 @@ MonoArray *PoolVector3Array_to_mono_array(const PoolVector3Array &p_array) {
real_t *raw = (real_t *)mono_array_addr_with_size(ret, sizeof(real_t) * 3, i);
const Vector3 &elem = p_array[i];
raw[0] = elem.x;
- raw[4] = elem.y;
- raw[8] = elem.z;
+ raw[1] = elem.y;
+ raw[2] = elem.z;
#endif
}
@@ -791,7 +780,7 @@ PoolVector3Array mono_array_to_PoolVector3Array(MonoArray *p_array) {
int length = mono_array_length(p_array);
for (int i = 0; i < length; i++) {
- real_t *raw_elem = mono_array_get(p_array, real_t *, i);
+ real_t *raw_elem = (real_t *)mono_array_addr_with_size(p_array, sizeof(real_t) * 3, i);
MARSHALLED_IN(Vector3, raw_elem, elem);
ret.push_back(elem);
}
diff --git a/modules/mono/mono_gd/gd_mono_marshal.h b/modules/mono/mono_gd/gd_mono_marshal.h
index 5fbafa0acb..38dd22357d 100644
--- a/modules/mono/mono_gd/gd_mono_marshal.h
+++ b/modules/mono/mono_gd/gd_mono_marshal.h
@@ -36,21 +36,10 @@
namespace GDMonoMarshal {
-#define UNBOX_CHAR_PTR(x) (char *)mono_object_unbox(x)
-#define UNBOX_FLOAT_PTR(x) (float *)mono_object_unbox(x)
-
-#define UNBOX_DOUBLE(x) *(double *)mono_object_unbox(x)
-#define UNBOX_FLOAT(x) *(float *)mono_object_unbox(x)
-#define UNBOX_INT64(x) *(int64_t *)mono_object_unbox(x)
-#define UNBOX_INT32(x) *(int32_t *)mono_object_unbox(x)
-#define UNBOX_INT16(x) *(int16_t *)mono_object_unbox(x)
-#define UNBOX_INT8(x) *(int8_t *)mono_object_unbox(x)
-#define UNBOX_UINT64(x) *(uint64_t *)mono_object_unbox(x)
-#define UNBOX_UINT32(x) *(uint32_t *)mono_object_unbox(x)
-#define UNBOX_UINT16(x) *(uint16_t *)mono_object_unbox(x)
-#define UNBOX_UINT8(x) *(uint8_t *)mono_object_unbox(x)
-#define UNBOX_BOOLEAN(x) *(MonoBoolean *)mono_object_unbox(x)
-#define UNBOX_PTR(x) mono_object_unbox(x)
+template <typename T>
+T unbox(MonoObject *p_obj) {
+ return *(T *)mono_object_unbox(p_obj);
+}
#define BOX_DOUBLE(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(double), &x)
#define BOX_FLOAT(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(float), &x)
diff --git a/modules/mono/mono_reg_utils.py b/modules/mono/mono_reg_utils.py
index 6f1620ff49..e9988625f5 100644
--- a/modules/mono/mono_reg_utils.py
+++ b/modules/mono/mono_reg_utils.py
@@ -1,7 +1,11 @@
import os
if os.name == 'nt':
- import _winreg as winreg
+ import sys
+ if sys.version_info < (3,):
+ import _winreg as winreg
+ else:
+ import winreg
def _reg_open_key(key, subkey):
diff --git a/modules/mono/register_types.cpp b/modules/mono/register_types.cpp
index 2a84f0d1a6..2656de5b14 100644
--- a/modules/mono/register_types.cpp
+++ b/modules/mono/register_types.cpp
@@ -44,6 +44,7 @@ void register_mono_types() {
_godotsharp = memnew(_GodotSharp);
+ ClassDB::register_class<_GodotSharp>();
ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("GodotSharp", _GodotSharp::get_singleton()));
script_language_cs = memnew(CSharpLanguage);