mirror of
				https://github.com/godotengine/godot.git
				synced 2025-11-04 07:31:16 +00:00 
			
		
		
		
	Merge pull request #15880 from neikeq/better-collections
Mono: Add Dictionary and Array classes
This commit is contained in:
		
						commit
						779c9d638e
					
				
					 19 changed files with 1415 additions and 183 deletions
				
			
		| 
						 | 
					@ -140,6 +140,11 @@ void Dictionary::erase(const Variant &p_key) {
 | 
				
			||||||
	_p->variant_map.erase(p_key);
 | 
						_p->variant_map.erase(p_key);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool Dictionary::erase_checked(const Variant &p_key) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return _p->variant_map.erase(p_key);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool Dictionary::operator==(const Dictionary &p_dictionary) const {
 | 
					bool Dictionary::operator==(const Dictionary &p_dictionary) const {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return _p == p_dictionary._p;
 | 
						return _p == p_dictionary._p;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -66,6 +66,7 @@ public:
 | 
				
			||||||
	bool has_all(const Array &p_keys) const;
 | 
						bool has_all(const Array &p_keys) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void erase(const Variant &p_key);
 | 
						void erase(const Variant &p_key);
 | 
				
			||||||
 | 
						bool erase_checked(const Variant &p_key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool operator==(const Dictionary &p_dictionary) const;
 | 
						bool operator==(const Dictionary &p_dictionary) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1609,7 +1609,7 @@ void CSharpScript::load_script_signals(GDMonoClass *p_class, GDMonoClass *p_nati
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool CSharpScript::_get_signal(GDMonoClass *p_class, GDMonoClass *p_delegate, Vector<Argument> ¶ms) {
 | 
					bool CSharpScript::_get_signal(GDMonoClass *p_class, GDMonoClass *p_delegate, Vector<Argument> ¶ms) {
 | 
				
			||||||
	if (p_delegate->has_attribute(CACHED_CLASS(SignalAttribute))) {
 | 
						if (p_delegate->has_attribute(CACHED_CLASS(SignalAttribute))) {
 | 
				
			||||||
		MonoType *raw_type = GDMonoClass::get_raw_type(p_delegate);
 | 
							MonoType *raw_type = p_delegate->get_mono_type();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (mono_type_get_type(raw_type) == MONO_TYPE_CLASS) {
 | 
							if (mono_type_get_type(raw_type) == MONO_TYPE_CLASS) {
 | 
				
			||||||
			// Arguments are accessibles as arguments of .Invoke method
 | 
								// Arguments are accessibles as arguments of .Invoke method
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -100,8 +100,6 @@
 | 
				
			||||||
#define C_METHOD_MONOSTR_FROM_GODOT C_NS_MONOMARSHAL "::mono_string_from_godot"
 | 
					#define C_METHOD_MONOSTR_FROM_GODOT C_NS_MONOMARSHAL "::mono_string_from_godot"
 | 
				
			||||||
#define C_METHOD_MONOARRAY_TO(m_type) C_NS_MONOMARSHAL "::mono_array_to_" #m_type
 | 
					#define C_METHOD_MONOARRAY_TO(m_type) C_NS_MONOMARSHAL "::mono_array_to_" #m_type
 | 
				
			||||||
#define C_METHOD_MONOARRAY_FROM(m_type) C_NS_MONOMARSHAL "::" #m_type "_to_mono_array"
 | 
					#define C_METHOD_MONOARRAY_FROM(m_type) C_NS_MONOMARSHAL "::" #m_type "_to_mono_array"
 | 
				
			||||||
#define C_METHOD_MANAGED_TO_DICT C_NS_MONOMARSHAL "::mono_object_to_Dictionary"
 | 
					 | 
				
			||||||
#define C_METHOD_MANAGED_FROM_DICT C_NS_MONOMARSHAL "::Dictionary_to_mono_object"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define BINDINGS_GENERATOR_VERSION UINT32_C(2)
 | 
					#define BINDINGS_GENERATOR_VERSION UINT32_C(2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1338,7 +1336,6 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf
 | 
				
			||||||
		} else if (return_type->cs_out.empty()) {
 | 
							} else if (return_type->cs_out.empty()) {
 | 
				
			||||||
			p_output.push_back("return " + im_call + ";\n");
 | 
								p_output.push_back("return " + im_call + ";\n");
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			p_output.push_back(INDENT3);
 | 
					 | 
				
			||||||
			p_output.push_back(sformat(return_type->cs_out, im_call, return_type->cs_type, return_type->im_type_out));
 | 
								p_output.push_back(sformat(return_type->cs_out, im_call, return_type->cs_type, return_type->im_type_out));
 | 
				
			||||||
			p_output.push_back("\n");
 | 
								p_output.push_back("\n");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -2344,7 +2341,6 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define INSERT_ARRAY(m_type, m_proxy_t) INSERT_ARRAY_FULL(m_type, m_type, m_proxy_t)
 | 
					#define INSERT_ARRAY(m_type, m_proxy_t) INSERT_ARRAY_FULL(m_type, m_type, m_proxy_t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	INSERT_ARRAY(Array, object);
 | 
					 | 
				
			||||||
	INSERT_ARRAY(PoolIntArray, int);
 | 
						INSERT_ARRAY(PoolIntArray, int);
 | 
				
			||||||
	INSERT_ARRAY_FULL(PoolByteArray, PoolByteArray, byte);
 | 
						INSERT_ARRAY_FULL(PoolByteArray, PoolByteArray, byte);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2362,20 +2358,36 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#undef INSERT_ARRAY
 | 
					#undef INSERT_ARRAY
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Array
 | 
				
			||||||
 | 
						itype = TypeInterface();
 | 
				
			||||||
 | 
						itype.name = "Array";
 | 
				
			||||||
 | 
						itype.cname = itype.name;
 | 
				
			||||||
 | 
						itype.proxy_name = "Array";
 | 
				
			||||||
 | 
						itype.c_out = "\treturn memnew(Array(%1));\n";
 | 
				
			||||||
 | 
						itype.c_type = itype.name;
 | 
				
			||||||
 | 
						itype.c_type_in = itype.c_type + "*";
 | 
				
			||||||
 | 
						itype.c_type_out = itype.c_type + "*";
 | 
				
			||||||
 | 
						itype.cs_type = itype.proxy_name;
 | 
				
			||||||
 | 
						itype.cs_in = "%0." CS_SMETHOD_GETINSTANCE "()";
 | 
				
			||||||
 | 
						itype.cs_out = "return new Array(%0);";
 | 
				
			||||||
 | 
						itype.im_type_in = "IntPtr";
 | 
				
			||||||
 | 
						itype.im_type_out = "IntPtr";
 | 
				
			||||||
 | 
						builtin_types.insert(itype.cname, itype);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Dictionary
 | 
						// Dictionary
 | 
				
			||||||
	itype = TypeInterface();
 | 
						itype = TypeInterface();
 | 
				
			||||||
	itype.name = "Dictionary";
 | 
						itype.name = "Dictionary";
 | 
				
			||||||
	itype.cname = itype.name;
 | 
						itype.cname = itype.name;
 | 
				
			||||||
	itype.proxy_name = "Dictionary<object, object>";
 | 
						itype.proxy_name = "Dictionary";
 | 
				
			||||||
	itype.c_in = "\t%0 %1_in = " C_METHOD_MANAGED_TO_DICT "(%1);\n";
 | 
						itype.c_out = "\treturn memnew(Dictionary(%1));\n";
 | 
				
			||||||
	itype.c_out = "\treturn " C_METHOD_MANAGED_FROM_DICT "(%1);\n";
 | 
					 | 
				
			||||||
	itype.c_arg_in = "&%s_in";
 | 
					 | 
				
			||||||
	itype.c_type = itype.name;
 | 
						itype.c_type = itype.name;
 | 
				
			||||||
	itype.c_type_in = "MonoObject*";
 | 
						itype.c_type_in = itype.c_type + "*";
 | 
				
			||||||
	itype.c_type_out = "MonoObject*";
 | 
						itype.c_type_out = itype.c_type + "*";
 | 
				
			||||||
	itype.cs_type = itype.proxy_name;
 | 
						itype.cs_type = itype.proxy_name;
 | 
				
			||||||
	itype.im_type_in = itype.proxy_name;
 | 
						itype.cs_in = "%0." CS_SMETHOD_GETINSTANCE "()";
 | 
				
			||||||
	itype.im_type_out = itype.proxy_name;
 | 
						itype.cs_out = "return new Dictionary(%0);";
 | 
				
			||||||
 | 
						itype.im_type_in = "IntPtr";
 | 
				
			||||||
 | 
						itype.im_type_out = "IntPtr";
 | 
				
			||||||
	builtin_types.insert(itype.cname, itype);
 | 
						builtin_types.insert(itype.cname, itype);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// void (fictitious type to represent the return type of methods that do not return anything)
 | 
						// void (fictitious type to represent the return type of methods that do not return anything)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										240
									
								
								modules/mono/glue/collections_glue.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										240
									
								
								modules/mono/glue/collections_glue.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,240 @@
 | 
				
			||||||
 | 
					/*************************************************************************/
 | 
				
			||||||
 | 
					/*  collections_glue.cpp                                                 */
 | 
				
			||||||
 | 
					/*************************************************************************/
 | 
				
			||||||
 | 
					/*                       This file is part of:                           */
 | 
				
			||||||
 | 
					/*                           GODOT ENGINE                                */
 | 
				
			||||||
 | 
					/*                      https://godotengine.org                          */
 | 
				
			||||||
 | 
					/*************************************************************************/
 | 
				
			||||||
 | 
					/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */
 | 
				
			||||||
 | 
					/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */
 | 
				
			||||||
 | 
					/*                                                                       */
 | 
				
			||||||
 | 
					/* Permission is hereby granted, free of charge, to any person obtaining */
 | 
				
			||||||
 | 
					/* a copy of this software and associated documentation files (the       */
 | 
				
			||||||
 | 
					/* "Software"), to deal in the Software without restriction, including   */
 | 
				
			||||||
 | 
					/* without limitation the rights to use, copy, modify, merge, publish,   */
 | 
				
			||||||
 | 
					/* distribute, sublicense, and/or sell copies of the Software, and to    */
 | 
				
			||||||
 | 
					/* permit persons to whom the Software is furnished to do so, subject to */
 | 
				
			||||||
 | 
					/* the following conditions:                                             */
 | 
				
			||||||
 | 
					/*                                                                       */
 | 
				
			||||||
 | 
					/* The above copyright notice and this permission notice shall be        */
 | 
				
			||||||
 | 
					/* included in all copies or substantial portions of the Software.       */
 | 
				
			||||||
 | 
					/*                                                                       */
 | 
				
			||||||
 | 
					/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
 | 
				
			||||||
 | 
					/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
 | 
				
			||||||
 | 
					/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
 | 
				
			||||||
 | 
					/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
 | 
				
			||||||
 | 
					/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
 | 
				
			||||||
 | 
					/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 | 
				
			||||||
 | 
					/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 | 
				
			||||||
 | 
					/*************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "collections_glue.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <mono/metadata/exception.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "../mono_gd/gd_mono_class.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Array *godot_icall_Array_Ctor() {
 | 
				
			||||||
 | 
						return memnew(Array);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void godot_icall_Array_Dtor(Array *ptr) {
 | 
				
			||||||
 | 
						memdelete(ptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MonoObject *godot_icall_Array_At(Array *ptr, int index) {
 | 
				
			||||||
 | 
						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));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void godot_icall_Array_SetAt(Array *ptr, int index, MonoObject *value) {
 | 
				
			||||||
 | 
						if (index < 0 || index > ptr->size()) {
 | 
				
			||||||
 | 
							GDMonoUtils::set_pending_exception(mono_get_exception_index_out_of_range());
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ptr->operator[](index) = GDMonoMarshal::mono_object_to_variant(value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int godot_icall_Array_Count(Array *ptr) {
 | 
				
			||||||
 | 
						return ptr->size();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void godot_icall_Array_Add(Array *ptr, MonoObject *item) {
 | 
				
			||||||
 | 
						ptr->append(GDMonoMarshal::mono_object_to_variant(item));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void godot_icall_Array_Clear(Array *ptr) {
 | 
				
			||||||
 | 
						ptr->clear();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool godot_icall_Array_Contains(Array *ptr, MonoObject *item) {
 | 
				
			||||||
 | 
						return ptr->find(GDMonoMarshal::mono_object_to_variant(item)) != -1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void godot_icall_Array_CopyTo(Array *ptr, MonoArray *array, int array_index) {
 | 
				
			||||||
 | 
						int count = ptr->size();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (mono_array_length(array) < (array_index + count)) {
 | 
				
			||||||
 | 
							MonoException *exc = mono_get_exception_argument("", "Destination array was not long enough. Check destIndex and length, and the array's lower bounds.");
 | 
				
			||||||
 | 
							GDMonoUtils::set_pending_exception(exc);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (int i = 0; i < count; i++) {
 | 
				
			||||||
 | 
							MonoObject *boxed = GDMonoMarshal::variant_to_mono_object(ptr->operator[](i));
 | 
				
			||||||
 | 
							mono_array_setref(array, array_index, boxed);
 | 
				
			||||||
 | 
							array_index++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int godot_icall_Array_IndexOf(Array *ptr, MonoObject *item) {
 | 
				
			||||||
 | 
						return ptr->find(GDMonoMarshal::mono_object_to_variant(item));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void godot_icall_Array_Insert(Array *ptr, int index, MonoObject *item) {
 | 
				
			||||||
 | 
						if (index < 0 || index > ptr->size()) {
 | 
				
			||||||
 | 
							GDMonoUtils::set_pending_exception(mono_get_exception_index_out_of_range());
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ptr->insert(index, GDMonoMarshal::mono_object_to_variant(item));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool godot_icall_Array_Remove(Array *ptr, MonoObject *item) {
 | 
				
			||||||
 | 
						int idx = ptr->find(GDMonoMarshal::mono_object_to_variant(item));
 | 
				
			||||||
 | 
						if (idx >= 0) {
 | 
				
			||||||
 | 
							ptr->remove(idx);
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void godot_icall_Array_RemoveAt(Array *ptr, int index) {
 | 
				
			||||||
 | 
						if (index < 0 || index > ptr->size()) {
 | 
				
			||||||
 | 
							GDMonoUtils::set_pending_exception(mono_get_exception_index_out_of_range());
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ptr->remove(index);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Dictionary *godot_icall_Dictionary_Ctor() {
 | 
				
			||||||
 | 
						return memnew(Dictionary);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void godot_icall_Dictionary_Dtor(Dictionary *ptr) {
 | 
				
			||||||
 | 
						memdelete(ptr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MonoObject *godot_icall_Dictionary_GetValue(Dictionary *ptr, MonoObject *key) {
 | 
				
			||||||
 | 
						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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Array *godot_icall_Dictionary_Keys(Dictionary *ptr) {
 | 
				
			||||||
 | 
						return memnew(Array(ptr->keys()));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Array *godot_icall_Dictionary_Values(Dictionary *ptr) {
 | 
				
			||||||
 | 
						return memnew(Array(ptr->values()));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int godot_icall_Dictionary_Count(Dictionary *ptr) {
 | 
				
			||||||
 | 
						return ptr->size();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void godot_icall_Dictionary_Add(Dictionary *ptr, MonoObject *key, MonoObject *value) {
 | 
				
			||||||
 | 
						Variant varKey = GDMonoMarshal::mono_object_to_variant(key);
 | 
				
			||||||
 | 
						Variant *ret = ptr->getptr(varKey);
 | 
				
			||||||
 | 
						if (ret != NULL) {
 | 
				
			||||||
 | 
							GDMonoUtils::set_pending_exception(mono_get_exception_argument("key", "An element with the same key already exists"));
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ptr->operator[](varKey) = GDMonoMarshal::mono_object_to_variant(value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void godot_icall_Dictionary_Clear(Dictionary *ptr) {
 | 
				
			||||||
 | 
						ptr->clear();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool godot_icall_Dictionary_Contains(Dictionary *ptr, MonoObject *key, MonoObject *value) {
 | 
				
			||||||
 | 
						// no dupes
 | 
				
			||||||
 | 
						Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key));
 | 
				
			||||||
 | 
						return ret != NULL && *ret == GDMonoMarshal::mono_object_to_variant(value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool godot_icall_Dictionary_ContainsKey(Dictionary *ptr, MonoObject *key) {
 | 
				
			||||||
 | 
						return ptr->has(GDMonoMarshal::mono_object_to_variant(key));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool godot_icall_Dictionary_RemoveKey(Dictionary *ptr, MonoObject *key) {
 | 
				
			||||||
 | 
						return ptr->erase_checked(GDMonoMarshal::mono_object_to_variant(key));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool godot_icall_Dictionary_Remove(Dictionary *ptr, MonoObject *key, MonoObject *value) {
 | 
				
			||||||
 | 
						Variant varKey = GDMonoMarshal::mono_object_to_variant(key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// no dupes
 | 
				
			||||||
 | 
						Variant *ret = ptr->getptr(varKey);
 | 
				
			||||||
 | 
						if (ret != NULL && *ret == GDMonoMarshal::mono_object_to_variant(value)) {
 | 
				
			||||||
 | 
							ptr->erase_checked(varKey);
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool godot_icall_Dictionary_TryGetValue(Dictionary *ptr, MonoObject *key, MonoObject **value) {
 | 
				
			||||||
 | 
						Variant *ret = ptr->getptr(GDMonoMarshal::mono_object_to_variant(key));
 | 
				
			||||||
 | 
						if (ret == NULL) {
 | 
				
			||||||
 | 
							*value = NULL;
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						*value = GDMonoMarshal::variant_to_mono_object(ret);
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void godot_register_collections_icalls() {
 | 
				
			||||||
 | 
						mono_add_internal_call("Godot.Array::godot_icall_Array_Ctor", (void *)godot_icall_Array_Ctor);
 | 
				
			||||||
 | 
						mono_add_internal_call("Godot.Array::godot_icall_Array_Dtor", (void *)godot_icall_Array_Dtor);
 | 
				
			||||||
 | 
						mono_add_internal_call("Godot.Array::godot_icall_Array_At", (void *)godot_icall_Array_At);
 | 
				
			||||||
 | 
						mono_add_internal_call("Godot.Array::godot_icall_Array_SetAt", (void *)godot_icall_Array_SetAt);
 | 
				
			||||||
 | 
						mono_add_internal_call("Godot.Array::godot_icall_Array_Count", (void *)godot_icall_Array_Count);
 | 
				
			||||||
 | 
						mono_add_internal_call("Godot.Array::godot_icall_Array_Add", (void *)godot_icall_Array_Add);
 | 
				
			||||||
 | 
						mono_add_internal_call("Godot.Array::godot_icall_Array_Clear", (void *)godot_icall_Array_Clear);
 | 
				
			||||||
 | 
						mono_add_internal_call("Godot.Array::godot_icall_Array_Contains", (void *)godot_icall_Array_Contains);
 | 
				
			||||||
 | 
						mono_add_internal_call("Godot.Array::godot_icall_Array_CopyTo", (void *)godot_icall_Array_CopyTo);
 | 
				
			||||||
 | 
						mono_add_internal_call("Godot.Array::godot_icall_Array_IndexOf", (void *)godot_icall_Array_IndexOf);
 | 
				
			||||||
 | 
						mono_add_internal_call("Godot.Array::godot_icall_Array_Insert", (void *)godot_icall_Array_Insert);
 | 
				
			||||||
 | 
						mono_add_internal_call("Godot.Array::godot_icall_Array_Remove", (void *)godot_icall_Array_Remove);
 | 
				
			||||||
 | 
						mono_add_internal_call("Godot.Array::godot_icall_Array_RemoveAt", (void *)godot_icall_Array_RemoveAt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_Ctor", (void *)godot_icall_Dictionary_Ctor);
 | 
				
			||||||
 | 
						mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_Dtor", (void *)godot_icall_Dictionary_Dtor);
 | 
				
			||||||
 | 
						mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_GetValue", (void *)godot_icall_Dictionary_GetValue);
 | 
				
			||||||
 | 
						mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_SetValue", (void *)godot_icall_Dictionary_SetValue);
 | 
				
			||||||
 | 
						mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_Keys", (void *)godot_icall_Dictionary_Keys);
 | 
				
			||||||
 | 
						mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_Values", (void *)godot_icall_Dictionary_Values);
 | 
				
			||||||
 | 
						mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_Count", (void *)godot_icall_Dictionary_Count);
 | 
				
			||||||
 | 
						mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_Add", (void *)godot_icall_Dictionary_Add);
 | 
				
			||||||
 | 
						mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_Clear", (void *)godot_icall_Dictionary_Clear);
 | 
				
			||||||
 | 
						mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_Contains", (void *)godot_icall_Dictionary_Contains);
 | 
				
			||||||
 | 
						mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_ContainsKey", (void *)godot_icall_Dictionary_ContainsKey);
 | 
				
			||||||
 | 
						mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_RemoveKey", (void *)godot_icall_Dictionary_RemoveKey);
 | 
				
			||||||
 | 
						mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_Remove", (void *)godot_icall_Dictionary_Remove);
 | 
				
			||||||
 | 
						mono_add_internal_call("Godot.Dictionary::godot_icall_Dictionary_TryGetValue", (void *)godot_icall_Dictionary_TryGetValue);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										100
									
								
								modules/mono/glue/collections_glue.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								modules/mono/glue/collections_glue.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,100 @@
 | 
				
			||||||
 | 
					/*************************************************************************/
 | 
				
			||||||
 | 
					/*  collections_glue.h                                                   */
 | 
				
			||||||
 | 
					/*************************************************************************/
 | 
				
			||||||
 | 
					/*                       This file is part of:                           */
 | 
				
			||||||
 | 
					/*                           GODOT ENGINE                                */
 | 
				
			||||||
 | 
					/*                      https://godotengine.org                          */
 | 
				
			||||||
 | 
					/*************************************************************************/
 | 
				
			||||||
 | 
					/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.                 */
 | 
				
			||||||
 | 
					/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)    */
 | 
				
			||||||
 | 
					/*                                                                       */
 | 
				
			||||||
 | 
					/* Permission is hereby granted, free of charge, to any person obtaining */
 | 
				
			||||||
 | 
					/* a copy of this software and associated documentation files (the       */
 | 
				
			||||||
 | 
					/* "Software"), to deal in the Software without restriction, including   */
 | 
				
			||||||
 | 
					/* without limitation the rights to use, copy, modify, merge, publish,   */
 | 
				
			||||||
 | 
					/* distribute, sublicense, and/or sell copies of the Software, and to    */
 | 
				
			||||||
 | 
					/* permit persons to whom the Software is furnished to do so, subject to */
 | 
				
			||||||
 | 
					/* the following conditions:                                             */
 | 
				
			||||||
 | 
					/*                                                                       */
 | 
				
			||||||
 | 
					/* The above copyright notice and this permission notice shall be        */
 | 
				
			||||||
 | 
					/* included in all copies or substantial portions of the Software.       */
 | 
				
			||||||
 | 
					/*                                                                       */
 | 
				
			||||||
 | 
					/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
 | 
				
			||||||
 | 
					/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
 | 
				
			||||||
 | 
					/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
 | 
				
			||||||
 | 
					/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
 | 
				
			||||||
 | 
					/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
 | 
				
			||||||
 | 
					/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
 | 
				
			||||||
 | 
					/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 | 
				
			||||||
 | 
					/*************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef COLLECTIONS_GLUE_H
 | 
				
			||||||
 | 
					#define COLLECTIONS_GLUE_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "core/array.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "../mono_gd/gd_mono_marshal.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Array
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Array *godot_icall_Array_Ctor();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void godot_icall_Array_Dtor(Array *ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MonoObject *godot_icall_Array_At(Array *ptr, int index);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void godot_icall_Array_SetAt(Array *ptr, int index, MonoObject *value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int godot_icall_Array_Count(Array *ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void godot_icall_Array_Add(Array *ptr, MonoObject *item);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void godot_icall_Array_Clear(Array *ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool godot_icall_Array_Contains(Array *ptr, MonoObject *item);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void godot_icall_Array_CopyTo(Array *ptr, MonoArray *array, int array_index);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int godot_icall_Array_IndexOf(Array *ptr, MonoObject *item);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void godot_icall_Array_Insert(Array *ptr, int index, MonoObject *item);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool godot_icall_Array_Remove(Array *ptr, MonoObject *item);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void godot_icall_Array_RemoveAt(Array *ptr, int index);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Dictionary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Dictionary *godot_icall_Dictionary_Ctor();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void godot_icall_Dictionary_Dtor(Dictionary *ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MonoObject *godot_icall_Dictionary_GetValue(Dictionary *ptr, MonoObject *key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void godot_icall_Dictionary_SetValue(Dictionary *ptr, MonoObject *key, MonoObject *value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Array *godot_icall_Dictionary_Keys(Dictionary *ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Array *godot_icall_Dictionary_Values(Dictionary *ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int godot_icall_Dictionary_Count(Dictionary *ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void godot_icall_Dictionary_Add(Dictionary *ptr, MonoObject *key, MonoObject *value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void godot_icall_Dictionary_Clear(Dictionary *ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool godot_icall_Dictionary_Contains(Dictionary *ptr, MonoObject *key, MonoObject *value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool godot_icall_Dictionary_ContainsKey(Dictionary *ptr, MonoObject *key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool godot_icall_Dictionary_RemoveKey(Dictionary *ptr, MonoObject *key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool godot_icall_Dictionary_Remove(Dictionary *ptr, MonoObject *key, MonoObject *value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool godot_icall_Dictionary_TryGetValue(Dictionary *ptr, MonoObject *key, MonoObject **value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Register internal calls
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void godot_register_collections_icalls();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // COLLECTIONS_GLUE_H
 | 
				
			||||||
							
								
								
									
										335
									
								
								modules/mono/glue/cs_files/Array.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										335
									
								
								modules/mono/glue/cs_files/Array.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,335 @@
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Collections;
 | 
				
			||||||
 | 
					using System.Runtime.CompilerServices;
 | 
				
			||||||
 | 
					using System.Runtime.InteropServices;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Godot
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    class ArraySafeHandle : SafeHandle
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public ArraySafeHandle(IntPtr handle) : base(IntPtr.Zero, true)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            this.handle = handle;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public override bool IsInvalid
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return handle == IntPtr.Zero;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected override bool ReleaseHandle()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Array.godot_icall_Array_Dtor(handle);
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public class Array : IList<object>, ICollection<object>, IEnumerable<object>, IDisposable
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        [MethodImpl(MethodImplOptions.InternalCall)]
 | 
				
			||||||
 | 
					        internal extern static IntPtr godot_icall_Array_Ctor();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [MethodImpl(MethodImplOptions.InternalCall)]
 | 
				
			||||||
 | 
					        internal extern static void godot_icall_Array_Dtor(IntPtr ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [MethodImpl(MethodImplOptions.InternalCall)]
 | 
				
			||||||
 | 
					        internal extern static object godot_icall_Array_At(IntPtr ptr, int index);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [MethodImpl(MethodImplOptions.InternalCall)]
 | 
				
			||||||
 | 
					        internal extern static void godot_icall_Array_SetAt(IntPtr ptr, int index, object value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [MethodImpl(MethodImplOptions.InternalCall)]
 | 
				
			||||||
 | 
					        internal extern static int godot_icall_Array_Count(IntPtr ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [MethodImpl(MethodImplOptions.InternalCall)]
 | 
				
			||||||
 | 
					        internal extern static void godot_icall_Array_Add(IntPtr ptr, object item);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [MethodImpl(MethodImplOptions.InternalCall)]
 | 
				
			||||||
 | 
					        internal extern static void godot_icall_Array_Clear(IntPtr ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [MethodImpl(MethodImplOptions.InternalCall)]
 | 
				
			||||||
 | 
					        internal extern static bool godot_icall_Array_Contains(IntPtr ptr, object item);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [MethodImpl(MethodImplOptions.InternalCall)]
 | 
				
			||||||
 | 
					        internal extern static void godot_icall_Array_CopyTo(IntPtr ptr, object[] array, int arrayIndex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [MethodImpl(MethodImplOptions.InternalCall)]
 | 
				
			||||||
 | 
					        internal extern static int godot_icall_Array_IndexOf(IntPtr ptr, object item);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [MethodImpl(MethodImplOptions.InternalCall)]
 | 
				
			||||||
 | 
					        internal extern static void godot_icall_Array_Insert(IntPtr ptr, int index, object item);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [MethodImpl(MethodImplOptions.InternalCall)]
 | 
				
			||||||
 | 
					        internal extern static bool godot_icall_Array_Remove(IntPtr ptr, object item);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [MethodImpl(MethodImplOptions.InternalCall)]
 | 
				
			||||||
 | 
					        internal extern static void godot_icall_Array_RemoveAt(IntPtr ptr, int index);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ArraySafeHandle safeHandle;
 | 
				
			||||||
 | 
					        bool disposed = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public Array()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            safeHandle = new ArraySafeHandle(godot_icall_Array_Ctor());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        internal Array(ArraySafeHandle handle)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            safeHandle = handle;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        internal Array(IntPtr handle)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            safeHandle = new ArraySafeHandle(handle);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        internal IntPtr GetPtr()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return safeHandle.DangerousGetHandle();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void Dispose()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Dispose(true);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected virtual void Dispose(bool disposing)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (disposed)
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (safeHandle != null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                safeHandle.Dispose();
 | 
				
			||||||
 | 
					                safeHandle = null;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            disposed = true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public object this[int index]
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return godot_icall_Array_At(GetPtr(), index);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            set
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                godot_icall_Array_SetAt(GetPtr(), index, value);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public int Count
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return godot_icall_Array_Count(GetPtr());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public bool IsReadOnly
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void Add(object item)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            godot_icall_Array_Add(GetPtr(), item);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void Clear()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            godot_icall_Array_Clear(GetPtr());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public bool Contains(object item)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return godot_icall_Array_Contains(GetPtr(), item);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void CopyTo(object[] array, int arrayIndex)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (array == null)
 | 
				
			||||||
 | 
					                throw new ArgumentNullException(nameof(array), "Value cannot be null.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (arrayIndex < 0)
 | 
				
			||||||
 | 
					                throw new ArgumentOutOfRangeException(nameof(arrayIndex), "Number was less than the array's lower bound in the first dimension.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Internal call may throw ArgumentException
 | 
				
			||||||
 | 
					            godot_icall_Array_CopyTo(GetPtr(), array, arrayIndex);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public IEnumerator<object> GetEnumerator()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            int count = Count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for (int i = 0; i < count; i++)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                yield return godot_icall_Array_At(GetPtr(), i);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public int IndexOf(object item)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return godot_icall_Array_IndexOf(GetPtr(), item);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void Insert(int index, object item)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            godot_icall_Array_Insert(GetPtr(), index, item);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public bool Remove(object item)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return godot_icall_Array_Remove(GetPtr(), item);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void RemoveAt(int index)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            godot_icall_Array_RemoveAt(GetPtr(), index);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        IEnumerator IEnumerable.GetEnumerator()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return GetEnumerator();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public class Array<T> : IList<T>, ICollection<T>, IEnumerable<T>
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Array objectArray;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public Array()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            objectArray = new Array();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public Array(Array array)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            objectArray = array;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        internal Array(IntPtr handle)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            objectArray = new Array(handle);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        internal Array(ArraySafeHandle handle)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            objectArray = new Array(handle);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public static explicit operator Array(Array<T> from)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return from.objectArray;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public T this[int index]
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return (T)objectArray[index];
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            set
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                objectArray[index] = value;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public int Count
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return objectArray.Count;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public bool IsReadOnly
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return objectArray.IsReadOnly;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void Add(T item)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            objectArray.Add(item);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void Clear()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            objectArray.Clear();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public bool Contains(T item)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return objectArray.Contains(item);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void CopyTo(T[] array, int arrayIndex)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (array == null)
 | 
				
			||||||
 | 
					                throw new ArgumentNullException(nameof(array), "Value cannot be null.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (arrayIndex < 0)
 | 
				
			||||||
 | 
					                throw new ArgumentOutOfRangeException(nameof(arrayIndex), "Number was less than the array's lower bound in the first dimension.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // TODO This may be quite slow because every element access is an internal call.
 | 
				
			||||||
 | 
					            // It could be moved entirely to an internal call if we find out how to do the cast there.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            int count = objectArray.Count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (array.Length < (arrayIndex + count))
 | 
				
			||||||
 | 
					                throw new ArgumentException("Destination array was not long enough. Check destIndex and length, and the array's lower bounds.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for (int i = 0; i < count; i++)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                array[arrayIndex] = (T)objectArray[i];
 | 
				
			||||||
 | 
					                arrayIndex++;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public IEnumerator<T> GetEnumerator()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            int count = objectArray.Count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for (int i = 0; i < count; i++)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                yield return (T)objectArray[i];
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public int IndexOf(T item)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return objectArray.IndexOf(item);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void Insert(int index, T item)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            objectArray.Insert(index, item);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public bool Remove(T item)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return objectArray.Remove(item);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void RemoveAt(int index)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            objectArray.RemoveAt(index);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        IEnumerator IEnumerable.GetEnumerator()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return GetEnumerator();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										401
									
								
								modules/mono/glue/cs_files/Dictionary.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										401
									
								
								modules/mono/glue/cs_files/Dictionary.cs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,401 @@
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Collections;
 | 
				
			||||||
 | 
					using System.Runtime.CompilerServices;
 | 
				
			||||||
 | 
					using System.Runtime.InteropServices;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Godot
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    class DictionarySafeHandle : SafeHandle
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        public DictionarySafeHandle(IntPtr handle) : base(IntPtr.Zero, true)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            this.handle = handle;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public override bool IsInvalid
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return handle == IntPtr.Zero;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected override bool ReleaseHandle()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Dictionary.godot_icall_Dictionary_Dtor(handle);
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public class Dictionary :
 | 
				
			||||||
 | 
					        IDictionary<object, object>,
 | 
				
			||||||
 | 
					        ICollection<KeyValuePair<object, object>>,
 | 
				
			||||||
 | 
					        IEnumerable<KeyValuePair<object, object>>,
 | 
				
			||||||
 | 
					        IDisposable
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        [MethodImpl(MethodImplOptions.InternalCall)]
 | 
				
			||||||
 | 
					        internal extern static IntPtr godot_icall_Dictionary_Ctor();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [MethodImpl(MethodImplOptions.InternalCall)]
 | 
				
			||||||
 | 
					        internal extern static void godot_icall_Dictionary_Dtor(IntPtr ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [MethodImpl(MethodImplOptions.InternalCall)]
 | 
				
			||||||
 | 
					        internal extern static object godot_icall_Dictionary_GetValue(IntPtr ptr, object key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [MethodImpl(MethodImplOptions.InternalCall)]
 | 
				
			||||||
 | 
					        internal extern static void godot_icall_Dictionary_SetValue(IntPtr ptr, object key, object value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [MethodImpl(MethodImplOptions.InternalCall)]
 | 
				
			||||||
 | 
					        internal extern static IntPtr godot_icall_Dictionary_Keys(IntPtr ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [MethodImpl(MethodImplOptions.InternalCall)]
 | 
				
			||||||
 | 
					        internal extern static IntPtr godot_icall_Dictionary_Values(IntPtr ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [MethodImpl(MethodImplOptions.InternalCall)]
 | 
				
			||||||
 | 
					        internal extern static int godot_icall_Dictionary_Count(IntPtr ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [MethodImpl(MethodImplOptions.InternalCall)]
 | 
				
			||||||
 | 
					        internal extern static void godot_icall_Dictionary_Add(IntPtr ptr, object key, object value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [MethodImpl(MethodImplOptions.InternalCall)]
 | 
				
			||||||
 | 
					        internal extern static void godot_icall_Dictionary_Clear(IntPtr ptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [MethodImpl(MethodImplOptions.InternalCall)]
 | 
				
			||||||
 | 
					        internal extern static bool godot_icall_Dictionary_Contains(IntPtr ptr, object key, object value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [MethodImpl(MethodImplOptions.InternalCall)]
 | 
				
			||||||
 | 
					        internal extern static bool godot_icall_Dictionary_ContainsKey(IntPtr ptr, object key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [MethodImpl(MethodImplOptions.InternalCall)]
 | 
				
			||||||
 | 
					        internal extern static bool godot_icall_Dictionary_RemoveKey(IntPtr ptr, object key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [MethodImpl(MethodImplOptions.InternalCall)]
 | 
				
			||||||
 | 
					        internal extern static bool godot_icall_Dictionary_Remove(IntPtr ptr, object key, object value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [MethodImpl(MethodImplOptions.InternalCall)]
 | 
				
			||||||
 | 
					        internal extern static bool godot_icall_Dictionary_TryGetValue(IntPtr ptr, object key, out object value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        DictionarySafeHandle safeHandle;
 | 
				
			||||||
 | 
					        bool disposed = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public Dictionary()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            safeHandle = new DictionarySafeHandle(godot_icall_Dictionary_Ctor());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        internal Dictionary(DictionarySafeHandle handle)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            safeHandle = handle;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        internal Dictionary(IntPtr handle)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            safeHandle = new DictionarySafeHandle(handle);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        internal IntPtr GetPtr()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return safeHandle.DangerousGetHandle();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void Dispose()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Dispose(true);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected virtual void Dispose(bool disposing)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (disposed)
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (safeHandle != null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                safeHandle.Dispose();
 | 
				
			||||||
 | 
					                safeHandle = null;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            disposed = true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public object this[object key]
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return godot_icall_Dictionary_GetValue(GetPtr(), key);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            set
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                godot_icall_Dictionary_SetValue(GetPtr(), key, value);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public ICollection<object> Keys
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                IntPtr handle = godot_icall_Dictionary_Keys(GetPtr());
 | 
				
			||||||
 | 
					                return new Array(new ArraySafeHandle(handle));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public ICollection<object> Values
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                IntPtr handle = godot_icall_Dictionary_Values(GetPtr());
 | 
				
			||||||
 | 
					                return new Array(new ArraySafeHandle(handle));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public int Count
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return godot_icall_Dictionary_Count(GetPtr());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public bool IsReadOnly
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void Add(object key, object value)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            godot_icall_Dictionary_Add(GetPtr(), key, value);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void Add(KeyValuePair<object, object> item)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Add(item.Key, item.Value);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void Clear()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            godot_icall_Dictionary_Clear(GetPtr());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public bool Contains(KeyValuePair<object, object> item)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return godot_icall_Dictionary_Contains(GetPtr(), item.Key, item.Value);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public bool ContainsKey(object key)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return godot_icall_Dictionary_ContainsKey(GetPtr(), key);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void CopyTo(KeyValuePair<object, object>[] array, int arrayIndex)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // TODO 3 internal calls, can reduce to 1
 | 
				
			||||||
 | 
					            Array keys = (Array)Keys;
 | 
				
			||||||
 | 
					            Array values = (Array)Values;
 | 
				
			||||||
 | 
					            int count = Count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for (int i = 0; i < count; i++)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // TODO 2 internal calls, can reduce to 1
 | 
				
			||||||
 | 
					                array[arrayIndex] = new KeyValuePair<object, object>(keys[i], values[i]);
 | 
				
			||||||
 | 
					                arrayIndex++;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public IEnumerator<KeyValuePair<object, object>> GetEnumerator()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // TODO 3 internal calls, can reduce to 1
 | 
				
			||||||
 | 
					            Array keys = (Array)Keys;
 | 
				
			||||||
 | 
					            Array values = (Array)Values;
 | 
				
			||||||
 | 
					            int count = Count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for (int i = 0; i < count; i++)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // TODO 2 internal calls, can reduce to 1
 | 
				
			||||||
 | 
					                yield return new KeyValuePair<object, object>(keys[i], values[i]);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public bool Remove(object key)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return godot_icall_Dictionary_RemoveKey(GetPtr(), key);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public bool Remove(KeyValuePair<object, object> item)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return godot_icall_Dictionary_Remove(GetPtr(), item.Key, item.Value);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public bool TryGetValue(object key, out object value)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            object retValue;
 | 
				
			||||||
 | 
					            bool found = godot_icall_Dictionary_TryGetValue(GetPtr(), key, out retValue);
 | 
				
			||||||
 | 
					            value = found ? retValue : default(object);
 | 
				
			||||||
 | 
					            return found;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        IEnumerator IEnumerable.GetEnumerator()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return GetEnumerator();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public class Dictionary<TKey, TValue> :
 | 
				
			||||||
 | 
					        IDictionary<TKey, TValue>,
 | 
				
			||||||
 | 
					        ICollection<KeyValuePair<TKey, TValue>>,
 | 
				
			||||||
 | 
					        IEnumerable<KeyValuePair<TKey, TValue>>
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Dictionary objectDict;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public Dictionary()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            objectDict = new Dictionary();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public Dictionary(Dictionary dictionary)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            objectDict = dictionary;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        internal Dictionary(IntPtr handle)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            objectDict = new Dictionary(handle);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        internal Dictionary(DictionarySafeHandle handle)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            objectDict = new Dictionary(handle);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public static explicit operator Dictionary(Dictionary<TKey, TValue> from)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return from.objectDict;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public TValue this[TKey key]
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return (TValue)objectDict[key];
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            set
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                objectDict[key] = value;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public ICollection<TKey> Keys
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                IntPtr handle = Dictionary.godot_icall_Dictionary_Keys(objectDict.GetPtr());
 | 
				
			||||||
 | 
					                return new Array<TKey>(new ArraySafeHandle(handle));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public ICollection<TValue> Values
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                IntPtr handle = Dictionary.godot_icall_Dictionary_Values(objectDict.GetPtr());
 | 
				
			||||||
 | 
					                return new Array<TValue>(new ArraySafeHandle(handle));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public int Count
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return objectDict.Count;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public bool IsReadOnly
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return objectDict.IsReadOnly;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void Add(TKey key, TValue value)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            objectDict.Add(key, value);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void Add(KeyValuePair<TKey, TValue> item)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            objectDict.Add(item.Key, item.Value);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void Clear()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            objectDict.Clear();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public bool Contains(KeyValuePair<TKey, TValue> item)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return objectDict.Contains(new KeyValuePair<object, object>(item.Key, item.Value));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public bool ContainsKey(TKey key)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return objectDict.ContainsKey(key);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // TODO 3 internal calls, can reduce to 1
 | 
				
			||||||
 | 
					            Array<TKey> keys = (Array<TKey>)Keys;
 | 
				
			||||||
 | 
					            Array<TValue> values = (Array<TValue>)Values;
 | 
				
			||||||
 | 
					            int count = Count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for (int i = 0; i < count; i++)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // TODO 2 internal calls, can reduce to 1
 | 
				
			||||||
 | 
					                array[arrayIndex] = new KeyValuePair<TKey, TValue>(keys[i], values[i]);
 | 
				
			||||||
 | 
					                arrayIndex++;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // TODO 3 internal calls, can reduce to 1
 | 
				
			||||||
 | 
					            Array<TKey> keys = (Array<TKey>)Keys;
 | 
				
			||||||
 | 
					            Array<TValue> values = (Array<TValue>)Values;
 | 
				
			||||||
 | 
					            int count = Count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for (int i = 0; i < count; i++)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // TODO 2 internal calls, can reduce to 1
 | 
				
			||||||
 | 
					                yield return new KeyValuePair<TKey, TValue>(keys[i], values[i]);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public bool Remove(TKey key)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return objectDict.Remove(key);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public bool Remove(KeyValuePair<TKey, TValue> item)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return objectDict.Remove(new KeyValuePair<object, object>(item.Key, item.Value));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public bool TryGetValue(TKey key, out TValue value)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            object retValue;
 | 
				
			||||||
 | 
					            bool found = objectDict.TryGetValue(key, out retValue);
 | 
				
			||||||
 | 
					            value = found ? (TValue)retValue : default(TValue);
 | 
				
			||||||
 | 
					            return found;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        IEnumerator IEnumerable.GetEnumerator()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return GetEnumerator();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,36 +1,17 @@
 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
using System.Collections.Generic;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Godot
 | 
					namespace Godot
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    internal static class MarshalUtils
 | 
					    static class MarshalUtils
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        private static Dictionary<object, object> ArraysToDictionary(object[] keys, object[] values)
 | 
					        static bool IsArrayGenericType(Type type)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var ret = new Dictionary<object, object>();
 | 
					            return type.GetGenericTypeDefinition() == typeof(Array<>);
 | 
				
			||||||
 | 
					 | 
				
			||||||
            for (int i = 0; i < keys.Length; i++)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                ret.Add(keys[i], values[i]);
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return ret;
 | 
					        static bool IsDictionaryGenericType(Type type)
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        private static void DictionaryToArrays(Dictionary<object, object> from, out object[] keysTo, out object[] valuesTo)
 | 
					 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var keys = from.Keys;
 | 
					            return type.GetGenericTypeDefinition() == typeof(Dictionary<, >);
 | 
				
			||||||
            keysTo = new object[keys.Count];
 | 
					 | 
				
			||||||
            keys.CopyTo(keysTo, 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            var values = from.Values;
 | 
					 | 
				
			||||||
            valuesTo = new object[values.Count];
 | 
					 | 
				
			||||||
            values.CopyTo(valuesTo, 0);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        private static Type GetDictionaryType()
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return typeof(Dictionary<object, object>);
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,6 +29,7 @@
 | 
				
			||||||
/*************************************************************************/
 | 
					/*************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "builtin_types_glue.h"
 | 
					#include "builtin_types_glue.h"
 | 
				
			||||||
 | 
					#include "collections_glue.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "../csharp_script.h"
 | 
					#include "../csharp_script.h"
 | 
				
			||||||
#include "../mono_gd/gd_mono_class.h"
 | 
					#include "../mono_gd/gd_mono_class.h"
 | 
				
			||||||
| 
						 | 
					@ -308,4 +309,5 @@ MonoObject *godot_icall_Godot_weakref(Object *p_obj) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void godot_register_header_icalls() {
 | 
					void godot_register_header_icalls() {
 | 
				
			||||||
	godot_register_builtin_type_icalls();
 | 
						godot_register_builtin_type_icalls();
 | 
				
			||||||
 | 
						godot_register_collections_icalls();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,10 +33,32 @@
 | 
				
			||||||
#include <mono/metadata/attrdefs.h>
 | 
					#include <mono/metadata/attrdefs.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "gd_mono_assembly.h"
 | 
					#include "gd_mono_assembly.h"
 | 
				
			||||||
 | 
					#include "gd_mono_marshal.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MonoType *GDMonoClass::get_raw_type(GDMonoClass *p_class) {
 | 
					String GDMonoClass::get_full_name(MonoClass *p_mono_class) {
 | 
				
			||||||
 | 
						// mono_type_get_full_name is not exposed to embedders, but this seems to do the job
 | 
				
			||||||
 | 
						MonoReflectionType *type_obj = mono_type_get_object(mono_domain_get(), get_mono_type(p_mono_class));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return mono_class_get_type(p_class->get_mono_ptr());
 | 
						MonoException *exc = NULL;
 | 
				
			||||||
 | 
						GD_MONO_BEGIN_RUNTIME_INVOKE;
 | 
				
			||||||
 | 
						MonoString *str = mono_object_to_string((MonoObject *)type_obj, (MonoObject **)&exc);
 | 
				
			||||||
 | 
						GD_MONO_END_RUNTIME_INVOKE;
 | 
				
			||||||
 | 
						UNLIKELY_UNHANDLED_EXCEPTION(exc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return GDMonoMarshal::mono_string_to_godot(str);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MonoType *GDMonoClass::get_mono_type(MonoClass *p_mono_class) {
 | 
				
			||||||
 | 
						return mono_class_get_type(p_mono_class);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					String GDMonoClass::get_full_name() const {
 | 
				
			||||||
 | 
						return get_full_name(mono_class);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MonoType *GDMonoClass::get_mono_type() {
 | 
				
			||||||
 | 
						// Care, you cannot compare MonoType pointers
 | 
				
			||||||
 | 
						return get_mono_type(mono_class);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool GDMonoClass::is_assignable_from(GDMonoClass *p_from) const {
 | 
					bool GDMonoClass::is_assignable_from(GDMonoClass *p_from) const {
 | 
				
			||||||
| 
						 | 
					@ -44,14 +66,6 @@ bool GDMonoClass::is_assignable_from(GDMonoClass *p_from) const {
 | 
				
			||||||
	return mono_class_is_assignable_from(mono_class, p_from->mono_class);
 | 
						return mono_class_is_assignable_from(mono_class, p_from->mono_class);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
String GDMonoClass::get_full_name() const {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	String res = namespace_name;
 | 
					 | 
				
			||||||
	if (res.length())
 | 
					 | 
				
			||||||
		res += ".";
 | 
					 | 
				
			||||||
	return res + class_name;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
GDMonoClass *GDMonoClass::get_parent_class() {
 | 
					GDMonoClass *GDMonoClass::get_parent_class() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (assembly) {
 | 
						if (assembly) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -98,7 +98,11 @@ class GDMonoClass {
 | 
				
			||||||
	GDMonoClass(const StringName &p_namespace, const StringName &p_name, MonoClass *p_class, GDMonoAssembly *p_assembly);
 | 
						GDMonoClass(const StringName &p_namespace, const StringName &p_name, MonoClass *p_class, GDMonoAssembly *p_assembly);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	static MonoType *get_raw_type(GDMonoClass *p_class);
 | 
						static String get_full_name(MonoClass *p_mono_class);
 | 
				
			||||||
 | 
						static MonoType *get_mono_type(MonoClass *p_mono_class);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						String get_full_name() const;
 | 
				
			||||||
 | 
						MonoType *get_mono_type();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool is_assignable_from(GDMonoClass *p_from) const;
 | 
						bool is_assignable_from(GDMonoClass *p_from) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -108,8 +112,6 @@ public:
 | 
				
			||||||
	_FORCE_INLINE_ MonoClass *get_mono_ptr() const { return mono_class; }
 | 
						_FORCE_INLINE_ MonoClass *get_mono_ptr() const { return mono_class; }
 | 
				
			||||||
	_FORCE_INLINE_ const GDMonoAssembly *get_assembly() const { return assembly; }
 | 
						_FORCE_INLINE_ const GDMonoAssembly *get_assembly() const { return assembly; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	String get_full_name() const;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	GDMonoClass *get_parent_class();
 | 
						GDMonoClass *get_parent_class();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef TOOLS_ENABLED
 | 
					#ifdef TOOLS_ENABLED
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -148,7 +148,7 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		case MONO_TYPE_ARRAY:
 | 
							case MONO_TYPE_ARRAY:
 | 
				
			||||||
		case MONO_TYPE_SZARRAY: {
 | 
							case MONO_TYPE_SZARRAY: {
 | 
				
			||||||
			MonoArrayType *array_type = mono_type_get_array_type(GDMonoClass::get_raw_type(type.type_class));
 | 
								MonoArrayType *array_type = mono_type_get_array_type(type.type_class->get_mono_type());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (array_type->eklass == CACHED_CLASS_RAW(MonoObject))
 | 
								if (array_type->eklass == CACHED_CLASS_RAW(MonoObject))
 | 
				
			||||||
				SET_FROM_ARRAY_AND_BREAK(Array);
 | 
									SET_FROM_ARRAY_AND_BREAK(Array);
 | 
				
			||||||
| 
						 | 
					@ -200,6 +200,18 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (CACHED_CLASS(Dictionary) == type_class) {
 | 
				
			||||||
 | 
									MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Dictionary(), CACHED_CLASS(Dictionary));
 | 
				
			||||||
 | 
									mono_field_set_value(p_object, mono_field, managed);
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (CACHED_CLASS(Array) == type_class) {
 | 
				
			||||||
 | 
									MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Array(), CACHED_CLASS(Array));
 | 
				
			||||||
 | 
									mono_field_set_value(p_object, mono_field, managed);
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			ERR_EXPLAIN(String() + "Attempted to set the value of a field of unmarshallable type: " + type_class->get_name());
 | 
								ERR_EXPLAIN(String() + "Attempted to set the value of a field of unmarshallable type: " + type_class->get_name());
 | 
				
			||||||
			ERR_FAIL();
 | 
								ERR_FAIL();
 | 
				
			||||||
		} break;
 | 
							} break;
 | 
				
			||||||
| 
						 | 
					@ -248,10 +260,13 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				case Variant::DICTIONARY: {
 | 
									case Variant::DICTIONARY: {
 | 
				
			||||||
					MonoObject *managed = GDMonoMarshal::Dictionary_to_mono_object(p_value.operator Dictionary());
 | 
										MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Dictionary(), CACHED_CLASS(Dictionary));
 | 
				
			||||||
 | 
										mono_field_set_value(p_object, mono_field, managed);
 | 
				
			||||||
 | 
									} break;
 | 
				
			||||||
 | 
									case Variant::ARRAY: {
 | 
				
			||||||
 | 
										MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Array(), CACHED_CLASS(Array));
 | 
				
			||||||
					mono_field_set_value(p_object, mono_field, managed);
 | 
										mono_field_set_value(p_object, mono_field, managed);
 | 
				
			||||||
				} break;
 | 
									} break;
 | 
				
			||||||
				case Variant::ARRAY: SET_FROM_ARRAY_AND_BREAK(Array);
 | 
					 | 
				
			||||||
				case Variant::POOL_BYTE_ARRAY: SET_FROM_ARRAY_AND_BREAK(PoolByteArray);
 | 
									case Variant::POOL_BYTE_ARRAY: SET_FROM_ARRAY_AND_BREAK(PoolByteArray);
 | 
				
			||||||
				case Variant::POOL_INT_ARRAY: SET_FROM_ARRAY_AND_BREAK(PoolIntArray);
 | 
									case Variant::POOL_INT_ARRAY: SET_FROM_ARRAY_AND_BREAK(PoolIntArray);
 | 
				
			||||||
				case Variant::POOL_REAL_ARRAY: SET_FROM_ARRAY_AND_BREAK(PoolRealArray);
 | 
									case Variant::POOL_REAL_ARRAY: SET_FROM_ARRAY_AND_BREAK(PoolRealArray);
 | 
				
			||||||
| 
						 | 
					@ -265,8 +280,28 @@ void GDMonoField::set_value_from_variant(MonoObject *p_object, const Variant &p_
 | 
				
			||||||
		} break;
 | 
							} break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		case MONO_TYPE_GENERICINST: {
 | 
							case MONO_TYPE_GENERICINST: {
 | 
				
			||||||
			if (CACHED_RAW_MONO_CLASS(Dictionary) == type.type_class->get_mono_ptr()) {
 | 
								MonoReflectionType *reftype = mono_type_get_object(SCRIPTS_DOMAIN, type.type_class->get_mono_type());
 | 
				
			||||||
				MonoObject *managed = GDMonoMarshal::Dictionary_to_mono_object(p_value.operator Dictionary());
 | 
					
 | 
				
			||||||
 | 
								MonoException *exc = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								GDMonoUtils::IsDictionaryGenericType type_is_dict = CACHED_METHOD_THUNK(MarshalUtils, IsDictionaryGenericType);
 | 
				
			||||||
 | 
								MonoBoolean is_dict = type_is_dict((MonoObject *)reftype, (MonoObject **)&exc);
 | 
				
			||||||
 | 
								UNLIKELY_UNHANDLED_EXCEPTION(exc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (is_dict) {
 | 
				
			||||||
 | 
									MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Dictionary(), type.type_class);
 | 
				
			||||||
 | 
									mono_field_set_value(p_object, mono_field, managed);
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								exc = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								GDMonoUtils::IsArrayGenericType type_is_array = CACHED_METHOD_THUNK(MarshalUtils, IsArrayGenericType);
 | 
				
			||||||
 | 
								MonoBoolean is_array = type_is_array((MonoObject *)reftype, (MonoObject **)&exc);
 | 
				
			||||||
 | 
								UNLIKELY_UNHANDLED_EXCEPTION(exc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (is_array) {
 | 
				
			||||||
 | 
									MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator Array(), type.type_class);
 | 
				
			||||||
				mono_field_set_value(p_object, mono_field, managed);
 | 
									mono_field_set_value(p_object, mono_field, managed);
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,7 +45,8 @@ struct ManagedType {
 | 
				
			||||||
	GDMonoClass *type_class;
 | 
						GDMonoClass *type_class;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ManagedType() {
 | 
						ManagedType() {
 | 
				
			||||||
		type_class = 0;
 | 
							type_encoding = 0;
 | 
				
			||||||
 | 
							type_class = NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -120,7 +120,7 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		case MONO_TYPE_ARRAY:
 | 
							case MONO_TYPE_ARRAY:
 | 
				
			||||||
		case MONO_TYPE_SZARRAY: {
 | 
							case MONO_TYPE_SZARRAY: {
 | 
				
			||||||
			MonoArrayType *array_type = mono_type_get_array_type(GDMonoClass::get_raw_type(p_type.type_class));
 | 
								MonoArrayType *array_type = mono_type_get_array_type(p_type.type_class->get_mono_type());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (array_type->eklass == CACHED_CLASS_RAW(MonoObject))
 | 
								if (array_type->eklass == CACHED_CLASS_RAW(MonoObject))
 | 
				
			||||||
				return Variant::ARRAY;
 | 
									return Variant::ARRAY;
 | 
				
			||||||
| 
						 | 
					@ -162,12 +162,36 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type) {
 | 
				
			||||||
			if (CACHED_CLASS(RID) == type_class) {
 | 
								if (CACHED_CLASS(RID) == type_class) {
 | 
				
			||||||
				return Variant::_RID;
 | 
									return Variant::_RID;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (CACHED_CLASS(Dictionary) == type_class) {
 | 
				
			||||||
 | 
									return Variant::DICTIONARY;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (CACHED_CLASS(Array) == type_class) {
 | 
				
			||||||
 | 
									return Variant::ARRAY;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		} break;
 | 
							} break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		case MONO_TYPE_GENERICINST: {
 | 
							case MONO_TYPE_GENERICINST: {
 | 
				
			||||||
			if (CACHED_RAW_MONO_CLASS(Dictionary) == p_type.type_class->get_mono_ptr()) {
 | 
								MonoReflectionType *reftype = mono_type_get_object(SCRIPTS_DOMAIN, p_type.type_class->get_mono_type());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								MonoException *exc = NULL;
 | 
				
			||||||
 | 
								GDMonoUtils::IsDictionaryGenericType type_is_dict = CACHED_METHOD_THUNK(MarshalUtils, IsDictionaryGenericType);
 | 
				
			||||||
 | 
								MonoBoolean is_dict = type_is_dict((MonoObject *)reftype, (MonoObject **)&exc);
 | 
				
			||||||
 | 
								UNLIKELY_UNHANDLED_EXCEPTION(exc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (is_dict) {
 | 
				
			||||||
				return Variant::DICTIONARY;
 | 
									return Variant::DICTIONARY;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								exc = NULL;
 | 
				
			||||||
 | 
								GDMonoUtils::IsArrayGenericType type_is_array = CACHED_METHOD_THUNK(MarshalUtils, IsArrayGenericType);
 | 
				
			||||||
 | 
								MonoBoolean is_array = type_is_array((MonoObject *)reftype, (MonoObject **)&exc);
 | 
				
			||||||
 | 
								UNLIKELY_UNHANDLED_EXCEPTION(exc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (is_array) {
 | 
				
			||||||
 | 
									return Variant::ARRAY;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		} break;
 | 
							} break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		default: {
 | 
							default: {
 | 
				
			||||||
| 
						 | 
					@ -216,6 +240,7 @@ MonoObject *variant_to_mono_object(const Variant *p_var) {
 | 
				
			||||||
	ManagedType type;
 | 
						ManagedType type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	type.type_encoding = MONO_TYPE_OBJECT;
 | 
						type.type_encoding = MONO_TYPE_OBJECT;
 | 
				
			||||||
 | 
						// type.type_class is not needed when we specify the MONO_TYPE_OBJECT encoding
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return variant_to_mono_object(p_var, type);
 | 
						return variant_to_mono_object(p_var, type);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -315,7 +340,7 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		case MONO_TYPE_ARRAY:
 | 
							case MONO_TYPE_ARRAY:
 | 
				
			||||||
		case MONO_TYPE_SZARRAY: {
 | 
							case MONO_TYPE_SZARRAY: {
 | 
				
			||||||
			MonoArrayType *array_type = mono_type_get_array_type(GDMonoClass::get_raw_type(p_type.type_class));
 | 
								MonoArrayType *array_type = mono_type_get_array_type(p_type.type_class->get_mono_type());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (array_type->eklass == CACHED_CLASS_RAW(MonoObject))
 | 
								if (array_type->eklass == CACHED_CLASS_RAW(MonoObject))
 | 
				
			||||||
				return (MonoObject *)Array_to_mono_array(p_var->operator Array());
 | 
									return (MonoObject *)Array_to_mono_array(p_var->operator Array());
 | 
				
			||||||
| 
						 | 
					@ -360,6 +385,14 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty
 | 
				
			||||||
			if (CACHED_CLASS(RID) == type_class) {
 | 
								if (CACHED_CLASS(RID) == type_class) {
 | 
				
			||||||
				return GDMonoUtils::create_managed_from(p_var->operator RID());
 | 
									return GDMonoUtils::create_managed_from(p_var->operator RID());
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (CACHED_CLASS(Dictionary) == type_class) {
 | 
				
			||||||
 | 
									return GDMonoUtils::create_managed_from(p_var->operator Dictionary(), CACHED_CLASS(Dictionary));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (CACHED_CLASS(Array) == type_class) {
 | 
				
			||||||
 | 
									return GDMonoUtils::create_managed_from(p_var->operator Array(), CACHED_CLASS(Array));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		} break;
 | 
							} break;
 | 
				
			||||||
		case MONO_TYPE_OBJECT: {
 | 
							case MONO_TYPE_OBJECT: {
 | 
				
			||||||
			// Variant
 | 
								// Variant
 | 
				
			||||||
| 
						 | 
					@ -411,9 +444,9 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty
 | 
				
			||||||
					return GDMonoUtils::unmanaged_get_managed(p_var->operator Object *());
 | 
										return GDMonoUtils::unmanaged_get_managed(p_var->operator Object *());
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				case Variant::DICTIONARY:
 | 
									case Variant::DICTIONARY:
 | 
				
			||||||
					return Dictionary_to_mono_object(p_var->operator Dictionary());
 | 
										return GDMonoUtils::create_managed_from(p_var->operator Dictionary(), CACHED_CLASS(Dictionary));
 | 
				
			||||||
				case Variant::ARRAY:
 | 
									case Variant::ARRAY:
 | 
				
			||||||
					return (MonoObject *)Array_to_mono_array(p_var->operator Array());
 | 
										return GDMonoUtils::create_managed_from(p_var->operator Array(), CACHED_CLASS(Array));
 | 
				
			||||||
				case Variant::POOL_BYTE_ARRAY:
 | 
									case Variant::POOL_BYTE_ARRAY:
 | 
				
			||||||
					return (MonoObject *)PoolByteArray_to_mono_array(p_var->operator PoolByteArray());
 | 
										return (MonoObject *)PoolByteArray_to_mono_array(p_var->operator PoolByteArray());
 | 
				
			||||||
				case Variant::POOL_INT_ARRAY:
 | 
									case Variant::POOL_INT_ARRAY:
 | 
				
			||||||
| 
						 | 
					@ -433,8 +466,24 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
			case MONO_TYPE_GENERICINST: {
 | 
								case MONO_TYPE_GENERICINST: {
 | 
				
			||||||
				if (CACHED_RAW_MONO_CLASS(Dictionary) == p_type.type_class->get_mono_ptr()) {
 | 
									MonoReflectionType *reftype = mono_type_get_object(SCRIPTS_DOMAIN, p_type.type_class->get_mono_type());
 | 
				
			||||||
					return Dictionary_to_mono_object(p_var->operator Dictionary());
 | 
					
 | 
				
			||||||
 | 
									MonoException *exc = NULL;
 | 
				
			||||||
 | 
									GDMonoUtils::IsDictionaryGenericType type_is_dict = CACHED_METHOD_THUNK(MarshalUtils, IsDictionaryGenericType);
 | 
				
			||||||
 | 
									MonoBoolean is_dict = type_is_dict((MonoObject *)reftype, (MonoObject **)&exc);
 | 
				
			||||||
 | 
									UNLIKELY_UNHANDLED_EXCEPTION(exc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (is_dict) {
 | 
				
			||||||
 | 
										return GDMonoUtils::create_managed_from(p_var->operator Dictionary(), p_type.type_class);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									exc = NULL;
 | 
				
			||||||
 | 
									GDMonoUtils::IsArrayGenericType type_is_array = CACHED_METHOD_THUNK(MarshalUtils, IsArrayGenericType);
 | 
				
			||||||
 | 
									MonoBoolean is_array = type_is_array((MonoObject *)reftype, (MonoObject **)&exc);
 | 
				
			||||||
 | 
									UNLIKELY_UNHANDLED_EXCEPTION(exc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (is_array) {
 | 
				
			||||||
 | 
										return GDMonoUtils::create_managed_from(p_var->operator Array(), p_type.type_class);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			} break;
 | 
								} break;
 | 
				
			||||||
		} break;
 | 
							} break;
 | 
				
			||||||
| 
						 | 
					@ -452,7 +501,7 @@ Variant mono_object_to_variant(MonoObject *p_obj) {
 | 
				
			||||||
	GDMonoClass *tclass = GDMono::get_singleton()->get_class(mono_object_get_class(p_obj));
 | 
						GDMonoClass *tclass = GDMono::get_singleton()->get_class(mono_object_get_class(p_obj));
 | 
				
			||||||
	ERR_FAIL_COND_V(!tclass, Variant());
 | 
						ERR_FAIL_COND_V(!tclass, Variant());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	MonoType *raw_type = tclass->get_raw_type(tclass);
 | 
						MonoType *raw_type = tclass->get_mono_type();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ManagedType type;
 | 
						ManagedType type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -531,7 +580,7 @@ Variant mono_object_to_variant(MonoObject *p_obj) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		case MONO_TYPE_ARRAY:
 | 
							case MONO_TYPE_ARRAY:
 | 
				
			||||||
		case MONO_TYPE_SZARRAY: {
 | 
							case MONO_TYPE_SZARRAY: {
 | 
				
			||||||
			MonoArrayType *array_type = mono_type_get_array_type(GDMonoClass::get_raw_type(type.type_class));
 | 
								MonoArrayType *array_type = mono_type_get_array_type(type.type_class->get_mono_type());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (array_type->eklass == CACHED_CLASS_RAW(MonoObject))
 | 
								if (array_type->eklass == CACHED_CLASS_RAW(MonoObject))
 | 
				
			||||||
				return mono_array_to_Array((MonoArray *)p_obj);
 | 
									return mono_array_to_Array((MonoArray *)p_obj);
 | 
				
			||||||
| 
						 | 
					@ -579,11 +628,51 @@ Variant mono_object_to_variant(MonoObject *p_obj) {
 | 
				
			||||||
				RID *ptr = unbox<RID *>(CACHED_FIELD(RID, ptr)->get_value(p_obj));
 | 
									RID *ptr = unbox<RID *>(CACHED_FIELD(RID, ptr)->get_value(p_obj));
 | 
				
			||||||
				return ptr ? Variant(*ptr) : Variant();
 | 
									return ptr ? Variant(*ptr) : Variant();
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (CACHED_CLASS(Array) == type_class) {
 | 
				
			||||||
 | 
									MonoException *exc = NULL;
 | 
				
			||||||
 | 
									GDMonoUtils::Array_GetPtr get_ptr = CACHED_METHOD_THUNK(Array, GetPtr);
 | 
				
			||||||
 | 
									Array *ptr = get_ptr(p_obj, (MonoObject **)&exc);
 | 
				
			||||||
 | 
									UNLIKELY_UNHANDLED_EXCEPTION(exc);
 | 
				
			||||||
 | 
									return ptr ? Variant(*ptr) : Variant();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (CACHED_CLASS(Dictionary) == type_class) {
 | 
				
			||||||
 | 
									MonoException *exc = NULL;
 | 
				
			||||||
 | 
									GDMonoUtils::Dictionary_GetPtr get_ptr = CACHED_METHOD_THUNK(Dictionary, GetPtr);
 | 
				
			||||||
 | 
									Dictionary *ptr = get_ptr(p_obj, (MonoObject **)&exc);
 | 
				
			||||||
 | 
									UNLIKELY_UNHANDLED_EXCEPTION(exc);
 | 
				
			||||||
 | 
									return ptr ? Variant(*ptr) : Variant();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		} break;
 | 
							} break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		case MONO_TYPE_GENERICINST: {
 | 
							case MONO_TYPE_GENERICINST: {
 | 
				
			||||||
			if (CACHED_RAW_MONO_CLASS(Dictionary) == type.type_class->get_mono_ptr()) {
 | 
								MonoReflectionType *reftype = mono_type_get_object(SCRIPTS_DOMAIN, type.type_class->get_mono_type());
 | 
				
			||||||
				return mono_object_to_Dictionary(p_obj);
 | 
					
 | 
				
			||||||
 | 
								MonoException *exc = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								GDMonoUtils::IsDictionaryGenericType type_is_dict = CACHED_METHOD_THUNK(MarshalUtils, IsDictionaryGenericType);
 | 
				
			||||||
 | 
								MonoBoolean is_dict = type_is_dict((MonoObject *)reftype, (MonoObject **)&exc);
 | 
				
			||||||
 | 
								UNLIKELY_UNHANDLED_EXCEPTION(exc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (is_dict) {
 | 
				
			||||||
 | 
									MonoException *exc = NULL;
 | 
				
			||||||
 | 
									MonoObject *ret = type.type_class->get_method("GetPtr")->invoke(p_obj, &exc);
 | 
				
			||||||
 | 
									UNLIKELY_UNHANDLED_EXCEPTION(exc);
 | 
				
			||||||
 | 
									return *unbox<Dictionary *>(ret);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								exc = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								GDMonoUtils::IsArrayGenericType type_is_array = CACHED_METHOD_THUNK(MarshalUtils, IsArrayGenericType);
 | 
				
			||||||
 | 
								MonoBoolean is_array = type_is_array((MonoObject *)reftype, (MonoObject **)&exc);
 | 
				
			||||||
 | 
								UNLIKELY_UNHANDLED_EXCEPTION(exc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (is_array) {
 | 
				
			||||||
 | 
									MonoException *exc = NULL;
 | 
				
			||||||
 | 
									MonoObject *ret = type.type_class->get_method("GetPtr")->invoke(p_obj, &exc);
 | 
				
			||||||
 | 
									UNLIKELY_UNHANDLED_EXCEPTION(exc);
 | 
				
			||||||
 | 
									return *unbox<Array *>(ret);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} break;
 | 
							} break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -822,66 +911,4 @@ PoolVector3Array mono_array_to_PoolVector3Array(MonoArray *p_array) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
MonoObject *Dictionary_to_mono_object(const Dictionary &p_dict) {
 | 
					 | 
				
			||||||
	MonoArray *keys = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(MonoObject), p_dict.size());
 | 
					 | 
				
			||||||
	MonoArray *values = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(MonoObject), p_dict.size());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	int i = 0;
 | 
					 | 
				
			||||||
	const Variant *dkey = NULL;
 | 
					 | 
				
			||||||
	while ((dkey = p_dict.next(dkey))) {
 | 
					 | 
				
			||||||
		mono_array_set(keys, MonoObject *, i, variant_to_mono_object(dkey));
 | 
					 | 
				
			||||||
		mono_array_set(values, MonoObject *, i, variant_to_mono_object(p_dict[*dkey]));
 | 
					 | 
				
			||||||
		i++;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	GDMonoUtils::MarshalUtils_ArraysToDict arrays_to_dict = CACHED_METHOD_THUNK(MarshalUtils, ArraysToDictionary);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	MonoException *exc = NULL;
 | 
					 | 
				
			||||||
	GD_MONO_BEGIN_RUNTIME_INVOKE;
 | 
					 | 
				
			||||||
	MonoObject *ret = arrays_to_dict(keys, values, (MonoObject **)&exc);
 | 
					 | 
				
			||||||
	GD_MONO_END_RUNTIME_INVOKE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (exc) {
 | 
					 | 
				
			||||||
		GDMonoUtils::set_pending_exception(exc);
 | 
					 | 
				
			||||||
		ERR_FAIL_V(NULL);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return ret;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Dictionary mono_object_to_Dictionary(MonoObject *p_dict) {
 | 
					 | 
				
			||||||
	Dictionary ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!p_dict)
 | 
					 | 
				
			||||||
		return ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	GDMonoUtils::MarshalUtils_DictToArrays dict_to_arrays = CACHED_METHOD_THUNK(MarshalUtils, DictionaryToArrays);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	MonoArray *keys = NULL;
 | 
					 | 
				
			||||||
	MonoArray *values = NULL;
 | 
					 | 
				
			||||||
	MonoException *exc = NULL;
 | 
					 | 
				
			||||||
	GD_MONO_BEGIN_RUNTIME_INVOKE;
 | 
					 | 
				
			||||||
	dict_to_arrays(p_dict, &keys, &values, (MonoObject **)&exc);
 | 
					 | 
				
			||||||
	GD_MONO_END_RUNTIME_INVOKE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (exc) {
 | 
					 | 
				
			||||||
		GDMonoUtils::set_pending_exception(exc);
 | 
					 | 
				
			||||||
		ERR_FAIL_V(Dictionary());
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	int length = mono_array_length(keys);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (int i = 0; i < length; i++) {
 | 
					 | 
				
			||||||
		MonoObject *key_obj = mono_array_get(keys, MonoObject *, i);
 | 
					 | 
				
			||||||
		MonoObject *value_obj = mono_array_get(values, MonoObject *, i);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		Variant key = key_obj ? mono_object_to_variant(key_obj) : Variant();
 | 
					 | 
				
			||||||
		Variant value = value_obj ? mono_object_to_variant(value_obj) : Variant();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		ret[key] = value;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return ret;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
} // namespace GDMonoMarshal
 | 
					} // namespace GDMonoMarshal
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -143,11 +143,6 @@ PoolVector2Array mono_array_to_PoolVector2Array(MonoArray *p_array);
 | 
				
			||||||
MonoArray *PoolVector3Array_to_mono_array(const PoolVector3Array &p_array);
 | 
					MonoArray *PoolVector3Array_to_mono_array(const PoolVector3Array &p_array);
 | 
				
			||||||
PoolVector3Array mono_array_to_PoolVector3Array(MonoArray *p_array);
 | 
					PoolVector3Array mono_array_to_PoolVector3Array(MonoArray *p_array);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Dictionary
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
MonoObject *Dictionary_to_mono_object(const Dictionary &p_dict);
 | 
					 | 
				
			||||||
Dictionary mono_object_to_Dictionary(MonoObject *p_dict);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef YOLO_COPY
 | 
					#ifdef YOLO_COPY
 | 
				
			||||||
#define MARSHALLED_OUT(m_t, m_in, m_out) m_t *m_out = (m_t *)&m_in;
 | 
					#define MARSHALLED_OUT(m_t, m_in, m_out) m_t *m_out = (m_t *)&m_in;
 | 
				
			||||||
#define MARSHALLED_IN(m_t, m_in, m_out) m_t m_out = *reinterpret_cast<m_t *>(m_in);
 | 
					#define MARSHALLED_IN(m_t, m_in, m_out) m_t m_out = *reinterpret_cast<m_t *>(m_in);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -139,23 +139,8 @@ bool GDMonoProperty::has_setter() {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void GDMonoProperty::set_value(MonoObject *p_object, MonoObject *p_value, MonoException **r_exc) {
 | 
					void GDMonoProperty::set_value(MonoObject *p_object, MonoObject *p_value, MonoException **r_exc) {
 | 
				
			||||||
	MonoMethod *prop_method = mono_property_get_set_method(mono_property);
 | 
						void *params[1] = { p_value };
 | 
				
			||||||
 | 
						set_value(p_object, params, r_exc);
 | 
				
			||||||
	MonoArray *params = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(MonoObject), 1);
 | 
					 | 
				
			||||||
	mono_array_set(params, MonoObject *, 0, p_value);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	MonoException *exc = NULL;
 | 
					 | 
				
			||||||
	GD_MONO_BEGIN_RUNTIME_INVOKE;
 | 
					 | 
				
			||||||
	mono_runtime_invoke_array(prop_method, p_object, params, (MonoObject **)&exc);
 | 
					 | 
				
			||||||
	GD_MONO_END_RUNTIME_INVOKE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (exc) {
 | 
					 | 
				
			||||||
		if (r_exc) {
 | 
					 | 
				
			||||||
			*r_exc = exc;
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			GDMonoUtils::set_pending_exception(exc);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void GDMonoProperty::set_value(MonoObject *p_object, void **p_params, MonoException **r_exc) {
 | 
					void GDMonoProperty::set_value(MonoObject *p_object, void **p_params, MonoException **r_exc) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -87,6 +87,8 @@ void MonoCache::clear_members() {
 | 
				
			||||||
	method_System_Diagnostics_StackTrace_ctor_Exception_bool = NULL;
 | 
						method_System_Diagnostics_StackTrace_ctor_Exception_bool = NULL;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						class_KeyNotFoundException = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rawclass_Dictionary = NULL;
 | 
						rawclass_Dictionary = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	class_Vector2 = NULL;
 | 
						class_Vector2 = NULL;
 | 
				
			||||||
| 
						 | 
					@ -107,6 +109,8 @@ void MonoCache::clear_members() {
 | 
				
			||||||
	class_Control = NULL;
 | 
						class_Control = NULL;
 | 
				
			||||||
	class_Spatial = NULL;
 | 
						class_Spatial = NULL;
 | 
				
			||||||
	class_WeakRef = NULL;
 | 
						class_WeakRef = NULL;
 | 
				
			||||||
 | 
						class_Array = NULL;
 | 
				
			||||||
 | 
						class_Dictionary = NULL;
 | 
				
			||||||
	class_MarshalUtils = NULL;
 | 
						class_MarshalUtils = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef DEBUG_ENABLED
 | 
					#ifdef DEBUG_ENABLED
 | 
				
			||||||
| 
						 | 
					@ -134,8 +138,10 @@ void MonoCache::clear_members() {
 | 
				
			||||||
	field_Image_ptr = NULL;
 | 
						field_Image_ptr = NULL;
 | 
				
			||||||
	field_RID_ptr = NULL;
 | 
						field_RID_ptr = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	methodthunk_MarshalUtils_DictionaryToArrays = NULL;
 | 
						methodthunk_Array_GetPtr = NULL;
 | 
				
			||||||
	methodthunk_MarshalUtils_ArraysToDictionary = NULL;
 | 
						methodthunk_Dictionary_GetPtr = NULL;
 | 
				
			||||||
 | 
						methodthunk_MarshalUtils_IsArrayGenericType = NULL;
 | 
				
			||||||
 | 
						methodthunk_MarshalUtils_IsDictionaryGenericType = NULL;
 | 
				
			||||||
	methodthunk_SignalAwaiter_SignalCallback = NULL;
 | 
						methodthunk_SignalAwaiter_SignalCallback = NULL;
 | 
				
			||||||
	methodthunk_SignalAwaiter_FailureCallback = NULL;
 | 
						methodthunk_SignalAwaiter_FailureCallback = NULL;
 | 
				
			||||||
	methodthunk_GodotTaskScheduler_Activate = NULL;
 | 
						methodthunk_GodotTaskScheduler_Activate = NULL;
 | 
				
			||||||
| 
						 | 
					@ -175,6 +181,8 @@ void update_corlib_cache() {
 | 
				
			||||||
	CACHE_METHOD_AND_CHECK(System_Diagnostics_StackTrace, ctor_Exception_bool, CACHED_CLASS(System_Diagnostics_StackTrace)->get_method_with_desc("System.Diagnostics.StackTrace:.ctor(System.Exception,bool)", true));
 | 
						CACHE_METHOD_AND_CHECK(System_Diagnostics_StackTrace, ctor_Exception_bool, CACHED_CLASS(System_Diagnostics_StackTrace)->get_method_with_desc("System.Diagnostics.StackTrace:.ctor(System.Exception,bool)", true));
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						CACHE_CLASS_AND_CHECK(KeyNotFoundException, GDMono::get_singleton()->get_corlib_assembly()->get_class("System.Collections.Generic", "KeyNotFoundException"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mono_cache.corlib_cache_updated = true;
 | 
						mono_cache.corlib_cache_updated = true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -198,6 +206,8 @@ void update_godot_api_cache() {
 | 
				
			||||||
	CACHE_CLASS_AND_CHECK(Control, GODOT_API_CLASS(Control));
 | 
						CACHE_CLASS_AND_CHECK(Control, GODOT_API_CLASS(Control));
 | 
				
			||||||
	CACHE_CLASS_AND_CHECK(Spatial, GODOT_API_CLASS(Spatial));
 | 
						CACHE_CLASS_AND_CHECK(Spatial, GODOT_API_CLASS(Spatial));
 | 
				
			||||||
	CACHE_CLASS_AND_CHECK(WeakRef, GODOT_API_CLASS(WeakRef));
 | 
						CACHE_CLASS_AND_CHECK(WeakRef, GODOT_API_CLASS(WeakRef));
 | 
				
			||||||
 | 
						CACHE_CLASS_AND_CHECK(Array, GODOT_API_CLASS(Array));
 | 
				
			||||||
 | 
						CACHE_CLASS_AND_CHECK(Dictionary, GODOT_API_CLASS(Dictionary));
 | 
				
			||||||
	CACHE_CLASS_AND_CHECK(MarshalUtils, GODOT_API_CLASS(MarshalUtils));
 | 
						CACHE_CLASS_AND_CHECK(MarshalUtils, GODOT_API_CLASS(MarshalUtils));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef DEBUG_ENABLED
 | 
					#ifdef DEBUG_ENABLED
 | 
				
			||||||
| 
						 | 
					@ -224,8 +234,10 @@ void update_godot_api_cache() {
 | 
				
			||||||
	CACHE_FIELD_AND_CHECK(NodePath, ptr, CACHED_CLASS(NodePath)->get_field(BINDINGS_PTR_FIELD));
 | 
						CACHE_FIELD_AND_CHECK(NodePath, ptr, CACHED_CLASS(NodePath)->get_field(BINDINGS_PTR_FIELD));
 | 
				
			||||||
	CACHE_FIELD_AND_CHECK(RID, ptr, CACHED_CLASS(RID)->get_field(BINDINGS_PTR_FIELD));
 | 
						CACHE_FIELD_AND_CHECK(RID, ptr, CACHED_CLASS(RID)->get_field(BINDINGS_PTR_FIELD));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, DictionaryToArrays, (MarshalUtils_DictToArrays)CACHED_CLASS(MarshalUtils)->get_method("DictionaryToArrays", 3)->get_thunk());
 | 
						CACHE_METHOD_THUNK_AND_CHECK(Array, GetPtr, (Array_GetPtr)GODOT_API_CLASS(Array)->get_method("GetPtr", 0)->get_thunk());
 | 
				
			||||||
	CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, ArraysToDictionary, (MarshalUtils_ArraysToDict)CACHED_CLASS(MarshalUtils)->get_method("ArraysToDictionary", 2)->get_thunk());
 | 
						CACHE_METHOD_THUNK_AND_CHECK(Dictionary, GetPtr, (Dictionary_GetPtr)GODOT_API_CLASS(Dictionary)->get_method("GetPtr", 0)->get_thunk());
 | 
				
			||||||
 | 
						CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, IsArrayGenericType, (IsArrayGenericType)GODOT_API_CLASS(MarshalUtils)->get_method("IsArrayGenericType", 1)->get_thunk());
 | 
				
			||||||
 | 
						CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, IsDictionaryGenericType, (IsDictionaryGenericType)GODOT_API_CLASS(MarshalUtils)->get_method("IsDictionaryGenericType", 1)->get_thunk());
 | 
				
			||||||
	CACHE_METHOD_THUNK_AND_CHECK(SignalAwaiter, SignalCallback, (SignalAwaiter_SignalCallback)GODOT_API_CLASS(SignalAwaiter)->get_method("SignalCallback", 1)->get_thunk());
 | 
						CACHE_METHOD_THUNK_AND_CHECK(SignalAwaiter, SignalCallback, (SignalAwaiter_SignalCallback)GODOT_API_CLASS(SignalAwaiter)->get_method("SignalCallback", 1)->get_thunk());
 | 
				
			||||||
	CACHE_METHOD_THUNK_AND_CHECK(SignalAwaiter, FailureCallback, (SignalAwaiter_FailureCallback)GODOT_API_CLASS(SignalAwaiter)->get_method("FailureCallback", 0)->get_thunk());
 | 
						CACHE_METHOD_THUNK_AND_CHECK(SignalAwaiter, FailureCallback, (SignalAwaiter_FailureCallback)GODOT_API_CLASS(SignalAwaiter)->get_method("FailureCallback", 0)->get_thunk());
 | 
				
			||||||
	CACHE_METHOD_THUNK_AND_CHECK(GodotTaskScheduler, Activate, (GodotTaskScheduler_Activate)GODOT_API_CLASS(GodotTaskScheduler)->get_method("Activate", 0)->get_thunk());
 | 
						CACHE_METHOD_THUNK_AND_CHECK(GodotTaskScheduler, Activate, (GodotTaskScheduler_Activate)GODOT_API_CLASS(GodotTaskScheduler)->get_method("Activate", 0)->get_thunk());
 | 
				
			||||||
| 
						 | 
					@ -234,24 +246,9 @@ void update_godot_api_cache() {
 | 
				
			||||||
	CACHE_METHOD_THUNK_AND_CHECK(DebuggingUtils, GetStackFrameInfo, (DebugUtils_StackFrameInfo)GODOT_API_CLASS(DebuggingUtils)->get_method("GetStackFrameInfo", 4)->get_thunk());
 | 
						CACHE_METHOD_THUNK_AND_CHECK(DebuggingUtils, GetStackFrameInfo, (DebugUtils_StackFrameInfo)GODOT_API_CLASS(DebuggingUtils)->get_method("GetStackFrameInfo", 4)->get_thunk());
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	{
 | 
						// TODO Move to CSharpLanguage::init()
 | 
				
			||||||
		/*
 | 
					 | 
				
			||||||
		 * TODO Right now we only support Dictionary<object, object>.
 | 
					 | 
				
			||||||
		 * It would be great if we could support other key/value types
 | 
					 | 
				
			||||||
		 * without forcing the user to copy the entries.
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
		GDMonoMethod *method_get_dict_type = CACHED_CLASS(MarshalUtils)->get_method("GetDictionaryType", 0);
 | 
					 | 
				
			||||||
		ERR_FAIL_NULL(method_get_dict_type);
 | 
					 | 
				
			||||||
		MonoReflectionType *dict_refl_type = (MonoReflectionType *)method_get_dict_type->invoke(NULL);
 | 
					 | 
				
			||||||
		ERR_FAIL_NULL(dict_refl_type);
 | 
					 | 
				
			||||||
		MonoType *dict_type = mono_reflection_type_get_type(dict_refl_type);
 | 
					 | 
				
			||||||
		ERR_FAIL_NULL(dict_type);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		CACHE_RAW_MONO_CLASS_AND_CHECK(Dictionary, mono_class_from_mono_type(dict_type));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	MonoObject *task_scheduler = mono_object_new(SCRIPTS_DOMAIN, GODOT_API_CLASS(GodotTaskScheduler)->get_mono_ptr());
 | 
						MonoObject *task_scheduler = mono_object_new(SCRIPTS_DOMAIN, GODOT_API_CLASS(GodotTaskScheduler)->get_mono_ptr());
 | 
				
			||||||
	mono_runtime_object_init(task_scheduler);
 | 
						GDMonoUtils::runtime_object_init(task_scheduler);
 | 
				
			||||||
	mono_cache.task_scheduler_handle = MonoGCHandle::create_strong(task_scheduler);
 | 
						mono_cache.task_scheduler_handle = MonoGCHandle::create_strong(task_scheduler);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mono_cache.godot_api_cache_updated = true;
 | 
						mono_cache.godot_api_cache_updated = true;
 | 
				
			||||||
| 
						 | 
					@ -304,6 +301,12 @@ MonoThread *get_current_thread() {
 | 
				
			||||||
	return mono_thread_current();
 | 
						return mono_thread_current();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void runtime_object_init(MonoObject *p_this_obj) {
 | 
				
			||||||
 | 
						GD_MONO_BEGIN_RUNTIME_INVOKE;
 | 
				
			||||||
 | 
						mono_runtime_object_init(p_this_obj);
 | 
				
			||||||
 | 
						GD_MONO_END_RUNTIME_INVOKE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GDMonoClass *get_object_class(MonoObject *p_object) {
 | 
					GDMonoClass *get_object_class(MonoObject *p_object) {
 | 
				
			||||||
	return GDMono::get_singleton()->get_class(mono_object_get_class(p_object));
 | 
						return GDMono::get_singleton()->get_class(mono_object_get_class(p_object));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -358,7 +361,7 @@ MonoObject *create_managed_for_godot_object(GDMonoClass *p_class, const StringNa
 | 
				
			||||||
	CACHED_FIELD(GodotObject, ptr)->set_value_raw(mono_object, p_object);
 | 
						CACHED_FIELD(GodotObject, ptr)->set_value_raw(mono_object, p_object);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Construct
 | 
						// Construct
 | 
				
			||||||
	mono_runtime_object_init(mono_object);
 | 
						GDMonoUtils::runtime_object_init(mono_object);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return mono_object;
 | 
						return mono_object;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -368,7 +371,7 @@ MonoObject *create_managed_from(const NodePath &p_from) {
 | 
				
			||||||
	ERR_FAIL_NULL_V(mono_object, NULL);
 | 
						ERR_FAIL_NULL_V(mono_object, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Construct
 | 
						// Construct
 | 
				
			||||||
	mono_runtime_object_init(mono_object);
 | 
						GDMonoUtils::runtime_object_init(mono_object);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	CACHED_FIELD(NodePath, ptr)->set_value_raw(mono_object, memnew(NodePath(p_from)));
 | 
						CACHED_FIELD(NodePath, ptr)->set_value_raw(mono_object, memnew(NodePath(p_from)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -380,13 +383,73 @@ MonoObject *create_managed_from(const RID &p_from) {
 | 
				
			||||||
	ERR_FAIL_NULL_V(mono_object, NULL);
 | 
						ERR_FAIL_NULL_V(mono_object, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Construct
 | 
						// Construct
 | 
				
			||||||
	mono_runtime_object_init(mono_object);
 | 
						GDMonoUtils::runtime_object_init(mono_object);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	CACHED_FIELD(RID, ptr)->set_value_raw(mono_object, memnew(RID(p_from)));
 | 
						CACHED_FIELD(RID, ptr)->set_value_raw(mono_object, memnew(RID(p_from)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return mono_object;
 | 
						return mono_object;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MonoObject *create_managed_from(const Array &p_from, GDMonoClass *p_class) {
 | 
				
			||||||
 | 
						MonoObject *mono_object = mono_object_new(SCRIPTS_DOMAIN, p_class->get_mono_ptr());
 | 
				
			||||||
 | 
						ERR_FAIL_NULL_V(mono_object, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Search constructor that takes a pointer as parameter
 | 
				
			||||||
 | 
						MonoMethod *m;
 | 
				
			||||||
 | 
						void *iter = NULL;
 | 
				
			||||||
 | 
						while ((m = mono_class_get_methods(p_class->get_mono_ptr(), &iter))) {
 | 
				
			||||||
 | 
							if (strcmp(mono_method_get_name(m), ".ctor") == 0) {
 | 
				
			||||||
 | 
								MonoMethodSignature *sig = mono_method_signature(m);
 | 
				
			||||||
 | 
								void *front = NULL;
 | 
				
			||||||
 | 
								if (mono_signature_get_param_count(sig) == 1 &&
 | 
				
			||||||
 | 
										mono_class_from_mono_type(mono_signature_get_params(sig, &front)) == CACHED_CLASS(IntPtr)->get_mono_ptr()) {
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						CRASH_COND(m == NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Array *new_array = memnew(Array(p_from));
 | 
				
			||||||
 | 
						void *args[1] = { &new_array };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						MonoException *exc = NULL;
 | 
				
			||||||
 | 
						mono_runtime_invoke(m, mono_object, args, (MonoObject **)&exc);
 | 
				
			||||||
 | 
						UNLIKELY_UNHANDLED_EXCEPTION(exc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return mono_object;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MonoObject *create_managed_from(const Dictionary &p_from, GDMonoClass *p_class) {
 | 
				
			||||||
 | 
						MonoObject *mono_object = mono_object_new(SCRIPTS_DOMAIN, p_class->get_mono_ptr());
 | 
				
			||||||
 | 
						ERR_FAIL_NULL_V(mono_object, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Search constructor that takes a pointer as parameter
 | 
				
			||||||
 | 
						MonoMethod *m;
 | 
				
			||||||
 | 
						void *iter = NULL;
 | 
				
			||||||
 | 
						while ((m = mono_class_get_methods(p_class->get_mono_ptr(), &iter))) {
 | 
				
			||||||
 | 
							if (strcmp(mono_method_get_name(m), ".ctor") == 0) {
 | 
				
			||||||
 | 
								MonoMethodSignature *sig = mono_method_signature(m);
 | 
				
			||||||
 | 
								void *front = NULL;
 | 
				
			||||||
 | 
								if (mono_signature_get_param_count(sig) == 1 &&
 | 
				
			||||||
 | 
										mono_class_from_mono_type(mono_signature_get_params(sig, &front)) == CACHED_CLASS(IntPtr)->get_mono_ptr()) {
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						CRASH_COND(m == NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Dictionary *new_dict = memnew(Dictionary(p_from));
 | 
				
			||||||
 | 
						void *args[1] = { &new_dict };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						MonoException *exc = NULL;
 | 
				
			||||||
 | 
						mono_runtime_invoke(m, mono_object, args, (MonoObject **)&exc);
 | 
				
			||||||
 | 
						UNLIKELY_UNHANDLED_EXCEPTION(exc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return mono_object;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MonoDomain *create_domain(const String &p_friendly_name) {
 | 
					MonoDomain *create_domain(const String &p_friendly_name) {
 | 
				
			||||||
	MonoDomain *domain = mono_domain_create_appdomain((char *)p_friendly_name.utf8().get_data(), NULL);
 | 
						MonoDomain *domain = mono_domain_create_appdomain((char *)p_friendly_name.utf8().get_data(), NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -400,10 +463,10 @@ MonoDomain *create_domain(const String &p_friendly_name) {
 | 
				
			||||||
	return domain;
 | 
						return domain;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
String get_exception_name_and_message(MonoException *p_ex) {
 | 
					String get_exception_name_and_message(MonoException *p_exc) {
 | 
				
			||||||
	String res;
 | 
						String res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	MonoClass *klass = mono_object_get_class((MonoObject *)p_ex);
 | 
						MonoClass *klass = mono_object_get_class((MonoObject *)p_exc);
 | 
				
			||||||
	MonoType *type = mono_class_get_type(klass);
 | 
						MonoType *type = mono_class_get_type(klass);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	char *full_name = mono_type_full_name(type);
 | 
						char *full_name = mono_type_full_name(type);
 | 
				
			||||||
| 
						 | 
					@ -413,12 +476,24 @@ String get_exception_name_and_message(MonoException *p_ex) {
 | 
				
			||||||
	res += ": ";
 | 
						res += ": ";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	MonoProperty *prop = mono_class_get_property_from_name(klass, "Message");
 | 
						MonoProperty *prop = mono_class_get_property_from_name(klass, "Message");
 | 
				
			||||||
	MonoString *msg = (MonoString *)mono_property_get_value(prop, (MonoObject *)p_ex, NULL, NULL);
 | 
						GD_MONO_BEGIN_RUNTIME_INVOKE;
 | 
				
			||||||
 | 
						MonoString *msg = (MonoString *)mono_property_get_value(prop, (MonoObject *)p_exc, NULL, NULL);
 | 
				
			||||||
 | 
						GD_MONO_END_RUNTIME_INVOKE;
 | 
				
			||||||
	res += GDMonoMarshal::mono_string_to_godot(msg);
 | 
						res += GDMonoMarshal::mono_string_to_godot(msg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return res;
 | 
						return res;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void set_exception_message(MonoException *p_exc, String message) {
 | 
				
			||||||
 | 
						MonoClass *klass = mono_object_get_class((MonoObject *)p_exc);
 | 
				
			||||||
 | 
						MonoProperty *prop = mono_class_get_property_from_name(klass, "Message");
 | 
				
			||||||
 | 
						MonoString *msg = GDMonoMarshal::mono_string_from_godot(message);
 | 
				
			||||||
 | 
						void *params[1] = { msg };
 | 
				
			||||||
 | 
						GD_MONO_BEGIN_RUNTIME_INVOKE;
 | 
				
			||||||
 | 
						mono_property_set_value(prop, (MonoObject *)p_exc, params, NULL);
 | 
				
			||||||
 | 
						GD_MONO_END_RUNTIME_INVOKE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void debug_print_unhandled_exception(MonoException *p_exc) {
 | 
					void debug_print_unhandled_exception(MonoException *p_exc) {
 | 
				
			||||||
	print_unhandled_exception(p_exc);
 | 
						print_unhandled_exception(p_exc);
 | 
				
			||||||
	debug_send_unhandled_exception_error(p_exc);
 | 
						debug_send_unhandled_exception_error(p_exc);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,14 +41,24 @@
 | 
				
			||||||
#include "object.h"
 | 
					#include "object.h"
 | 
				
			||||||
#include "reference.h"
 | 
					#include "reference.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define UNLIKELY_UNHANDLED_EXCEPTION(m_exc)            \
 | 
				
			||||||
 | 
						if (unlikely(m_exc != NULL)) {                     \
 | 
				
			||||||
 | 
							GDMonoUtils::debug_unhandled_exception(m_exc); \
 | 
				
			||||||
 | 
							_UNREACHABLE_();                               \
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace GDMonoUtils {
 | 
					namespace GDMonoUtils {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef MonoObject *(*MarshalUtils_DictToArrays)(MonoObject *, MonoArray **, MonoArray **, MonoObject **);
 | 
					typedef Array *(*Array_GetPtr)(MonoObject *, MonoObject **);
 | 
				
			||||||
typedef MonoObject *(*MarshalUtils_ArraysToDict)(MonoArray *, MonoArray *, MonoObject **);
 | 
					typedef Dictionary *(*Dictionary_GetPtr)(MonoObject *, MonoObject **);
 | 
				
			||||||
typedef MonoObject *(*SignalAwaiter_SignalCallback)(MonoObject *, MonoArray *, MonoObject **);
 | 
					typedef MonoObject *(*SignalAwaiter_SignalCallback)(MonoObject *, MonoArray *, MonoObject **);
 | 
				
			||||||
typedef MonoObject *(*SignalAwaiter_FailureCallback)(MonoObject *, MonoObject **);
 | 
					typedef MonoObject *(*SignalAwaiter_FailureCallback)(MonoObject *, MonoObject **);
 | 
				
			||||||
typedef MonoObject *(*GodotTaskScheduler_Activate)(MonoObject *, MonoObject **);
 | 
					typedef MonoObject *(*GodotTaskScheduler_Activate)(MonoObject *, MonoObject **);
 | 
				
			||||||
typedef MonoArray *(*StackTrace_GetFrames)(MonoObject *, MonoObject **);
 | 
					typedef MonoArray *(*StackTrace_GetFrames)(MonoObject *, MonoObject **);
 | 
				
			||||||
 | 
					typedef MonoBoolean (*IsArrayGenericType)(MonoObject *, MonoObject **);
 | 
				
			||||||
 | 
					typedef MonoBoolean (*IsDictionaryGenericType)(MonoObject *, MonoObject **);
 | 
				
			||||||
 | 
					typedef MonoBoolean (*IsArrayGenericType)(MonoObject *, MonoObject **);
 | 
				
			||||||
 | 
					typedef MonoBoolean (*IsDictionaryGenericType)(MonoObject *, MonoObject **);
 | 
				
			||||||
typedef void (*DebugUtils_StackFrameInfo)(MonoObject *, MonoString **, int *, MonoString **, MonoObject **);
 | 
					typedef void (*DebugUtils_StackFrameInfo)(MonoObject *, MonoString **, int *, MonoString **, MonoObject **);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct MonoCache {
 | 
					struct MonoCache {
 | 
				
			||||||
| 
						 | 
					@ -79,6 +89,8 @@ struct MonoCache {
 | 
				
			||||||
	GDMonoMethod *method_System_Diagnostics_StackTrace_ctor_Exception_bool;
 | 
						GDMonoMethod *method_System_Diagnostics_StackTrace_ctor_Exception_bool;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						GDMonoClass *class_KeyNotFoundException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	MonoClass *rawclass_Dictionary;
 | 
						MonoClass *rawclass_Dictionary;
 | 
				
			||||||
	// -----------------------------------------------
 | 
						// -----------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -100,6 +112,8 @@ struct MonoCache {
 | 
				
			||||||
	GDMonoClass *class_Control;
 | 
						GDMonoClass *class_Control;
 | 
				
			||||||
	GDMonoClass *class_Spatial;
 | 
						GDMonoClass *class_Spatial;
 | 
				
			||||||
	GDMonoClass *class_WeakRef;
 | 
						GDMonoClass *class_WeakRef;
 | 
				
			||||||
 | 
						GDMonoClass *class_Array;
 | 
				
			||||||
 | 
						GDMonoClass *class_Dictionary;
 | 
				
			||||||
	GDMonoClass *class_MarshalUtils;
 | 
						GDMonoClass *class_MarshalUtils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef DEBUG_ENABLED
 | 
					#ifdef DEBUG_ENABLED
 | 
				
			||||||
| 
						 | 
					@ -127,8 +141,10 @@ struct MonoCache {
 | 
				
			||||||
	GDMonoField *field_Image_ptr;
 | 
						GDMonoField *field_Image_ptr;
 | 
				
			||||||
	GDMonoField *field_RID_ptr;
 | 
						GDMonoField *field_RID_ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	MarshalUtils_DictToArrays methodthunk_MarshalUtils_DictionaryToArrays;
 | 
						Array_GetPtr methodthunk_Array_GetPtr;
 | 
				
			||||||
	MarshalUtils_ArraysToDict methodthunk_MarshalUtils_ArraysToDictionary;
 | 
						Dictionary_GetPtr methodthunk_Dictionary_GetPtr;
 | 
				
			||||||
 | 
						IsArrayGenericType methodthunk_MarshalUtils_IsArrayGenericType;
 | 
				
			||||||
 | 
						IsDictionaryGenericType methodthunk_MarshalUtils_IsDictionaryGenericType;
 | 
				
			||||||
	SignalAwaiter_SignalCallback methodthunk_SignalAwaiter_SignalCallback;
 | 
						SignalAwaiter_SignalCallback methodthunk_SignalAwaiter_SignalCallback;
 | 
				
			||||||
	SignalAwaiter_FailureCallback methodthunk_SignalAwaiter_FailureCallback;
 | 
						SignalAwaiter_FailureCallback methodthunk_SignalAwaiter_FailureCallback;
 | 
				
			||||||
	GodotTaskScheduler_Activate methodthunk_GodotTaskScheduler_Activate;
 | 
						GodotTaskScheduler_Activate methodthunk_GodotTaskScheduler_Activate;
 | 
				
			||||||
| 
						 | 
					@ -175,6 +191,8 @@ _FORCE_INLINE_ bool is_main_thread() {
 | 
				
			||||||
	return mono_domain_get() != NULL && mono_thread_get_main() == mono_thread_current();
 | 
						return mono_domain_get() != NULL && mono_thread_get_main() == mono_thread_current();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void runtime_object_init(MonoObject *p_this_obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GDMonoClass *get_object_class(MonoObject *p_object);
 | 
					GDMonoClass *get_object_class(MonoObject *p_object);
 | 
				
			||||||
GDMonoClass *type_get_proxy_class(const StringName &p_type);
 | 
					GDMonoClass *type_get_proxy_class(const StringName &p_type);
 | 
				
			||||||
GDMonoClass *get_class_native_base(GDMonoClass *p_class);
 | 
					GDMonoClass *get_class_native_base(GDMonoClass *p_class);
 | 
				
			||||||
| 
						 | 
					@ -183,10 +201,13 @@ MonoObject *create_managed_for_godot_object(GDMonoClass *p_class, const StringNa
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MonoObject *create_managed_from(const NodePath &p_from);
 | 
					MonoObject *create_managed_from(const NodePath &p_from);
 | 
				
			||||||
MonoObject *create_managed_from(const RID &p_from);
 | 
					MonoObject *create_managed_from(const RID &p_from);
 | 
				
			||||||
 | 
					MonoObject *create_managed_from(const Array &p_from, GDMonoClass *p_class);
 | 
				
			||||||
 | 
					MonoObject *create_managed_from(const Dictionary &p_from, GDMonoClass *p_class);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MonoDomain *create_domain(const String &p_friendly_name);
 | 
					MonoDomain *create_domain(const String &p_friendly_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
String get_exception_name_and_message(MonoException *p_ex);
 | 
					String get_exception_name_and_message(MonoException *p_exc);
 | 
				
			||||||
 | 
					void set_exception_message(MonoException *p_exc, String message);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void debug_print_unhandled_exception(MonoException *p_exc);
 | 
					void debug_print_unhandled_exception(MonoException *p_exc);
 | 
				
			||||||
void debug_send_unhandled_exception_error(MonoException *p_exc);
 | 
					void debug_send_unhandled_exception_error(MonoException *p_exc);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue