From cf729f21115a5fb530b9891a63982dcfc7aa0423 Mon Sep 17 00:00:00 2001 From: Ignacio Etcheverry Date: Wed, 22 Apr 2020 17:19:45 +0200 Subject: [PATCH] Mono/C#: Allow exporting System.Array of type Godot.Object (cherry picked from commit 0fec3cb5ed2a009454555440b3853bc4309bc434) --- modules/mono/mono_gd/gd_mono_field.cpp | 7 ++++++ modules/mono/mono_gd/gd_mono_marshal.cpp | 31 ++++++++++++++++++++++++ modules/mono/mono_gd/gd_mono_marshal.h | 1 + 3 files changed, 39 insertions(+) diff --git a/modules/mono/mono_gd/gd_mono_field.cpp b/modules/mono/mono_gd/gd_mono_field.cpp index 3e0f9a3f15b..08f8342c8c5 100644 --- a/modules/mono/mono_gd/gd_mono_field.cpp +++ b/modules/mono/mono_gd/gd_mono_field.cpp @@ -281,6 +281,13 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_ break; } + GDMonoClass *array_type_class = GDMono::get_singleton()->get_class(array_type->eklass); + if (CACHED_CLASS(GodotObject)->is_assignable_from(array_type_class)) { + MonoArray *managed = GDMonoMarshal::Array_to_mono_array(p_value.operator ::Array(), array_type_class); + mono_field_set_value(p_object, mono_field, managed); + break; + } + ERR_FAIL_MSG("Attempted to convert Variant to a managed array of unmarshallable element type."); } break; diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp index b81c20348da..f410eae3383 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.cpp +++ b/modules/mono/mono_gd/gd_mono_marshal.cpp @@ -132,6 +132,10 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type) { if (array_type->eklass == CACHED_CLASS_RAW(Color)) return Variant::POOL_COLOR_ARRAY; + + GDMonoClass *array_type_class = GDMono::get_singleton()->get_class(array_type->eklass); + if (CACHED_CLASS(GodotObject)->is_assignable_from(array_type_class)) + return Variant::ARRAY; } break; case MONO_TYPE_CLASS: { @@ -217,6 +221,13 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type) { bool try_get_array_element_type(const ManagedType &p_array_type, ManagedType &r_elem_type) { switch (p_array_type.type_encoding) { + case MONO_TYPE_ARRAY: + case MONO_TYPE_SZARRAY: { + MonoArrayType *array_type = mono_type_get_array_type(p_array_type.type_class->get_mono_type()); + GDMonoClass *array_type_class = GDMono::get_singleton()->get_class(array_type->eklass); + r_elem_type = ManagedType::from_class(array_type_class); + return true; + } break; case MONO_TYPE_GENERICINST: { MonoReflectionType *array_reftype = mono_type_get_object(mono_domain_get(), p_array_type.type_class->get_mono_type()); @@ -511,6 +522,10 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty if (array_type->eklass == CACHED_CLASS_RAW(Color)) return (MonoObject *)PoolColorArray_to_mono_array(p_var->operator PoolColorArray()); + GDMonoClass *array_type_class = GDMono::get_singleton()->get_class(array_type->eklass); + if (CACHED_CLASS(GodotObject)->is_assignable_from(array_type_class)) + return (MonoObject *)Array_to_mono_array(p_var->operator Array(), array_type_class); + ERR_FAIL_V_MSG(NULL, "Attempted to convert Variant to a managed array of unmarshallable element type."); } break; @@ -805,6 +820,10 @@ Variant mono_object_to_variant_impl(MonoObject *p_obj, const ManagedType &p_type if (array_type->eklass == CACHED_CLASS_RAW(Color)) return mono_array_to_PoolColorArray((MonoArray *)p_obj); + GDMonoClass *array_type_class = GDMono::get_singleton()->get_class(array_type->eklass); + if (CACHED_CLASS(GodotObject)->is_assignable_from(array_type_class)) + return mono_array_to_Array((MonoArray *)p_obj); + if (p_fail_with_err) { ERR_FAIL_V_MSG(Variant(), "Attempted to convert a managed array of unmarshallable element type to Variant."); } else { @@ -970,6 +989,18 @@ MonoArray *Array_to_mono_array(const Array &p_array) { return ret; } +MonoArray *Array_to_mono_array(const Array &p_array, GDMonoClass *p_array_type_class) { + int length = p_array.size(); + MonoArray *ret = mono_array_new(mono_domain_get(), p_array_type_class->get_mono_ptr(), length); + + for (int i = 0; i < length; i++) { + MonoObject *boxed = variant_to_mono_object(p_array[i]); + mono_array_setref(ret, i, boxed); + } + + return ret; +} + Array mono_array_to_Array(MonoArray *p_array) { Array ret; if (!p_array) diff --git a/modules/mono/mono_gd/gd_mono_marshal.h b/modules/mono/mono_gd/gd_mono_marshal.h index e662e7814ef..2499c779205 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.h +++ b/modules/mono/mono_gd/gd_mono_marshal.h @@ -125,6 +125,7 @@ String mono_object_to_variant_string(MonoObject *p_obj, MonoException **r_exc); // Array MonoArray *Array_to_mono_array(const Array &p_array); +MonoArray *Array_to_mono_array(const Array &p_array, GDMonoClass *p_array_type_class); Array mono_array_to_Array(MonoArray *p_array); // PoolIntArray