diff options
Diffstat (limited to 'modules/mono')
-rw-r--r-- | modules/mono/glue/Managed/Files/Array.cs | 10 | ||||
-rw-r--r-- | modules/mono/glue/Managed/Files/Dictionary.cs | 10 | ||||
-rw-r--r-- | modules/mono/glue/Managed/Files/DynamicObject.cs | 2 | ||||
-rw-r--r-- | modules/mono/glue/Managed/Files/Object.base.cs | 10 | ||||
-rw-r--r-- | modules/mono/glue/Managed/Files/RID.cs | 2 | ||||
-rw-r--r-- | modules/mono/glue/base_object_glue.cpp | 5 | ||||
-rw-r--r-- | modules/mono/glue/base_object_glue.h | 2 | ||||
-rw-r--r-- | modules/mono/glue/collections_glue.cpp | 10 | ||||
-rw-r--r-- | modules/mono/glue/collections_glue.h | 4 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono.cpp | 5 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_internals.cpp | 3 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_log.cpp | 76 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_log.h | 1 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_utils.cpp | 5 |
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) > 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 < 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(); } |