diff options
Diffstat (limited to 'modules')
-rw-r--r-- | modules/gdnative/gdnative/string.cpp | 264 | ||||
-rw-r--r-- | modules/gdnative/gdnative/transform.cpp | 4 | ||||
-rw-r--r-- | modules/gdnative/gdnative_api.json | 82 | ||||
-rw-r--r-- | modules/gdnative/include/gdnative/string.h | 32 | ||||
-rw-r--r-- | modules/gdnative/include/gdnative/transform.h | 4 | ||||
-rw-r--r-- | modules/gdnative/pluginscript/pluginscript_language.cpp | 8 | ||||
-rw-r--r-- | modules/gdscript/gdscript.h | 4 | ||||
-rw-r--r-- | modules/mono/csharp_script.cpp | 72 | ||||
-rw-r--r-- | modules/mono/csharp_script.h | 4 | ||||
-rw-r--r-- | modules/mono/editor/bindings_generator.cpp | 58 | ||||
-rw-r--r-- | modules/mono/editor/bindings_generator.h | 3 | ||||
-rw-r--r-- | modules/mono/editor/godotsharp_editor.cpp | 7 | ||||
-rw-r--r-- | modules/mono/glue/cs_files/Color.cs | 26 | ||||
-rw-r--r-- | modules/mono/glue/cs_files/DebuggingUtils.cs | 77 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono.cpp | 2 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_class.cpp | 14 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_class.h | 6 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_utils.cpp | 73 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_utils.h | 24 |
19 files changed, 528 insertions, 236 deletions
diff --git a/modules/gdnative/gdnative/string.cpp b/modules/gdnative/gdnative/string.cpp index 350dc540f7..9ce2b1406d 100644 --- a/modules/gdnative/gdnative/string.cpp +++ b/modules/gdnative/gdnative/string.cpp @@ -40,6 +40,24 @@ extern "C" { #endif +godot_int GDAPI godot_char_string_length(const godot_char_string *p_cs) { + const CharString *cs = (const CharString *)p_cs; + + return cs->length(); +} + +const char GDAPI *godot_char_string_get_data(const godot_char_string *p_cs) { + const CharString *cs = (const CharString *)p_cs; + + return cs->get_data(); +} + +void GDAPI godot_char_string_destroy(godot_char_string *p_cs) { + CharString *cs = (CharString *)p_cs; + + cs->~CharString(); +} + void GDAPI godot_string_new(godot_string *r_dest) { String *dest = (String *)r_dest; memnew_placement(dest, String); @@ -51,35 +69,11 @@ void GDAPI godot_string_new_copy(godot_string *r_dest, const godot_string *p_src memnew_placement(dest, String(*src)); } -void GDAPI godot_string_new_data(godot_string *r_dest, const char *p_contents, const int p_size) { - String *dest = (String *)r_dest; - memnew_placement(dest, String(String::utf8(p_contents, p_size))); -} - -void GDAPI godot_string_new_unicode_data(godot_string *r_dest, const wchar_t *p_contents, const int p_size) { +void GDAPI godot_string_new_with_wide_string(godot_string *r_dest, const wchar_t *p_contents, const int p_size) { String *dest = (String *)r_dest; memnew_placement(dest, String(p_contents, p_size)); } -void GDAPI godot_string_get_data(const godot_string *p_self, char *p_dest, int *p_size) { - String *self = (String *)p_self; - - if (p_size) { - // we have a length pointer, that means we either want to know - // the length or want to write *p_size bytes into a buffer - - CharString utf8_string = self->utf8(); - - int len = utf8_string.length(); - - if (p_dest) { - memcpy(p_dest, utf8_string.get_data(), *p_size); - } else { - *p_size = len; - } - } -} - wchar_t GDAPI *godot_string_operator_index(godot_string *p_self, const godot_int p_idx) { String *self = (String *)p_self; return &(self->operator[](p_idx)); @@ -90,7 +84,7 @@ wchar_t GDAPI godot_string_operator_index_const(const godot_string *p_self, cons return self->operator[](p_idx); } -const wchar_t GDAPI *godot_string_unicode_str(const godot_string *p_self) { +const wchar_t GDAPI *godot_string_wide_str(const godot_string *p_self) { const String *self = (const String *)p_self; return self->c_str(); } @@ -130,6 +124,26 @@ godot_int GDAPI godot_string_length(const godot_string *p_self) { /* Helpers */ +signed char GDAPI godot_string_casecmp_to(const godot_string *p_self, const godot_string *p_str) { + const String *self = (const String *)p_self; + const String *str = (const String *)p_str; + + return self->casecmp_to(*str); +} + +signed char GDAPI godot_string_nocasecmp_to(const godot_string *p_self, const godot_string *p_str) { + const String *self = (const String *)p_self; + const String *str = (const String *)p_str; + + return self->nocasecmp_to(*str); +} +signed char GDAPI godot_string_naturalnocasecmp_to(const godot_string *p_self, const godot_string *p_str) { + const String *self = (const String *)p_self; + const String *str = (const String *)p_str; + + return self->naturalnocasecmp_to(*str); +} + godot_bool GDAPI godot_string_begins_with(const godot_string *p_self, const godot_string *p_string) { const String *self = (const String *)p_self; const String *string = (const String *)p_string; @@ -534,7 +548,7 @@ godot_string GDAPI godot_string_capitalize(const godot_string *p_self) { memnew_placement(&result, String(self->capitalize())); return result; -}; +} godot_string GDAPI godot_string_camelcase_to_underscore(const godot_string *p_self) { const String *self = (const String *)p_self; @@ -542,7 +556,7 @@ godot_string GDAPI godot_string_camelcase_to_underscore(const godot_string *p_se memnew_placement(&result, String(self->camelcase_to_underscore(false))); return result; -}; +} godot_string GDAPI godot_string_camelcase_to_underscore_lowercased(const godot_string *p_self) { const String *self = (const String *)p_self; @@ -550,45 +564,45 @@ godot_string GDAPI godot_string_camelcase_to_underscore_lowercased(const godot_s memnew_placement(&result, String(self->camelcase_to_underscore())); return result; -}; +} double GDAPI godot_string_char_to_double(const char *p_what) { return String::to_double(p_what); -}; +} godot_int GDAPI godot_string_char_to_int(const char *p_what) { return String::to_int(p_what); -}; +} int64_t GDAPI godot_string_wchar_to_int(const wchar_t *p_str) { return String::to_int(p_str); -}; +} godot_int GDAPI godot_string_char_to_int_with_len(const char *p_what, godot_int p_len) { return String::to_int(p_what, p_len); -}; +} int64_t GDAPI godot_string_char_to_int64_with_len(const wchar_t *p_str, int p_len) { return String::to_int(p_str, p_len); -}; +} int64_t GDAPI godot_string_hex_to_int64(const godot_string *p_self) { const String *self = (const String *)p_self; return self->hex_to_int64(false); -}; +} int64_t GDAPI godot_string_hex_to_int64_with_prefix(const godot_string *p_self) { const String *self = (const String *)p_self; return self->hex_to_int64(); -}; +} int64_t GDAPI godot_string_to_int64(const godot_string *p_self) { const String *self = (const String *)p_self; return self->to_int64(); -}; +} double GDAPI godot_string_unicode_char_to_double(const wchar_t *p_str, const wchar_t **r_end) { return String::to_double(p_str, r_end); @@ -601,7 +615,7 @@ godot_string GDAPI godot_string_get_slice(const godot_string *p_self, godot_stri memnew_placement(&result, String(self->get_slice(*splitter, p_slice))); return result; -}; +} godot_string GDAPI godot_string_get_slicec(const godot_string *p_self, wchar_t p_splitter, godot_int p_slice) { const String *self = (const String *)p_self; @@ -609,7 +623,7 @@ godot_string GDAPI godot_string_get_slicec(const godot_string *p_self, wchar_t p memnew_placement(&result, String(self->get_slicec(p_splitter, p_slice))); return result; -}; +} godot_array GDAPI godot_string_split(const godot_string *p_self, const godot_string *p_splitter) { const String *self = (const String *)p_self; @@ -625,7 +639,7 @@ godot_array GDAPI godot_string_split(const godot_string *p_self, const godot_str } return result; -}; +} godot_array GDAPI godot_string_split_allow_empty(const godot_string *p_self, const godot_string *p_splitter) { const String *self = (const String *)p_self; @@ -641,7 +655,7 @@ godot_array GDAPI godot_string_split_allow_empty(const godot_string *p_self, con } return result; -}; +} godot_array GDAPI godot_string_split_floats(const godot_string *p_self, const godot_string *p_splitter) { const String *self = (const String *)p_self; @@ -657,7 +671,7 @@ godot_array GDAPI godot_string_split_floats(const godot_string *p_self, const go } return result; -}; +} godot_array GDAPI godot_string_split_floats_allows_empty(const godot_string *p_self, const godot_string *p_splitter) { const String *self = (const String *)p_self; @@ -673,7 +687,7 @@ godot_array GDAPI godot_string_split_floats_allows_empty(const godot_string *p_s } return result; -}; +} godot_array GDAPI godot_string_split_floats_mk(const godot_string *p_self, const godot_array *p_splitters) { const String *self = (const String *)p_self; @@ -696,7 +710,7 @@ godot_array GDAPI godot_string_split_floats_mk(const godot_string *p_self, const } return result; -}; +} godot_array GDAPI godot_string_split_floats_mk_allows_empty(const godot_string *p_self, const godot_array *p_splitters) { const String *self = (const String *)p_self; @@ -719,7 +733,7 @@ godot_array GDAPI godot_string_split_floats_mk_allows_empty(const godot_string * } return result; -}; +} godot_array GDAPI godot_string_split_ints(const godot_string *p_self, const godot_string *p_splitter) { const String *self = (const String *)p_self; @@ -735,7 +749,7 @@ godot_array GDAPI godot_string_split_ints(const godot_string *p_self, const godo } return result; -}; +} godot_array GDAPI godot_string_split_ints_allows_empty(const godot_string *p_self, const godot_string *p_splitter) { const String *self = (const String *)p_self; @@ -751,7 +765,7 @@ godot_array GDAPI godot_string_split_ints_allows_empty(const godot_string *p_sel } return result; -}; +} godot_array GDAPI godot_string_split_ints_mk(const godot_string *p_self, const godot_array *p_splitters) { const String *self = (const String *)p_self; @@ -774,7 +788,7 @@ godot_array GDAPI godot_string_split_ints_mk(const godot_string *p_self, const g } return result; -}; +} godot_array GDAPI godot_string_split_ints_mk_allows_empty(const godot_string *p_self, const godot_array *p_splitters) { const String *self = (const String *)p_self; @@ -797,7 +811,7 @@ godot_array GDAPI godot_string_split_ints_mk_allows_empty(const godot_string *p_ } return result; -}; +} godot_array GDAPI godot_string_split_spaces(const godot_string *p_self) { const String *self = (const String *)p_self; @@ -812,22 +826,22 @@ godot_array GDAPI godot_string_split_spaces(const godot_string *p_self) { } return result; -}; +} godot_int GDAPI godot_string_get_slice_count(const godot_string *p_self, godot_string p_splitter) { const String *self = (const String *)p_self; String *splitter = (String *)&p_splitter; return self->get_slice_count(*splitter); -}; +} wchar_t GDAPI godot_string_char_lowercase(wchar_t p_char) { return String::char_lowercase(p_char); -}; +} wchar_t GDAPI godot_string_char_uppercase(wchar_t p_char) { return String::char_uppercase(p_char); -}; +} godot_string GDAPI godot_string_to_lower(const godot_string *p_self) { const String *self = (const String *)p_self; @@ -835,7 +849,7 @@ godot_string GDAPI godot_string_to_lower(const godot_string *p_self) { memnew_placement(&result, String(self->to_lower())); return result; -}; +} godot_string GDAPI godot_string_to_upper(const godot_string *p_self) { const String *self = (const String *)p_self; @@ -843,7 +857,7 @@ godot_string GDAPI godot_string_to_upper(const godot_string *p_self) { memnew_placement(&result, String(self->to_upper())); return result; -}; +} godot_string GDAPI godot_string_get_basename(const godot_string *p_self) { const String *self = (const String *)p_self; @@ -851,7 +865,7 @@ godot_string GDAPI godot_string_get_basename(const godot_string *p_self) { memnew_placement(&result, String(self->get_basename())); return result; -}; +} godot_string GDAPI godot_string_get_extension(const godot_string *p_self) { const String *self = (const String *)p_self; @@ -859,7 +873,7 @@ godot_string GDAPI godot_string_get_extension(const godot_string *p_self) { memnew_placement(&result, String(self->get_extension())); return result; -}; +} godot_string GDAPI godot_string_left(const godot_string *p_self, godot_int p_pos) { const String *self = (const String *)p_self; @@ -867,13 +881,13 @@ godot_string GDAPI godot_string_left(const godot_string *p_self, godot_int p_pos memnew_placement(&result, String(self->left(p_pos))); return result; -}; +} wchar_t GDAPI godot_string_ord_at(const godot_string *p_self, godot_int p_idx) { const String *self = (const String *)p_self; return self->ord_at(p_idx); -}; +} godot_string GDAPI godot_string_plus_file(const godot_string *p_self, const godot_string *p_file) { const String *self = (const String *)p_self; @@ -882,7 +896,7 @@ godot_string GDAPI godot_string_plus_file(const godot_string *p_self, const godo memnew_placement(&result, String(self->plus_file(*file))); return result; -}; +} godot_string GDAPI godot_string_right(const godot_string *p_self, godot_int p_pos) { const String *self = (const String *)p_self; @@ -890,7 +904,7 @@ godot_string GDAPI godot_string_right(const godot_string *p_self, godot_int p_po memnew_placement(&result, String(self->right(p_pos))); return result; -}; +} godot_string GDAPI godot_string_strip_edges(const godot_string *p_self, godot_bool p_left, godot_bool p_right) { const String *self = (const String *)p_self; @@ -898,7 +912,7 @@ godot_string GDAPI godot_string_strip_edges(const godot_string *p_self, godot_bo memnew_placement(&result, String(self->strip_edges(p_left, p_right))); return result; -}; +} godot_string GDAPI godot_string_strip_escapes(const godot_string *p_self) { const String *self = (const String *)p_self; @@ -906,94 +920,96 @@ godot_string GDAPI godot_string_strip_escapes(const godot_string *p_self) { memnew_placement(&result, String(self->strip_escapes())); return result; -}; +} void GDAPI godot_string_erase(godot_string *p_self, godot_int p_pos, godot_int p_chars) { String *self = (String *)p_self; return self->erase(p_pos, p_chars); -}; +} -void GDAPI godot_string_ascii(godot_string *p_self, char *result) { - String *self = (String *)p_self; - Vector<char> return_value = self->ascii(); +godot_char_string GDAPI godot_string_ascii(const godot_string *p_self) { + const String *self = (const String *)p_self; + godot_char_string result; - for (int i = 0; i < return_value.size(); i++) { - result[i] = return_value[i]; - } + memnew_placement(&result, String(self->ascii())); + + return result; } -void GDAPI godot_string_ascii_extended(godot_string *p_self, char *result) { - String *self = (String *)p_self; - Vector<char> return_value = self->ascii(true); +godot_char_string GDAPI godot_string_ascii_extended(const godot_string *p_self) { + const String *self = (const String *)p_self; - for (int i = 0; i < return_value.size(); i++) { - result[i] = return_value[i]; - } + godot_char_string result; + + memnew_placement(&result, String(self->ascii(true))); + + return result; } -void GDAPI godot_string_utf8(godot_string *p_self, char *result) { - String *self = (String *)p_self; - Vector<char> return_value = self->utf8(); +godot_char_string GDAPI godot_string_utf8(const godot_string *p_self) { + const String *self = (const String *)p_self; - for (int i = 0; i < return_value.size(); i++) { - result[i] = return_value[i]; - } + godot_char_string result; + + memnew_placement(&result, String(self->utf8())); + + return result; } godot_bool GDAPI godot_string_parse_utf8(godot_string *p_self, const char *p_utf8) { String *self = (String *)p_self; return self->parse_utf8(p_utf8); -}; +} godot_bool GDAPI godot_string_parse_utf8_with_len(godot_string *p_self, const char *p_utf8, godot_int p_len) { String *self = (String *)p_self; return self->parse_utf8(p_utf8, p_len); -}; +} godot_string GDAPI godot_string_chars_to_utf8(const char *p_utf8) { godot_string result; memnew_placement(&result, String(String::utf8(p_utf8))); return result; -}; +} godot_string GDAPI godot_string_chars_to_utf8_with_len(const char *p_utf8, godot_int p_len) { godot_string result; memnew_placement(&result, String(String::utf8(p_utf8, p_len))); return result; -}; +} uint32_t GDAPI godot_string_hash(const godot_string *p_self) { const String *self = (const String *)p_self; return self->hash(); -}; +} uint64_t GDAPI godot_string_hash64(const godot_string *p_self) { const String *self = (const String *)p_self; return self->hash64(); -}; +} uint32_t GDAPI godot_string_hash_chars(const char *p_cstr) { return String::hash(p_cstr); -}; +} uint32_t GDAPI godot_string_hash_chars_with_len(const char *p_cstr, godot_int p_len) { return String::hash(p_cstr, p_len); -}; +} uint32_t GDAPI godot_string_hash_utf8_chars(const wchar_t *p_str) { return String::hash(p_str); -}; +} uint32_t GDAPI godot_string_hash_utf8_chars_with_len(const wchar_t *p_str, godot_int p_len) { return String::hash(p_str, p_len); -}; +} godot_pool_byte_array GDAPI godot_string_md5_buffer(const godot_string *p_self) { const String *self = (const String *)p_self; @@ -1010,7 +1026,7 @@ godot_pool_byte_array GDAPI godot_string_md5_buffer(const godot_string *p_self) } return result; -}; +} godot_string GDAPI godot_string_md5_text(const godot_string *p_self) { const String *self = (const String *)p_self; @@ -1018,7 +1034,7 @@ godot_string GDAPI godot_string_md5_text(const godot_string *p_self) { memnew_placement(&result, String(self->md5_text())); return result; -}; +} godot_pool_byte_array GDAPI godot_string_sha256_buffer(const godot_string *p_self) { const String *self = (const String *)p_self; @@ -1035,7 +1051,7 @@ godot_pool_byte_array GDAPI godot_string_sha256_buffer(const godot_string *p_sel } return result; -}; +} godot_string GDAPI godot_string_sha256_text(const godot_string *p_self) { const String *self = (const String *)p_self; @@ -1043,13 +1059,13 @@ godot_string GDAPI godot_string_sha256_text(const godot_string *p_self) { memnew_placement(&result, String(self->sha256_text())); return result; -}; +} godot_bool godot_string_empty(const godot_string *p_self) { const String *self = (const String *)p_self; return self->empty(); -}; +} // path functions godot_string GDAPI godot_string_get_base_dir(const godot_string *p_self) { @@ -1059,7 +1075,7 @@ godot_string GDAPI godot_string_get_base_dir(const godot_string *p_self) { memnew_placement(&result, String(return_value)); return result; -}; +} godot_string GDAPI godot_string_get_file(const godot_string *p_self) { const String *self = (const String *)p_self; @@ -1068,7 +1084,7 @@ godot_string GDAPI godot_string_get_file(const godot_string *p_self) { memnew_placement(&result, String(return_value)); return result; -}; +} godot_string GDAPI godot_string_humanize_size(size_t p_size) { godot_string result; @@ -1076,25 +1092,25 @@ godot_string GDAPI godot_string_humanize_size(size_t p_size) { memnew_placement(&result, String(return_value)); return result; -}; +} godot_bool GDAPI godot_string_is_abs_path(const godot_string *p_self) { const String *self = (const String *)p_self; return self->is_abs_path(); -}; +} godot_bool GDAPI godot_string_is_rel_path(const godot_string *p_self) { const String *self = (const String *)p_self; return self->is_rel_path(); -}; +} godot_bool GDAPI godot_string_is_resource_file(const godot_string *p_self) { const String *self = (const String *)p_self; return self->is_resource_file(); -}; +} godot_string GDAPI godot_string_path_to(const godot_string *p_self, const godot_string *p_path) { const String *self = (const String *)p_self; @@ -1104,7 +1120,7 @@ godot_string GDAPI godot_string_path_to(const godot_string *p_self, const godot_ memnew_placement(&result, String(return_value)); return result; -}; +} godot_string GDAPI godot_string_path_to_file(const godot_string *p_self, const godot_string *p_path) { const String *self = (const String *)p_self; @@ -1114,7 +1130,7 @@ godot_string GDAPI godot_string_path_to_file(const godot_string *p_self, const g memnew_placement(&result, String(return_value)); return result; -}; +} godot_string GDAPI godot_string_simplify_path(const godot_string *p_self) { const String *self = (const String *)p_self; @@ -1123,7 +1139,7 @@ godot_string GDAPI godot_string_simplify_path(const godot_string *p_self) { memnew_placement(&result, String(return_value)); return result; -}; +} godot_string GDAPI godot_string_c_escape(const godot_string *p_self) { const String *self = (const String *)p_self; @@ -1132,7 +1148,7 @@ godot_string GDAPI godot_string_c_escape(const godot_string *p_self) { memnew_placement(&result, String(return_value)); return result; -}; +} godot_string GDAPI godot_string_c_escape_multiline(const godot_string *p_self) { const String *self = (const String *)p_self; @@ -1141,7 +1157,7 @@ godot_string GDAPI godot_string_c_escape_multiline(const godot_string *p_self) { memnew_placement(&result, String(return_value)); return result; -}; +} godot_string GDAPI godot_string_c_unescape(const godot_string *p_self) { const String *self = (const String *)p_self; @@ -1150,7 +1166,7 @@ godot_string GDAPI godot_string_c_unescape(const godot_string *p_self) { memnew_placement(&result, String(return_value)); return result; -}; +} godot_string GDAPI godot_string_http_escape(const godot_string *p_self) { const String *self = (const String *)p_self; @@ -1159,7 +1175,7 @@ godot_string GDAPI godot_string_http_escape(const godot_string *p_self) { memnew_placement(&result, String(return_value)); return result; -}; +} godot_string GDAPI godot_string_http_unescape(const godot_string *p_self) { const String *self = (const String *)p_self; @@ -1168,7 +1184,7 @@ godot_string GDAPI godot_string_http_unescape(const godot_string *p_self) { memnew_placement(&result, String(return_value)); return result; -}; +} godot_string GDAPI godot_string_json_escape(const godot_string *p_self) { const String *self = (const String *)p_self; @@ -1177,7 +1193,7 @@ godot_string GDAPI godot_string_json_escape(const godot_string *p_self) { memnew_placement(&result, String(return_value)); return result; -}; +} godot_string GDAPI godot_string_word_wrap(const godot_string *p_self, godot_int p_chars_per_line) { const String *self = (const String *)p_self; @@ -1186,7 +1202,7 @@ godot_string GDAPI godot_string_word_wrap(const godot_string *p_self, godot_int memnew_placement(&result, String(return_value)); return result; -}; +} godot_string GDAPI godot_string_xml_escape(const godot_string *p_self) { const String *self = (const String *)p_self; @@ -1195,7 +1211,7 @@ godot_string GDAPI godot_string_xml_escape(const godot_string *p_self) { memnew_placement(&result, String(return_value)); return result; -}; +} godot_string GDAPI godot_string_xml_escape_with_quotes(const godot_string *p_self) { const String *self = (const String *)p_self; @@ -1204,7 +1220,7 @@ godot_string GDAPI godot_string_xml_escape_with_quotes(const godot_string *p_sel memnew_placement(&result, String(return_value)); return result; -}; +} godot_string GDAPI godot_string_xml_unescape(const godot_string *p_self) { const String *self = (const String *)p_self; @@ -1213,7 +1229,7 @@ godot_string GDAPI godot_string_xml_unescape(const godot_string *p_self) { memnew_placement(&result, String(return_value)); return result; -}; +} godot_string GDAPI godot_string_percent_decode(const godot_string *p_self) { const String *self = (const String *)p_self; @@ -1222,7 +1238,7 @@ godot_string GDAPI godot_string_percent_decode(const godot_string *p_self) { memnew_placement(&result, String(return_value)); return result; -}; +} godot_string GDAPI godot_string_percent_encode(const godot_string *p_self) { const String *self = (const String *)p_self; @@ -1231,43 +1247,43 @@ godot_string GDAPI godot_string_percent_encode(const godot_string *p_self) { memnew_placement(&result, String(return_value)); return result; -}; +} godot_bool GDAPI godot_string_is_valid_float(const godot_string *p_self) { const String *self = (const String *)p_self; return self->is_valid_float(); -}; +} godot_bool GDAPI godot_string_is_valid_hex_number(const godot_string *p_self, godot_bool p_with_prefix) { const String *self = (const String *)p_self; return self->is_valid_hex_number(p_with_prefix); -}; +} godot_bool GDAPI godot_string_is_valid_html_color(const godot_string *p_self) { const String *self = (const String *)p_self; return self->is_valid_html_color(); -}; +} godot_bool GDAPI godot_string_is_valid_identifier(const godot_string *p_self) { const String *self = (const String *)p_self; return self->is_valid_identifier(); -}; +} godot_bool GDAPI godot_string_is_valid_integer(const godot_string *p_self) { const String *self = (const String *)p_self; return self->is_valid_integer(); -}; +} godot_bool GDAPI godot_string_is_valid_ip_address(const godot_string *p_self) { const String *self = (const String *)p_self; return self->is_valid_ip_address(); -}; +} #ifdef __cplusplus } diff --git a/modules/gdnative/gdnative/transform.cpp b/modules/gdnative/gdnative/transform.cpp index 9bd8c99612..715f2e3c08 100644 --- a/modules/gdnative/gdnative/transform.cpp +++ b/modules/gdnative/gdnative/transform.cpp @@ -63,7 +63,7 @@ godot_basis GDAPI godot_transform_get_basis(const godot_transform *p_self) { return dest; } -void GDAPI godot_transform_set_basis(godot_transform *p_self, godot_basis *p_v) { +void GDAPI godot_transform_set_basis(godot_transform *p_self, const godot_basis *p_v) { Transform *self = (Transform *)p_self; const Basis *v = (const Basis *)p_v; self->basis = *v; @@ -76,7 +76,7 @@ godot_vector3 GDAPI godot_transform_get_origin(const godot_transform *p_self) { return dest; } -void GDAPI godot_transform_set_origin(godot_transform *p_self, godot_vector3 *p_v) { +void GDAPI godot_transform_set_origin(godot_transform *p_self, const godot_vector3 *p_v) { Transform *self = (Transform *)p_self; const Vector3 *v = (const Vector3 *)p_v; self->origin = *v; diff --git a/modules/gdnative/gdnative_api.json b/modules/gdnative/gdnative_api.json index 06c6e9f410..6e3cf16758 100644 --- a/modules/gdnative/gdnative_api.json +++ b/modules/gdnative/gdnative_api.json @@ -3516,7 +3516,7 @@ "return_type": "void", "arguments": [ ["godot_transform *", "p_self"], - ["godot_basis *", "p_v"] + ["const godot_basis *", "p_v"] ] }, { @@ -3531,7 +3531,7 @@ "return_type": "void", "arguments": [ ["godot_transform *", "p_self"], - ["godot_vector3 *", "p_v"] + ["const godot_vector3 *", "p_v"] ] }, { @@ -4324,45 +4324,48 @@ ] }, { - "name": "godot_string_new", - "return_type": "void", + "name": "godot_char_string_length", + "return_type": "godot_int", "arguments": [ - ["godot_string *", "r_dest"] + ["const godot_char_string *", "p_cs"] ] }, { - "name": "godot_string_new_copy", + "name": "godot_char_string_get_data", + "return_type": "const char *", + "arguments": [ + ["const godot_char_string *", "p_cs"] + ] + }, + { + "name": "godot_char_string_destroy", "return_type": "void", "arguments": [ - ["godot_string *", "r_dest"], - ["const godot_string *", "p_src"] + ["godot_char_string *", "p_cs"] ] }, { - "name": "godot_string_new_data", + "name": "godot_string_new", "return_type": "void", "arguments": [ - ["godot_string *", "r_dest"], - ["const char *", "p_contents"], - ["const int", "p_size"] + ["godot_string *", "r_dest"] ] }, { - "name": "godot_string_new_unicode_data", + "name": "godot_string_new_copy", "return_type": "void", "arguments": [ ["godot_string *", "r_dest"], - ["const wchar_t *", "p_contents"], - ["const int", "p_size"] + ["const godot_string *", "p_src"] ] }, { - "name": "godot_string_get_data", + "name": "godot_string_new_with_wide_string", "return_type": "void", "arguments": [ - ["const godot_string *", "p_self"], - ["char *", "p_dest"], - ["int *", "p_size"] + ["godot_string *", "r_dest"], + ["const wchar_t *", "p_contents"], + ["const int", "p_size"] ] }, { @@ -4382,7 +4385,7 @@ ] }, { - "name": "godot_string_unicode_str", + "name": "godot_string_wide_str", "return_type": "const wchar_t *", "arguments": [ ["const godot_string *", "p_self"] @@ -4420,6 +4423,30 @@ ] }, { + "name": "godot_string_casecmp_to", + "return_type": "signed char", + "arguments": [ + ["const godot_string *", "p_self"], + ["const godot_string *", "p_str"] + ] + }, + { + "name": "godot_string_nocasecmp_to", + "return_type": "signed char", + "arguments": [ + ["const godot_string *", "p_self"], + ["const godot_string *", "p_str"] + ] + }, + { + "name": "godot_string_naturalnocasecmp_to", + "return_type": "signed char", + "arguments": [ + ["const godot_string *", "p_self"], + ["const godot_string *", "p_str"] + ] + }, + { "name": "godot_string_begins_with", "return_type": "godot_bool", "arguments": [ @@ -5125,26 +5152,23 @@ }, { "name": "godot_string_ascii", - "return_type": "void", + "return_type": "godot_char_string", "arguments": [ - ["godot_string *", "p_self"], - ["char *", "result"] + ["const godot_string *", "p_self"] ] }, { "name": "godot_string_ascii_extended", - "return_type": "void", + "return_type": "godot_char_string", "arguments": [ - ["godot_string *", "p_self"], - ["char *", "result"] + ["const godot_string *", "p_self"] ] }, { "name": "godot_string_utf8", - "return_type": "void", + "return_type": "godot_char_string", "arguments": [ - ["godot_string *", "p_self"], - ["char *", "result"] + ["const godot_string *", "p_self"] ] }, { diff --git a/modules/gdnative/include/gdnative/string.h b/modules/gdnative/include/gdnative/string.h index 080c0aa171..73245160c1 100644 --- a/modules/gdnative/include/gdnative/string.h +++ b/modules/gdnative/include/gdnative/string.h @@ -38,13 +38,24 @@ extern "C" { #include <stdint.h> #include <wchar.h> +typedef wchar_t godot_char_type; + #define GODOT_STRING_SIZE sizeof(void *) +#define GODOT_CHAR_STRING_SIZE sizeof(void *) #ifndef GODOT_CORE_API_GODOT_STRING_TYPE_DEFINED #define GODOT_CORE_API_GODOT_STRING_TYPE_DEFINED typedef struct { uint8_t _dont_touch_that[GODOT_STRING_SIZE]; } godot_string; + +#endif + +#ifndef GODOT_CORE_API_GODOT_CHAR_STRING_TYPE_DEFINED +#define GODOT_CORE_API_GODOT_CHAR_STRING_TYPE_DEFINED +typedef struct { + uint8_t _dont_touch_that[GODOT_CHAR_STRING_SIZE]; +} godot_char_string; #endif // reduce extern "C" nesting for VS2013 @@ -60,16 +71,17 @@ typedef struct { extern "C" { #endif +godot_int GDAPI godot_char_string_length(const godot_char_string *p_cs); +const char GDAPI *godot_char_string_get_data(const godot_char_string *p_cs); +void GDAPI godot_char_string_destroy(godot_char_string *p_cs); + void GDAPI godot_string_new(godot_string *r_dest); void GDAPI godot_string_new_copy(godot_string *r_dest, const godot_string *p_src); -void GDAPI godot_string_new_data(godot_string *r_dest, const char *p_contents, const int p_size); -void GDAPI godot_string_new_unicode_data(godot_string *r_dest, const wchar_t *p_contents, const int p_size); - -void GDAPI godot_string_get_data(const godot_string *p_self, char *p_dest, int *p_size); +void GDAPI godot_string_new_with_wide_string(godot_string *r_dest, const wchar_t *p_contents, const int p_size); wchar_t GDAPI *godot_string_operator_index(godot_string *p_self, const godot_int p_idx); wchar_t GDAPI godot_string_operator_index_const(const godot_string *p_self, const godot_int p_idx); -const wchar_t GDAPI *godot_string_unicode_str(const godot_string *p_self); +const wchar_t GDAPI *godot_string_wide_str(const godot_string *p_self); godot_bool GDAPI godot_string_operator_equal(const godot_string *p_self, const godot_string *p_b); godot_bool GDAPI godot_string_operator_less(const godot_string *p_self, const godot_string *p_b); @@ -81,6 +93,10 @@ godot_int GDAPI godot_string_length(const godot_string *p_self); /* Helpers */ +signed char GDAPI godot_string_casecmp_to(const godot_string *p_self, const godot_string *p_str); +signed char GDAPI godot_string_nocasecmp_to(const godot_string *p_self, const godot_string *p_str); +signed char GDAPI godot_string_naturalnocasecmp_to(const godot_string *p_self, const godot_string *p_str); + godot_bool GDAPI godot_string_begins_with(const godot_string *p_self, const godot_string *p_string); godot_bool GDAPI godot_string_begins_with_char_array(const godot_string *p_self, const char *p_char_array); godot_array GDAPI godot_string_bigrams(const godot_string *p_self); @@ -177,9 +193,9 @@ godot_string GDAPI godot_string_strip_escapes(const godot_string *p_self); void GDAPI godot_string_erase(godot_string *p_self, godot_int p_pos, godot_int p_chars); -void GDAPI godot_string_ascii(godot_string *p_self, char *result); -void GDAPI godot_string_ascii_extended(godot_string *p_self, char *result); -void GDAPI godot_string_utf8(godot_string *p_self, char *result); +godot_char_string GDAPI godot_string_ascii(const godot_string *p_self); +godot_char_string GDAPI godot_string_ascii_extended(const godot_string *p_self); +godot_char_string GDAPI godot_string_utf8(const godot_string *p_self); godot_bool GDAPI godot_string_parse_utf8(godot_string *p_self, const char *p_utf8); godot_bool GDAPI godot_string_parse_utf8_with_len(godot_string *p_self, const char *p_utf8, godot_int p_len); godot_string GDAPI godot_string_chars_to_utf8(const char *p_utf8); diff --git a/modules/gdnative/include/gdnative/transform.h b/modules/gdnative/include/gdnative/transform.h index 10a242b205..a646da146a 100644 --- a/modules/gdnative/include/gdnative/transform.h +++ b/modules/gdnative/include/gdnative/transform.h @@ -64,10 +64,10 @@ void GDAPI godot_transform_new_with_axis_origin(godot_transform *r_dest, const g void GDAPI godot_transform_new(godot_transform *r_dest, const godot_basis *p_basis, const godot_vector3 *p_origin); godot_basis GDAPI godot_transform_get_basis(const godot_transform *p_self); -void GDAPI godot_transform_set_basis(godot_transform *p_self, godot_basis *p_v); +void GDAPI godot_transform_set_basis(godot_transform *p_self, const godot_basis *p_v); godot_vector3 GDAPI godot_transform_get_origin(const godot_transform *p_self); -void GDAPI godot_transform_set_origin(godot_transform *p_self, godot_vector3 *p_v); +void GDAPI godot_transform_set_origin(godot_transform *p_self, const godot_vector3 *p_v); godot_string GDAPI godot_transform_as_string(const godot_transform *p_self); diff --git a/modules/gdnative/pluginscript/pluginscript_language.cpp b/modules/gdnative/pluginscript/pluginscript_language.cpp index 2405afc677..8101ebc6f3 100644 --- a/modules/gdnative/pluginscript/pluginscript_language.cpp +++ b/modules/gdnative/pluginscript/pluginscript_language.cpp @@ -45,7 +45,11 @@ void PluginScriptLanguage::init() { } String PluginScriptLanguage::get_type() const { - return String(_desc.type); + // We should use _desc.type here, however the returned type is used to + // query ClassDB which would complain given the type is not registered + // from his point of view... + // To solve this we just use a more generic (but present in ClassDB) type. + return String("PluginScript"); } String PluginScriptLanguage::get_extension() const { @@ -168,7 +172,7 @@ Error PluginScriptLanguage::complete_code(const String &p_code, const String &p_ for (int i = 0; i < options.size(); i++) { r_options->push_back(String(options[i])); } - Error err = *(Error *)tmp; + Error err = *(Error *)&tmp; return err; } return ERR_UNAVAILABLE; diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h index b5bbaa6dc9..9566e3b32e 100644 --- a/modules/gdscript/gdscript.h +++ b/modules/gdscript/gdscript.h @@ -349,7 +349,9 @@ public: csi.resize(_debug_call_stack_pos); for (int i = 0; i < _debug_call_stack_pos; i++) { csi[_debug_call_stack_pos - i - 1].line = _call_stack[i].line ? *_call_stack[i].line : 0; - csi[_debug_call_stack_pos - i - 1].script = Ref<GDScript>(_call_stack[i].function->get_script()); + if (_call_stack[i].function) + csi[_debug_call_stack_pos - i - 1].func = _call_stack[i].function->get_name(); + csi[_debug_call_stack_pos - i - 1].file = _call_stack[i].function->get_script()->get_path(); } return csi; } diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 949c636050..db2d0a9780 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -445,6 +445,72 @@ String CSharpLanguage::_get_indentation() const { return "\t"; } +Vector<ScriptLanguage::StackInfo> CSharpLanguage::debug_get_current_stack_info() { + + // Printing an error here will result in endless recursion, so we must be careful + + if (!gdmono->is_runtime_initialized() && GDMono::get_singleton()->get_api_assembly()) + return Vector<StackInfo>(); + + MonoObject *stack_trace = mono_object_new(mono_domain_get(), CACHED_CLASS(System_Diagnostics_StackTrace)->get_mono_ptr()); + + MonoBoolean need_file_info = true; + void *ctor_args[1] = { &need_file_info }; + + CACHED_METHOD(System_Diagnostics_StackTrace, ctor_bool)->invoke_raw(stack_trace, ctor_args); + + Vector<StackInfo> si; + si = stack_trace_get_info(stack_trace); + + return si; +} + +Vector<ScriptLanguage::StackInfo> CSharpLanguage::stack_trace_get_info(MonoObject *p_stack_trace) { + + // Printing an error here could result in endless recursion, so we must be careful + + MonoObject *exc = NULL; + + GDMonoUtils::StackTrace_GetFrames st_get_frames = CACHED_METHOD_THUNK(System_Diagnostics_StackTrace, GetFrames); + MonoArray *frames = st_get_frames(p_stack_trace, &exc); + + if (exc) { + GDMonoUtils::print_unhandled_exception(exc, true /* fail silently to avoid endless recursion */); + return Vector<StackInfo>(); + } + + int frame_count = mono_array_length(frames); + + if (frame_count <= 0) + return Vector<StackInfo>(); + + GDMonoUtils::DebugUtils_StackFrameInfo get_sf_info = CACHED_METHOD_THUNK(DebuggingUtils, GetStackFrameInfo); + + Vector<StackInfo> si; + si.resize(frame_count); + + for (int i = 0; i < frame_count; i++) { + StackInfo &sif = si[i]; + MonoObject *frame = mono_array_get(frames, MonoObject *, i); + + MonoString *file_name; + int file_line_num; + MonoString *method_decl; + get_sf_info(frame, &file_name, &file_line_num, &method_decl, &exc); + + if (exc) { + GDMonoUtils::print_unhandled_exception(exc, true /* fail silently to avoid endless recursion */); + return Vector<StackInfo>(); + } + + sif.file = GDMonoMarshal::mono_string_to_godot(file_name); + sif.line = file_line_num; + sif.func = GDMonoMarshal::mono_string_to_godot(method_decl); + } + + return si; +} + void CSharpLanguage::frame() { const Ref<MonoGCHandle> &task_scheduler_handle = GDMonoUtils::mono_cache.task_scheduler_handle; @@ -1049,7 +1115,7 @@ bool CSharpInstance::has_method(const StringName &p_method) const { GDMonoClass *top = script->script_class; while (top && top != script->native) { - if (top->has_method(p_method)) { + if (top->has_fetched_method_unknown_params(p_method)) { return true; } @@ -1227,7 +1293,7 @@ ScriptInstance::RPCMode CSharpInstance::get_rpc_mode(const StringName &p_method) GDMonoClass *top = script->script_class; while (top && top != script->native) { - GDMonoMethod *method = top->get_method(p_method); + GDMonoMethod *method = top->get_fetched_method_unknown_params(p_method); if (method && !method->is_static()) return _member_get_rpc_mode(method); @@ -1848,7 +1914,7 @@ void CSharpScript::set_source_code(const String &p_code) { bool CSharpScript::has_method(const StringName &p_method) const { - return script_class->has_method(p_method); + return script_class->has_fetched_method_unknown_params(p_method); } Error CSharpScript::reload(bool p_keep_state) { diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h index 171601f3d8..3ce8a9b64e 100644 --- a/modules/mono/csharp_script.h +++ b/modules/mono/csharp_script.h @@ -303,7 +303,7 @@ public: /* TODO */ virtual void debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {} /* TODO */ virtual void debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {} /* TODO */ virtual String debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems, int p_max_depth) { return ""; } - /* TODO */ virtual Vector<StackInfo> debug_get_current_stack_info() { return Vector<StackInfo>(); } + virtual Vector<StackInfo> debug_get_current_stack_info(); /* PROFILING FUNCTIONS */ /* TODO */ virtual void profiling_start() {} @@ -335,6 +335,8 @@ public: virtual void *alloc_instance_binding_data(Object *p_object); virtual void free_instance_binding_data(void *p_data); + Vector<StackInfo> stack_trace_get_info(MonoObject *p_stack_trace); + CSharpLanguage(); ~CSharpLanguage(); }; diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index 2205ac4e98..800e3b723b 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -448,14 +448,14 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bo compile_items.push_back(output_file); } - for (Map<StringName, TypeInterface>::Element *E = obj_types.front(); E; E = E->next()) { - const TypeInterface &itype = E->get(); + for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next()) { + const TypeInterface &itype = E.get(); if (itype.api_type == ClassDB::API_EDITOR) continue; - String output_file = path_join(obj_type_dir, E->get().proxy_name + ".cs"); - Error err = _generate_cs_type(E->get(), output_file); + String output_file = path_join(obj_type_dir, itype.proxy_name + ".cs"); + Error err = _generate_cs_type(itype, output_file); if (err == ERR_SKIP) continue; @@ -580,14 +580,14 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_output_dir, if (!solution.set_path(p_output_dir)) return ERR_FILE_NOT_FOUND; - for (Map<StringName, TypeInterface>::Element *E = obj_types.front(); E; E = E->next()) { - const TypeInterface &itype = E->get(); + for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next()) { + const TypeInterface &itype = E.get(); if (itype.api_type != ClassDB::API_EDITOR) continue; - String output_file = path_join(obj_type_dir, E->get().proxy_name + ".cs"); - Error err = _generate_cs_type(E->get(), output_file); + String output_file = path_join(obj_type_dir, itype.proxy_name + ".cs"); + Error err = _generate_cs_type(itype, output_file); if (err == ERR_SKIP) continue; @@ -945,7 +945,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str return ERR_BUG; } - Map<StringName, TypeInterface>::Element *object_itype = obj_types.find("Object"); + OrderedHashMap<StringName, TypeInterface>::Element object_itype = obj_types.find("Object"); if (!object_itype) { ERR_PRINT("BUG: Object type interface not found!"); @@ -953,7 +953,7 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str } output.push_back(MEMBER_BEGIN "public " CS_CLASS_SIGNALAWAITER " ToSignal("); - output.push_back(object_itype->get().cs_type); + output.push_back(object_itype.get().cs_type); output.push_back(" source, string signal)\n" OPEN_BLOCK_L2 "return new " CS_CLASS_SIGNALAWAITER "(source, signal, this);\n" CLOSE_BLOCK_L2); } @@ -999,9 +999,9 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte // Search it in base types too const TypeInterface *current_type = &p_itype; while (!setter && current_type->base_name != StringName()) { - Map<StringName, TypeInterface>::Element *base_match = obj_types.find(current_type->base_name); - ERR_FAIL_NULL_V(base_match, ERR_BUG); - current_type = &base_match->get(); + OrderedHashMap<StringName, TypeInterface>::Element base_match = obj_types.find(current_type->base_name); + ERR_FAIL_COND_V(!base_match, ERR_BUG); + current_type = &base_match.get(); setter = current_type->find_method_by_name(p_iprop.setter); } @@ -1010,9 +1010,9 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte // Search it in base types too current_type = &p_itype; while (!getter && current_type->base_name != StringName()) { - Map<StringName, TypeInterface>::Element *base_match = obj_types.find(current_type->base_name); - ERR_FAIL_NULL_V(base_match, ERR_BUG); - current_type = &base_match->get(); + OrderedHashMap<StringName, TypeInterface>::Element base_match = obj_types.find(current_type->base_name); + ERR_FAIL_COND_V(!base_match, ERR_BUG); + current_type = &base_match.get(); getter = current_type->find_method_by_name(p_iprop.getter); } @@ -1324,8 +1324,8 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) { generated_icall_funcs.clear(); - for (Map<StringName, TypeInterface>::Element *type_elem = obj_types.front(); type_elem; type_elem = type_elem->next()) { - const TypeInterface &itype = type_elem->get(); + for (OrderedHashMap<StringName, TypeInterface>::Element type_elem = obj_types.front(); type_elem; type_elem = type_elem.next()) { + const TypeInterface &itype = type_elem.get(); List<InternalCall> &custom_icalls = itype.api_type == ClassDB::API_EDITOR ? editor_custom_icalls : core_custom_icalls; @@ -1631,20 +1631,20 @@ Error BindingsGenerator::_generate_glue_method(const BindingsGenerator::TypeInte const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_by_name_or_null(const StringName &p_cname) { - const Map<StringName, TypeInterface>::Element *match = builtin_types.find(p_cname); + const Map<StringName, TypeInterface>::Element *builtin_type_match = builtin_types.find(p_cname); - if (match) - return &match->get(); + if (builtin_type_match) + return &builtin_type_match->get(); - match = obj_types.find(p_cname); + const OrderedHashMap<StringName, TypeInterface>::Element obj_type_match = obj_types.find(p_cname); - if (match) - return &match->get(); + if (obj_type_match) + return &obj_type_match.get(); - match = enum_types.find(p_cname); + const Map<StringName, TypeInterface>::Element *enum_match = enum_types.find(p_cname); - if (match) - return &match->get(); + if (enum_match) + return &enum_match->get(); return NULL; } @@ -2484,8 +2484,8 @@ void BindingsGenerator::initialize() { _generate_header_icalls(); - for (Map<StringName, TypeInterface>::Element *E = obj_types.front(); E; E = E->next()) - _generate_method_icalls(E->get()); + for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next()) + _generate_method_icalls(E.get()); _generate_method_icalls(builtin_types["NodePath"]); _generate_method_icalls(builtin_types["RID"]); diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h index 717a6b7a6b..8929b45cce 100644 --- a/modules/mono/editor/bindings_generator.h +++ b/modules/mono/editor/bindings_generator.h @@ -429,10 +429,11 @@ class BindingsGenerator { static bool verbose_output; + OrderedHashMap<StringName, TypeInterface> obj_types; + Map<StringName, TypeInterface> placeholder_types; Map<StringName, TypeInterface> builtin_types; Map<StringName, TypeInterface> enum_types; - Map<StringName, TypeInterface> obj_types; List<EnumInterface> global_enums; List<ConstantInterface> global_constants; diff --git a/modules/mono/editor/godotsharp_editor.cpp b/modules/mono/editor/godotsharp_editor.cpp index da0a7b4fbd..9e48da68c1 100644 --- a/modules/mono/editor/godotsharp_editor.cpp +++ b/modules/mono/editor/godotsharp_editor.cpp @@ -151,7 +151,7 @@ Error GodotSharpEditor::open_in_external_editor(const Ref<Script> &p_script, int if (p_line >= 0) { args.push_back("-g"); - args.push_back(script_path + ":" + itos(p_line) + ":" + itos(p_col)); + args.push_back(script_path + ":" + itos(p_line + 1) + ":" + itos(p_col)); } else { args.push_back(script_path); } @@ -170,6 +170,11 @@ Error GodotSharpEditor::open_in_external_editor(const Ref<Script> &p_script, int monodevel_instance = memnew(MonoDevelopInstance(GodotSharpDirs::get_project_sln_path())); String script_path = ProjectSettings::get_singleton()->globalize_path(p_script->get_path()); + + if (p_line >= 0) { + script_path += ";" + itos(p_line + 1) + ";" + itos(p_col); + } + monodevel_instance->execute(script_path); } break; default: diff --git a/modules/mono/glue/cs_files/Color.cs b/modules/mono/glue/cs_files/Color.cs index db0e1fb744..f9e31e9703 100644 --- a/modules/mono/glue/cs_files/Color.cs +++ b/modules/mono/glue/cs_files/Color.cs @@ -336,7 +336,7 @@ namespace Godot this.r = (rgba & 0xFF) / 255.0f; } - private static float _parse_col(string str, int ofs) + private static int _parse_col(string str, int ofs) { int ig = 0; @@ -415,17 +415,17 @@ namespace Godot if (alpha) { - if ((int)_parse_col(color, 0) < 0) + if (_parse_col(color, 0) < 0) return false; } int from = alpha ? 2 : 0; - if ((int)_parse_col(color, from + 0) < 0) + if (_parse_col(color, from + 0) < 0) return false; - if ((int)_parse_col(color, from + 2) < 0) + if (_parse_col(color, from + 2) < 0) return false; - if ((int)_parse_col(color, from + 4) < 0) + if (_parse_col(color, from + 4) < 0) return false; return true; @@ -467,10 +467,10 @@ namespace Godot if (alpha) { - a = _parse_col(rgba, 0); + a = _parse_col(rgba, 0) / 255f; if (a < 0) - throw new ArgumentOutOfRangeException("Invalid color code. Alpha is " + a + " but zero or greater is expected: " + rgba); + throw new ArgumentOutOfRangeException("Invalid color code. Alpha part is not valid hexadecimal: " + rgba); } else { @@ -479,20 +479,20 @@ namespace Godot int from = alpha ? 2 : 0; - r = _parse_col(rgba, from + 0); + r = _parse_col(rgba, from + 0) / 255f; if (r < 0) - throw new ArgumentOutOfRangeException("Invalid color code. Red is " + r + " but zero or greater is expected: " + rgba); + throw new ArgumentOutOfRangeException("Invalid color code. Red part is not valid hexadecimal: " + rgba); - g = _parse_col(rgba, from + 2); + g = _parse_col(rgba, from + 2) / 255f; if (g < 0) - throw new ArgumentOutOfRangeException("Invalid color code. Green is " + g + " but zero or greater is expected: " + rgba); + throw new ArgumentOutOfRangeException("Invalid color code. Green part is not valid hexadecimal: " + rgba); - b = _parse_col(rgba, from + 4); + b = _parse_col(rgba, from + 4) / 255f; if (b < 0) - throw new ArgumentOutOfRangeException("Invalid color code. Blue is " + b + " but zero or greater is expected: " + rgba); + throw new ArgumentOutOfRangeException("Invalid color code. Blue part is not valid hexadecimal: " + rgba); } public static bool operator ==(Color left, Color right) diff --git a/modules/mono/glue/cs_files/DebuggingUtils.cs b/modules/mono/glue/cs_files/DebuggingUtils.cs new file mode 100644 index 0000000000..ced78f658d --- /dev/null +++ b/modules/mono/glue/cs_files/DebuggingUtils.cs @@ -0,0 +1,77 @@ +using System; +using System.Diagnostics; +using System.Reflection; +using System.Text; + +namespace Godot +{ + internal static class DebuggingUtils + { + internal static void AppendTypeName(this StringBuilder sb, Type type) + { + if (type.IsPrimitive) + sb.Append(type.Name); + else if (type == typeof(void)) + sb.Append("void"); + else + sb.Append(type.ToString()); + + sb.Append(" "); + } + + public static void GetStackFrameInfo(StackFrame frame, out string fileName, out int fileLineNumber, out string methodDecl) + { + fileName = frame.GetFileName(); + fileLineNumber = frame.GetFileLineNumber(); + + MethodBase methodBase = frame.GetMethod(); + + StringBuilder sb = new StringBuilder(); + + if (methodBase is MethodInfo methodInfo) + sb.AppendTypeName(methodInfo.ReturnType); + + sb.Append(methodBase.DeclaringType.FullName); + sb.Append("."); + sb.Append(methodBase.Name); + + if (methodBase.IsGenericMethod) + { + Type[] genericParams = methodBase.GetGenericArguments(); + + sb.Append("<"); + + for (int j = 0; j < genericParams.Length; j++) + { + if (j > 0) + sb.Append(", "); + + sb.AppendTypeName(genericParams[j]); + } + + sb.Append(">"); + } + + sb.Append("("); + + bool varArgs = (methodBase.CallingConvention & CallingConventions.VarArgs) != 0; + + ParameterInfo[] parameter = methodBase.GetParameters(); + + for (int i = 0; i < parameter.Length; i++) + { + if (i > 0) + sb.Append(", "); + + if (i == parameter.Length - 1 && varArgs) + sb.Append("params "); + + sb.AppendTypeName(parameter[i].ParameterType); + } + + sb.Append(")"); + + methodDecl = sb.ToString(); + } + } +} diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index d4df7e0cb2..6c07c90f79 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -226,7 +226,7 @@ void GDMono::initialize() { mono_install_unhandled_exception_hook(gdmono_unhandled_exception_hook, NULL); - OS::get_singleton()->print("Mono: ALL IS GOOD\n"); + OS::get_singleton()->print("Mono: INITIALIZED\n"); } #ifndef MONO_GLUE_DISABLED diff --git a/modules/mono/mono_gd/gd_mono_class.cpp b/modules/mono/mono_gd/gd_mono_class.cpp index d3315568cb..b826352f02 100644 --- a/modules/mono/mono_gd/gd_mono_class.cpp +++ b/modules/mono/mono_gd/gd_mono_class.cpp @@ -89,11 +89,6 @@ Vector<MonoClassField *> GDMonoClass::get_enum_fields() { } #endif -bool GDMonoClass::has_method(const StringName &p_name) { - - return get_method(p_name) != NULL; -} - bool GDMonoClass::has_attribute(GDMonoClass *p_attr_class) { #ifdef DEBUG_ENABLED @@ -225,7 +220,7 @@ void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base methods_fetched = true; } -GDMonoMethod *GDMonoClass::get_method(const StringName &p_name) { +GDMonoMethod *GDMonoClass::get_fetched_method_unknown_params(const StringName &p_name) { ERR_FAIL_COND_V(!methods_fetched, NULL); @@ -239,6 +234,11 @@ GDMonoMethod *GDMonoClass::get_method(const StringName &p_name) { return NULL; } +bool GDMonoClass::has_fetched_method_unknown_params(const StringName &p_name) { + + return get_fetched_method_unknown_params(p_name) != NULL; +} + GDMonoMethod *GDMonoClass::get_method(const StringName &p_name, int p_params_count) { MethodKey key = MethodKey(p_name, p_params_count); @@ -303,6 +303,8 @@ GDMonoMethod *GDMonoClass::get_method_with_desc(const String &p_description, boo MonoMethod *method = mono_method_desc_search_in_class(desc, mono_class); mono_method_desc_free(desc); + ERR_FAIL_COND_V(mono_method_get_class(method) != mono_class, NULL); + return get_method(method); } diff --git a/modules/mono/mono_gd/gd_mono_class.h b/modules/mono/mono_gd/gd_mono_class.h index b6052ac0ed..f5895be144 100644 --- a/modules/mono/mono_gd/gd_mono_class.h +++ b/modules/mono/mono_gd/gd_mono_class.h @@ -112,7 +112,8 @@ public: Vector<MonoClassField *> get_enum_fields(); #endif - bool has_method(const StringName &p_name); + GDMonoMethod *get_fetched_method_unknown_params(const StringName &p_name); + bool has_fetched_method_unknown_params(const StringName &p_name); bool has_attribute(GDMonoClass *p_attr_class); MonoObject *get_attribute(GDMonoClass *p_attr_class); @@ -120,8 +121,7 @@ public: void fetch_attributes(); void fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base); - GDMonoMethod *get_method(const StringName &p_name); - GDMonoMethod *get_method(const StringName &p_name, int p_params_count); + GDMonoMethod *get_method(const StringName &p_name, int p_params_count = 0); GDMonoMethod *get_method(MonoMethod *p_raw_method); GDMonoMethod *get_method(MonoMethod *p_raw_method, const StringName &p_name); GDMonoMethod *get_method(MonoMethod *p_raw_method, const StringName &p_name, int p_params_count); diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp index ff999b36f2..d02c73978e 100644 --- a/modules/mono/mono_gd/gd_mono_utils.cpp +++ b/modules/mono/mono_gd/gd_mono_utils.cpp @@ -31,6 +31,7 @@ #include "gd_mono_utils.h" #include "os/dir_access.h" +#include "os/os.h" #include "project_settings.h" #include "reference.h" @@ -53,6 +54,7 @@ MonoCache mono_cache; #define CACHE_NS_CLASS_AND_CHECK(m_ns, m_class, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.class_##m_ns##_##m_class, m_val) #define CACHE_RAW_MONO_CLASS_AND_CHECK(m_class, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.rawclass_##m_class, m_val) #define CACHE_FIELD_AND_CHECK(m_class, m_field, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.field_##m_class##_##m_field, m_val) +#define CACHE_METHOD_AND_CHECK(m_class, m_method, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.method_##m_class##_##m_method, m_val) #define CACHE_METHOD_THUNK_AND_CHECK(m_class, m_method, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.methodthunk_##m_class##_##m_method, m_val) void MonoCache::clear_members() { @@ -72,6 +74,13 @@ void MonoCache::clear_members() { class_String = NULL; class_IntPtr = NULL; +#ifdef DEBUG_ENABLED + class_System_Diagnostics_StackTrace = NULL; + methodthunk_System_Diagnostics_StackTrace_GetFrames = NULL; + method_System_Diagnostics_StackTrace_ctor_bool = NULL; + method_System_Diagnostics_StackTrace_ctor_Exception_bool = NULL; +#endif + rawclass_Dictionary = NULL; class_Vector2 = NULL; @@ -94,6 +103,11 @@ void MonoCache::clear_members() { class_WeakRef = NULL; class_MarshalUtils = NULL; +#ifdef DEBUG_ENABLED + class_DebuggingUtils = NULL; + methodthunk_DebuggingUtils_GetStackFrameInfo = NULL; +#endif + class_ExportAttribute = NULL; field_ExportAttribute_hint = NULL; field_ExportAttribute_hintString = NULL; @@ -137,6 +151,13 @@ void update_corlib_cache() { CACHE_CLASS_AND_CHECK(double, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_double_class())); CACHE_CLASS_AND_CHECK(String, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_string_class())); CACHE_CLASS_AND_CHECK(IntPtr, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_intptr_class())); + +#ifdef DEBUG_ENABLED + CACHE_CLASS_AND_CHECK(System_Diagnostics_StackTrace, GDMono::get_singleton()->get_corlib_assembly()->get_class("System.Diagnostics", "StackTrace")); + CACHE_METHOD_THUNK_AND_CHECK(System_Diagnostics_StackTrace, GetFrames, (StackTrace_GetFrames)CACHED_CLASS(System_Diagnostics_StackTrace)->get_method("GetFrames")->get_thunk()); + CACHE_METHOD_AND_CHECK(System_Diagnostics_StackTrace, ctor_bool, CACHED_CLASS(System_Diagnostics_StackTrace)->get_method_with_desc("System.Diagnostics.StackTrace:.ctor(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 } void update_godot_api_cache() { @@ -161,6 +182,10 @@ void update_godot_api_cache() { CACHE_CLASS_AND_CHECK(WeakRef, GODOT_API_CLASS(WeakRef)); CACHE_CLASS_AND_CHECK(MarshalUtils, GODOT_API_CLASS(MarshalUtils)); +#ifdef DEBUG_ENABLED + CACHE_CLASS_AND_CHECK(DebuggingUtils, GODOT_API_CLASS(DebuggingUtils)); +#endif + // Attributes CACHE_CLASS_AND_CHECK(ExportAttribute, GODOT_API_CLASS(ExportAttribute)); CACHE_FIELD_AND_CHECK(ExportAttribute, hint, CACHED_CLASS(ExportAttribute)->get_field("hint")); @@ -183,6 +208,10 @@ void update_godot_api_cache() { 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()); +#ifdef DEBUG_ENABLED + CACHE_METHOD_THUNK_AND_CHECK(DebuggingUtils, GetStackFrameInfo, (DebugUtils_StackFrameInfo)GODOT_API_CLASS(DebuggingUtils)->get_method("GetStackFrameInfo", 4)->get_thunk()); +#endif + { /* * TODO Right now we only support Dictionary<object, object>. @@ -366,9 +395,47 @@ String get_exception_name_and_message(MonoObject *p_ex) { return res; } -void print_unhandled_exception(MonoObject *p_ex) { - ERR_PRINT(GDMonoUtils::get_exception_name_and_message(p_ex).utf8()); - mono_print_unhandled_exception(p_ex); +void print_unhandled_exception(MonoObject *p_exc) { + print_unhandled_exception(p_exc, false); +} + +void print_unhandled_exception(MonoObject *p_exc, bool p_recursion_caution) { + mono_print_unhandled_exception(p_exc); +#ifdef DEBUG_ENABLED + GDMonoClass *st_klass = CACHED_CLASS(System_Diagnostics_StackTrace); + MonoObject *stack_trace = mono_object_new(mono_domain_get(), st_klass->get_mono_ptr()); + + MonoBoolean need_file_info = true; + void *ctor_args[2] = { p_exc, &need_file_info }; + + MonoObject *unexpected_exc = NULL; + CACHED_METHOD(System_Diagnostics_StackTrace, ctor_Exception_bool)->invoke_raw(stack_trace, ctor_args, &unexpected_exc); + + if (unexpected_exc != NULL) { + mono_print_unhandled_exception(unexpected_exc); + + if (p_recursion_caution) { + // Called from CSharpLanguage::get_current_stack_info, + // so printing an error here could result in endless recursion + OS::get_singleton()->printerr("Mono: Method GDMonoUtils::print_unhandled_exception failed"); + return; + } else { + ERR_FAIL(); + } + } + + Vector<ScriptLanguage::StackInfo> si; + if (stack_trace != NULL && !p_recursion_caution) + si = CSharpLanguage::get_singleton()->stack_trace_get_info(stack_trace); + + String file = si.size() ? si[0].file : __FILE__; + String func = si.size() ? si[0].func : FUNCTION_STR; + int line = si.size() ? si[0].line : __LINE__; + String error_msg = "Unhandled exception"; + String exc_msg = GDMonoUtils::get_exception_name_and_message(p_exc); + + ScriptDebugger::get_singleton()->send_error(func, file, line, error_msg, exc_msg, ERR_HANDLER_ERROR, si); +#endif } } // namespace GDMonoUtils diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h index 284585856e..597397eced 100644 --- a/modules/mono/mono_gd/gd_mono_utils.h +++ b/modules/mono/mono_gd/gd_mono_utils.h @@ -46,13 +46,10 @@ typedef MonoObject *(*MarshalUtils_ArraysToDict)(MonoArray *, MonoArray *, MonoO typedef MonoObject *(*SignalAwaiter_SignalCallback)(MonoObject *, MonoArray **, MonoObject **); typedef MonoObject *(*SignalAwaiter_FailureCallback)(MonoObject *, MonoObject **); typedef MonoObject *(*GodotTaskScheduler_Activate)(MonoObject *, MonoObject **); +typedef MonoArray *(*StackTrace_GetFrames)(MonoObject *, MonoObject **); +typedef void (*DebugUtils_StackFrameInfo)(MonoObject *, MonoString **, int *, MonoString **, MonoObject **); struct MonoCache { - // Format for cached classes in the Godot namespace: class_<Class> - // Macro: CACHED_CLASS(<Class>) - - // Format for cached classes in a different namespace: class_<Namespace>_<Class> - // Macro: CACHED_NS_CLASS(<Namespace>, <Class>) // ----------------------------------------------- // corlib classes @@ -73,6 +70,13 @@ struct MonoCache { GDMonoClass *class_String; GDMonoClass *class_IntPtr; +#ifdef DEBUG_ENABLED + GDMonoClass *class_System_Diagnostics_StackTrace; + StackTrace_GetFrames methodthunk_System_Diagnostics_StackTrace_GetFrames; + GDMonoMethod *method_System_Diagnostics_StackTrace_ctor_bool; + GDMonoMethod *method_System_Diagnostics_StackTrace_ctor_Exception_bool; +#endif + MonoClass *rawclass_Dictionary; // ----------------------------------------------- @@ -96,6 +100,11 @@ struct MonoCache { GDMonoClass *class_WeakRef; GDMonoClass *class_MarshalUtils; +#ifdef DEBUG_ENABLED + GDMonoClass *class_DebuggingUtils; + DebugUtils_StackFrameInfo methodthunk_DebuggingUtils_GetStackFrameInfo; +#endif + GDMonoClass *class_ExportAttribute; GDMonoField *field_ExportAttribute_hint; GDMonoField *field_ExportAttribute_hintString; @@ -167,7 +176,8 @@ MonoDomain *create_domain(const String &p_friendly_name); String get_exception_name_and_message(MonoObject *p_ex); -void print_unhandled_exception(MonoObject *p_ex); +void print_unhandled_exception(MonoObject *p_exc); +void print_unhandled_exception(MonoObject *p_exc, bool p_recursion_caution); } // namespace GDMonoUtils @@ -175,9 +185,9 @@ void print_unhandled_exception(MonoObject *p_ex); #define CACHED_CLASS(m_class) (GDMonoUtils::mono_cache.class_##m_class) #define CACHED_CLASS_RAW(m_class) (GDMonoUtils::mono_cache.class_##m_class->get_mono_ptr()) -#define CACHED_NS_CLASS(m_ns, m_class) (GDMonoUtils::mono_cache.class_##m_ns##_##m_class) #define CACHED_RAW_MONO_CLASS(m_class) (GDMonoUtils::mono_cache.rawclass_##m_class) #define CACHED_FIELD(m_class, m_field) (GDMonoUtils::mono_cache.field_##m_class##_##m_field) +#define CACHED_METHOD(m_class, m_method) (GDMonoUtils::mono_cache.method_##m_class##_##m_method) #define CACHED_METHOD_THUNK(m_class, m_method) (GDMonoUtils::mono_cache.methodthunk_##m_class##_##m_method) #ifdef REAL_T_IS_DOUBLE |