Merge pull request #34750 from neikeq/issue-18969
Mono/C#: Make 'GD.Print' and its variants fallback to 'ToString()'
This commit is contained in:
commit
1c88ee6c96
3 changed files with 153 additions and 33 deletions
|
@ -71,48 +71,114 @@ MonoObject *godot_icall_GD_instance_from_id(uint64_t p_instance_id) {
|
|||
}
|
||||
|
||||
void godot_icall_GD_print(MonoArray *p_what) {
|
||||
Array what = GDMonoMarshal::mono_array_to_Array(p_what);
|
||||
String str;
|
||||
for (int i = 0; i < what.size(); i++)
|
||||
str += what[i].operator String();
|
||||
int length = mono_array_length(p_what);
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
MonoObject *elem = mono_array_get(p_what, MonoObject *, i);
|
||||
|
||||
MonoException *exc = NULL;
|
||||
String elem_str = GDMonoMarshal::mono_object_to_variant_string(elem, &exc);
|
||||
|
||||
if (exc) {
|
||||
GDMonoUtils::set_pending_exception(exc);
|
||||
return;
|
||||
}
|
||||
|
||||
str += elem_str;
|
||||
}
|
||||
|
||||
print_line(str);
|
||||
}
|
||||
|
||||
void godot_icall_GD_printerr(MonoArray *p_what) {
|
||||
Array what = GDMonoMarshal::mono_array_to_Array(p_what);
|
||||
|
||||
String str;
|
||||
for (int i = 0; i < what.size(); i++)
|
||||
str += what[i].operator String();
|
||||
int length = mono_array_length(p_what);
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
MonoObject *elem = mono_array_get(p_what, MonoObject *, i);
|
||||
|
||||
MonoException *exc = NULL;
|
||||
String elem_str = GDMonoMarshal::mono_object_to_variant_string(elem, &exc);
|
||||
|
||||
if (exc) {
|
||||
GDMonoUtils::set_pending_exception(exc);
|
||||
return;
|
||||
}
|
||||
|
||||
str += elem_str;
|
||||
}
|
||||
|
||||
print_error(str);
|
||||
}
|
||||
|
||||
void godot_icall_GD_printraw(MonoArray *p_what) {
|
||||
Array what = GDMonoMarshal::mono_array_to_Array(p_what);
|
||||
String str;
|
||||
for (int i = 0; i < what.size(); i++)
|
||||
str += what[i].operator String();
|
||||
int length = mono_array_length(p_what);
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
MonoObject *elem = mono_array_get(p_what, MonoObject *, i);
|
||||
|
||||
MonoException *exc = NULL;
|
||||
String elem_str = GDMonoMarshal::mono_object_to_variant_string(elem, &exc);
|
||||
|
||||
if (exc) {
|
||||
GDMonoUtils::set_pending_exception(exc);
|
||||
return;
|
||||
}
|
||||
|
||||
str += elem_str;
|
||||
}
|
||||
|
||||
OS::get_singleton()->print("%s", str.utf8().get_data());
|
||||
}
|
||||
|
||||
void godot_icall_GD_prints(MonoArray *p_what) {
|
||||
Array what = GDMonoMarshal::mono_array_to_Array(p_what);
|
||||
String str;
|
||||
for (int i = 0; i < what.size(); i++) {
|
||||
int length = mono_array_length(p_what);
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
MonoObject *elem = mono_array_get(p_what, MonoObject *, i);
|
||||
|
||||
MonoException *exc = NULL;
|
||||
String elem_str = GDMonoMarshal::mono_object_to_variant_string(elem, &exc);
|
||||
|
||||
if (exc) {
|
||||
GDMonoUtils::set_pending_exception(exc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (i)
|
||||
str += " ";
|
||||
str += what[i].operator String();
|
||||
|
||||
str += elem_str;
|
||||
}
|
||||
|
||||
print_line(str);
|
||||
}
|
||||
|
||||
void godot_icall_GD_printt(MonoArray *p_what) {
|
||||
Array what = GDMonoMarshal::mono_array_to_Array(p_what);
|
||||
String str;
|
||||
for (int i = 0; i < what.size(); i++) {
|
||||
int length = mono_array_length(p_what);
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
MonoObject *elem = mono_array_get(p_what, MonoObject *, i);
|
||||
|
||||
MonoException *exc = NULL;
|
||||
String elem_str = GDMonoMarshal::mono_object_to_variant_string(elem, &exc);
|
||||
|
||||
if (exc) {
|
||||
GDMonoUtils::set_pending_exception(exc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (i)
|
||||
str += "\t";
|
||||
str += what[i].operator String();
|
||||
|
||||
str += elem_str;
|
||||
}
|
||||
|
||||
print_line(str);
|
||||
}
|
||||
|
||||
|
|
|
@ -700,15 +700,11 @@ MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_ty
|
|||
p_type.type_class->get_name() + "' Encoding: " + itos(p_type.type_encoding) + ".");
|
||||
}
|
||||
|
||||
Variant mono_object_to_variant(MonoObject *p_obj) {
|
||||
if (!p_obj)
|
||||
return Variant();
|
||||
Variant mono_object_to_variant_impl(MonoObject *p_obj, const ManagedType &p_type, bool p_fail_with_err = true) {
|
||||
|
||||
ManagedType type = ManagedType::from_class(mono_object_get_class(p_obj));
|
||||
ERR_FAIL_COND_V(!p_type.type_class, Variant());
|
||||
|
||||
ERR_FAIL_COND_V(!type.type_class, Variant());
|
||||
|
||||
switch (type.type_encoding) {
|
||||
switch (p_type.type_encoding) {
|
||||
case MONO_TYPE_BOOLEAN:
|
||||
return (bool)unbox<MonoBoolean>(p_obj);
|
||||
|
||||
|
@ -745,7 +741,7 @@ Variant mono_object_to_variant(MonoObject *p_obj) {
|
|||
} break;
|
||||
|
||||
case MONO_TYPE_VALUETYPE: {
|
||||
GDMonoClass *vtclass = type.type_class;
|
||||
GDMonoClass *vtclass = p_type.type_class;
|
||||
|
||||
if (vtclass == CACHED_CLASS(Vector2))
|
||||
return MARSHALLED_IN(Vector2, (GDMonoMarshal::M_Vector2 *)mono_object_unbox(p_obj));
|
||||
|
@ -783,7 +779,7 @@ Variant mono_object_to_variant(MonoObject *p_obj) {
|
|||
|
||||
case MONO_TYPE_ARRAY:
|
||||
case MONO_TYPE_SZARRAY: {
|
||||
MonoArrayType *array_type = mono_type_get_array_type(type.type_class->get_mono_type());
|
||||
MonoArrayType *array_type = mono_type_get_array_type(p_type.type_class->get_mono_type());
|
||||
|
||||
if (array_type->eklass == CACHED_CLASS_RAW(MonoObject))
|
||||
return mono_array_to_Array((MonoArray *)p_obj);
|
||||
|
@ -809,11 +805,15 @@ Variant mono_object_to_variant(MonoObject *p_obj) {
|
|||
if (array_type->eklass == CACHED_CLASS_RAW(Color))
|
||||
return mono_array_to_PoolColorArray((MonoArray *)p_obj);
|
||||
|
||||
ERR_FAIL_V_MSG(Variant(), "Attempted to convert a managed array of unmarshallable element type to Variant.");
|
||||
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 = type.type_class;
|
||||
GDMonoClass *type_class = p_type.type_class;
|
||||
|
||||
// GodotObject
|
||||
if (CACHED_CLASS(GodotObject)->is_assignable_from(type_class)) {
|
||||
|
@ -871,18 +871,18 @@ Variant mono_object_to_variant(MonoObject *p_obj) {
|
|||
} break;
|
||||
|
||||
case MONO_TYPE_GENERICINST: {
|
||||
MonoReflectionType *reftype = mono_type_get_object(mono_domain_get(), type.type_class->get_mono_type());
|
||||
MonoReflectionType *reftype = mono_type_get_object(mono_domain_get(), p_type.type_class->get_mono_type());
|
||||
|
||||
if (GDMonoUtils::Marshal::type_is_generic_dictionary(reftype)) {
|
||||
MonoException *exc = NULL;
|
||||
MonoObject *ret = type.type_class->get_method("GetPtr")->invoke(p_obj, &exc);
|
||||
MonoObject *ret = p_type.type_class->get_method("GetPtr")->invoke(p_obj, &exc);
|
||||
UNHANDLED_EXCEPTION(exc);
|
||||
return *unbox<Dictionary *>(ret);
|
||||
}
|
||||
|
||||
if (GDMonoUtils::Marshal::type_is_generic_array(reftype)) {
|
||||
MonoException *exc = NULL;
|
||||
MonoObject *ret = type.type_class->get_method("GetPtr")->invoke(p_obj, &exc);
|
||||
MonoObject *ret = p_type.type_class->get_method("GetPtr")->invoke(p_obj, &exc);
|
||||
UNHANDLED_EXCEPTION(exc);
|
||||
return *unbox<Array *>(ret);
|
||||
}
|
||||
|
@ -893,7 +893,7 @@ Variant mono_object_to_variant(MonoObject *p_obj) {
|
|||
return GDMonoUtils::Marshal::generic_idictionary_to_dictionary(p_obj);
|
||||
}
|
||||
|
||||
if (type.type_class->implements_interface(CACHED_CLASS(System_Collections_IDictionary))) {
|
||||
if (p_type.type_class->implements_interface(CACHED_CLASS(System_Collections_IDictionary))) {
|
||||
return GDMonoUtils::Marshal::idictionary_to_dictionary(p_obj);
|
||||
}
|
||||
|
||||
|
@ -901,14 +901,62 @@ Variant mono_object_to_variant(MonoObject *p_obj) {
|
|||
return GDMonoUtils::Marshal::enumerable_to_array(p_obj);
|
||||
}
|
||||
|
||||
if (type.type_class->implements_interface(CACHED_CLASS(System_Collections_IEnumerable))) {
|
||||
if (p_type.type_class->implements_interface(CACHED_CLASS(System_Collections_IEnumerable))) {
|
||||
return GDMonoUtils::Marshal::enumerable_to_array(p_obj);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
ERR_FAIL_V_MSG(Variant(), "Attempted to convert an unmarshallable managed type to Variant. Name: '" +
|
||||
type.type_class->get_name() + "' Encoding: " + itos(type.type_encoding) + ".");
|
||||
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) {
|
||||
if (!p_obj)
|
||||
return Variant();
|
||||
|
||||
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) {
|
||||
if (!p_obj)
|
||||
return Variant();
|
||||
|
||||
return mono_object_to_variant_impl(p_obj, p_type);
|
||||
}
|
||||
|
||||
Variant mono_object_to_variant_no_err(MonoObject *p_obj, const ManagedType &p_type) {
|
||||
if (!p_obj)
|
||||
return Variant();
|
||||
|
||||
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) {
|
||||
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) {
|
||||
// Cannot convert MonoObject* to Variant; fallback to 'ToString()'.
|
||||
MonoException *exc = NULL;
|
||||
MonoString *mono_str = GDMonoUtils::object_to_string(p_obj, &exc);
|
||||
|
||||
if (exc) {
|
||||
if (r_exc)
|
||||
*r_exc = exc;
|
||||
return String();
|
||||
}
|
||||
|
||||
return GDMonoMarshal::mono_string_to_godot(mono_str);
|
||||
} else {
|
||||
return var.operator String();
|
||||
}
|
||||
}
|
||||
|
||||
MonoArray *Array_to_mono_array(const Array &p_array) {
|
||||
|
|
|
@ -115,6 +115,12 @@ _FORCE_INLINE_ MonoObject *variant_to_mono_object(const Variant &p_var, const Ma
|
|||
}
|
||||
|
||||
Variant mono_object_to_variant(MonoObject *p_obj);
|
||||
Variant mono_object_to_variant(MonoObject *p_obj, const ManagedType &p_type);
|
||||
Variant mono_object_to_variant_no_err(MonoObject *p_obj, const ManagedType &p_type);
|
||||
|
||||
/// Tries to convert the MonoObject* to Variant and then convert the Variant to String.
|
||||
/// If the MonoObject* cannot be converted to Variant, then 'ToString()' is called instead.
|
||||
String mono_object_to_variant_string(MonoObject *p_obj, MonoException **r_exc);
|
||||
|
||||
// Array
|
||||
|
||||
|
|
Loading…
Reference in a new issue