diff --git a/modules/mono/glue/Managed/Files/Extensions/NodeExtensions.cs b/modules/mono/glue/Managed/Files/Extensions/NodeExtensions.cs index 366d89b1c2f..5023725f174 100644 --- a/modules/mono/glue/Managed/Files/Extensions/NodeExtensions.cs +++ b/modules/mono/glue/Managed/Files/Extensions/NodeExtensions.cs @@ -24,12 +24,12 @@ namespace Godot public T GetOwner() where T : class { - return (T)(object)GetOwner(); + return (T)(object)Owner; } public T GetOwnerOrNull() where T : class { - return GetOwner() as T; + return Owner as T; } public T GetParent() where T : class diff --git a/modules/mono/glue/Managed/Files/MarshalUtils.cs b/modules/mono/glue/Managed/Files/MarshalUtils.cs index 730a1e15854..a1d63a62ef2 100644 --- a/modules/mono/glue/Managed/Files/MarshalUtils.cs +++ b/modules/mono/glue/Managed/Files/MarshalUtils.cs @@ -23,7 +23,7 @@ namespace Godot /// /// Returns if the generic type definition of - /// is ; otherwise returns . + /// is ; otherwise returns . /// /// /// is not a generic type. That is, IsGenericType returns false. @@ -45,6 +45,44 @@ namespace Godot valueType = genericArgs[1]; } + static bool GenericIEnumerableIsAssignableFromType(Type type) + { + if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>)) + return true; + + foreach (var interfaceType in type.GetInterfaces()) + { + if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == typeof(IEnumerable<>)) + return true; + } + + Type baseType = type.BaseType; + + if (baseType == null) + return false; + + return GenericIEnumerableIsAssignableFromType(baseType); + } + + static bool GenericIDictionaryIsAssignableFromType(Type type) + { + if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IDictionary<,>)) + return true; + + foreach (var interfaceType in type.GetInterfaces()) + { + if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == typeof(IDictionary<,>)) + return true; + } + + Type baseType = type.BaseType; + + if (baseType == null) + return false; + + return GenericIDictionaryIsAssignableFromType(baseType); + } + static bool GenericIEnumerableIsAssignableFromType(Type type, out Type elementType) { if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>)) diff --git a/modules/mono/glue/Managed/IgnoredFiles/Node.cs b/modules/mono/glue/Managed/IgnoredFiles/Node.cs index 99ba0f827ae..cff61b1e0b7 100644 --- a/modules/mono/glue/Managed/IgnoredFiles/Node.cs +++ b/modules/mono/glue/Managed/IgnoredFiles/Node.cs @@ -15,9 +15,10 @@ namespace Godot throw new NotImplementedException(); } - public Node GetOwner() + public Node Owner { - throw new NotImplementedException(); + get => throw new NotImplementedException(); + set => throw new NotImplementedException(); } public Node GetParent() diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp index 461dcf3ec01..c462b8f71d3 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.cpp +++ b/modules/mono/mono_gd/gd_mono_marshal.cpp @@ -161,8 +161,7 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type) { MonoReflectionType *reftype = mono_type_get_object(SCRIPTS_DOMAIN, type_class->get_mono_type()); - MonoReflectionType *key_reftype, *value_reftype; - if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(reftype, &key_reftype, &value_reftype)) { + if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(reftype)) { return Variant::DICTIONARY; } @@ -170,8 +169,7 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type) { return Variant::DICTIONARY; } - MonoReflectionType *elem_reftype; - if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(reftype, &elem_reftype)) { + if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(reftype)) { return Variant::ARRAY; } @@ -193,16 +191,14 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type) { // The order in which we check the following interfaces is very important (dictionaries and generics first) - MonoReflectionType *key_reftype, *value_reftype; - if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(reftype, &key_reftype, &value_reftype)) + if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(reftype)) return Variant::DICTIONARY; if (p_type.type_class->implements_interface(CACHED_CLASS(System_Collections_IDictionary))) { return Variant::DICTIONARY; } - MonoReflectionType *elem_reftype; - if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(reftype, &elem_reftype)) + if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(reftype)) return Variant::ARRAY; if (p_type.type_class->implements_interface(CACHED_CLASS(System_Collections_IEnumerable))) { @@ -850,8 +846,7 @@ Variant mono_object_to_variant(MonoObject *p_obj) { MonoReflectionType *reftype = mono_type_get_object(SCRIPTS_DOMAIN, type_class->get_mono_type()); - MonoReflectionType *key_reftype, *value_reftype; - if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(reftype, &key_reftype, &value_reftype)) { + if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(reftype)) { return GDMonoUtils::Marshal::generic_idictionary_to_dictionary(p_obj); } @@ -859,8 +854,7 @@ Variant mono_object_to_variant(MonoObject *p_obj) { return GDMonoUtils::Marshal::idictionary_to_dictionary(p_obj); } - MonoReflectionType *elem_reftype; - if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(reftype, &elem_reftype)) { + if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(reftype)) { return GDMonoUtils::Marshal::enumerable_to_array(p_obj); } @@ -888,8 +882,7 @@ Variant mono_object_to_variant(MonoObject *p_obj) { // The order in which we check the following interfaces is very important (dictionaries and generics first) - MonoReflectionType *key_reftype, *value_reftype; - if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(reftype, &key_reftype, &value_reftype)) { + if (GDMonoUtils::Marshal::generic_idictionary_is_assignable_from(reftype)) { return GDMonoUtils::Marshal::generic_idictionary_to_dictionary(p_obj); } @@ -897,8 +890,7 @@ Variant mono_object_to_variant(MonoObject *p_obj) { return GDMonoUtils::Marshal::idictionary_to_dictionary(p_obj); } - MonoReflectionType *elem_reftype; - if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(reftype, &elem_reftype)) { + if (GDMonoUtils::Marshal::generic_ienumerable_is_assignable_from(reftype)) { return GDMonoUtils::Marshal::enumerable_to_array(p_obj); } diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp index 8d8c85972a2..413c8cba85e 100644 --- a/modules/mono/mono_gd/gd_mono_utils.cpp +++ b/modules/mono/mono_gd/gd_mono_utils.cpp @@ -161,6 +161,8 @@ void MonoCache::clear_members() { methodthunk_MarshalUtils_GenericIEnumerableIsAssignableFromType = NULL; methodthunk_MarshalUtils_GenericIDictionaryIsAssignableFromType = NULL; + methodthunk_MarshalUtils_GenericIEnumerableIsAssignableFromType_with_info = NULL; + methodthunk_MarshalUtils_GenericIDictionaryIsAssignableFromType_with_info = NULL; methodthunk_MarshalUtils_MakeGenericArrayType = NULL; methodthunk_MarshalUtils_MakeGenericDictionaryType = NULL; @@ -282,8 +284,10 @@ void update_godot_api_cache() { CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, ArrayGetElementType, (ArrayGetElementType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("ArrayGetElementType", 2)); CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, DictionaryGetKeyValueTypes, (DictionaryGetKeyValueTypes)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("DictionaryGetKeyValueTypes", 3)); - CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIEnumerableIsAssignableFromType, (GenericIEnumerableIsAssignableFromType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("GenericIEnumerableIsAssignableFromType", 2)); - CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIDictionaryIsAssignableFromType, (GenericIDictionaryIsAssignableFromType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("GenericIDictionaryIsAssignableFromType", 3)); + CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIEnumerableIsAssignableFromType, (GenericIEnumerableIsAssignableFromType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("GenericIEnumerableIsAssignableFromType", 1)); + CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIDictionaryIsAssignableFromType, (GenericIDictionaryIsAssignableFromType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("GenericIDictionaryIsAssignableFromType", 1)); + CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIEnumerableIsAssignableFromType_with_info, (GenericIEnumerableIsAssignableFromType_with_info)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("GenericIEnumerableIsAssignableFromType", 2)); + CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, GenericIEnumerableIsAssignableFromType_with_info, (GenericIEnumerableIsAssignableFromType_with_info)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("GenericIDictionaryIsAssignableFromType", 3)); CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, MakeGenericArrayType, (MakeGenericArrayType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("MakeGenericArrayType", 1)); CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, MakeGenericDictionaryType, (MakeGenericDictionaryType)GODOT_API_CLASS(MarshalUtils)->get_method_thunk("MakeGenericDictionaryType", 2)); @@ -787,16 +791,32 @@ void dictionary_get_key_value_types(MonoReflectionType *p_dict_reftype, MonoRefl UNLIKELY_UNHANDLED_EXCEPTION(exc); } -MonoBoolean generic_ienumerable_is_assignable_from(MonoReflectionType *p_reftype, MonoReflectionType **r_elem_reftype) { +MonoBoolean generic_ienumerable_is_assignable_from(MonoReflectionType *p_reftype) { GenericIEnumerableIsAssignableFromType thunk = CACHED_METHOD_THUNK(MarshalUtils, GenericIEnumerableIsAssignableFromType); MonoException *exc = NULL; + MonoBoolean res = invoke_method_thunk(thunk, p_reftype, &exc); + UNLIKELY_UNHANDLED_EXCEPTION(exc); + return res; +} + +MonoBoolean generic_idictionary_is_assignable_from(MonoReflectionType *p_reftype) { + GenericIDictionaryIsAssignableFromType thunk = CACHED_METHOD_THUNK(MarshalUtils, GenericIDictionaryIsAssignableFromType); + MonoException *exc = NULL; + MonoBoolean res = invoke_method_thunk(thunk, p_reftype, &exc); + UNLIKELY_UNHANDLED_EXCEPTION(exc); + return res; +} + +MonoBoolean generic_ienumerable_is_assignable_from(MonoReflectionType *p_reftype, MonoReflectionType **r_elem_reftype) { + GenericIEnumerableIsAssignableFromType_with_info thunk = CACHED_METHOD_THUNK(MarshalUtils, GenericIEnumerableIsAssignableFromType_with_info); + MonoException *exc = NULL; MonoBoolean res = invoke_method_thunk(thunk, p_reftype, r_elem_reftype, &exc); UNLIKELY_UNHANDLED_EXCEPTION(exc); return res; } MonoBoolean generic_idictionary_is_assignable_from(MonoReflectionType *p_reftype, MonoReflectionType **r_key_reftype, MonoReflectionType **r_value_reftype) { - GenericIDictionaryIsAssignableFromType thunk = CACHED_METHOD_THUNK(MarshalUtils, GenericIDictionaryIsAssignableFromType); + GenericIDictionaryIsAssignableFromType_with_info thunk = CACHED_METHOD_THUNK(MarshalUtils, GenericIDictionaryIsAssignableFromType_with_info); MonoException *exc = NULL; MonoBoolean res = invoke_method_thunk(thunk, p_reftype, r_key_reftype, r_value_reftype, &exc); UNLIKELY_UNHANDLED_EXCEPTION(exc); diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h index c9f02ecc712..ee239be9594 100644 --- a/modules/mono/mono_gd/gd_mono_utils.h +++ b/modules/mono/mono_gd/gd_mono_utils.h @@ -64,8 +64,10 @@ typedef MonoBoolean (*TypeIsGenericDictionary)(MonoReflectionType *, MonoExcepti typedef void (*ArrayGetElementType)(MonoReflectionType *, MonoReflectionType **, MonoException **); typedef void (*DictionaryGetKeyValueTypes)(MonoReflectionType *, MonoReflectionType **, MonoReflectionType **, MonoException **); -typedef MonoBoolean (*GenericIEnumerableIsAssignableFromType)(MonoReflectionType *, MonoReflectionType **, MonoException **); -typedef MonoBoolean (*GenericIDictionaryIsAssignableFromType)(MonoReflectionType *, MonoReflectionType **, MonoReflectionType **, MonoException **); +typedef MonoBoolean (*GenericIEnumerableIsAssignableFromType)(MonoReflectionType *, MonoException **); +typedef MonoBoolean (*GenericIDictionaryIsAssignableFromType)(MonoReflectionType *, MonoException **); +typedef MonoBoolean (*GenericIEnumerableIsAssignableFromType_with_info)(MonoReflectionType *, MonoReflectionType **, MonoException **); +typedef MonoBoolean (*GenericIDictionaryIsAssignableFromType_with_info)(MonoReflectionType *, MonoReflectionType **, MonoReflectionType **, MonoException **); typedef MonoReflectionType *(*MakeGenericArrayType)(MonoReflectionType *, MonoException **); typedef MonoReflectionType *(*MakeGenericDictionaryType)(MonoReflectionType *, MonoReflectionType *, MonoException **); @@ -82,6 +84,8 @@ MonoBoolean type_is_generic_dictionary(MonoReflectionType *p_reftype); void array_get_element_type(MonoReflectionType *p_array_reftype, MonoReflectionType **r_elem_reftype); void dictionary_get_key_value_types(MonoReflectionType *p_dict_reftype, MonoReflectionType **r_key_reftype, MonoReflectionType **r_value_reftype); +MonoBoolean generic_ienumerable_is_assignable_from(MonoReflectionType *p_reftype); +MonoBoolean generic_idictionary_is_assignable_from(MonoReflectionType *p_reftype); MonoBoolean generic_ienumerable_is_assignable_from(MonoReflectionType *p_reftype, MonoReflectionType **r_elem_reftype); MonoBoolean generic_idictionary_is_assignable_from(MonoReflectionType *p_reftype, MonoReflectionType **r_key_reftype, MonoReflectionType **r_value_reftype); @@ -197,6 +201,8 @@ struct MonoCache { GenericIEnumerableIsAssignableFromType methodthunk_MarshalUtils_GenericIEnumerableIsAssignableFromType; GenericIDictionaryIsAssignableFromType methodthunk_MarshalUtils_GenericIDictionaryIsAssignableFromType; + GenericIEnumerableIsAssignableFromType_with_info methodthunk_MarshalUtils_GenericIEnumerableIsAssignableFromType_with_info; + GenericIDictionaryIsAssignableFromType_with_info methodthunk_MarshalUtils_GenericIDictionaryIsAssignableFromType_with_info; MakeGenericArrayType methodthunk_MarshalUtils_MakeGenericArrayType; MakeGenericDictionaryType methodthunk_MarshalUtils_MakeGenericDictionaryType;