Browse Source

Mono: Fix not creating generic Array or Dictionary where expected

Ignacio Etcheverry 7 years ago
parent
commit
50fd5ef3b5

+ 1 - 1
modules/mono/csharp_script.cpp

@@ -1174,7 +1174,7 @@ bool CSharpInstance::set(const StringName &p_name, const Variant &p_value) {
 		GDMonoProperty *property = script->script_class->get_property(p_name);
 		GDMonoProperty *property = script->script_class->get_property(p_name);
 
 
 		if (property) {
 		if (property) {
-			property->set_value(mono_object, GDMonoMarshal::variant_to_mono_object(p_value));
+			property->set_value(mono_object, GDMonoMarshal::variant_to_mono_object(p_value, property->get_type()));
 			return true;
 			return true;
 		}
 		}
 
 

+ 18 - 4
modules/mono/glue/Managed/Files/Array.cs

@@ -128,7 +128,7 @@ namespace Godot.Collections
 
 
             for (int i = 0; i < count; i++)
             for (int i = 0; i < count; i++)
             {
             {
-                yield return godot_icall_Array_At(GetPtr(), i);
+                yield return this[i];
             }
             }
         }
         }
 
 
@@ -166,6 +166,9 @@ namespace Godot.Collections
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
         internal extern static object godot_icall_Array_At(IntPtr ptr, int index);
         internal extern static object godot_icall_Array_At(IntPtr ptr, int index);
 
 
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        internal extern static object godot_icall_Array_At_Generic(IntPtr ptr, int index, int elemTypeEncoding, IntPtr elemTypeClass);
+
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
         internal extern static void godot_icall_Array_SetAt(IntPtr ptr, int index, object value);
         internal extern static void godot_icall_Array_SetAt(IntPtr ptr, int index, object value);
 
 
@@ -195,12 +198,23 @@ namespace Godot.Collections
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
         internal extern static void godot_icall_Array_RemoveAt(IntPtr ptr, int index);
         internal extern static void godot_icall_Array_RemoveAt(IntPtr ptr, int index);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        internal extern static void godot_icall_Array_Generic_GetElementTypeInfo(Type elemType, out int elemTypeEncoding, out IntPtr elemTypeClass);
     }
     }
 
 
     public class Array<T> : IList<T>, ICollection<T>, IEnumerable<T>
     public class Array<T> : IList<T>, ICollection<T>, IEnumerable<T>
     {
     {
         Array objectArray;
         Array objectArray;
 
 
+        internal static int elemTypeEncoding;
+        internal static IntPtr elemTypeClass;
+
+        static Array()
+        {
+            Array.godot_icall_Array_Generic_GetElementTypeInfo(typeof(T), out elemTypeEncoding, out elemTypeClass);
+        }
+
         public Array()
         public Array()
         {
         {
             objectArray = new Array();
             objectArray = new Array();
@@ -230,7 +244,7 @@ namespace Godot.Collections
         {
         {
             get
             get
             {
             {
-                return (T)objectArray[index];
+                return (T)Array.godot_icall_Array_At_Generic(GetPtr(), index, elemTypeEncoding, elemTypeClass);
             }
             }
             set
             set
             {
             {
@@ -287,7 +301,7 @@ namespace Godot.Collections
 
 
             for (int i = 0; i < count; i++)
             for (int i = 0; i < count; i++)
             {
             {
-                array[arrayIndex] = (T)objectArray[i];
+                array[arrayIndex] = (T)this[i];
                 arrayIndex++;
                 arrayIndex++;
             }
             }
         }
         }
@@ -298,7 +312,7 @@ namespace Godot.Collections
 
 
             for (int i = 0; i < count; i++)
             for (int i = 0; i < count; i++)
             {
             {
-                yield return (T)objectArray[i];
+                yield return (T)this[i];
             }
             }
         }
         }
 
 

+ 19 - 2
modules/mono/glue/Managed/Files/Dictionary.cs

@@ -203,6 +203,9 @@ namespace Godot.Collections
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
         internal extern static object godot_icall_Dictionary_GetValue(IntPtr ptr, object key);
         internal extern static object godot_icall_Dictionary_GetValue(IntPtr ptr, object key);
 
 
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        internal extern static object godot_icall_Dictionary_GetValue_Generic(IntPtr ptr, object key, int valTypeEncoding, IntPtr valTypeClass);
+
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
         internal extern static void godot_icall_Dictionary_SetValue(IntPtr ptr, object key, object value);
         internal extern static void godot_icall_Dictionary_SetValue(IntPtr ptr, object key, object value);
 
 
@@ -235,6 +238,12 @@ namespace Godot.Collections
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
         internal extern static bool godot_icall_Dictionary_TryGetValue(IntPtr ptr, object key, out object value);
         internal extern static bool godot_icall_Dictionary_TryGetValue(IntPtr ptr, object key, out object value);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        internal extern static bool godot_icall_Dictionary_TryGetValue_Generic(IntPtr ptr, object key, out object value, int valTypeEncoding, IntPtr valTypeClass);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        internal extern static void godot_icall_Dictionary_Generic_GetValueTypeInfo(Type valueType, out int valTypeEncoding, out IntPtr valTypeClass);
     }
     }
 
 
     public class Dictionary<TKey, TValue> :
     public class Dictionary<TKey, TValue> :
@@ -244,6 +253,14 @@ namespace Godot.Collections
     {
     {
         Dictionary objectDict;
         Dictionary objectDict;
 
 
+        internal static int valTypeEncoding;
+        internal static IntPtr valTypeClass;
+
+        static Dictionary()
+        {
+            Dictionary.godot_icall_Dictionary_Generic_GetValueTypeInfo(typeof(TValue), out valTypeEncoding, out valTypeClass);
+        }
+
         public Dictionary()
         public Dictionary()
         {
         {
             objectDict = new Dictionary();
             objectDict = new Dictionary();
@@ -273,7 +290,7 @@ namespace Godot.Collections
         {
         {
             get
             get
             {
             {
-                return (TValue)objectDict[key];
+                return (TValue)Dictionary.godot_icall_Dictionary_GetValue_Generic(objectDict.GetPtr(), key, valTypeEncoding, valTypeClass);
             }
             }
             set
             set
             {
             {
@@ -382,7 +399,7 @@ namespace Godot.Collections
         public bool TryGetValue(TKey key, out TValue value)
         public bool TryGetValue(TKey key, out TValue value)
         {
         {
             object retValue;
             object retValue;
-            bool found = objectDict.TryGetValue(key, out retValue);
+            bool found = Dictionary.godot_icall_Dictionary_TryGetValue_Generic(GetPtr(), key, out retValue, valTypeEncoding, valTypeClass);
             value = found ? (TValue)retValue : default(TValue);
             value = found ? (TValue)retValue : default(TValue);
             return found;
             return found;
         }
         }

+ 53 - 0
modules/mono/glue/collections_glue.cpp

@@ -53,6 +53,14 @@ MonoObject *godot_icall_Array_At(Array *ptr, int index) {
 	return GDMonoMarshal::variant_to_mono_object(ptr->operator[](index));
 	return GDMonoMarshal::variant_to_mono_object(ptr->operator[](index));
 }
 }
 
 
+MonoObject *godot_icall_Array_At_Generic(Array *ptr, int index, uint32_t type_encoding, GDMonoClass *type_class) {
+	if (index < 0 || index > ptr->size()) {
+		GDMonoUtils::set_pending_exception(mono_get_exception_index_out_of_range());
+		return NULL;
+	}
+	return GDMonoMarshal::variant_to_mono_object(ptr->operator[](index), ManagedType(type_encoding, type_class));
+}
+
 void godot_icall_Array_SetAt(Array *ptr, int index, MonoObject *value) {
 void godot_icall_Array_SetAt(Array *ptr, int index, MonoObject *value) {
 	if (index < 0 || index > ptr->size()) {
 	if (index < 0 || index > ptr->size()) {
 		GDMonoUtils::set_pending_exception(mono_get_exception_index_out_of_range());
 		GDMonoUtils::set_pending_exception(mono_get_exception_index_out_of_range());
@@ -122,6 +130,14 @@ void godot_icall_Array_RemoveAt(Array *ptr, int index) {
 	ptr->remove(index);
 	ptr->remove(index);
 }
 }
 
 
+void godot_icall_Array_Generic_GetElementTypeInfo(MonoReflectionType *refltype, uint32_t *type_encoding, GDMonoClass **type_class) {
+	MonoType *elem_type = mono_reflection_type_get_type(refltype);
+
+	*type_encoding = mono_type_get_type(elem_type);
+	MonoClass *type_class_raw = mono_class_from_mono_type(elem_type);
+	*type_class = GDMono::get_singleton()->get_class(type_class_raw);
+}
+
 Dictionary *godot_icall_Dictionary_Ctor() {
 Dictionary *godot_icall_Dictionary_Ctor() {
 	return memnew(Dictionary);
 	return memnew(Dictionary);
 }
 }
@@ -144,6 +160,20 @@ MonoObject *godot_icall_Dictionary_GetValue(Dictionary *ptr, MonoObject *key) {
 	return GDMonoMarshal::variant_to_mono_object(ret);
 	return GDMonoMarshal::variant_to_mono_object(ret);
 }
 }
 
 
+MonoObject *godot_icall_Dictionary_GetValue_Generic(Dictionary *ptr, MonoObject *key, uint32_t type_encoding, GDMonoClass *type_class) {
+	Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key));
+	if (ret == NULL) {
+		MonoObject *exc = mono_object_new(mono_domain_get(), CACHED_CLASS(KeyNotFoundException)->get_mono_ptr());
+#ifdef DEBUG_ENABLED
+		CRASH_COND(!exc);
+#endif
+		GDMonoUtils::runtime_object_init(exc);
+		GDMonoUtils::set_pending_exception((MonoException *)exc);
+		return NULL;
+	}
+	return GDMonoMarshal::variant_to_mono_object(ret, ManagedType(type_encoding, type_class));
+}
+
 void godot_icall_Dictionary_SetValue(Dictionary *ptr, MonoObject *key, MonoObject *value) {
 void godot_icall_Dictionary_SetValue(Dictionary *ptr, MonoObject *key, MonoObject *value) {
 	ptr->operator[](GDMonoMarshal::mono_object_to_variant(key)) = GDMonoMarshal::mono_object_to_variant(value);
 	ptr->operator[](GDMonoMarshal::mono_object_to_variant(key)) = GDMonoMarshal::mono_object_to_variant(value);
 }
 }
@@ -211,10 +241,29 @@ bool godot_icall_Dictionary_TryGetValue(Dictionary *ptr, MonoObject *key, MonoOb
 	return true;
 	return true;
 }
 }
 
 
+bool godot_icall_Dictionary_TryGetValue_Generic(Dictionary *ptr, MonoObject *key, MonoObject **value, uint32_t type_encoding, GDMonoClass *type_class) {
+	Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key));
+	if (ret == NULL) {
+		*value = NULL;
+		return false;
+	}
+	*value = GDMonoMarshal::variant_to_mono_object(ret, ManagedType(type_encoding, type_class));
+	return true;
+}
+
+void godot_icall_Dictionary_Generic_GetValueTypeInfo(MonoReflectionType *refltype, uint32_t *type_encoding, GDMonoClass **type_class) {
+	MonoType *value_type = mono_reflection_type_get_type(refltype);
+
+	*type_encoding = mono_type_get_type(value_type);
+	MonoClass *type_class_raw = mono_class_from_mono_type(value_type);
+	*type_class = GDMono::get_singleton()->get_class(type_class_raw);
+}
+
 void godot_register_collections_icalls() {
 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_Ctor", (void *)godot_icall_Array_Ctor);
 	mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Dtor", (void *)godot_icall_Array_Dtor);
 	mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Dtor", (void *)godot_icall_Array_Dtor);
 	mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_At", (void *)godot_icall_Array_At);
 	mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_At", (void *)godot_icall_Array_At);
+	mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_At_Generic", (void *)godot_icall_Array_At_Generic);
 	mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_SetAt", (void *)godot_icall_Array_SetAt);
 	mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_SetAt", (void *)godot_icall_Array_SetAt);
 	mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Count", (void *)godot_icall_Array_Count);
 	mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Count", (void *)godot_icall_Array_Count);
 	mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Add", (void *)godot_icall_Array_Add);
 	mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Add", (void *)godot_icall_Array_Add);
@@ -225,10 +274,12 @@ void godot_register_collections_icalls() {
 	mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Insert", (void *)godot_icall_Array_Insert);
 	mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Insert", (void *)godot_icall_Array_Insert);
 	mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Remove", (void *)godot_icall_Array_Remove);
 	mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Remove", (void *)godot_icall_Array_Remove);
 	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_RemoveAt", (void *)godot_icall_Array_RemoveAt);
+	mono_add_internal_call("Godot.Collections.Array::godot_icall_Array_Generic_GetElementTypeInfo", (void *)godot_icall_Array_Generic_GetElementTypeInfo);
 
 
 	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_Ctor", (void *)godot_icall_Dictionary_Ctor);
 	mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Dtor", (void *)godot_icall_Dictionary_Dtor);
 	mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Dtor", (void *)godot_icall_Dictionary_Dtor);
 	mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_GetValue", (void *)godot_icall_Dictionary_GetValue);
 	mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_GetValue", (void *)godot_icall_Dictionary_GetValue);
+	mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_GetValue_Generic", (void *)godot_icall_Dictionary_GetValue_Generic);
 	mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_SetValue", (void *)godot_icall_Dictionary_SetValue);
 	mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_SetValue", (void *)godot_icall_Dictionary_SetValue);
 	mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Keys", (void *)godot_icall_Dictionary_Keys);
 	mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Keys", (void *)godot_icall_Dictionary_Keys);
 	mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Values", (void *)godot_icall_Dictionary_Values);
 	mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Values", (void *)godot_icall_Dictionary_Values);
@@ -240,6 +291,8 @@ void godot_register_collections_icalls() {
 	mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_RemoveKey", (void *)godot_icall_Dictionary_RemoveKey);
 	mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_RemoveKey", (void *)godot_icall_Dictionary_RemoveKey);
 	mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Remove", (void *)godot_icall_Dictionary_Remove);
 	mono_add_internal_call("Godot.Collections.Dictionary::godot_icall_Dictionary_Remove", (void *)godot_icall_Dictionary_Remove);
 	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", (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);
 }
 }
 
 
 #endif // MONO_GLUE_ENABLED
 #endif // MONO_GLUE_ENABLED

+ 10 - 0
modules/mono/glue/collections_glue.h

@@ -45,6 +45,8 @@ void godot_icall_Array_Dtor(Array *ptr);
 
 
 MonoObject *godot_icall_Array_At(Array *ptr, int index);
 MonoObject *godot_icall_Array_At(Array *ptr, int index);
 
 
+MonoObject *godot_icall_Array_At_Generic(Array *ptr, int index, uint32_t type_encoding, GDMonoClass *type_class);
+
 void godot_icall_Array_SetAt(Array *ptr, int index, MonoObject *value);
 void godot_icall_Array_SetAt(Array *ptr, int index, MonoObject *value);
 
 
 int godot_icall_Array_Count(Array *ptr);
 int godot_icall_Array_Count(Array *ptr);
@@ -65,6 +67,8 @@ bool godot_icall_Array_Remove(Array *ptr, MonoObject *item);
 
 
 void godot_icall_Array_RemoveAt(Array *ptr, int index);
 void godot_icall_Array_RemoveAt(Array *ptr, int index);
 
 
+void godot_icall_Array_Generic_GetElementTypeInfo(MonoReflectionType *refltype, uint32_t *type_encoding, GDMonoClass **type_class);
+
 // Dictionary
 // Dictionary
 
 
 Dictionary *godot_icall_Dictionary_Ctor();
 Dictionary *godot_icall_Dictionary_Ctor();
@@ -73,6 +77,8 @@ void godot_icall_Dictionary_Dtor(Dictionary *ptr);
 
 
 MonoObject *godot_icall_Dictionary_GetValue(Dictionary *ptr, MonoObject *key);
 MonoObject *godot_icall_Dictionary_GetValue(Dictionary *ptr, MonoObject *key);
 
 
+MonoObject *godot_icall_Dictionary_GetValue_Generic(Dictionary *ptr, MonoObject *key, uint32_t type_encoding, GDMonoClass *type_class);
+
 void godot_icall_Dictionary_SetValue(Dictionary *ptr, MonoObject *key, MonoObject *value);
 void godot_icall_Dictionary_SetValue(Dictionary *ptr, MonoObject *key, MonoObject *value);
 
 
 Array *godot_icall_Dictionary_Keys(Dictionary *ptr);
 Array *godot_icall_Dictionary_Keys(Dictionary *ptr);
@@ -95,6 +101,10 @@ bool godot_icall_Dictionary_Remove(Dictionary *ptr, MonoObject *key, MonoObject
 
 
 bool godot_icall_Dictionary_TryGetValue(Dictionary *ptr, MonoObject *key, MonoObject **value);
 bool godot_icall_Dictionary_TryGetValue(Dictionary *ptr, MonoObject *key, MonoObject **value);
 
 
+bool godot_icall_Dictionary_TryGetValue_Generic(Dictionary *ptr, MonoObject *key, MonoObject **value, uint32_t type_encoding, GDMonoClass *type_class);
+
+void godot_icall_Dictionary_Generic_GetValueTypeInfo(MonoReflectionType *refltype, uint32_t *type_encoding, GDMonoClass **type_class);
+
 // Register internal calls
 // Register internal calls
 
 
 void godot_register_collections_icalls();
 void godot_register_collections_icalls();

+ 8 - 3
modules/mono/mono_gd/gd_mono_header.h

@@ -44,9 +44,14 @@ struct ManagedType {
 	int type_encoding;
 	int type_encoding;
 	GDMonoClass *type_class;
 	GDMonoClass *type_class;
 
 
-	ManagedType() {
-		type_encoding = 0;
-		type_class = NULL;
+	ManagedType() :
+			type_encoding(0),
+			type_class(NULL) {
+	}
+
+	ManagedType(int p_type_encoding, GDMonoClass *p_type_class) :
+			type_encoding(p_type_encoding),
+			type_class(p_type_class) {
 	}
 	}
 };
 };
 
 

+ 5 - 1
modules/mono/mono_gd/gd_mono_marshal.h

@@ -97,10 +97,14 @@ _FORCE_INLINE_ MonoString *mono_string_from_godot(const String &p_string) {
 MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_type);
 MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_type);
 MonoObject *variant_to_mono_object(const Variant *p_var);
 MonoObject *variant_to_mono_object(const Variant *p_var);
 
 
-_FORCE_INLINE_ MonoObject *variant_to_mono_object(Variant p_var) {
+_FORCE_INLINE_ MonoObject *variant_to_mono_object(const Variant &p_var) {
 	return variant_to_mono_object(&p_var);
 	return variant_to_mono_object(&p_var);
 }
 }
 
 
+_FORCE_INLINE_ MonoObject *variant_to_mono_object(const Variant &p_var, const ManagedType &p_type) {
+	return variant_to_mono_object(&p_var, p_type);
+}
+
 Variant mono_object_to_variant(MonoObject *p_obj);
 Variant mono_object_to_variant(MonoObject *p_obj);
 
 
 // Array
 // Array