summaryrefslogtreecommitdiff
path: root/modules/mono
diff options
context:
space:
mode:
Diffstat (limited to 'modules/mono')
-rw-r--r--modules/mono/glue/Managed/Files/Array.cs10
-rw-r--r--modules/mono/glue/Managed/Files/Dictionary.cs10
-rw-r--r--modules/mono/glue/Managed/Files/DynamicObject.cs2
-rw-r--r--modules/mono/glue/Managed/Files/Object.base.cs10
-rw-r--r--modules/mono/glue/Managed/Files/RID.cs2
-rw-r--r--modules/mono/glue/base_object_glue.cpp5
-rw-r--r--modules/mono/glue/base_object_glue.h2
-rw-r--r--modules/mono/glue/collections_glue.cpp10
-rw-r--r--modules/mono/glue/collections_glue.h4
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp5
-rw-r--r--modules/mono/mono_gd/gd_mono_internals.cpp3
-rw-r--r--modules/mono/mono_gd/gd_mono_log.cpp76
-rw-r--r--modules/mono/mono_gd/gd_mono_log.h1
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.cpp5
14 files changed, 115 insertions, 30 deletions
diff --git a/modules/mono/glue/Managed/Files/Array.cs b/modules/mono/glue/Managed/Files/Array.cs
index 2277c7bf18..0e7b0362e0 100644
--- a/modules/mono/glue/Managed/Files/Array.cs
+++ b/modules/mono/glue/Managed/Files/Array.cs
@@ -143,6 +143,11 @@ namespace Godot.Collections
}
}
+ public override string ToString()
+ {
+ return godot_icall_Array_ToString(GetPtr());
+ }
+
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static IntPtr godot_icall_Array_Ctor();
@@ -190,6 +195,9 @@ namespace Godot.Collections
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static void godot_icall_Array_Generic_GetElementTypeInfo(Type elemType, out int elemTypeEncoding, out IntPtr elemTypeClass);
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal extern static string godot_icall_Array_ToString(IntPtr ptr);
}
public class Array<T> : IList<T>, ICollection<T>, IEnumerable<T>
@@ -353,5 +361,7 @@ namespace Godot.Collections
{
return GetEnumerator();
}
+
+ public override string ToString() => objectArray.ToString();
}
}
diff --git a/modules/mono/glue/Managed/Files/Dictionary.cs b/modules/mono/glue/Managed/Files/Dictionary.cs
index af1782b79a..6ab8549a01 100644
--- a/modules/mono/glue/Managed/Files/Dictionary.cs
+++ b/modules/mono/glue/Managed/Files/Dictionary.cs
@@ -193,6 +193,11 @@ namespace Godot.Collections
}
}
+ public override string ToString()
+ {
+ return godot_icall_Dictionary_ToString(GetPtr());
+ }
+
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static IntPtr godot_icall_Dictionary_Ctor();
@@ -243,6 +248,9 @@ namespace Godot.Collections
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static void godot_icall_Dictionary_Generic_GetValueTypeInfo(Type valueType, out int valTypeEncoding, out IntPtr valTypeClass);
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal extern static string godot_icall_Dictionary_ToString(IntPtr ptr);
}
public class Dictionary<TKey, TValue> :
@@ -442,5 +450,7 @@ namespace Godot.Collections
{
return GetEnumerator();
}
+
+ public override string ToString() => objectDict.ToString();
}
}
diff --git a/modules/mono/glue/Managed/Files/DynamicObject.cs b/modules/mono/glue/Managed/Files/DynamicObject.cs
index 9504415664..9860feafdd 100644
--- a/modules/mono/glue/Managed/Files/DynamicObject.cs
+++ b/modules/mono/glue/Managed/Files/DynamicObject.cs
@@ -26,7 +26,7 @@ namespace Godot
/// dynamic sprite = GetNode("Sprite").DynamicGodotObject;
/// sprite.add_child(this);
///
- /// if ((sprite.hframes * sprite.vframes) > 0)
+ /// if ((sprite.hframes * sprite.vframes) &gt; 0)
/// sprite.frame = 0;
/// </code>
/// </example>
diff --git a/modules/mono/glue/Managed/Files/Object.base.cs b/modules/mono/glue/Managed/Files/Object.base.cs
index e152d56871..de80f7fddc 100644
--- a/modules/mono/glue/Managed/Files/Object.base.cs
+++ b/modules/mono/glue/Managed/Files/Object.base.cs
@@ -73,6 +73,11 @@ namespace Godot
disposed = true;
}
+ public override string ToString()
+ {
+ return godot_icall_Object_ToString(GetPtr(this));
+ }
+
/// <summary>
/// Returns a new <see cref="Godot.SignalAwaiter"/> awaiter configured to complete when the instance
/// <paramref name="source"/> emits the signal specified by the <paramref name="signal"/> parameter.
@@ -88,7 +93,7 @@ namespace Godot
/// <code>
/// public override void _Ready()
/// {
- /// for (int i = 0; i < 100; i++)
+ /// for (int i = 0; i &lt; 100; i++)
/// {
/// await ToSignal(GetTree(), "idle_frame");
/// GD.Print($"Frame {i}");
@@ -115,6 +120,9 @@ namespace Godot
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static void godot_icall_Reference_Disposed(Object obj, IntPtr ptr, bool isFinalizer);
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal extern static string godot_icall_Object_ToString(IntPtr ptr);
+
// Used by the generated API
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static IntPtr godot_icall_Object_ClassDB_get_method(string type, string method);
diff --git a/modules/mono/glue/Managed/Files/RID.cs b/modules/mono/glue/Managed/Files/RID.cs
index f1268c8518..12064beca2 100644
--- a/modules/mono/glue/Managed/Files/RID.cs
+++ b/modules/mono/glue/Managed/Files/RID.cs
@@ -70,6 +70,8 @@ namespace Godot
return godot_icall_RID_get_id(RID.GetPtr(this));
}
+ public override string ToString() => "[RID]";
+
[MethodImpl(MethodImplOptions.InternalCall)]
internal extern static IntPtr godot_icall_RID_Ctor(IntPtr from);
diff --git a/modules/mono/glue/base_object_glue.cpp b/modules/mono/glue/base_object_glue.cpp
index 7f367fa095..7385014a53 100644
--- a/modules/mono/glue/base_object_glue.cpp
+++ b/modules/mono/glue/base_object_glue.cpp
@@ -218,11 +218,16 @@ MonoBoolean godot_icall_DynamicGodotObject_SetMember(Object *p_ptr, MonoString *
return valid;
}
+MonoString *godot_icall_Object_ToString(Object *p_ptr) {
+ return GDMonoMarshal::mono_string_from_godot(Variant(p_ptr).operator String());
+}
+
void godot_register_object_icalls() {
mono_add_internal_call("Godot.Object::godot_icall_Object_Ctor", (void *)godot_icall_Object_Ctor);
mono_add_internal_call("Godot.Object::godot_icall_Object_Disposed", (void *)godot_icall_Object_Disposed);
mono_add_internal_call("Godot.Object::godot_icall_Reference_Disposed", (void *)godot_icall_Reference_Disposed);
mono_add_internal_call("Godot.Object::godot_icall_Object_ClassDB_get_method", (void *)godot_icall_Object_ClassDB_get_method);
+ mono_add_internal_call("Godot.Object::godot_icall_Object_ToString", (void *)godot_icall_Object_ToString);
mono_add_internal_call("Godot.Object::godot_icall_Object_weakref", (void *)godot_icall_Object_weakref);
mono_add_internal_call("Godot.SignalAwaiter::godot_icall_SignalAwaiter_connect", (void *)godot_icall_SignalAwaiter_connect);
mono_add_internal_call("Godot.DynamicGodotObject::godot_icall_DynamicGodotObject_SetMemberList", (void *)godot_icall_DynamicGodotObject_SetMemberList);
diff --git a/modules/mono/glue/base_object_glue.h b/modules/mono/glue/base_object_glue.h
index 9b5224a347..e4ac9fb99d 100644
--- a/modules/mono/glue/base_object_glue.h
+++ b/modules/mono/glue/base_object_glue.h
@@ -60,6 +60,8 @@ MonoBoolean godot_icall_DynamicGodotObject_GetMember(Object *p_ptr, MonoString *
MonoBoolean godot_icall_DynamicGodotObject_SetMember(Object *p_ptr, MonoString *p_name, MonoObject *p_value);
+MonoString *godot_icall_Object_ToString(Object *p_ptr);
+
// Register internal calls
void godot_register_object_icalls();
diff --git a/modules/mono/glue/collections_glue.cpp b/modules/mono/glue/collections_glue.cpp
index 84c3f354d8..4aef5684fd 100644
--- a/modules/mono/glue/collections_glue.cpp
+++ b/modules/mono/glue/collections_glue.cpp
@@ -143,6 +143,10 @@ void godot_icall_Array_Generic_GetElementTypeInfo(MonoReflectionType *refltype,
*type_class = GDMono::get_singleton()->get_class(type_class_raw);
}
+MonoString *godot_icall_Array_ToString(Array *ptr) {
+ return GDMonoMarshal::mono_string_from_godot(Variant(*ptr).operator String());
+}
+
Dictionary *godot_icall_Dictionary_Ctor() {
return memnew(Dictionary);
}
@@ -264,6 +268,10 @@ void godot_icall_Dictionary_Generic_GetValueTypeInfo(MonoReflectionType *refltyp
*type_class = GDMono::get_singleton()->get_class(type_class_raw);
}
+MonoString *godot_icall_Dictionary_ToString(Dictionary *ptr) {
+ return GDMonoMarshal::mono_string_from_godot(Variant(*ptr).operator String());
+}
+
void godot_register_collections_icalls() {
mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Ctor", (void *)godot_icall_Array_Ctor);
mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Dtor", (void *)godot_icall_Array_Dtor);
@@ -281,6 +289,7 @@ void godot_register_collections_icalls() {
mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_RemoveAt", (void *)godot_icall_Array_RemoveAt);
mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Resize", (void *)godot_icall_Array_Resize);
mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Generic_GetElementTypeInfo", (void *)godot_icall_Array_Generic_GetElementTypeInfo);
+ mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_ToString", (void *)godot_icall_Array_ToString);
mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Ctor", (void *)godot_icall_Dictionary_Ctor);
mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Dtor", (void *)godot_icall_Dictionary_Dtor);
@@ -299,6 +308,7 @@ void godot_register_collections_icalls() {
mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_TryGetValue", (void *)godot_icall_Dictionary_TryGetValue);
mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_TryGetValue_Generic", (void *)godot_icall_Dictionary_TryGetValue_Generic);
mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Generic_GetValueTypeInfo", (void *)godot_icall_Dictionary_Generic_GetValueTypeInfo);
+ mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_ToString", (void *)godot_icall_Dictionary_ToString);
}
#endif // MONO_GLUE_ENABLED
diff --git a/modules/mono/glue/collections_glue.h b/modules/mono/glue/collections_glue.h
index 69768500d8..54ed42c3b6 100644
--- a/modules/mono/glue/collections_glue.h
+++ b/modules/mono/glue/collections_glue.h
@@ -71,6 +71,8 @@ Error godot_icall_Array_Resize(Array *ptr, int new_size);
void godot_icall_Array_Generic_GetElementTypeInfo(MonoReflectionType *refltype, uint32_t *type_encoding, GDMonoClass **type_class);
+MonoString *godot_icall_Array_ToString(Array *ptr);
+
// Dictionary
Dictionary *godot_icall_Dictionary_Ctor();
@@ -107,6 +109,8 @@ MonoBoolean godot_icall_Dictionary_TryGetValue_Generic(Dictionary *ptr, MonoObje
void godot_icall_Dictionary_Generic_GetValueTypeInfo(MonoReflectionType *refltype, uint32_t *type_encoding, GDMonoClass **type_class);
+MonoString *godot_icall_Dictionary_ToString(Dictionary *ptr);
+
// Register internal calls
void godot_register_collections_icalls();
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index 48bea4addf..bfb6c13224 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -30,6 +30,7 @@
#include "gd_mono.h"
+#include <mono/metadata/environment.h>
#include <mono/metadata/exception.h>
#include <mono/metadata/mono-config.h>
#include <mono/metadata/mono-debug.h>
@@ -1008,7 +1009,9 @@ void GDMono::unhandled_exception_hook(MonoObject *p_exc, void *) {
if (ScriptDebugger::get_singleton())
ScriptDebugger::get_singleton()->idle_poll();
#endif
- abort();
+
+ exit(mono_environment_exitcode_get());
+
GD_UNREACHABLE();
}
diff --git a/modules/mono/mono_gd/gd_mono_internals.cpp b/modules/mono/mono_gd/gd_mono_internals.cpp
index c8cba5cf1b..63bcfe053c 100644
--- a/modules/mono/mono_gd/gd_mono_internals.cpp
+++ b/modules/mono/mono_gd/gd_mono_internals.cpp
@@ -111,7 +111,8 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) {
void unhandled_exception(MonoException *p_exc) {
mono_unhandled_exception((MonoObject *)p_exc); // prints the exception as well
- abort();
+ // Too bad 'mono_invoke_unhandled_exception_hook' is not exposed to embedders
+ GDMono::unhandled_exception_hook((MonoObject *)p_exc, NULL);
GD_UNREACHABLE();
}
diff --git a/modules/mono/mono_gd/gd_mono_log.cpp b/modules/mono/mono_gd/gd_mono_log.cpp
index ec89df1959..3191cdbd53 100644
--- a/modules/mono/mono_gd/gd_mono_log.cpp
+++ b/modules/mono/mono_gd/gd_mono_log.cpp
@@ -72,8 +72,11 @@ static void mono_log_callback(const char *log_domain, const char *log_level, con
if (fatal) {
ERR_PRINTS("Mono: FATAL ERROR, ABORTING! Logfile: " + GDMonoLog::get_singleton()->get_log_file_path() + "\n");
- // If we were to abort without flushing, the log wouldn't get written.
+ // Make sure to flush before aborting
f->flush();
+ f->close();
+ memdelete(f);
+
abort();
}
}
@@ -93,17 +96,9 @@ bool GDMonoLog::_try_create_logs_dir(const String &p_logs_dir) {
return true;
}
-void GDMonoLog::_open_log_file(const String &p_file_path) {
-
- log_file = FileAccess::open(p_file_path, FileAccess::WRITE);
-
- ERR_EXPLAIN("Failed to create log file");
- ERR_FAIL_COND(!log_file);
-}
-
void GDMonoLog::_delete_old_log_files(const String &p_logs_dir) {
- static const uint64_t MAX_SECS = 5 * 86400;
+ static const uint64_t MAX_SECS = 5 * 86400; // 5 days
DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
ERR_FAIL_COND(!da);
@@ -120,10 +115,9 @@ void GDMonoLog::_delete_old_log_files(const String &p_logs_dir) {
if (!current.ends_with(".txt"))
continue;
- String name = current.get_basename();
- uint64_t unixtime = (uint64_t)name.to_int64();
+ uint64_t modified_time = FileAccess::get_modified_time(da->get_current_dir().plus_file(current));
- if (OS::get_singleton()->get_unix_time() - unixtime > MAX_SECS) {
+ if (OS::get_singleton()->get_unix_time() - modified_time > MAX_SECS) {
da->remove(current);
}
}
@@ -131,28 +125,70 @@ void GDMonoLog::_delete_old_log_files(const String &p_logs_dir) {
da->list_dir_end();
}
+static String format(const char *p_fmt, ...) {
+ va_list args;
+
+ va_start(args, p_fmt);
+ int len = vsnprintf(NULL, 0, p_fmt, args);
+ va_end(args);
+
+ len += 1; // for the trailing '/0'
+
+ char *buffer(memnew_arr(char, len));
+
+ va_start(args, p_fmt);
+ vsnprintf(buffer, len, p_fmt, args);
+ va_end(args);
+
+ String res(buffer);
+ memdelete_arr(buffer);
+
+ return res;
+}
+
void GDMonoLog::initialize() {
+ CharString log_level = OS::get_singleton()->get_environment("GODOT_MONO_LOG_LEVEL").utf8();
+
+ if (log_level.length() != 0 && log_level_get_id(log_level.get_data()) == -1) {
+ ERR_PRINTS(String() + "Mono: Ignoring invalid log level (GODOT_MONO_LOG_LEVEL): " + log_level.get_data());
+ log_level = CharString();
+ }
+
+ if (log_level.length() == 0) {
#ifdef DEBUG_ENABLED
- const char *log_level = "debug";
+ log_level = String("info").utf8();
#else
- const char *log_level = "warning";
+ log_level = String("warning").utf8();
#endif
+ }
String logs_dir = GodotSharpDirs::get_mono_logs_dir();
if (_try_create_logs_dir(logs_dir)) {
_delete_old_log_files(logs_dir);
- log_file_path = logs_dir.plus_file(String::num_int64(OS::get_singleton()->get_unix_time()) + ".txt");
- _open_log_file(log_file_path);
+ OS::Date date_now = OS::get_singleton()->get_date();
+ OS::Time time_now = OS::get_singleton()->get_time();
+ int pid = OS::get_singleton()->get_process_id();
+
+ String log_file_name = format("%d-%02d-%02d %02d:%02d:%02d (%d).txt",
+ date_now.year, date_now.month, date_now.day,
+ time_now.hour, time_now.min, time_now.sec, pid);
+
+ log_file_path = logs_dir.plus_file(log_file_name);
+
+ log_file = FileAccess::open(log_file_path, FileAccess::WRITE);
+ if (!log_file) {
+ ERR_PRINT("Mono: Cannot create log file");
+ }
}
- mono_trace_set_level_string(log_level);
- log_level_id = log_level_get_id(log_level);
+ mono_trace_set_level_string(log_level.get_data());
+ log_level_id = log_level_get_id(log_level.get_data());
if (log_file) {
- print_verbose("Mono: Logfile is " + log_file_path);
+ OS::get_singleton()->print("Mono: Logfile is: %s\n", log_file_path.utf8().get_data());
mono_trace_set_log_handler(mono_log_callback, this);
} else {
OS::get_singleton()->printerr("Mono: No log file, using default log handler\n");
diff --git a/modules/mono/mono_gd/gd_mono_log.h b/modules/mono/mono_gd/gd_mono_log.h
index a477e5edee..91d0557aa3 100644
--- a/modules/mono/mono_gd/gd_mono_log.h
+++ b/modules/mono/mono_gd/gd_mono_log.h
@@ -41,7 +41,6 @@ class GDMonoLog {
String log_file_path;
bool _try_create_logs_dir(const String &p_logs_dir);
- void _open_log_file(const String &p_file_path);
void _delete_old_log_files(const String &p_logs_dir);
static GDMonoLog *singleton;
diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp
index 429d4f68d9..bcf5712d16 100644
--- a/modules/mono/mono_gd/gd_mono_utils.cpp
+++ b/modules/mono/mono_gd/gd_mono_utils.cpp
@@ -632,11 +632,6 @@ void debug_send_unhandled_exception_error(MonoException *p_exc) {
}
void debug_unhandled_exception(MonoException *p_exc) {
-#ifdef DEBUG_ENABLED
- GDMonoUtils::debug_send_unhandled_exception_error(p_exc);
- if (ScriptDebugger::get_singleton())
- ScriptDebugger::get_singleton()->idle_poll();
-#endif
GDMonoInternals::unhandled_exception(p_exc); // prints the exception as well
GD_UNREACHABLE();
}