diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml index 3b6f81aebc6..7331b5a6812 100644 --- a/doc/classes/TextEdit.xml +++ b/doc/classes/TextEdit.xml @@ -349,9 +349,12 @@ - + + - Returns the line and column at the given position. In the returned vector, [code]x[/code] is the column, [code]y[/code] is the line. If [param allow_out_of_bounds] is [code]false[/code] and the position is not over the text, both vector values will be set to [code]-1[/code]. + Returns the line and column at the given position. In the returned vector, [code]x[/code] is the column and [code]y[/code] is the line. + If [param clamp_line] is [code]false[/code] and [param position] is below the last line, [code]Vector2i(-1, -1)[/code] is returned. + If [param clamp_column] is [code]false[/code] and [param position] is outside the column range of the line, [code]Vector2i(-1, -1)[/code] is returned. diff --git a/misc/extension_api_validation/4.3-stable.expected b/misc/extension_api_validation/4.3-stable.expected index 7b5889f464b..9c96811f875 100644 --- a/misc/extension_api_validation/4.3-stable.expected +++ b/misc/extension_api_validation/4.3-stable.expected @@ -309,3 +309,10 @@ Validate extension JSON: API was removed: classes/EditorSceneFormatImporter/meth This virtual method, and the internal public `get_import_flags`, were never used by the engine, since it was open sourced. So we're removing it despite the compat breakage as there's no way for users to rely on this affecting engine behavior. + + +GH-100913 +--------- +Validate extension JSON: Error: Field 'classes/TextEdit/methods/get_line_column_at_pos/arguments': size changed value in new API, from 2 to 3. + +Added optional argument to disallow positions that are outside the column range of the line. Compatibility method registered. diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp index 66080e51035..98cdd549acc 100644 --- a/scene/gui/code_edit.cpp +++ b/scene/gui/code_edit.cpp @@ -420,7 +420,7 @@ void CodeEdit::gui_input(const Ref &p_gui_input) { mpos.x = get_size().x - mpos.x; } - Point2i pos = get_line_column_at_pos(mpos, false); + Point2i pos = get_line_column_at_pos(mpos, false, false); int line = pos.y; int col = pos.x; @@ -442,18 +442,18 @@ void CodeEdit::gui_input(const Ref &p_gui_input) { if (symbol_lookup_on_click_enabled) { if (mm->is_command_or_control_pressed() && mm->get_button_mask().is_empty()) { - symbol_lookup_pos = get_line_column_at_pos(mpos); + symbol_lookup_pos = get_line_column_at_pos(mpos, false, false); symbol_lookup_new_word = get_word_at_pos(mpos); if (symbol_lookup_new_word != symbol_lookup_word) { emit_signal(SNAME("symbol_validate"), symbol_lookup_new_word); } - } else if (!mm->is_command_or_control_pressed() || (!mm->get_button_mask().is_empty() && symbol_lookup_pos != get_line_column_at_pos(mpos))) { + } else if (!mm->is_command_or_control_pressed() || (!mm->get_button_mask().is_empty() && symbol_lookup_pos != get_line_column_at_pos(mpos, false, false))) { set_symbol_lookup_word_as_valid(false); } } if (symbol_tooltip_on_hover_enabled) { - symbol_tooltip_pos = get_line_column_at_pos(mpos, false); + symbol_tooltip_pos = get_line_column_at_pos(mpos, false, false); symbol_tooltip_word = get_word_at_pos(mpos); symbol_tooltip_timer->start(); } @@ -2387,7 +2387,7 @@ bool CodeEdit::is_symbol_lookup_on_click_enabled() const { String CodeEdit::get_text_for_symbol_lookup() const { Point2i mp = get_local_mouse_pos(); - Point2i pos = get_line_column_at_pos(mp, false); + Point2i pos = get_line_column_at_pos(mp, false, false); int line = pos.y; int col = pos.x; diff --git a/scene/gui/text_edit.compat.inc b/scene/gui/text_edit.compat.inc index bf73229868e..d15740390e9 100644 --- a/scene/gui/text_edit.compat.inc +++ b/scene/gui/text_edit.compat.inc @@ -34,8 +34,13 @@ void TextEdit::_set_selection_mode_compat_86978(SelectionMode p_mode, int p_line set_selection_mode(p_mode); } +Point2i TextEdit::_get_line_column_at_pos_bind_compat_100913(const Point2i &p_pos, bool p_allow_out_of_bounds) const { + return get_line_column_at_pos(p_pos, p_allow_out_of_bounds, true); +} + void TextEdit::_bind_compatibility_methods() { ClassDB::bind_compatibility_method(D_METHOD("set_selection_mode", "mode", "line", "column", "caret_index"), &TextEdit::_set_selection_mode_compat_86978, DEFVAL(-1), DEFVAL(-1), DEFVAL(0)); + ClassDB::bind_compatibility_method(D_METHOD("get_line_column_at_pos", "position", "allow_out_of_bounds"), &TextEdit::_get_line_column_at_pos_bind_compat_100913, DEFVAL(true)); } #endif diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 4943e7ee34c..aa85b3d9cc8 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -4370,9 +4370,12 @@ Point2 TextEdit::get_local_mouse_pos() const { } String TextEdit::get_word_at_pos(const Vector2 &p_pos) const { - Point2i pos = get_line_column_at_pos(p_pos); + Point2i pos = get_line_column_at_pos(p_pos, false, false); int row = pos.y; int col = pos.x; + if (row < 0 || col < 0) { + return ""; + } String s = text[row]; if (s.length() == 0) { @@ -4408,7 +4411,7 @@ String TextEdit::get_word_at_pos(const Vector2 &p_pos) const { return String(); } -Point2i TextEdit::get_line_column_at_pos(const Point2i &p_pos, bool p_allow_out_of_bounds) const { +Point2i TextEdit::get_line_column_at_pos(const Point2i &p_pos, bool p_clamp_line, bool p_clamp_column) const { float rows = p_pos.y - theme_cache.style_normal->get_margin(SIDE_TOP); if (!editable) { rows -= theme_cache.style_readonly->get_offset().y / 2; @@ -4435,10 +4438,10 @@ Point2i TextEdit::get_line_column_at_pos(const Point2i &p_pos, bool p_allow_out_ int visible_lines = get_visible_line_count_in_range(first_vis_line, row); if (rows > visible_lines) { - if (!p_allow_out_of_bounds) { - return Point2i(-1, -1); + if (p_clamp_line) { + return Point2i(text[row].length(), row); } - return Point2i(text[row].length(), row); + return Point2i(-1, -1); } int colx = p_pos.x - (theme_cache.style_normal->get_margin(SIDE_LEFT) + gutters_width + gutter_padding); @@ -4455,6 +4458,11 @@ Point2i TextEdit::get_line_column_at_pos(const Point2i &p_pos, bool p_allow_out_ } else { colx -= wrap_indent; } + + if (!p_clamp_column && (colx < 0 || colx > TS->shaped_text_get_size(text_rid).x)) { + return Point2i(-1, -1); + } + int col = TS->shaped_text_hit_test_position(text_rid, colx); if (!caret_mid_grapheme_enabled) { col = TS->shaped_text_closest_character_pos(text_rid, col); @@ -6642,7 +6650,7 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("get_word_at_pos", "position"), &TextEdit::get_word_at_pos); - ClassDB::bind_method(D_METHOD("get_line_column_at_pos", "position", "allow_out_of_bounds"), &TextEdit::get_line_column_at_pos, DEFVAL(true)); + ClassDB::bind_method(D_METHOD("get_line_column_at_pos", "position", "clamp_line", "clamp_column"), &TextEdit::get_line_column_at_pos, DEFVAL(true), DEFVAL(true)); ClassDB::bind_method(D_METHOD("get_pos_at_line_column", "line", "column"), &TextEdit::get_pos_at_line_column); ClassDB::bind_method(D_METHOD("get_rect_at_line_column", "line", "column"), &TextEdit::get_rect_at_line_column); diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 9109e346c6c..44168a8a268 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -657,6 +657,7 @@ protected: #ifndef DISABLE_DEPRECATED void _set_selection_mode_compat_86978(SelectionMode p_mode, int p_line = -1, int p_column = -1, int p_caret = 0); + Point2i _get_line_column_at_pos_bind_compat_100913(const Point2i &p_pos, bool p_allow_out_of_bounds = true) const; static void _bind_compatibility_methods(); #endif // DISABLE_DEPRECATED @@ -859,7 +860,7 @@ public: String get_word_at_pos(const Vector2 &p_pos) const; - Point2i get_line_column_at_pos(const Point2i &p_pos, bool p_allow_out_of_bounds = true) const; + Point2i get_line_column_at_pos(const Point2i &p_pos, bool p_clamp_line = true, bool p_clamp_column = true) const; Point2i get_pos_at_line_column(int p_line, int p_column) const; Rect2i get_rect_at_line_column(int p_line, int p_column) const;