2023-05-23 17:54:30 +02:00
/**************************************************************************/
/* gd_mono_marshal.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* 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 "gd_mono_marshal.h"
# include "gd_mono.h"
# include "gd_mono_cache.h"
# include "gd_mono_class.h"
namespace GDMonoMarshal {
Variant : : Type managed_to_variant_type ( const ManagedType & p_type ) {
switch ( p_type . type_encoding ) {
case MONO_TYPE_BOOLEAN :
return Variant : : BOOL ;
case MONO_TYPE_I1 :
return Variant : : INT ;
case MONO_TYPE_I2 :
return Variant : : INT ;
case MONO_TYPE_I4 :
return Variant : : INT ;
case MONO_TYPE_I8 :
return Variant : : INT ;
case MONO_TYPE_U1 :
return Variant : : INT ;
case MONO_TYPE_U2 :
return Variant : : INT ;
case MONO_TYPE_U4 :
return Variant : : INT ;
case MONO_TYPE_U8 :
return Variant : : INT ;
case MONO_TYPE_R4 :
return Variant : : REAL ;
case MONO_TYPE_R8 :
return Variant : : REAL ;
case MONO_TYPE_STRING : {
return Variant : : STRING ;
} break ;
case MONO_TYPE_VALUETYPE : {
GDMonoClass * vtclass = p_type . type_class ;
2023-06-01 14:14:19 +02:00
if ( vtclass = = CACHED_CLASS ( Vector2 ) ) {
2023-05-23 17:54:30 +02:00
return Variant : : VECTOR2 ;
2023-06-01 14:14:19 +02:00
}
if ( vtclass = = CACHED_CLASS ( Vector2i ) ) {
return Variant : : VECTOR2I ;
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( vtclass = = CACHED_CLASS ( Rect2 ) ) {
2023-05-23 17:54:30 +02:00
return Variant : : RECT2 ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( vtclass = = CACHED_CLASS ( Rect2i ) ) {
return Variant : : RECT2I ;
}
if ( vtclass = = CACHED_CLASS ( Transform2D ) ) {
2023-05-23 17:54:30 +02:00
return Variant : : TRANSFORM2D ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( vtclass = = CACHED_CLASS ( Vector3 ) ) {
2023-05-23 17:54:30 +02:00
return Variant : : VECTOR3 ;
2023-06-01 14:14:19 +02:00
}
if ( vtclass = = CACHED_CLASS ( Vector3i ) ) {
return Variant : : VECTOR3I ;
}
if ( vtclass = = CACHED_CLASS ( Vector4 ) ) {
return Variant : : VECTOR4 ;
}
if ( vtclass = = CACHED_CLASS ( Vector4i ) ) {
return Variant : : VECTOR4I ;
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( vtclass = = CACHED_CLASS ( Basis ) ) {
2023-05-23 17:54:30 +02:00
return Variant : : BASIS ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( vtclass = = CACHED_CLASS ( Quaternion ) ) {
2023-05-23 20:55:56 +02:00
return Variant : : QUATERNION ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( vtclass = = CACHED_CLASS ( Transform ) ) {
2023-05-23 17:54:30 +02:00
return Variant : : TRANSFORM ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( vtclass = = CACHED_CLASS ( Projection ) ) {
return Variant : : PROJECTION ;
}
if ( vtclass = = CACHED_CLASS ( AABB ) ) {
2023-05-23 17:54:30 +02:00
return Variant : : AABB ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( vtclass = = CACHED_CLASS ( Color ) ) {
2023-05-23 17:54:30 +02:00
return Variant : : COLOR ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( vtclass = = CACHED_CLASS ( Plane ) ) {
2023-05-23 17:54:30 +02:00
return Variant : : PLANE ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( mono_class_is_enum ( vtclass - > get_mono_ptr ( ) ) ) {
2023-05-23 17:54:30 +02:00
return Variant : : INT ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
} break ;
case MONO_TYPE_ARRAY :
case MONO_TYPE_SZARRAY : {
MonoClass * elem_class = mono_class_get_element_class ( p_type . type_class - > get_mono_ptr ( ) ) ;
2023-06-01 14:14:19 +02:00
if ( elem_class = = CACHED_CLASS_RAW ( MonoObject ) ) {
2023-05-23 17:54:30 +02:00
return Variant : : ARRAY ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( elem_class = = CACHED_CLASS_RAW ( uint8_t ) ) {
2023-05-23 17:54:30 +02:00
return Variant : : POOL_BYTE_ARRAY ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( elem_class = = CACHED_CLASS_RAW ( int32_t ) ) {
2023-05-23 17:54:30 +02:00
return Variant : : POOL_INT_ARRAY ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( elem_class = = REAL_T_MONOCLASS ) {
2023-05-23 17:54:30 +02:00
return Variant : : POOL_REAL_ARRAY ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( elem_class = = CACHED_CLASS_RAW ( String ) ) {
2023-05-23 17:54:30 +02:00
return Variant : : POOL_STRING_ARRAY ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( elem_class = = CACHED_CLASS_RAW ( Vector2 ) ) {
2023-05-23 17:54:30 +02:00
return Variant : : POOL_VECTOR2_ARRAY ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( elem_class = = CACHED_CLASS_RAW ( Vector2i ) ) {
return Variant : : POOL_VECTOR2I_ARRAY ;
}
if ( elem_class = = CACHED_CLASS_RAW ( Vector3 ) ) {
2023-05-23 17:54:30 +02:00
return Variant : : POOL_VECTOR3_ARRAY ;
2023-06-01 14:14:19 +02:00
}
if ( elem_class = = CACHED_CLASS_RAW ( Vector3i ) ) {
return Variant : : POOL_VECTOR3I_ARRAY ;
}
if ( elem_class = = CACHED_CLASS_RAW ( Vector4 ) ) {
return Variant : : POOL_VECTOR4_ARRAY ;
}
if ( elem_class = = CACHED_CLASS_RAW ( Vector4i ) ) {
return Variant : : POOL_VECTOR4I_ARRAY ;
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( elem_class = = CACHED_CLASS_RAW ( Color ) ) {
2023-05-23 17:54:30 +02:00
return Variant : : POOL_COLOR_ARRAY ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( elem_class = = CACHED_CLASS_RAW ( NodePath ) ) {
2023-05-23 17:54:30 +02:00
return Variant : : ARRAY ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( elem_class = = CACHED_CLASS_RAW ( StringName ) ) {
2023-05-23 17:54:30 +02:00
return Variant : : ARRAY ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( elem_class = = CACHED_CLASS_RAW ( RID ) ) {
2023-05-23 17:54:30 +02:00
return Variant : : ARRAY ;
2023-06-01 14:14:19 +02:00
}
if ( mono_class_is_enum ( elem_class ) ) {
return Variant : : ARRAY ;
}
2023-05-23 17:54:30 +02:00
GDMonoClass * array_type_class = GDMono : : get_singleton ( ) - > get_class ( elem_class ) ;
2023-06-01 14:14:19 +02:00
if ( CACHED_CLASS ( GodotObject ) - > is_assignable_from ( array_type_class ) ) {
2023-05-23 17:54:30 +02:00
return Variant : : ARRAY ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
} break ;
case MONO_TYPE_CLASS : {
GDMonoClass * type_class = p_type . type_class ;
// GodotObject
if ( CACHED_CLASS ( GodotObject ) - > is_assignable_from ( type_class ) ) {
return Variant : : OBJECT ;
}
if ( CACHED_CLASS ( NodePath ) = = type_class ) {
return Variant : : NODE_PATH ;
}
2023-06-01 14:14:19 +02:00
if ( CACHED_CLASS ( StringName ) = = type_class ) {
return Variant : : STRING_NAME ;
}
2023-05-23 17:54:30 +02:00
if ( CACHED_CLASS ( RID ) = = type_class ) {
2023-05-23 20:55:56 +02:00
return Variant : : RID ;
2023-05-23 17:54:30 +02:00
}
if ( CACHED_CLASS ( Dictionary ) = = type_class ) {
return Variant : : DICTIONARY ;
}
if ( CACHED_CLASS ( Array ) = = type_class ) {
return Variant : : ARRAY ;
}
// IDictionary
if ( p_type . type_class = = CACHED_CLASS ( System_Collections_IDictionary ) ) {
return Variant : : DICTIONARY ;
}
// ICollection or IEnumerable
if ( p_type . type_class = = CACHED_CLASS ( System_Collections_ICollection ) | |
p_type . type_class = = CACHED_CLASS ( System_Collections_IEnumerable ) ) {
return Variant : : ARRAY ;
}
} break ;
case MONO_TYPE_GENERICINST : {
MonoReflectionType * reftype = mono_type_get_object ( mono_domain_get ( ) , p_type . type_class - > get_mono_type ( ) ) ;
// Godot.Collections.Dictionary<TKey, TValue>
if ( GDMonoUtils : : Marshal : : type_is_generic_dictionary ( reftype ) ) {
return Variant : : DICTIONARY ;
}
// Godot.Collections.Array<T>
if ( GDMonoUtils : : Marshal : : type_is_generic_array ( reftype ) ) {
return Variant : : ARRAY ;
}
// System.Collections.Generic.Dictionary<TKey, TValue>
if ( GDMonoUtils : : Marshal : : type_is_system_generic_dictionary ( reftype ) ) {
return Variant : : DICTIONARY ;
}
// System.Collections.Generic.List<T>
if ( GDMonoUtils : : Marshal : : type_is_system_generic_list ( reftype ) ) {
return Variant : : ARRAY ;
}
// IDictionary<TKey, TValue>
if ( GDMonoUtils : : Marshal : : type_is_generic_idictionary ( reftype ) ) {
return Variant : : DICTIONARY ;
}
// ICollection<T> or IEnumerable<T>
if ( GDMonoUtils : : Marshal : : type_is_generic_icollection ( reftype ) | | GDMonoUtils : : Marshal : : type_is_generic_ienumerable ( reftype ) ) {
return Variant : : ARRAY ;
}
// GodotObject
GDMonoClass * type_class = p_type . type_class ;
if ( CACHED_CLASS ( GodotObject ) - > is_assignable_from ( type_class ) ) {
return Variant : : OBJECT ;
}
} break ;
default : {
} break ;
}
// Unknown
return Variant : : NIL ;
}
bool try_get_array_element_type ( const ManagedType & p_array_type , ManagedType & r_elem_type ) {
switch ( p_array_type . type_encoding ) {
case MONO_TYPE_ARRAY :
case MONO_TYPE_SZARRAY : {
MonoClass * elem_class = mono_class_get_element_class ( p_array_type . type_class - > get_mono_ptr ( ) ) ;
r_elem_type = ManagedType : : from_class ( elem_class ) ;
return true ;
} break ;
case MONO_TYPE_GENERICINST : {
MonoReflectionType * array_reftype = mono_type_get_object ( mono_domain_get ( ) , p_array_type . type_class - > get_mono_type ( ) ) ;
if ( GDMonoUtils : : Marshal : : type_is_generic_array ( array_reftype ) | |
GDMonoUtils : : Marshal : : type_is_system_generic_list ( array_reftype ) | |
GDMonoUtils : : Marshal : : type_is_generic_icollection ( array_reftype ) | |
GDMonoUtils : : Marshal : : type_is_generic_ienumerable ( array_reftype ) ) {
MonoReflectionType * elem_reftype ;
GDMonoUtils : : Marshal : : array_get_element_type ( array_reftype , & elem_reftype ) ;
r_elem_type = ManagedType : : from_reftype ( elem_reftype ) ;
return true ;
}
} break ;
default : {
} break ;
}
return false ;
}
bool try_get_dictionary_key_value_types ( const ManagedType & p_dictionary_type , ManagedType & r_key_type , ManagedType & r_value_type ) {
switch ( p_dictionary_type . type_encoding ) {
case MONO_TYPE_GENERICINST : {
MonoReflectionType * dict_reftype = mono_type_get_object ( mono_domain_get ( ) , p_dictionary_type . type_class - > get_mono_type ( ) ) ;
if ( GDMonoUtils : : Marshal : : type_is_generic_dictionary ( dict_reftype ) | |
GDMonoUtils : : Marshal : : type_is_system_generic_dictionary ( dict_reftype ) | |
GDMonoUtils : : Marshal : : type_is_generic_idictionary ( dict_reftype ) ) {
MonoReflectionType * key_reftype ;
MonoReflectionType * value_reftype ;
GDMonoUtils : : Marshal : : dictionary_get_key_value_types ( dict_reftype , & key_reftype , & value_reftype ) ;
r_key_type = ManagedType : : from_reftype ( key_reftype ) ;
r_value_type = ManagedType : : from_reftype ( value_reftype ) ;
return true ;
}
} break ;
default : {
} break ;
}
return false ;
}
String mono_to_utf8_string ( MonoString * p_mono_string ) {
MonoError error ;
char * utf8 = mono_string_to_utf8_checked ( p_mono_string , & error ) ;
if ( ! mono_error_ok ( & error ) ) {
ERR_PRINT ( String ( ) + " Failed to convert MonoString* to UTF-8: ' " + mono_error_get_message ( & error ) + " '. " ) ;
mono_error_cleanup ( & error ) ;
return String ( ) ;
}
String ret = String : : utf8 ( utf8 ) ;
mono_free ( utf8 ) ;
return ret ;
}
String mono_to_utf16_string ( MonoString * p_mono_string ) {
int len = mono_string_length ( p_mono_string ) ;
String ret ;
2023-06-01 14:14:19 +02:00
if ( len = = 0 ) {
2023-05-23 17:54:30 +02:00
return ret ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
ret . resize ( len + 1 ) ;
ret . set ( len , 0 ) ;
CharType * src = ( CharType * ) mono_string_chars ( p_mono_string ) ;
CharType * dst = ret . ptrw ( ) ;
for ( int i = 0 ; i < len ; i + + ) {
dst [ i ] = src [ i ] ;
}
return ret ;
}
MonoString * variant_to_mono_string ( const Variant & p_var ) {
if ( p_var . get_type ( ) = = Variant : : NIL ) {
return NULL ; // Otherwise, Variant -> String would return the string "Null"
}
return mono_string_from_godot ( p_var . operator String ( ) ) ;
}
MonoArray * variant_to_mono_array ( const Variant & p_var , GDMonoClass * p_type_class ) {
MonoArrayType * array_type = mono_type_get_array_type ( p_type_class - > get_mono_type ( ) ) ;
if ( array_type - > eklass = = CACHED_CLASS_RAW ( MonoObject ) ) {
return Array_to_mono_array ( p_var . operator Array ( ) ) ;
}
if ( array_type - > eklass = = CACHED_CLASS_RAW ( uint8_t ) ) {
return PoolByteArray_to_mono_array ( p_var . operator PoolByteArray ( ) ) ;
}
if ( array_type - > eklass = = CACHED_CLASS_RAW ( int32_t ) ) {
return PoolIntArray_to_mono_array ( p_var . operator PoolIntArray ( ) ) ;
}
if ( array_type - > eklass = = REAL_T_MONOCLASS ) {
return PoolRealArray_to_mono_array ( p_var . operator PoolRealArray ( ) ) ;
}
if ( array_type - > eklass = = CACHED_CLASS_RAW ( String ) ) {
return PoolStringArray_to_mono_array ( p_var . operator PoolStringArray ( ) ) ;
}
if ( array_type - > eklass = = CACHED_CLASS_RAW ( Vector2 ) ) {
return PoolVector2Array_to_mono_array ( p_var . operator PoolVector2Array ( ) ) ;
}
2023-06-01 14:14:19 +02:00
if ( array_type - > eklass = = CACHED_CLASS_RAW ( Vector2i ) ) {
return PoolVector2iArray_to_mono_array ( p_var . operator PoolVector2iArray ( ) ) ;
}
2023-05-23 17:54:30 +02:00
if ( array_type - > eklass = = CACHED_CLASS_RAW ( Vector3 ) ) {
return PoolVector3Array_to_mono_array ( p_var . operator PoolVector3Array ( ) ) ;
}
2023-06-01 14:14:19 +02:00
if ( array_type - > eklass = = CACHED_CLASS_RAW ( Vector3i ) ) {
return PoolVector3iArray_to_mono_array ( p_var . operator PoolVector3iArray ( ) ) ;
}
if ( array_type - > eklass = = CACHED_CLASS_RAW ( Vector4 ) ) {
return PoolVector4Array_to_mono_array ( p_var . operator PoolVector4Array ( ) ) ;
}
if ( array_type - > eklass = = CACHED_CLASS_RAW ( Vector4i ) ) {
return PoolVector4iArray_to_mono_array ( p_var . operator PoolVector4iArray ( ) ) ;
}
2023-05-23 17:54:30 +02:00
if ( array_type - > eklass = = CACHED_CLASS_RAW ( Color ) ) {
return PoolColorArray_to_mono_array ( p_var . operator PoolColorArray ( ) ) ;
}
if ( array_type - > eklass = = CACHED_CLASS_RAW ( NodePath ) ) {
return Array_to_mono_array ( p_var . operator Array ( ) ) ;
}
2023-06-01 14:14:19 +02:00
if ( array_type - > eklass = = CACHED_CLASS_RAW ( StringName ) ) {
return Array_to_mono_array ( p_var . operator Array ( ) ) ;
}
2023-05-23 17:54:30 +02:00
if ( array_type - > eklass = = CACHED_CLASS_RAW ( RID ) ) {
return Array_to_mono_array ( p_var . operator Array ( ) ) ;
}
if ( mono_class_is_assignable_from ( CACHED_CLASS ( GodotObject ) - > get_mono_ptr ( ) , array_type - > eklass ) ) {
return Array_to_mono_array ( p_var . operator : : Array ( ) , array_type - > eklass ) ;
}
ERR_FAIL_V_MSG ( nullptr , " Attempted to convert Variant to array of unsupported element type: " + GDMonoClass : : get_full_name ( array_type - > eklass ) + " '. " ) ;
}
MonoObject * variant_to_mono_object_of_class ( const Variant & p_var , GDMonoClass * p_type_class ) {
// GodotObject
if ( CACHED_CLASS ( GodotObject ) - > is_assignable_from ( p_type_class ) ) {
return GDMonoUtils : : unmanaged_get_managed ( p_var . operator Object * ( ) ) ;
}
if ( CACHED_CLASS ( NodePath ) = = p_type_class ) {
return GDMonoUtils : : create_managed_from ( p_var . operator NodePath ( ) ) ;
}
2023-06-01 14:14:19 +02:00
if ( CACHED_CLASS ( StringName ) = = p_type_class ) {
return GDMonoUtils : : create_managed_from ( p_var . operator StringName ( ) ) ;
}
2023-05-23 17:54:30 +02:00
if ( CACHED_CLASS ( RID ) = = p_type_class ) {
return GDMonoUtils : : create_managed_from ( p_var . operator : : RID ( ) ) ;
}
// Godot.Collections.Dictionary or IDictionary
if ( CACHED_CLASS ( Dictionary ) = = p_type_class | | CACHED_CLASS ( System_Collections_IDictionary ) = = p_type_class ) {
return GDMonoUtils : : create_managed_from ( p_var . operator Dictionary ( ) , CACHED_CLASS ( Dictionary ) ) ;
}
// Godot.Collections.Array or ICollection or IEnumerable
if ( CACHED_CLASS ( Array ) = = p_type_class | |
CACHED_CLASS ( System_Collections_ICollection ) = = p_type_class | |
CACHED_CLASS ( System_Collections_IEnumerable ) = = p_type_class ) {
return GDMonoUtils : : create_managed_from ( p_var . operator Array ( ) , CACHED_CLASS ( Array ) ) ;
}
ERR_FAIL_V_MSG ( nullptr , " Attempted to convert Variant to unsupported type: ' " + p_type_class - > get_full_name ( ) + " '. " ) ;
}
MonoObject * variant_to_mono_object_of_genericinst ( const Variant & p_var , GDMonoClass * p_type_class ) {
MonoReflectionType * reftype = mono_type_get_object ( mono_domain_get ( ) , p_type_class - > get_mono_type ( ) ) ;
// Godot.Collections.Dictionary<TKey, TValue>
if ( GDMonoUtils : : Marshal : : type_is_generic_dictionary ( reftype ) ) {
return GDMonoUtils : : create_managed_from ( p_var . operator Dictionary ( ) , p_type_class ) ;
}
// Godot.Collections.Array<T>
if ( GDMonoUtils : : Marshal : : type_is_generic_array ( reftype ) ) {
return GDMonoUtils : : create_managed_from ( p_var . operator Array ( ) , p_type_class ) ;
}
// System.Collections.Generic.Dictionary<TKey, TValue>
if ( GDMonoUtils : : Marshal : : type_is_system_generic_dictionary ( reftype ) ) {
MonoReflectionType * key_reftype = nullptr ;
MonoReflectionType * value_reftype = nullptr ;
GDMonoUtils : : Marshal : : dictionary_get_key_value_types ( reftype , & key_reftype , & value_reftype ) ;
return Dictionary_to_system_generic_dict ( p_var . operator Dictionary ( ) , p_type_class , key_reftype , value_reftype ) ;
}
// System.Collections.Generic.List<T>
if ( GDMonoUtils : : Marshal : : type_is_system_generic_list ( reftype ) ) {
MonoReflectionType * elem_reftype = nullptr ;
GDMonoUtils : : Marshal : : array_get_element_type ( reftype , & elem_reftype ) ;
return Array_to_system_generic_list ( p_var . operator Array ( ) , p_type_class , elem_reftype ) ;
}
// IDictionary<TKey, TValue>
if ( GDMonoUtils : : Marshal : : type_is_generic_idictionary ( reftype ) ) {
MonoReflectionType * key_reftype ;
MonoReflectionType * value_reftype ;
GDMonoUtils : : Marshal : : dictionary_get_key_value_types ( reftype , & key_reftype , & value_reftype ) ;
GDMonoClass * godot_dict_class = GDMonoUtils : : Marshal : : make_generic_dictionary_type ( key_reftype , value_reftype ) ;
return GDMonoUtils : : create_managed_from ( p_var . operator Dictionary ( ) , godot_dict_class ) ;
}
// ICollection<T> or IEnumerable<T>
if ( GDMonoUtils : : Marshal : : type_is_generic_icollection ( reftype ) | | GDMonoUtils : : Marshal : : type_is_generic_ienumerable ( reftype ) ) {
MonoReflectionType * elem_reftype ;
GDMonoUtils : : Marshal : : array_get_element_type ( reftype , & elem_reftype ) ;
GDMonoClass * godot_array_class = GDMonoUtils : : Marshal : : make_generic_array_type ( elem_reftype ) ;
return GDMonoUtils : : create_managed_from ( p_var . operator Array ( ) , godot_array_class ) ;
}
// GodotObject
if ( CACHED_CLASS ( GodotObject ) - > is_assignable_from ( p_type_class ) ) {
return GDMonoUtils : : unmanaged_get_managed ( p_var . operator Object * ( ) ) ;
}
ERR_FAIL_V_MSG ( nullptr , " Attempted to convert Variant to unsupported generic type: ' " + p_type_class - > get_full_name ( ) + " '. " ) ;
}
MonoObject * variant_to_mono_object ( const Variant & p_var ) {
// Variant
switch ( p_var . get_type ( ) ) {
case Variant : : BOOL : {
MonoBoolean val = p_var . operator bool ( ) ;
return BOX_BOOLEAN ( val ) ;
}
case Variant : : INT : {
int32_t val = p_var . operator signed int ( ) ;
return BOX_INT32 ( val ) ;
}
case Variant : : REAL : {
# ifdef REAL_T_IS_DOUBLE
double val = p_var . operator double ( ) ;
return BOX_DOUBLE ( val ) ;
# else
float val = p_var . operator float ( ) ;
return BOX_FLOAT ( val ) ;
# endif
}
case Variant : : STRING :
return ( MonoObject * ) mono_string_from_godot ( p_var . operator String ( ) ) ;
case Variant : : VECTOR2 : {
GDMonoMarshal : : M_Vector2 from = MARSHALLED_OUT ( Vector2 , p_var . operator : : Vector2 ( ) ) ;
return mono_value_box ( mono_domain_get ( ) , CACHED_CLASS_RAW ( Vector2 ) , & from ) ;
}
case Variant : : RECT2 : {
GDMonoMarshal : : M_Rect2 from = MARSHALLED_OUT ( Rect2 , p_var . operator : : Rect2 ( ) ) ;
return mono_value_box ( mono_domain_get ( ) , CACHED_CLASS_RAW ( Rect2 ) , & from ) ;
}
2023-06-01 14:14:19 +02:00
case Variant : : VECTOR2I : {
GDMonoMarshal : : M_Vector2i from = MARSHALLED_OUT ( Vector2i , p_var . operator : : Vector2i ( ) ) ;
return mono_value_box ( mono_domain_get ( ) , CACHED_CLASS_RAW ( Vector2i ) , & from ) ;
}
case Variant : : RECT2I : {
GDMonoMarshal : : M_Rect2i from = MARSHALLED_OUT ( Rect2i , p_var . operator : : Rect2i ( ) ) ;
return mono_value_box ( mono_domain_get ( ) , CACHED_CLASS_RAW ( Rect2i ) , & from ) ;
}
2023-05-23 17:54:30 +02:00
case Variant : : VECTOR3 : {
GDMonoMarshal : : M_Vector3 from = MARSHALLED_OUT ( Vector3 , p_var . operator : : Vector3 ( ) ) ;
return mono_value_box ( mono_domain_get ( ) , CACHED_CLASS_RAW ( Vector3 ) , & from ) ;
}
2023-06-01 14:14:19 +02:00
case Variant : : VECTOR3I : {
GDMonoMarshal : : M_Vector3i from = MARSHALLED_OUT ( Vector3i , p_var . operator : : Vector3i ( ) ) ;
return mono_value_box ( mono_domain_get ( ) , CACHED_CLASS_RAW ( Vector3i ) , & from ) ;
}
case Variant : : VECTOR4 : {
GDMonoMarshal : : M_Vector4 from = MARSHALLED_OUT ( Vector4 , p_var . operator : : Vector4 ( ) ) ;
return mono_value_box ( mono_domain_get ( ) , CACHED_CLASS_RAW ( Vector4 ) , & from ) ;
}
case Variant : : VECTOR4I : {
GDMonoMarshal : : M_Vector4i from = MARSHALLED_OUT ( Vector4i , p_var . operator : : Vector4i ( ) ) ;
return mono_value_box ( mono_domain_get ( ) , CACHED_CLASS_RAW ( Vector4i ) , & from ) ;
}
2023-05-23 17:54:30 +02:00
case Variant : : TRANSFORM2D : {
GDMonoMarshal : : M_Transform2D from = MARSHALLED_OUT ( Transform2D , p_var . operator : : Transform2D ( ) ) ;
return mono_value_box ( mono_domain_get ( ) , CACHED_CLASS_RAW ( Transform2D ) , & from ) ;
}
case Variant : : PLANE : {
GDMonoMarshal : : M_Plane from = MARSHALLED_OUT ( Plane , p_var . operator : : Plane ( ) ) ;
return mono_value_box ( mono_domain_get ( ) , CACHED_CLASS_RAW ( Plane ) , & from ) ;
}
2023-05-23 20:55:56 +02:00
case Variant : : QUATERNION : {
GDMonoMarshal : : M_Quaternion from = MARSHALLED_OUT ( Quaternion , p_var . operator : : Quaternion ( ) ) ;
return mono_value_box ( mono_domain_get ( ) , CACHED_CLASS_RAW ( Quaternion ) , & from ) ;
2023-05-23 17:54:30 +02:00
}
case Variant : : AABB : {
GDMonoMarshal : : M_AABB from = MARSHALLED_OUT ( AABB , p_var . operator : : AABB ( ) ) ;
return mono_value_box ( mono_domain_get ( ) , CACHED_CLASS_RAW ( AABB ) , & from ) ;
}
case Variant : : BASIS : {
GDMonoMarshal : : M_Basis from = MARSHALLED_OUT ( Basis , p_var . operator : : Basis ( ) ) ;
return mono_value_box ( mono_domain_get ( ) , CACHED_CLASS_RAW ( Basis ) , & from ) ;
}
case Variant : : TRANSFORM : {
GDMonoMarshal : : M_Transform from = MARSHALLED_OUT ( Transform , p_var . operator : : Transform ( ) ) ;
return mono_value_box ( mono_domain_get ( ) , CACHED_CLASS_RAW ( Transform ) , & from ) ;
}
2023-06-01 14:14:19 +02:00
case Variant : : PROJECTION : {
GDMonoMarshal : : M_Projection from = MARSHALLED_OUT ( Projection , p_var . operator : : Projection ( ) ) ;
return mono_value_box ( mono_domain_get ( ) , CACHED_CLASS_RAW ( Projection ) , & from ) ;
}
2023-05-23 17:54:30 +02:00
case Variant : : COLOR : {
GDMonoMarshal : : M_Color from = MARSHALLED_OUT ( Color , p_var . operator : : Color ( ) ) ;
return mono_value_box ( mono_domain_get ( ) , CACHED_CLASS_RAW ( Color ) , & from ) ;
}
case Variant : : NODE_PATH :
return GDMonoUtils : : create_managed_from ( p_var . operator NodePath ( ) ) ;
2023-06-01 14:14:19 +02:00
case Variant : : STRING_NAME :
return GDMonoUtils : : create_managed_from ( p_var . operator StringName ( ) ) ;
2023-05-23 20:55:56 +02:00
case Variant : : RID :
2023-05-23 17:54:30 +02:00
return GDMonoUtils : : create_managed_from ( p_var . operator : : RID ( ) ) ;
case Variant : : OBJECT :
return GDMonoUtils : : unmanaged_get_managed ( p_var . operator Object * ( ) ) ;
case Variant : : DICTIONARY :
return GDMonoUtils : : create_managed_from ( p_var . operator Dictionary ( ) , CACHED_CLASS ( Dictionary ) ) ;
case Variant : : ARRAY :
return GDMonoUtils : : create_managed_from ( p_var . operator Array ( ) , CACHED_CLASS ( Array ) ) ;
case Variant : : POOL_BYTE_ARRAY :
return ( MonoObject * ) PoolByteArray_to_mono_array ( p_var . operator PoolByteArray ( ) ) ;
case Variant : : POOL_INT_ARRAY :
return ( MonoObject * ) PoolIntArray_to_mono_array ( p_var . operator PoolIntArray ( ) ) ;
case Variant : : POOL_REAL_ARRAY :
return ( MonoObject * ) PoolRealArray_to_mono_array ( p_var . operator PoolRealArray ( ) ) ;
case Variant : : POOL_STRING_ARRAY :
return ( MonoObject * ) PoolStringArray_to_mono_array ( p_var . operator PoolStringArray ( ) ) ;
case Variant : : POOL_VECTOR2_ARRAY :
return ( MonoObject * ) PoolVector2Array_to_mono_array ( p_var . operator PoolVector2Array ( ) ) ;
2023-06-01 14:14:19 +02:00
case Variant : : POOL_VECTOR2I_ARRAY :
return ( MonoObject * ) PoolVector2iArray_to_mono_array ( p_var . operator PoolVector2iArray ( ) ) ;
2023-05-23 17:54:30 +02:00
case Variant : : POOL_VECTOR3_ARRAY :
return ( MonoObject * ) PoolVector3Array_to_mono_array ( p_var . operator PoolVector3Array ( ) ) ;
2023-06-01 14:14:19 +02:00
case Variant : : POOL_VECTOR3I_ARRAY :
return ( MonoObject * ) PoolVector3iArray_to_mono_array ( p_var . operator PoolVector3iArray ( ) ) ;
case Variant : : POOL_VECTOR4_ARRAY :
return ( MonoObject * ) PoolVector4Array_to_mono_array ( p_var . operator PoolVector4Array ( ) ) ;
case Variant : : POOL_VECTOR4I_ARRAY :
return ( MonoObject * ) PoolVector4iArray_to_mono_array ( p_var . operator PoolVector4iArray ( ) ) ;
2023-05-23 17:54:30 +02:00
case Variant : : POOL_COLOR_ARRAY :
return ( MonoObject * ) PoolColorArray_to_mono_array ( p_var . operator PoolColorArray ( ) ) ;
default :
return nullptr ;
}
}
size_t variant_get_managed_unboxed_size ( const ManagedType & p_type ) {
// This method prints no errors for unsupported types. It's called on all methods, not only
// those that end up being invoked with Variant parameters.
// For MonoObject* we return 0, as it doesn't need to be stored.
constexpr size_t zero_for_mono_object = 0 ;
switch ( p_type . type_encoding ) {
case MONO_TYPE_BOOLEAN :
return sizeof ( MonoBoolean ) ;
case MONO_TYPE_CHAR :
return sizeof ( uint16_t ) ;
case MONO_TYPE_I1 :
return sizeof ( int8_t ) ;
case MONO_TYPE_I2 :
return sizeof ( int16_t ) ;
case MONO_TYPE_I4 :
return sizeof ( int32_t ) ;
case MONO_TYPE_I8 :
return sizeof ( int64_t ) ;
case MONO_TYPE_U1 :
return sizeof ( uint8_t ) ;
case MONO_TYPE_U2 :
return sizeof ( uint16_t ) ;
case MONO_TYPE_U4 :
return sizeof ( uint32_t ) ;
case MONO_TYPE_U8 :
return sizeof ( uint64_t ) ;
case MONO_TYPE_R4 :
return sizeof ( float ) ;
case MONO_TYPE_R8 :
return sizeof ( double ) ;
case MONO_TYPE_VALUETYPE : {
GDMonoClass * vtclass = p_type . type_class ;
# define RETURN_CHECK_FOR_STRUCT(m_struct) \
if ( vtclass = = CACHED_CLASS ( m_struct ) ) { \
return sizeof ( M_ # # m_struct ) ; \
}
RETURN_CHECK_FOR_STRUCT ( Vector2 ) ;
RETURN_CHECK_FOR_STRUCT ( Rect2 ) ;
2023-06-01 14:14:19 +02:00
RETURN_CHECK_FOR_STRUCT ( Vector2i ) ;
RETURN_CHECK_FOR_STRUCT ( Rect2i ) ;
2023-05-23 17:54:30 +02:00
RETURN_CHECK_FOR_STRUCT ( Transform2D ) ;
RETURN_CHECK_FOR_STRUCT ( Vector3 ) ;
2023-06-01 14:14:19 +02:00
RETURN_CHECK_FOR_STRUCT ( Vector3i ) ;
RETURN_CHECK_FOR_STRUCT ( Vector4 ) ;
RETURN_CHECK_FOR_STRUCT ( Vector4i ) ;
2023-05-23 17:54:30 +02:00
RETURN_CHECK_FOR_STRUCT ( Basis ) ;
2023-05-23 20:55:56 +02:00
RETURN_CHECK_FOR_STRUCT ( Quaternion ) ;
2023-05-23 17:54:30 +02:00
RETURN_CHECK_FOR_STRUCT ( Transform ) ;
2023-06-01 14:14:19 +02:00
RETURN_CHECK_FOR_STRUCT ( Projection ) ;
2023-05-23 17:54:30 +02:00
RETURN_CHECK_FOR_STRUCT ( AABB ) ;
RETURN_CHECK_FOR_STRUCT ( Color ) ;
RETURN_CHECK_FOR_STRUCT ( Plane ) ;
# undef RETURN_CHECK_FOR_STRUCT
if ( mono_class_is_enum ( vtclass - > get_mono_ptr ( ) ) ) {
MonoType * enum_basetype = mono_class_enum_basetype ( vtclass - > get_mono_ptr ( ) ) ;
switch ( mono_type_get_type ( enum_basetype ) ) {
case MONO_TYPE_BOOLEAN :
return sizeof ( MonoBoolean ) ;
case MONO_TYPE_CHAR :
return sizeof ( uint16_t ) ;
case MONO_TYPE_I1 :
return sizeof ( int8_t ) ;
case MONO_TYPE_I2 :
return sizeof ( int16_t ) ;
case MONO_TYPE_I4 :
return sizeof ( int32_t ) ;
case MONO_TYPE_I8 :
return sizeof ( int64_t ) ;
case MONO_TYPE_U1 :
return sizeof ( uint8_t ) ;
case MONO_TYPE_U2 :
return sizeof ( uint16_t ) ;
case MONO_TYPE_U4 :
return sizeof ( uint32_t ) ;
case MONO_TYPE_U8 :
return sizeof ( uint64_t ) ;
default : {
// Enum with unsupported base type. We return nullptr MonoObject* on error.
return zero_for_mono_object ;
}
}
}
// Enum with unsupported value type. We return nullptr MonoObject* on error.
} break ;
case MONO_TYPE_STRING :
return zero_for_mono_object ;
case MONO_TYPE_ARRAY :
case MONO_TYPE_SZARRAY :
case MONO_TYPE_CLASS :
case MONO_TYPE_GENERICINST :
return zero_for_mono_object ;
case MONO_TYPE_OBJECT :
return zero_for_mono_object ;
}
// Unsupported type encoding. We return nullptr MonoObject* on error.
return zero_for_mono_object ;
}
void * variant_to_managed_unboxed ( const Variant & p_var , const ManagedType & p_type , void * r_buffer , unsigned int & r_offset ) {
# define RETURN_TYPE_VAL(m_type, m_val) \
* reinterpret_cast < m_type * > ( r_buffer ) = m_val ; \
r_offset + = sizeof ( m_type ) ; \
return r_buffer ;
switch ( p_type . type_encoding ) {
case MONO_TYPE_BOOLEAN :
RETURN_TYPE_VAL ( MonoBoolean , ( MonoBoolean ) p_var . operator bool ( ) ) ;
case MONO_TYPE_CHAR :
RETURN_TYPE_VAL ( uint16_t , p_var . operator unsigned short ( ) ) ;
case MONO_TYPE_I1 :
RETURN_TYPE_VAL ( int8_t , p_var . operator signed char ( ) ) ;
case MONO_TYPE_I2 :
RETURN_TYPE_VAL ( int16_t , p_var . operator signed short ( ) ) ;
case MONO_TYPE_I4 :
RETURN_TYPE_VAL ( int32_t , p_var . operator signed int ( ) ) ;
case MONO_TYPE_I8 :
RETURN_TYPE_VAL ( int64_t , p_var . operator int64_t ( ) ) ;
case MONO_TYPE_U1 :
RETURN_TYPE_VAL ( uint8_t , p_var . operator unsigned char ( ) ) ;
case MONO_TYPE_U2 :
RETURN_TYPE_VAL ( uint16_t , p_var . operator unsigned short ( ) ) ;
case MONO_TYPE_U4 :
RETURN_TYPE_VAL ( uint32_t , p_var . operator unsigned int ( ) ) ;
case MONO_TYPE_U8 :
RETURN_TYPE_VAL ( uint64_t , p_var . operator uint64_t ( ) ) ;
case MONO_TYPE_R4 :
RETURN_TYPE_VAL ( float , p_var . operator float ( ) ) ;
case MONO_TYPE_R8 :
RETURN_TYPE_VAL ( double , p_var . operator double ( ) ) ;
case MONO_TYPE_VALUETYPE : {
GDMonoClass * vtclass = p_type . type_class ;
# define RETURN_CHECK_FOR_STRUCT(m_struct) \
if ( vtclass = = CACHED_CLASS ( m_struct ) ) { \
GDMonoMarshal : : M_ # # m_struct from = MARSHALLED_OUT ( m_struct , p_var . operator : : m_struct ( ) ) ; \
RETURN_TYPE_VAL ( M_ # # m_struct , from ) ; \
}
RETURN_CHECK_FOR_STRUCT ( Vector2 ) ;
RETURN_CHECK_FOR_STRUCT ( Rect2 ) ;
2023-06-01 14:14:19 +02:00
RETURN_CHECK_FOR_STRUCT ( Vector2i ) ;
RETURN_CHECK_FOR_STRUCT ( Rect2i ) ;
2023-05-23 17:54:30 +02:00
RETURN_CHECK_FOR_STRUCT ( Transform2D ) ;
RETURN_CHECK_FOR_STRUCT ( Vector3 ) ;
2023-06-01 14:14:19 +02:00
RETURN_CHECK_FOR_STRUCT ( Vector3i ) ;
RETURN_CHECK_FOR_STRUCT ( Vector4 ) ;
RETURN_CHECK_FOR_STRUCT ( Vector4i ) ;
2023-05-23 17:54:30 +02:00
RETURN_CHECK_FOR_STRUCT ( Basis ) ;
2023-05-23 20:55:56 +02:00
RETURN_CHECK_FOR_STRUCT ( Quaternion ) ;
2023-05-23 17:54:30 +02:00
RETURN_CHECK_FOR_STRUCT ( Transform ) ;
2023-06-01 14:14:19 +02:00
RETURN_CHECK_FOR_STRUCT ( Projection ) ;
2023-05-23 17:54:30 +02:00
RETURN_CHECK_FOR_STRUCT ( AABB ) ;
RETURN_CHECK_FOR_STRUCT ( Color ) ;
RETURN_CHECK_FOR_STRUCT ( Plane ) ;
# undef RETURN_CHECK_FOR_STRUCT
if ( mono_class_is_enum ( vtclass - > get_mono_ptr ( ) ) ) {
MonoType * enum_basetype = mono_class_enum_basetype ( vtclass - > get_mono_ptr ( ) ) ;
switch ( mono_type_get_type ( enum_basetype ) ) {
case MONO_TYPE_BOOLEAN : {
MonoBoolean val = p_var . operator bool ( ) ;
RETURN_TYPE_VAL ( MonoBoolean , val ) ;
}
case MONO_TYPE_CHAR : {
uint16_t val = p_var . operator unsigned short ( ) ;
RETURN_TYPE_VAL ( uint16_t , val ) ;
}
case MONO_TYPE_I1 : {
int8_t val = p_var . operator signed char ( ) ;
RETURN_TYPE_VAL ( int8_t , val ) ;
}
case MONO_TYPE_I2 : {
int16_t val = p_var . operator signed short ( ) ;
RETURN_TYPE_VAL ( int16_t , val ) ;
}
case MONO_TYPE_I4 : {
int32_t val = p_var . operator signed int ( ) ;
RETURN_TYPE_VAL ( int32_t , val ) ;
}
case MONO_TYPE_I8 : {
int64_t val = p_var . operator int64_t ( ) ;
RETURN_TYPE_VAL ( int64_t , val ) ;
}
case MONO_TYPE_U1 : {
uint8_t val = p_var . operator unsigned char ( ) ;
RETURN_TYPE_VAL ( uint8_t , val ) ;
}
case MONO_TYPE_U2 : {
uint16_t val = p_var . operator unsigned short ( ) ;
RETURN_TYPE_VAL ( uint16_t , val ) ;
}
case MONO_TYPE_U4 : {
uint32_t val = p_var . operator unsigned int ( ) ;
RETURN_TYPE_VAL ( uint32_t , val ) ;
}
case MONO_TYPE_U8 : {
uint64_t val = p_var . operator uint64_t ( ) ;
RETURN_TYPE_VAL ( uint64_t , val ) ;
}
default : {
ERR_FAIL_V_MSG ( nullptr , " Attempted to convert Variant to enum value of unsupported base type: ' " + GDMonoClass : : get_full_name ( mono_class_from_mono_type ( enum_basetype ) ) + " '. " ) ;
}
}
}
ERR_FAIL_V_MSG ( nullptr , " Attempted to convert Variant to unsupported value type: ' " + p_type . type_class - > get_full_name ( ) + " '. " ) ;
} break ;
# undef RETURN_TYPE_VAL
case MONO_TYPE_STRING :
return variant_to_mono_string ( p_var ) ;
case MONO_TYPE_ARRAY :
case MONO_TYPE_SZARRAY :
return variant_to_mono_array ( p_var , p_type . type_class ) ;
case MONO_TYPE_CLASS :
return variant_to_mono_object_of_class ( p_var , p_type . type_class ) ;
case MONO_TYPE_GENERICINST :
return variant_to_mono_object_of_genericinst ( p_var , p_type . type_class ) ;
case MONO_TYPE_OBJECT :
return variant_to_mono_object ( p_var ) ;
}
ERR_FAIL_V_MSG ( nullptr , " Attempted to convert Variant to unsupported type with encoding: " + itos ( p_type . type_encoding ) + " . " ) ;
}
MonoObject * variant_to_mono_object ( const Variant & p_var , const ManagedType & p_type ) {
switch ( p_type . type_encoding ) {
case MONO_TYPE_BOOLEAN : {
MonoBoolean val = p_var . operator bool ( ) ;
return BOX_BOOLEAN ( val ) ;
}
case MONO_TYPE_CHAR : {
uint16_t val = p_var . operator unsigned short ( ) ;
return BOX_UINT16 ( val ) ;
}
case MONO_TYPE_I1 : {
int8_t val = p_var . operator signed char ( ) ;
return BOX_INT8 ( val ) ;
}
case MONO_TYPE_I2 : {
int16_t val = p_var . operator signed short ( ) ;
return BOX_INT16 ( val ) ;
}
case MONO_TYPE_I4 : {
int32_t val = p_var . operator signed int ( ) ;
return BOX_INT32 ( val ) ;
}
case MONO_TYPE_I8 : {
int64_t val = p_var . operator int64_t ( ) ;
return BOX_INT64 ( val ) ;
}
case MONO_TYPE_U1 : {
uint8_t val = p_var . operator unsigned char ( ) ;
return BOX_UINT8 ( val ) ;
}
case MONO_TYPE_U2 : {
uint16_t val = p_var . operator unsigned short ( ) ;
return BOX_UINT16 ( val ) ;
}
case MONO_TYPE_U4 : {
uint32_t val = p_var . operator unsigned int ( ) ;
return BOX_UINT32 ( val ) ;
}
case MONO_TYPE_U8 : {
uint64_t val = p_var . operator uint64_t ( ) ;
return BOX_UINT64 ( val ) ;
}
case MONO_TYPE_R4 : {
float val = p_var . operator float ( ) ;
return BOX_FLOAT ( val ) ;
}
case MONO_TYPE_R8 : {
double val = p_var . operator double ( ) ;
return BOX_DOUBLE ( val ) ;
}
case MONO_TYPE_VALUETYPE : {
GDMonoClass * vtclass = p_type . type_class ;
# define RETURN_CHECK_FOR_STRUCT(m_struct) \
if ( vtclass = = CACHED_CLASS ( m_struct ) ) { \
GDMonoMarshal : : M_ # # m_struct from = MARSHALLED_OUT ( m_struct , p_var . operator : : m_struct ( ) ) ; \
return mono_value_box ( mono_domain_get ( ) , CACHED_CLASS_RAW ( m_struct ) , & from ) ; \
}
RETURN_CHECK_FOR_STRUCT ( Vector2 ) ;
RETURN_CHECK_FOR_STRUCT ( Rect2 ) ;
2023-06-01 14:14:19 +02:00
RETURN_CHECK_FOR_STRUCT ( Vector2i ) ;
RETURN_CHECK_FOR_STRUCT ( Rect2i ) ;
2023-05-23 17:54:30 +02:00
RETURN_CHECK_FOR_STRUCT ( Transform2D ) ;
RETURN_CHECK_FOR_STRUCT ( Vector3 ) ;
2023-06-01 14:14:19 +02:00
RETURN_CHECK_FOR_STRUCT ( Vector3i ) ;
RETURN_CHECK_FOR_STRUCT ( Vector4 ) ;
RETURN_CHECK_FOR_STRUCT ( Vector4i ) ;
2023-05-23 17:54:30 +02:00
RETURN_CHECK_FOR_STRUCT ( Basis ) ;
2023-05-23 20:55:56 +02:00
RETURN_CHECK_FOR_STRUCT ( Quaternion ) ;
2023-05-23 17:54:30 +02:00
RETURN_CHECK_FOR_STRUCT ( Transform ) ;
2023-06-01 14:14:19 +02:00
RETURN_CHECK_FOR_STRUCT ( Projection ) ;
2023-05-23 17:54:30 +02:00
RETURN_CHECK_FOR_STRUCT ( AABB ) ;
RETURN_CHECK_FOR_STRUCT ( Color ) ;
RETURN_CHECK_FOR_STRUCT ( Plane ) ;
# undef RETURN_CHECK_FOR_STRUCT
if ( mono_class_is_enum ( vtclass - > get_mono_ptr ( ) ) ) {
MonoType * enum_basetype = mono_class_enum_basetype ( vtclass - > get_mono_ptr ( ) ) ;
MonoClass * enum_baseclass = mono_class_from_mono_type ( enum_basetype ) ;
switch ( mono_type_get_type ( enum_basetype ) ) {
case MONO_TYPE_BOOLEAN : {
MonoBoolean val = p_var . operator bool ( ) ;
return BOX_ENUM ( enum_baseclass , val ) ;
}
case MONO_TYPE_CHAR : {
uint16_t val = p_var . operator unsigned short ( ) ;
return BOX_ENUM ( enum_baseclass , val ) ;
}
case MONO_TYPE_I1 : {
int8_t val = p_var . operator signed char ( ) ;
return BOX_ENUM ( enum_baseclass , val ) ;
}
case MONO_TYPE_I2 : {
int16_t val = p_var . operator signed short ( ) ;
return BOX_ENUM ( enum_baseclass , val ) ;
}
case MONO_TYPE_I4 : {
int32_t val = p_var . operator signed int ( ) ;
return BOX_ENUM ( enum_baseclass , val ) ;
}
case MONO_TYPE_I8 : {
int64_t val = p_var . operator int64_t ( ) ;
return BOX_ENUM ( enum_baseclass , val ) ;
}
case MONO_TYPE_U1 : {
uint8_t val = p_var . operator unsigned char ( ) ;
return BOX_ENUM ( enum_baseclass , val ) ;
}
case MONO_TYPE_U2 : {
uint16_t val = p_var . operator unsigned short ( ) ;
return BOX_ENUM ( enum_baseclass , val ) ;
}
case MONO_TYPE_U4 : {
uint32_t val = p_var . operator unsigned int ( ) ;
return BOX_ENUM ( enum_baseclass , val ) ;
}
case MONO_TYPE_U8 : {
uint64_t val = p_var . operator uint64_t ( ) ;
return BOX_ENUM ( enum_baseclass , val ) ;
}
default : {
ERR_FAIL_V_MSG ( nullptr , " Attempted to convert Variant to enum value of unsupported base type: ' " + GDMonoClass : : get_full_name ( enum_baseclass ) + " '. " ) ;
}
}
}
ERR_FAIL_V_MSG ( nullptr , " Attempted to convert Variant to unsupported value type: ' " + p_type . type_class - > get_full_name ( ) + " '. " ) ;
} break ;
case MONO_TYPE_STRING :
return ( MonoObject * ) variant_to_mono_string ( p_var ) ;
case MONO_TYPE_ARRAY :
case MONO_TYPE_SZARRAY :
return ( MonoObject * ) variant_to_mono_array ( p_var , p_type . type_class ) ;
case MONO_TYPE_CLASS :
return variant_to_mono_object_of_class ( p_var , p_type . type_class ) ;
case MONO_TYPE_GENERICINST :
return variant_to_mono_object_of_genericinst ( p_var , p_type . type_class ) ;
case MONO_TYPE_OBJECT :
return variant_to_mono_object ( p_var ) ;
}
ERR_FAIL_V_MSG ( nullptr , " Attempted to convert Variant to unsupported type with encoding: " + itos ( p_type . type_encoding ) + " . " ) ;
}
Variant mono_object_to_variant_impl ( MonoObject * p_obj , const ManagedType & p_type , bool p_fail_with_err = true ) {
ERR_FAIL_COND_V ( ! p_type . type_class , Variant ( ) ) ;
# ifdef DEBUG_ENABLED
CRASH_COND_MSG ( p_type . type_encoding = = MONO_TYPE_OBJECT , " Type of object should be known. " ) ;
# endif
switch ( p_type . type_encoding ) {
case MONO_TYPE_BOOLEAN :
return ( bool ) unbox < MonoBoolean > ( p_obj ) ;
case MONO_TYPE_CHAR :
return unbox < uint16_t > ( p_obj ) ;
case MONO_TYPE_I1 :
return unbox < int8_t > ( p_obj ) ;
case MONO_TYPE_I2 :
return unbox < int16_t > ( p_obj ) ;
case MONO_TYPE_I4 :
return unbox < int32_t > ( p_obj ) ;
case MONO_TYPE_I8 :
return unbox < int64_t > ( p_obj ) ;
case MONO_TYPE_U1 :
return unbox < uint8_t > ( p_obj ) ;
case MONO_TYPE_U2 :
return unbox < uint16_t > ( p_obj ) ;
case MONO_TYPE_U4 :
return unbox < uint32_t > ( p_obj ) ;
case MONO_TYPE_U8 :
return unbox < uint64_t > ( p_obj ) ;
case MONO_TYPE_R4 :
return unbox < float > ( p_obj ) ;
case MONO_TYPE_R8 :
return unbox < double > ( p_obj ) ;
case MONO_TYPE_VALUETYPE : {
GDMonoClass * vtclass = p_type . type_class ;
2023-06-01 14:14:19 +02:00
if ( vtclass = = CACHED_CLASS ( Vector2 ) ) {
2023-05-23 17:54:30 +02:00
return MARSHALLED_IN ( Vector2 , unbox_addr < GDMonoMarshal : : M_Vector2 > ( p_obj ) ) ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( vtclass = = CACHED_CLASS ( Rect2 ) ) {
2023-05-23 17:54:30 +02:00
return MARSHALLED_IN ( Rect2 , unbox_addr < GDMonoMarshal : : M_Rect2 > ( p_obj ) ) ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( vtclass = = CACHED_CLASS ( Vector2i ) ) {
return MARSHALLED_IN ( Vector2i , unbox_addr < GDMonoMarshal : : M_Vector2i > ( p_obj ) ) ;
}
if ( vtclass = = CACHED_CLASS ( Rect2i ) ) {
return MARSHALLED_IN ( Rect2i , unbox_addr < GDMonoMarshal : : M_Rect2i > ( p_obj ) ) ;
}
if ( vtclass = = CACHED_CLASS ( Transform2D ) ) {
2023-05-23 17:54:30 +02:00
return MARSHALLED_IN ( Transform2D , unbox_addr < GDMonoMarshal : : M_Transform2D > ( p_obj ) ) ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( vtclass = = CACHED_CLASS ( Vector3 ) ) {
2023-05-23 17:54:30 +02:00
return MARSHALLED_IN ( Vector3 , unbox_addr < GDMonoMarshal : : M_Vector3 > ( p_obj ) ) ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( vtclass = = CACHED_CLASS ( Vector3i ) ) {
return MARSHALLED_IN ( Vector3i , unbox_addr < GDMonoMarshal : : M_Vector3i > ( p_obj ) ) ;
}
if ( vtclass = = CACHED_CLASS ( Vector4 ) ) {
return MARSHALLED_IN ( Vector4 , unbox_addr < GDMonoMarshal : : M_Vector4 > ( p_obj ) ) ;
}
if ( vtclass = = CACHED_CLASS ( Vector4i ) ) {
return MARSHALLED_IN ( Vector4i , unbox_addr < GDMonoMarshal : : M_Vector4i > ( p_obj ) ) ;
}
if ( vtclass = = CACHED_CLASS ( Basis ) ) {
2023-05-23 17:54:30 +02:00
return MARSHALLED_IN ( Basis , unbox_addr < GDMonoMarshal : : M_Basis > ( p_obj ) ) ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( vtclass = = CACHED_CLASS ( Quaternion ) ) {
2023-05-23 20:55:56 +02:00
return MARSHALLED_IN ( Quaternion , unbox_addr < GDMonoMarshal : : M_Quaternion > ( p_obj ) ) ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( vtclass = = CACHED_CLASS ( Transform ) ) {
2023-05-23 17:54:30 +02:00
return MARSHALLED_IN ( Transform , unbox_addr < GDMonoMarshal : : M_Transform > ( p_obj ) ) ;
2023-06-01 14:14:19 +02:00
}
if ( vtclass = = CACHED_CLASS ( Projection ) ) {
return MARSHALLED_IN ( Projection , unbox_addr < GDMonoMarshal : : M_Projection > ( p_obj ) ) ;
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( vtclass = = CACHED_CLASS ( AABB ) ) {
2023-05-23 17:54:30 +02:00
return MARSHALLED_IN ( AABB , unbox_addr < GDMonoMarshal : : M_AABB > ( p_obj ) ) ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( vtclass = = CACHED_CLASS ( Color ) ) {
2023-05-23 17:54:30 +02:00
return MARSHALLED_IN ( Color , unbox_addr < GDMonoMarshal : : M_Color > ( p_obj ) ) ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( vtclass = = CACHED_CLASS ( Plane ) ) {
2023-05-23 17:54:30 +02:00
return MARSHALLED_IN ( Plane , unbox_addr < GDMonoMarshal : : M_Plane > ( p_obj ) ) ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( mono_class_is_enum ( vtclass - > get_mono_ptr ( ) ) ) {
2023-05-23 17:54:30 +02:00
return unbox < int32_t > ( p_obj ) ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
} break ;
case MONO_TYPE_STRING : {
if ( p_obj = = NULL ) {
return Variant ( ) ; // NIL
}
return mono_string_to_godot_not_null ( ( MonoString * ) p_obj ) ;
} break ;
case MONO_TYPE_ARRAY :
case MONO_TYPE_SZARRAY : {
MonoArrayType * array_type = mono_type_get_array_type ( p_type . type_class - > get_mono_type ( ) ) ;
2023-06-01 14:14:19 +02:00
if ( array_type - > eklass = = CACHED_CLASS_RAW ( MonoObject ) ) {
2023-05-23 17:54:30 +02:00
return mono_array_to_Array ( ( MonoArray * ) p_obj ) ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( array_type - > eklass = = CACHED_CLASS_RAW ( uint8_t ) ) {
2023-05-23 17:54:30 +02:00
return mono_array_to_PoolByteArray ( ( MonoArray * ) p_obj ) ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( array_type - > eklass = = CACHED_CLASS_RAW ( int32_t ) ) {
2023-05-23 17:54:30 +02:00
return mono_array_to_PoolIntArray ( ( MonoArray * ) p_obj ) ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( array_type - > eklass = = REAL_T_MONOCLASS ) {
2023-05-23 17:54:30 +02:00
return mono_array_to_PoolRealArray ( ( MonoArray * ) p_obj ) ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( array_type - > eklass = = CACHED_CLASS_RAW ( String ) ) {
2023-05-23 17:54:30 +02:00
return mono_array_to_PoolStringArray ( ( MonoArray * ) p_obj ) ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( array_type - > eklass = = CACHED_CLASS_RAW ( Vector2 ) ) {
2023-05-23 17:54:30 +02:00
return mono_array_to_PoolVector2Array ( ( MonoArray * ) p_obj ) ;
2023-06-01 14:14:19 +02:00
}
if ( array_type - > eklass = = CACHED_CLASS_RAW ( Vector2i ) ) {
return mono_array_to_PoolVector2iArray ( ( MonoArray * ) p_obj ) ;
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( array_type - > eklass = = CACHED_CLASS_RAW ( Vector3 ) ) {
2023-05-23 17:54:30 +02:00
return mono_array_to_PoolVector3Array ( ( MonoArray * ) p_obj ) ;
2023-06-01 14:14:19 +02:00
}
if ( array_type - > eklass = = CACHED_CLASS_RAW ( Vector3i ) ) {
return mono_array_to_PoolVector3iArray ( ( MonoArray * ) p_obj ) ;
}
if ( array_type - > eklass = = CACHED_CLASS_RAW ( Vector4 ) ) {
return mono_array_to_PoolVector4Array ( ( MonoArray * ) p_obj ) ;
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( array_type - > eklass = = CACHED_CLASS_RAW ( Vector4i ) ) {
return mono_array_to_PoolVector4iArray ( ( MonoArray * ) p_obj ) ;
}
if ( array_type - > eklass = = CACHED_CLASS_RAW ( Color ) ) {
2023-05-23 17:54:30 +02:00
return mono_array_to_PoolColorArray ( ( MonoArray * ) p_obj ) ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( array_type - > eklass = = CACHED_CLASS_RAW ( NodePath ) ) {
2023-05-23 17:54:30 +02:00
return mono_array_to_Array ( ( MonoArray * ) p_obj ) ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
2023-06-01 14:14:19 +02:00
if ( array_type - > eklass = = CACHED_CLASS_RAW ( StringName ) ) {
2023-05-23 17:54:30 +02:00
return mono_array_to_Array ( ( MonoArray * ) p_obj ) ;
2023-06-01 14:14:19 +02:00
}
if ( array_type - > eklass = = CACHED_CLASS_RAW ( RID ) ) {
return mono_array_to_Array ( ( MonoArray * ) p_obj ) ;
}
2023-05-23 17:54:30 +02:00
GDMonoClass * array_type_class = GDMono : : get_singleton ( ) - > get_class ( array_type - > eklass ) ;
2023-06-01 14:14:19 +02:00
if ( CACHED_CLASS ( GodotObject ) - > is_assignable_from ( array_type_class ) ) {
2023-05-23 17:54:30 +02:00
return mono_array_to_Array ( ( MonoArray * ) p_obj ) ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
if ( p_fail_with_err ) {
ERR_FAIL_V_MSG ( Variant ( ) , " Attempted to convert a managed array of unmarshallable element type to Variant. " ) ;
} else {
return Variant ( ) ;
}
} break ;
case MONO_TYPE_CLASS : {
GDMonoClass * type_class = p_type . type_class ;
// GodotObject
if ( CACHED_CLASS ( GodotObject ) - > is_assignable_from ( type_class ) ) {
Object * ptr = unbox < Object * > ( CACHED_FIELD ( GodotObject , ptr ) - > get_value ( p_obj ) ) ;
if ( ptr ! = NULL ) {
Reference * ref = Object : : cast_to < Reference > ( ptr ) ;
return ref ? Variant ( Ref < Reference > ( ref ) ) : Variant ( ptr ) ;
}
return Variant ( ) ;
}
if ( CACHED_CLASS ( NodePath ) = = type_class ) {
NodePath * ptr = unbox < NodePath * > ( CACHED_FIELD ( NodePath , ptr ) - > get_value ( p_obj ) ) ;
return ptr ? Variant ( * ptr ) : Variant ( ) ;
}
2023-06-01 14:14:19 +02:00
if ( CACHED_CLASS ( StringName ) = = type_class ) {
StringName * ptr = unbox < StringName * > ( CACHED_FIELD ( StringName , ptr ) - > get_value ( p_obj ) ) ;
return ptr ? Variant ( * ptr ) : Variant ( ) ;
}
2023-05-23 17:54:30 +02:00
if ( CACHED_CLASS ( RID ) = = type_class ) {
RID * ptr = unbox < RID * > ( CACHED_FIELD ( RID , ptr ) - > get_value ( p_obj ) ) ;
return ptr ? Variant ( * ptr ) : Variant ( ) ;
}
// Godot.Collections.Dictionary
if ( CACHED_CLASS ( Dictionary ) = = type_class ) {
MonoException * exc = NULL ;
Dictionary * ptr = CACHED_METHOD_THUNK ( Dictionary , GetPtr ) . invoke ( p_obj , & exc ) ;
UNHANDLED_EXCEPTION ( exc ) ;
return ptr ? Variant ( * ptr ) : Variant ( ) ;
}
// Godot.Collections.Array
if ( CACHED_CLASS ( Array ) = = type_class ) {
MonoException * exc = NULL ;
Array * ptr = CACHED_METHOD_THUNK ( Array , GetPtr ) . invoke ( p_obj , & exc ) ;
UNHANDLED_EXCEPTION ( exc ) ;
return ptr ? Variant ( * ptr ) : Variant ( ) ;
}
} break ;
case MONO_TYPE_GENERICINST : {
MonoReflectionType * reftype = mono_type_get_object ( mono_domain_get ( ) , p_type . type_class - > get_mono_type ( ) ) ;
// Godot.Collections.Dictionary<TKey, TValue>
if ( GDMonoUtils : : Marshal : : type_is_generic_dictionary ( reftype ) ) {
MonoException * exc = NULL ;
MonoObject * ret = p_type . type_class - > get_method ( " GetPtr " ) - > invoke ( p_obj , & exc ) ;
UNHANDLED_EXCEPTION ( exc ) ;
return * unbox < Dictionary * > ( ret ) ;
}
// Godot.Collections.Array<T>
if ( GDMonoUtils : : Marshal : : type_is_generic_array ( reftype ) ) {
MonoException * exc = NULL ;
MonoObject * ret = p_type . type_class - > get_method ( " GetPtr " ) - > invoke ( p_obj , & exc ) ;
UNHANDLED_EXCEPTION ( exc ) ;
return * unbox < Array * > ( ret ) ;
}
// System.Collections.Generic.Dictionary<TKey, TValue>
if ( GDMonoUtils : : Marshal : : type_is_system_generic_dictionary ( reftype ) ) {
MonoReflectionType * key_reftype = nullptr ;
MonoReflectionType * value_reftype = nullptr ;
GDMonoUtils : : Marshal : : dictionary_get_key_value_types ( reftype , & key_reftype , & value_reftype ) ;
return system_generic_dict_to_Dictionary ( p_obj , p_type . type_class , key_reftype , value_reftype ) ;
}
// System.Collections.Generic.List<T>
if ( GDMonoUtils : : Marshal : : type_is_system_generic_list ( reftype ) ) {
MonoReflectionType * elem_reftype = nullptr ;
GDMonoUtils : : Marshal : : array_get_element_type ( reftype , & elem_reftype ) ;
return system_generic_list_to_Array_variant ( p_obj , p_type . type_class , elem_reftype ) ;
}
// GodotObject
GDMonoClass * type_class = p_type . type_class ;
if ( CACHED_CLASS ( GodotObject ) - > is_assignable_from ( type_class ) ) {
Object * ptr = unbox < Object * > ( CACHED_FIELD ( GodotObject , ptr ) - > get_value ( p_obj ) ) ;
if ( ptr ! = NULL ) {
Reference * ref = Object : : cast_to < Reference > ( ptr ) ;
return ref ? Variant ( Ref < Reference > ( ref ) ) : Variant ( ptr ) ;
}
return Variant ( ) ;
}
} break ;
}
if ( p_fail_with_err ) {
ERR_FAIL_V_MSG ( Variant ( ) , " Attempted to convert an unmarshallable managed type to Variant. Name: ' " + p_type . type_class - > get_name ( ) + " ' Encoding: " + itos ( p_type . type_encoding ) + " . " ) ;
} else {
return Variant ( ) ;
}
}
Variant mono_object_to_variant ( MonoObject * p_obj ) {
2023-06-01 14:14:19 +02:00
if ( ! p_obj ) {
2023-05-23 17:54:30 +02:00
return Variant ( ) ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
ManagedType type = ManagedType : : from_class ( mono_object_get_class ( p_obj ) ) ;
return mono_object_to_variant_impl ( p_obj , type ) ;
}
Variant mono_object_to_variant ( MonoObject * p_obj , const ManagedType & p_type ) {
2023-06-01 14:14:19 +02:00
if ( ! p_obj ) {
2023-05-23 17:54:30 +02:00
return Variant ( ) ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
return mono_object_to_variant_impl ( p_obj , p_type ) ;
}
Variant mono_object_to_variant_no_err ( MonoObject * p_obj , const ManagedType & p_type ) {
2023-06-01 14:14:19 +02:00
if ( ! p_obj ) {
2023-05-23 17:54:30 +02:00
return Variant ( ) ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
return mono_object_to_variant_impl ( p_obj , p_type , /* fail_with_err: */ false ) ;
}
String mono_object_to_variant_string ( MonoObject * p_obj , MonoException * * r_exc ) {
if ( p_obj = = nullptr ) {
return String ( " null " ) ;
}
ManagedType type = ManagedType : : from_class ( mono_object_get_class ( p_obj ) ) ;
Variant var = GDMonoMarshal : : mono_object_to_variant_no_err ( p_obj , type ) ;
if ( var . get_type ( ) = = Variant : : NIL ) { // `&& p_obj != NULL` but omitted because always true
// Cannot convert MonoObject* to Variant; fallback to 'ToString()'.
MonoException * exc = NULL ;
MonoString * mono_str = GDMonoUtils : : object_to_string ( p_obj , & exc ) ;
if ( exc ) {
2023-06-01 14:14:19 +02:00
if ( r_exc ) {
2023-05-23 17:54:30 +02:00
* r_exc = exc ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
return String ( ) ;
}
return GDMonoMarshal : : mono_string_to_godot ( mono_str ) ;
} else {
return var . operator String ( ) ;
}
}
MonoObject * Dictionary_to_system_generic_dict ( const Dictionary & p_dict , GDMonoClass * p_class , MonoReflectionType * p_key_reftype , MonoReflectionType * p_value_reftype ) {
String ctor_desc = " :.ctor(System.Collections.Generic.IDictionary`2< " + GDMonoUtils : : get_type_desc ( p_key_reftype ) +
" , " + GDMonoUtils : : get_type_desc ( p_value_reftype ) + " >) " ;
GDMonoMethod * ctor = p_class - > get_method_with_desc ( ctor_desc , true ) ;
CRASH_COND ( ctor = = nullptr ) ;
MonoObject * mono_object = mono_object_new ( mono_domain_get ( ) , p_class - > get_mono_ptr ( ) ) ;
ERR_FAIL_NULL_V ( mono_object , nullptr ) ;
GDMonoClass * godot_dict_class = GDMonoUtils : : Marshal : : make_generic_dictionary_type ( p_key_reftype , p_value_reftype ) ;
MonoObject * godot_dict = GDMonoUtils : : create_managed_from ( p_dict , godot_dict_class ) ;
void * ctor_args [ 1 ] = { godot_dict } ;
MonoException * exc = nullptr ;
ctor - > invoke_raw ( mono_object , ctor_args , & exc ) ;
UNHANDLED_EXCEPTION ( exc ) ;
return mono_object ;
}
Dictionary system_generic_dict_to_Dictionary ( MonoObject * p_obj , GDMonoClass * p_class , MonoReflectionType * p_key_reftype , MonoReflectionType * p_value_reftype ) {
GDMonoClass * godot_dict_class = GDMonoUtils : : Marshal : : make_generic_dictionary_type ( p_key_reftype , p_value_reftype ) ;
String ctor_desc = " :.ctor(System.Collections.Generic.IDictionary`2< " + GDMonoUtils : : get_type_desc ( p_key_reftype ) +
" , " + GDMonoUtils : : get_type_desc ( p_value_reftype ) + " >) " ;
GDMonoMethod * godot_dict_ctor = godot_dict_class - > get_method_with_desc ( ctor_desc , true ) ;
CRASH_COND ( godot_dict_ctor = = nullptr ) ;
MonoObject * godot_dict = mono_object_new ( mono_domain_get ( ) , godot_dict_class - > get_mono_ptr ( ) ) ;
ERR_FAIL_NULL_V ( godot_dict , Dictionary ( ) ) ;
void * ctor_args [ 1 ] = { p_obj } ;
MonoException * exc = nullptr ;
godot_dict_ctor - > invoke_raw ( godot_dict , ctor_args , & exc ) ;
UNHANDLED_EXCEPTION ( exc ) ;
exc = nullptr ;
MonoObject * ret = godot_dict_class - > get_method ( " GetPtr " ) - > invoke ( godot_dict , & exc ) ;
UNHANDLED_EXCEPTION ( exc ) ;
return * unbox < Dictionary * > ( ret ) ;
}
MonoObject * Array_to_system_generic_list ( const Array & p_array , GDMonoClass * p_class , MonoReflectionType * p_elem_reftype ) {
MonoType * elem_type = mono_reflection_type_get_type ( p_elem_reftype ) ;
String ctor_desc = " :.ctor(System.Collections.Generic.IEnumerable`1< " + GDMonoUtils : : get_type_desc ( elem_type ) + " >) " ;
GDMonoMethod * ctor = p_class - > get_method_with_desc ( ctor_desc , true ) ;
CRASH_COND ( ctor = = nullptr ) ;
MonoObject * mono_object = mono_object_new ( mono_domain_get ( ) , p_class - > get_mono_ptr ( ) ) ;
ERR_FAIL_NULL_V ( mono_object , nullptr ) ;
GDMonoClass * godot_array_class = GDMonoUtils : : Marshal : : make_generic_array_type ( p_elem_reftype ) ;
MonoObject * godot_array = GDMonoUtils : : create_managed_from ( p_array , godot_array_class ) ;
void * ctor_args [ 1 ] = { godot_array } ;
MonoException * exc = nullptr ;
ctor - > invoke_raw ( mono_object , ctor_args , & exc ) ;
UNHANDLED_EXCEPTION ( exc ) ;
return mono_object ;
}
Variant system_generic_list_to_Array_variant ( MonoObject * p_obj , GDMonoClass * p_class , MonoReflectionType * p_elem_reftype ) {
GDMonoMethod * to_array = p_class - > get_method ( " ToArray " , 0 ) ;
CRASH_COND ( to_array = = nullptr ) ;
MonoException * exc = nullptr ;
MonoObject * array = to_array - > invoke_raw ( p_obj , nullptr , & exc ) ;
UNHANDLED_EXCEPTION ( exc ) ;
ERR_FAIL_NULL_V ( array , Variant ( ) ) ;
ManagedType type = ManagedType : : from_class ( mono_object_get_class ( array ) ) ;
bool result_is_array = type . type_encoding ! = MONO_TYPE_SZARRAY & & type . type_encoding ! = MONO_TYPE_ARRAY ;
ERR_FAIL_COND_V ( result_is_array , Variant ( ) ) ;
return mono_object_to_variant ( array , type ) ;
}
MonoArray * Array_to_mono_array ( const Array & p_array ) {
int length = p_array . size ( ) ;
MonoArray * ret = mono_array_new ( mono_domain_get ( ) , CACHED_CLASS_RAW ( MonoObject ) , length ) ;
for ( int i = 0 ; i < length ; i + + ) {
MonoObject * boxed = variant_to_mono_object ( p_array [ i ] ) ;
mono_array_setref ( ret , i , boxed ) ;
}
return ret ;
}
MonoArray * Array_to_mono_array ( const Array & p_array , MonoClass * p_array_type_class ) {
int length = p_array . size ( ) ;
MonoArray * ret = mono_array_new ( mono_domain_get ( ) , p_array_type_class , length ) ;
for ( int i = 0 ; i < length ; i + + ) {
MonoObject * boxed = variant_to_mono_object ( p_array [ i ] ) ;
mono_array_setref ( ret , i , boxed ) ;
}
return ret ;
}
Array mono_array_to_Array ( MonoArray * p_array ) {
Array ret ;
2023-06-01 14:14:19 +02:00
if ( ! p_array ) {
2023-05-23 17:54:30 +02:00
return ret ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
int length = mono_array_length ( p_array ) ;
ret . resize ( length ) ;
for ( int i = 0 ; i < length ; i + + ) {
MonoObject * elem = mono_array_get ( p_array , MonoObject * , i ) ;
ret [ i ] = mono_object_to_variant ( elem ) ;
}
return ret ;
}
// TODO: Use memcpy where possible
MonoArray * PoolIntArray_to_mono_array ( const PoolIntArray & p_array ) {
PoolIntArray : : Read r = p_array . read ( ) ;
MonoArray * ret = mono_array_new ( mono_domain_get ( ) , CACHED_CLASS_RAW ( int32_t ) , p_array . size ( ) ) ;
for ( int i = 0 ; i < p_array . size ( ) ; i + + ) {
mono_array_set ( ret , int32_t , i , r [ i ] ) ;
}
return ret ;
}
PoolIntArray mono_array_to_PoolIntArray ( MonoArray * p_array ) {
PoolIntArray ret ;
2023-06-01 14:14:19 +02:00
if ( ! p_array ) {
2023-05-23 17:54:30 +02:00
return ret ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
int length = mono_array_length ( p_array ) ;
ret . resize ( length ) ;
PoolIntArray : : Write w = ret . write ( ) ;
for ( int i = 0 ; i < length ; i + + ) {
w [ i ] = mono_array_get ( p_array , int32_t , i ) ;
}
return ret ;
}
MonoArray * PoolByteArray_to_mono_array ( const PoolByteArray & p_array ) {
PoolByteArray : : Read r = p_array . read ( ) ;
MonoArray * ret = mono_array_new ( mono_domain_get ( ) , CACHED_CLASS_RAW ( uint8_t ) , p_array . size ( ) ) ;
for ( int i = 0 ; i < p_array . size ( ) ; i + + ) {
mono_array_set ( ret , uint8_t , i , r [ i ] ) ;
}
return ret ;
}
PoolByteArray mono_array_to_PoolByteArray ( MonoArray * p_array ) {
PoolByteArray ret ;
2023-06-01 14:14:19 +02:00
if ( ! p_array ) {
2023-05-23 17:54:30 +02:00
return ret ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
int length = mono_array_length ( p_array ) ;
ret . resize ( length ) ;
PoolByteArray : : Write w = ret . write ( ) ;
for ( int i = 0 ; i < length ; i + + ) {
w [ i ] = mono_array_get ( p_array , uint8_t , i ) ;
}
return ret ;
}
MonoArray * PoolRealArray_to_mono_array ( const PoolRealArray & p_array ) {
PoolRealArray : : Read r = p_array . read ( ) ;
MonoArray * ret = mono_array_new ( mono_domain_get ( ) , REAL_T_MONOCLASS , p_array . size ( ) ) ;
for ( int i = 0 ; i < p_array . size ( ) ; i + + ) {
mono_array_set ( ret , real_t , i , r [ i ] ) ;
}
return ret ;
}
PoolRealArray mono_array_to_PoolRealArray ( MonoArray * p_array ) {
PoolRealArray ret ;
2023-06-01 14:14:19 +02:00
if ( ! p_array ) {
2023-05-23 17:54:30 +02:00
return ret ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
int length = mono_array_length ( p_array ) ;
ret . resize ( length ) ;
PoolRealArray : : Write w = ret . write ( ) ;
for ( int i = 0 ; i < length ; i + + ) {
w [ i ] = mono_array_get ( p_array , real_t , i ) ;
}
return ret ;
}
MonoArray * PoolStringArray_to_mono_array ( const PoolStringArray & p_array ) {
PoolStringArray : : Read r = p_array . read ( ) ;
MonoArray * ret = mono_array_new ( mono_domain_get ( ) , CACHED_CLASS_RAW ( String ) , p_array . size ( ) ) ;
for ( int i = 0 ; i < p_array . size ( ) ; i + + ) {
MonoString * boxed = mono_string_from_godot ( r [ i ] ) ;
mono_array_setref ( ret , i , boxed ) ;
}
return ret ;
}
PoolStringArray mono_array_to_PoolStringArray ( MonoArray * p_array ) {
PoolStringArray ret ;
2023-06-01 14:14:19 +02:00
if ( ! p_array ) {
2023-05-23 17:54:30 +02:00
return ret ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
int length = mono_array_length ( p_array ) ;
ret . resize ( length ) ;
PoolStringArray : : Write w = ret . write ( ) ;
for ( int i = 0 ; i < length ; i + + ) {
MonoString * elem = mono_array_get ( p_array , MonoString * , i ) ;
w [ i ] = mono_string_to_godot ( elem ) ;
}
return ret ;
}
MonoArray * PoolColorArray_to_mono_array ( const PoolColorArray & p_array ) {
PoolColorArray : : Read r = p_array . read ( ) ;
MonoArray * ret = mono_array_new ( mono_domain_get ( ) , CACHED_CLASS_RAW ( Color ) , p_array . size ( ) ) ;
for ( int i = 0 ; i < p_array . size ( ) ; i + + ) {
M_Color * raw = ( M_Color * ) mono_array_addr_with_size ( ret , sizeof ( M_Color ) , i ) ;
* raw = MARSHALLED_OUT ( Color , r [ i ] ) ;
}
return ret ;
}
PoolColorArray mono_array_to_PoolColorArray ( MonoArray * p_array ) {
PoolColorArray ret ;
2023-06-01 14:14:19 +02:00
if ( ! p_array ) {
2023-05-23 17:54:30 +02:00
return ret ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
int length = mono_array_length ( p_array ) ;
ret . resize ( length ) ;
PoolColorArray : : Write w = ret . write ( ) ;
for ( int i = 0 ; i < length ; i + + ) {
w [ i ] = MARSHALLED_IN ( Color , ( M_Color * ) mono_array_addr_with_size ( p_array , sizeof ( M_Color ) , i ) ) ;
}
return ret ;
}
MonoArray * PoolVector2Array_to_mono_array ( const PoolVector2Array & p_array ) {
PoolVector2Array : : Read r = p_array . read ( ) ;
MonoArray * ret = mono_array_new ( mono_domain_get ( ) , CACHED_CLASS_RAW ( Vector2 ) , p_array . size ( ) ) ;
for ( int i = 0 ; i < p_array . size ( ) ; i + + ) {
M_Vector2 * raw = ( M_Vector2 * ) mono_array_addr_with_size ( ret , sizeof ( M_Vector2 ) , i ) ;
* raw = MARSHALLED_OUT ( Vector2 , r [ i ] ) ;
}
return ret ;
}
PoolVector2Array mono_array_to_PoolVector2Array ( MonoArray * p_array ) {
PoolVector2Array ret ;
2023-06-01 14:14:19 +02:00
if ( ! p_array ) {
2023-05-23 17:54:30 +02:00
return ret ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
int length = mono_array_length ( p_array ) ;
ret . resize ( length ) ;
PoolVector2Array : : Write w = ret . write ( ) ;
for ( int i = 0 ; i < length ; i + + ) {
w [ i ] = MARSHALLED_IN ( Vector2 , ( M_Vector2 * ) mono_array_addr_with_size ( p_array , sizeof ( M_Vector2 ) , i ) ) ;
}
return ret ;
}
2023-06-01 14:14:19 +02:00
MonoArray * PoolVector2iArray_to_mono_array ( const PoolVector2iArray & p_array ) {
PoolVector2iArray : : Read r = p_array . read ( ) ;
MonoArray * ret = mono_array_new ( mono_domain_get ( ) , CACHED_CLASS_RAW ( Vector2i ) , p_array . size ( ) ) ;
for ( int i = 0 ; i < p_array . size ( ) ; i + + ) {
M_Vector2i * raw = ( M_Vector2i * ) mono_array_addr_with_size ( ret , sizeof ( M_Vector2i ) , i ) ;
* raw = MARSHALLED_OUT ( Vector2i , r [ i ] ) ;
}
return ret ;
}
PoolVector2iArray mono_array_to_PoolVector2iArray ( MonoArray * p_array ) {
PoolVector2iArray ret ;
if ( ! p_array ) {
return ret ;
}
int length = mono_array_length ( p_array ) ;
ret . resize ( length ) ;
PoolVector2iArray : : Write w = ret . write ( ) ;
for ( int i = 0 ; i < length ; i + + ) {
w [ i ] = MARSHALLED_IN ( Vector2i , ( M_Vector2i * ) mono_array_addr_with_size ( p_array , sizeof ( M_Vector2i ) , i ) ) ;
}
return ret ;
}
2023-05-23 17:54:30 +02:00
MonoArray * PoolVector3Array_to_mono_array ( const PoolVector3Array & p_array ) {
PoolVector3Array : : Read r = p_array . read ( ) ;
MonoArray * ret = mono_array_new ( mono_domain_get ( ) , CACHED_CLASS_RAW ( Vector3 ) , p_array . size ( ) ) ;
for ( int i = 0 ; i < p_array . size ( ) ; i + + ) {
M_Vector3 * raw = ( M_Vector3 * ) mono_array_addr_with_size ( ret , sizeof ( M_Vector3 ) , i ) ;
* raw = MARSHALLED_OUT ( Vector3 , r [ i ] ) ;
}
return ret ;
}
PoolVector3Array mono_array_to_PoolVector3Array ( MonoArray * p_array ) {
PoolVector3Array ret ;
2023-06-01 14:14:19 +02:00
if ( ! p_array ) {
2023-05-23 17:54:30 +02:00
return ret ;
2023-06-01 14:14:19 +02:00
}
2023-05-23 17:54:30 +02:00
int length = mono_array_length ( p_array ) ;
ret . resize ( length ) ;
PoolVector3Array : : Write w = ret . write ( ) ;
for ( int i = 0 ; i < length ; i + + ) {
w [ i ] = MARSHALLED_IN ( Vector3 , ( M_Vector3 * ) mono_array_addr_with_size ( p_array , sizeof ( M_Vector3 ) , i ) ) ;
}
return ret ;
}
2023-06-01 14:14:19 +02:00
MonoArray * PoolVector3iArray_to_mono_array ( const PoolVector3iArray & p_array ) {
PoolVector3iArray : : Read r = p_array . read ( ) ;
MonoArray * ret = mono_array_new ( mono_domain_get ( ) , CACHED_CLASS_RAW ( Vector3i ) , p_array . size ( ) ) ;
for ( int i = 0 ; i < p_array . size ( ) ; i + + ) {
M_Vector3i * raw = ( M_Vector3i * ) mono_array_addr_with_size ( ret , sizeof ( M_Vector3i ) , i ) ;
* raw = MARSHALLED_OUT ( Vector3i , r [ i ] ) ;
}
return ret ;
}
PoolVector3iArray mono_array_to_PoolVector3iArray ( MonoArray * p_array ) {
PoolVector3iArray ret ;
if ( ! p_array ) {
return ret ;
}
int length = mono_array_length ( p_array ) ;
ret . resize ( length ) ;
PoolVector3iArray : : Write w = ret . write ( ) ;
for ( int i = 0 ; i < length ; i + + ) {
w [ i ] = MARSHALLED_IN ( Vector3i , ( M_Vector3i * ) mono_array_addr_with_size ( p_array , sizeof ( M_Vector3i ) , i ) ) ;
}
return ret ;
}
MonoArray * PoolVector4Array_to_mono_array ( const PoolVector4Array & p_array ) {
PoolVector4Array : : Read r = p_array . read ( ) ;
MonoArray * ret = mono_array_new ( mono_domain_get ( ) , CACHED_CLASS_RAW ( Vector4 ) , p_array . size ( ) ) ;
for ( int i = 0 ; i < p_array . size ( ) ; i + + ) {
M_Vector4 * raw = ( M_Vector4 * ) mono_array_addr_with_size ( ret , sizeof ( M_Vector4 ) , i ) ;
* raw = MARSHALLED_OUT ( Vector4 , r [ i ] ) ;
}
return ret ;
}
PoolVector4Array mono_array_to_PoolVector4Array ( MonoArray * p_array ) {
PoolVector4Array ret ;
if ( ! p_array ) {
return ret ;
}
int length = mono_array_length ( p_array ) ;
ret . resize ( length ) ;
PoolVector4Array : : Write w = ret . write ( ) ;
for ( int i = 0 ; i < length ; i + + ) {
w [ i ] = MARSHALLED_IN ( Vector4 , ( M_Vector4 * ) mono_array_addr_with_size ( p_array , sizeof ( M_Vector4 ) , i ) ) ;
}
return ret ;
}
MonoArray * PoolVector4iArray_to_mono_array ( const PoolVector4iArray & p_array ) {
PoolVector4iArray : : Read r = p_array . read ( ) ;
MonoArray * ret = mono_array_new ( mono_domain_get ( ) , CACHED_CLASS_RAW ( Vector4i ) , p_array . size ( ) ) ;
for ( int i = 0 ; i < p_array . size ( ) ; i + + ) {
M_Vector4i * raw = ( M_Vector4i * ) mono_array_addr_with_size ( ret , sizeof ( M_Vector4i ) , i ) ;
* raw = MARSHALLED_OUT ( Vector4i , r [ i ] ) ;
}
return ret ;
}
PoolVector4iArray mono_array_to_PoolVector4iArray ( MonoArray * p_array ) {
PoolVector4iArray ret ;
if ( ! p_array ) {
return ret ;
}
int length = mono_array_length ( p_array ) ;
ret . resize ( length ) ;
PoolVector4iArray : : Write w = ret . write ( ) ;
for ( int i = 0 ; i < length ; i + + ) {
w [ i ] = MARSHALLED_IN ( Vector4i , ( M_Vector4i * ) mono_array_addr_with_size ( p_array , sizeof ( M_Vector4i ) , i ) ) ;
}
return ret ;
}
2023-05-23 17:54:30 +02:00
} // namespace GDMonoMarshal