From a116801ec76fa2159191609d0dbef666d92385a4 Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Mon, 15 Apr 2024 22:14:41 +0300 Subject: [PATCH] Improve TextEdit/LineEdit word selection. --- doc/classes/TextServer.xml | 1 + doc/classes/TextServerExtension.xml | 1 + .../4.2-stable.expected | 7 ++++ servers/text/text_server_extension.cpp | 8 ++-- servers/text/text_server_extension.h | 4 +- servers/text_server.compat.inc | 41 +++++++++++++++++++ servers/text_server.cpp | 13 +++--- servers/text_server.h | 7 +++- 8 files changed, 70 insertions(+), 12 deletions(-) create mode 100644 servers/text_server.compat.inc diff --git a/doc/classes/TextServer.xml b/doc/classes/TextServer.xml index c0cd7f79e7e..c30e83a85d6 100644 --- a/doc/classes/TextServer.xml +++ b/doc/classes/TextServer.xml @@ -1505,6 +1505,7 @@ + Breaks text into words and returns array of character ranges. Use [param grapheme_flags] to set what characters are used for breaking (see [enum GraphemeFlag]). diff --git a/doc/classes/TextServerExtension.xml b/doc/classes/TextServerExtension.xml index 06a0daece6d..94fd69c8635 100644 --- a/doc/classes/TextServerExtension.xml +++ b/doc/classes/TextServerExtension.xml @@ -1664,6 +1664,7 @@ + [b]Optional.[/b] Breaks text into words and returns array of character ranges. Use [param grapheme_flags] to set what characters are used for breaking (see [enum TextServer.GraphemeFlag]). diff --git a/misc/extension_api_validation/4.2-stable.expected b/misc/extension_api_validation/4.2-stable.expected index de60e5114c9..4706ed37f0c 100644 --- a/misc/extension_api_validation/4.2-stable.expected +++ b/misc/extension_api_validation/4.2-stable.expected @@ -308,3 +308,10 @@ Validate extension JSON: Error: Field 'classes/XRServer/methods/remove_tracker/a All trackers now have an XRTracker base, and the XRServer uses the XRTracker type. + +GH-90732 +-------- +Validate extension JSON: Error: Field 'classes/TextServer/methods/shaped_text_get_word_breaks/arguments': size changed value in new API, from 2 to 3. +Validate extension JSON: Error: Field 'classes/TextServerExtension/methods/_shaped_text_get_word_breaks/arguments': size changed value in new API, from 2 to 3. + +Added optional argument. Compatibility method registered. diff --git a/servers/text/text_server_extension.cpp b/servers/text/text_server_extension.cpp index 53e1d119fd2..8f9797805f8 100644 --- a/servers/text/text_server_extension.cpp +++ b/servers/text/text_server_extension.cpp @@ -285,7 +285,7 @@ void TextServerExtension::_bind_methods() { GDVIRTUAL_BIND(_shaped_text_get_line_breaks_adv, "shaped", "width", "start", "once", "break_flags"); GDVIRTUAL_BIND(_shaped_text_get_line_breaks, "shaped", "width", "start", "break_flags"); - GDVIRTUAL_BIND(_shaped_text_get_word_breaks, "shaped", "grapheme_flags"); + GDVIRTUAL_BIND(_shaped_text_get_word_breaks, "shaped", "grapheme_flags", "skip_grapheme_flags"); GDVIRTUAL_BIND(_shaped_text_get_trim_pos, "shaped"); GDVIRTUAL_BIND(_shaped_text_get_ellipsis_pos, "shaped"); @@ -1256,12 +1256,12 @@ PackedInt32Array TextServerExtension::shaped_text_get_line_breaks(const RID &p_s return TextServer::shaped_text_get_line_breaks(p_shaped, p_width, p_start, p_break_flags); } -PackedInt32Array TextServerExtension::shaped_text_get_word_breaks(const RID &p_shaped, BitField p_grapheme_flags) const { +PackedInt32Array TextServerExtension::shaped_text_get_word_breaks(const RID &p_shaped, BitField p_grapheme_flags, BitField p_skip_grapheme_flags) const { PackedInt32Array ret; - if (GDVIRTUAL_CALL(_shaped_text_get_word_breaks, p_shaped, p_grapheme_flags, ret)) { + if (GDVIRTUAL_CALL(_shaped_text_get_word_breaks, p_shaped, p_grapheme_flags, p_skip_grapheme_flags, ret)) { return ret; } - return TextServer::shaped_text_get_word_breaks(p_shaped, p_grapheme_flags); + return TextServer::shaped_text_get_word_breaks(p_shaped, p_grapheme_flags, p_skip_grapheme_flags); } int64_t TextServerExtension::shaped_text_get_trim_pos(const RID &p_shaped) const { diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h index 53d30abee42..f447f0f5bdd 100644 --- a/servers/text/text_server_extension.h +++ b/servers/text/text_server_extension.h @@ -472,10 +472,10 @@ public: virtual PackedInt32Array shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start = 0, bool p_once = true, BitField p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const override; virtual PackedInt32Array shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start = 0, BitField p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const override; - virtual PackedInt32Array shaped_text_get_word_breaks(const RID &p_shaped, BitField p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const override; + virtual PackedInt32Array shaped_text_get_word_breaks(const RID &p_shaped, BitField p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION, BitField p_skip_grapheme_flags = GRAPHEME_IS_VIRTUAL) const override; GDVIRTUAL5RC(PackedInt32Array, _shaped_text_get_line_breaks_adv, RID, const PackedFloat32Array &, int64_t, bool, BitField); GDVIRTUAL4RC(PackedInt32Array, _shaped_text_get_line_breaks, RID, double, int64_t, BitField); - GDVIRTUAL2RC(PackedInt32Array, _shaped_text_get_word_breaks, RID, BitField); + GDVIRTUAL3RC(PackedInt32Array, _shaped_text_get_word_breaks, RID, BitField, BitField); virtual int64_t shaped_text_get_trim_pos(const RID &p_shaped) const override; virtual int64_t shaped_text_get_ellipsis_pos(const RID &p_shaped) const override; diff --git a/servers/text_server.compat.inc b/servers/text_server.compat.inc new file mode 100644 index 00000000000..0ff35721a3f --- /dev/null +++ b/servers/text_server.compat.inc @@ -0,0 +1,41 @@ +/**************************************************************************/ +/* text_server.compat.inc */ +/**************************************************************************/ +/* 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. */ +/**************************************************************************/ + +#ifndef DISABLE_DEPRECATED + +PackedInt32Array TextServer::_shaped_text_get_word_breaks_bind_compat_90732(const RID &p_shaped, BitField p_grapheme_flags) const { + return shaped_text_get_word_breaks(p_shaped, p_grapheme_flags, 0); +} + +void TextServer::_bind_compatibility_methods() { + ClassDB::bind_compatibility_method(D_METHOD("shaped_text_get_word_breaks", "shaped", "grapheme_flags"), &TextServer::_shaped_text_get_word_breaks_bind_compat_90732, DEFVAL(GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION)); +} + +#endif diff --git a/servers/text_server.cpp b/servers/text_server.cpp index fac9e32d01b..562f2df411c 100644 --- a/servers/text_server.cpp +++ b/servers/text_server.cpp @@ -29,6 +29,8 @@ /**************************************************************************/ #include "servers/text_server.h" +#include "text_server.compat.inc" + #include "core/variant/typed_array.h" #include "servers/rendering_server.h" @@ -435,7 +437,7 @@ void TextServer::_bind_methods() { ClassDB::bind_method(D_METHOD("shaped_text_get_range", "shaped"), &TextServer::shaped_text_get_range); ClassDB::bind_method(D_METHOD("shaped_text_get_line_breaks_adv", "shaped", "width", "start", "once", "break_flags"), &TextServer::shaped_text_get_line_breaks_adv, DEFVAL(0), DEFVAL(true), DEFVAL(BREAK_MANDATORY | BREAK_WORD_BOUND)); ClassDB::bind_method(D_METHOD("shaped_text_get_line_breaks", "shaped", "width", "start", "break_flags"), &TextServer::shaped_text_get_line_breaks, DEFVAL(0), DEFVAL(BREAK_MANDATORY | BREAK_WORD_BOUND)); - ClassDB::bind_method(D_METHOD("shaped_text_get_word_breaks", "shaped", "grapheme_flags"), &TextServer::shaped_text_get_word_breaks, DEFVAL(GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION)); + ClassDB::bind_method(D_METHOD("shaped_text_get_word_breaks", "shaped", "grapheme_flags", "skip_grapheme_flags"), &TextServer::shaped_text_get_word_breaks, DEFVAL(GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION), DEFVAL(GRAPHEME_IS_VIRTUAL)); ClassDB::bind_method(D_METHOD("shaped_text_get_trim_pos", "shaped"), &TextServer::shaped_text_get_trim_pos); ClassDB::bind_method(D_METHOD("shaped_text_get_ellipsis_pos", "shaped"), &TextServer::shaped_text_get_ellipsis_pos); @@ -1094,7 +1096,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do return lines; } -PackedInt32Array TextServer::shaped_text_get_word_breaks(const RID &p_shaped, BitField p_grapheme_flags) const { +PackedInt32Array TextServer::shaped_text_get_word_breaks(const RID &p_shaped, BitField p_grapheme_flags, BitField p_skip_grapheme_flags) const { PackedInt32Array words; const_cast(this)->shaped_text_update_justification_ops(p_shaped); @@ -1107,10 +1109,11 @@ PackedInt32Array TextServer::shaped_text_get_word_breaks(const RID &p_shaped, Bi for (int i = 0; i < l_size; i++) { if (l_gl[i].count > 0) { - if ((l_gl[i].flags & p_grapheme_flags) != 0) { - if (word_start != l_gl[i].start) { + if ((l_gl[i].flags & p_grapheme_flags) != 0 && (l_gl[i].flags & p_skip_grapheme_flags) == 0) { + int next = (i == 0) ? l_gl[i].start : l_gl[i - 1].end; + if (word_start < next) { words.push_back(word_start); - words.push_back(l_gl[i].start); + words.push_back(next); } word_start = l_gl[i].end; } diff --git a/servers/text_server.h b/servers/text_server.h index 396d7ca8e5e..775dbb55086 100644 --- a/servers/text_server.h +++ b/servers/text_server.h @@ -226,6 +226,11 @@ protected: static void _bind_methods(); +#ifndef DISABLE_DEPRECATED + PackedInt32Array _shaped_text_get_word_breaks_bind_compat_90732(const RID &p_shaped, BitField p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const; + static void _bind_compatibility_methods(); +#endif + public: virtual bool has_feature(Feature p_feature) const = 0; virtual String get_name() const = 0; @@ -483,7 +488,7 @@ public: virtual PackedInt32Array shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start = 0, bool p_once = true, BitField p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const; virtual PackedInt32Array shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start = 0, BitField p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const; - virtual PackedInt32Array shaped_text_get_word_breaks(const RID &p_shaped, BitField p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const; + virtual PackedInt32Array shaped_text_get_word_breaks(const RID &p_shaped, BitField p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION, BitField p_skip_grapheme_flags = GRAPHEME_IS_VIRTUAL) const; virtual int64_t shaped_text_get_trim_pos(const RID &p_shaped) const = 0; virtual int64_t shaped_text_get_ellipsis_pos(const RID &p_shaped) const = 0;