summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/csg/csg.cpp2
-rw-r--r--modules/freetype/SCsub33
-rw-r--r--modules/freetype/config.py8
-rw-r--r--modules/gdscript/tests/gdscript_test_runner.cpp5
-rw-r--r--modules/lightmapper_rd/lightmapper_rd.h2
-rw-r--r--modules/mono/config.py50
-rw-r--r--modules/mono/editor/code_completion.cpp2
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs16
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs59
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs58
-rw-r--r--modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs16
-rw-r--r--modules/multiplayer/editor/replication_editor_plugin.cpp3
-rw-r--r--modules/multiplayer/editor/replication_editor_plugin.h2
-rw-r--r--modules/regex/doc_classes/RegEx.xml9
-rw-r--r--modules/regex/regex.cpp13
-rw-r--r--modules/regex/regex.h5
-rw-r--r--modules/text_server_adv/SCsub22
-rw-r--r--modules/text_server_adv/config.py8
-rw-r--r--modules/text_server_adv/text_server_adv.cpp275
-rw-r--r--modules/text_server_adv/text_server_adv.h5
-rw-r--r--modules/text_server_fb/text_server_fb.cpp2
-rw-r--r--modules/visual_script/editor/visual_script_editor.cpp67
-rw-r--r--modules/visual_script/editor/visual_script_editor.h26
23 files changed, 569 insertions, 119 deletions
diff --git a/modules/csg/csg.cpp b/modules/csg/csg.cpp
index 93533e1690..6b05c146e6 100644
--- a/modules/csg/csg.cpp
+++ b/modules/csg/csg.cpp
@@ -729,7 +729,7 @@ void CSGBrushOperation::MeshMerge::mark_inside_faces() {
}
}
-void CSGBrushOperation::MeshMerge::add_face(const Vector3 p_points[], const Vector2 p_uvs[], bool p_smooth, bool p_invert, const Ref<Material> &p_material, bool p_from_b) {
+void CSGBrushOperation::MeshMerge::add_face(const Vector3 p_points[3], const Vector2 p_uvs[3], bool p_smooth, bool p_invert, const Ref<Material> &p_material, bool p_from_b) {
int indices[3];
for (int i = 0; i < 3; i++) {
VertexKey vk;
diff --git a/modules/freetype/SCsub b/modules/freetype/SCsub
index 4b2ea6faa5..8efcd72fb6 100644
--- a/modules/freetype/SCsub
+++ b/modules/freetype/SCsub
@@ -58,22 +58,23 @@ if env["builtin_freetype"]:
]
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
- thirdparty_brotli_dir = "#thirdparty/brotli/"
- thirdparty_brotli_sources = [
- "common/constants.c",
- "common/context.c",
- "common/dictionary.c",
- "common/platform.c",
- "common/shared_dictionary.c",
- "common/transform.c",
- "dec/bit_reader.c",
- "dec/decode.c",
- "dec/huffman.c",
- "dec/state.c",
- ]
- thirdparty_sources += [thirdparty_brotli_dir + file for file in thirdparty_brotli_sources]
- env_freetype.Append(CPPDEFINES=["FT_CONFIG_OPTION_USE_BROTLI"])
- env_freetype.Prepend(CPPPATH=[thirdparty_brotli_dir + "include"])
+ if env["brotli"]:
+ thirdparty_brotli_dir = "#thirdparty/brotli/"
+ thirdparty_brotli_sources = [
+ "common/constants.c",
+ "common/context.c",
+ "common/dictionary.c",
+ "common/platform.c",
+ "common/shared_dictionary.c",
+ "common/transform.c",
+ "dec/bit_reader.c",
+ "dec/decode.c",
+ "dec/huffman.c",
+ "dec/state.c",
+ ]
+ thirdparty_sources += [thirdparty_brotli_dir + file for file in thirdparty_brotli_sources]
+ env_freetype.Append(CPPDEFINES=["FT_CONFIG_OPTION_USE_BROTLI"])
+ env_freetype.Prepend(CPPPATH=[thirdparty_brotli_dir + "include"])
if env.get("use_ubsan") or env.get("use_asan") or env.get("use_tsan") or env.get("use_lsan") or env.get("use_msan"):
env_freetype.Append(CPPDEFINES=["BROTLI_BUILD_PORTABLE"])
diff --git a/modules/freetype/config.py b/modules/freetype/config.py
index d22f9454ed..c0586d5536 100644
--- a/modules/freetype/config.py
+++ b/modules/freetype/config.py
@@ -2,5 +2,13 @@ def can_build(env, platform):
return True
+def get_opts(platform):
+ from SCons.Variables import BoolVariable
+
+ return [
+ BoolVariable("brotli", "Enable Brotli decompressor for WOFF2 fonts support", True),
+ ]
+
+
def configure(env):
pass
diff --git a/modules/gdscript/tests/gdscript_test_runner.cpp b/modules/gdscript/tests/gdscript_test_runner.cpp
index ff4832bde0..e3b956369d 100644
--- a/modules/gdscript/tests/gdscript_test_runner.cpp
+++ b/modules/gdscript/tests/gdscript_test_runner.cpp
@@ -36,6 +36,7 @@
#include "../gdscript_parser.h"
#include "core/config/project_settings.h"
+#include "core/core_globals.h"
#include "core/core_string_names.h"
#include "core/io/dir_access.h"
#include "core/io/file_access_pack.h"
@@ -142,8 +143,8 @@ GDScriptTestRunner::GDScriptTestRunner(const String &p_source_dir, bool p_init_l
#endif
// Enable printing to show results
- _print_line_enabled = true;
- _print_error_enabled = true;
+ CoreGlobals::print_line_enabled = true;
+ CoreGlobals::print_error_enabled = true;
}
GDScriptTestRunner::~GDScriptTestRunner() {
diff --git a/modules/lightmapper_rd/lightmapper_rd.h b/modules/lightmapper_rd/lightmapper_rd.h
index 88860ad0d4..bf6b4399ca 100644
--- a/modules/lightmapper_rd/lightmapper_rd.h
+++ b/modules/lightmapper_rd/lightmapper_rd.h
@@ -183,7 +183,7 @@ class LightmapperRD : public Lightmapper {
}
};
- void _plot_triangle_into_triangle_index_list(int p_size, const Vector3i &p_ofs, const AABB &p_bounds, const Vector3 p_points[], uint32_t p_triangle_index, LocalVector<TriangleSort> &triangles, uint32_t p_grid_size);
+ void _plot_triangle_into_triangle_index_list(int p_size, const Vector3i &p_ofs, const AABB &p_bounds, const Vector3 p_points[3], uint32_t p_triangle_index, LocalVector<TriangleSort> &triangles, uint32_t p_grid_size);
struct RasterPushConstant {
float atlas_size[2] = {};
diff --git a/modules/mono/config.py b/modules/mono/config.py
index 3e6584590c..d895d2d92d 100644
--- a/modules/mono/config.py
+++ b/modules/mono/config.py
@@ -5,52 +5,44 @@ def can_build(env, platform):
return not env["arch"].startswith("rv")
-def configure(env):
- platform = env["platform"]
-
- if platform not in supported_platforms:
- raise RuntimeError("This module does not currently support building for this platform")
-
- env.add_module_version_string("mono")
-
- from SCons.Script import BoolVariable, PathVariable, Variables, Help
+def get_opts(platform):
+ from SCons.Variables import BoolVariable, PathVariable
default_mono_static = platform in ["ios", "javascript"]
default_mono_bundles_zlib = platform in ["javascript"]
- envvars = Variables()
- envvars.Add(
+ return [
PathVariable(
"mono_prefix",
"Path to the Mono installation directory for the target platform and architecture",
"",
PathVariable.PathAccept,
- )
- )
- envvars.Add(
+ ),
PathVariable(
"mono_bcl",
"Path to a custom Mono BCL (Base Class Library) directory for the target platform",
"",
PathVariable.PathAccept,
- )
- )
- envvars.Add(BoolVariable("mono_static", "Statically link Mono", default_mono_static))
- envvars.Add(BoolVariable("mono_glue", "Build with the Mono glue sources", True))
- envvars.Add(BoolVariable("build_cil", "Build C# solutions", True))
- envvars.Add(
- BoolVariable("copy_mono_root", "Make a copy of the Mono installation directory to bundle with the editor", True)
- )
-
- # TODO: It would be great if this could be detected automatically instead
- envvars.Add(
+ ),
+ BoolVariable("mono_static", "Statically link Mono", default_mono_static),
+ BoolVariable("mono_glue", "Build with the Mono glue sources", True),
+ BoolVariable("build_cil", "Build C# solutions", True),
+ BoolVariable(
+ "copy_mono_root", "Make a copy of the Mono installation directory to bundle with the editor", True
+ ),
BoolVariable(
"mono_bundles_zlib", "Specify if the Mono runtime was built with bundled zlib", default_mono_bundles_zlib
- )
- )
+ ),
+ ]
+
+
+def configure(env):
+ platform = env["platform"]
- envvars.Update(env)
- Help(envvars.GenerateHelpText(env))
+ if platform not in supported_platforms:
+ raise RuntimeError("This module does not currently support building for this platform")
+
+ env.add_module_version_string("mono")
if env["mono_bundles_zlib"]:
# Mono may come with zlib bundled for WASM or on newer version when built with MinGW.
diff --git a/modules/mono/editor/code_completion.cpp b/modules/mono/editor/code_completion.cpp
index a1789412f4..7bce6f2c21 100644
--- a/modules/mono/editor/code_completion.cpp
+++ b/modules/mono/editor/code_completion.cpp
@@ -172,7 +172,7 @@ PackedStringArray get_code_completion(CompletionKind p_kind, const String &p_scr
}
} break;
case CompletionKind::SHADER_PARAMS: {
- print_verbose("Shared params completion for C# not implemented.");
+ print_verbose("Shader uniforms completion for C# is not implemented yet.");
} break;
case CompletionKind::SIGNALS: {
Ref<Script> script = ResourceLoader::load(p_script_file.simplify_path());
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs
index b1f1decd72..437878818c 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs
@@ -828,6 +828,22 @@ namespace Godot
}
/// <summary>
+ /// Constructs a pure scale basis matrix with no rotation or shearing.
+ /// The scale values are set as the main diagonal of the matrix,
+ /// and all of the other parts of the matrix are zero.
+ /// </summary>
+ /// <param name="scale">The scale Vector3.</param>
+ /// <returns>A pure scale Basis matrix.</returns>
+ public static Basis FromScale(Vector3 scale)
+ {
+ return new Basis(
+ scale.x, 0, 0,
+ 0, scale.y, 0,
+ 0, 0, scale.z
+ );
+ }
+
+ /// <summary>
/// Composes these two basis matrices by multiplying them
/// together. This has the effect of transforming the second basis
/// (the child) by the first basis (the parent).
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
index 7861ece61b..68d097eb4e 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs
@@ -297,7 +297,9 @@ namespace Godot
}
/// <summary>
- /// Rotates the transform by <paramref name="angle"/> (in radians), using matrix multiplication.
+ /// Rotates the transform by <paramref name="angle"/> (in radians).
+ /// The operation is done in the parent/global frame, equivalent to
+ /// multiplying the matrix from the left.
/// </summary>
/// <param name="angle">The angle to rotate, in radians.</param>
/// <returns>The rotated transformation matrix.</returns>
@@ -307,7 +309,21 @@ namespace Godot
}
/// <summary>
- /// Scales the transform by the given scaling factor, using matrix multiplication.
+ /// Rotates the transform by <paramref name="angle"/> (in radians).
+ /// The operation is done in the local frame, equivalent to
+ /// multiplying the matrix from the right.
+ /// </summary>
+ /// <param name="angle">The angle to rotate, in radians.</param>
+ /// <returns>The rotated transformation matrix.</returns>
+ public Transform2D RotatedLocal(real_t angle)
+ {
+ return new Transform2D(angle, new Vector2()) * this;
+ }
+
+ /// <summary>
+ /// Scales the transform by the given scaling factor.
+ /// The operation is done in the parent/global frame, equivalent to
+ /// multiplying the matrix from the left.
/// </summary>
/// <param name="scale">The scale to introduce.</param>
/// <returns>The scaled transformation matrix.</returns>
@@ -320,12 +336,19 @@ namespace Godot
return copy;
}
- private void ScaleBasis(Vector2 scale)
+ /// <summary>
+ /// Scales the transform by the given scaling factor.
+ /// The operation is done in the local frame, equivalent to
+ /// multiplying the matrix from the right.
+ /// </summary>
+ /// <param name="scale">The scale to introduce.</param>
+ /// <returns>The scaled transformation matrix.</returns>
+ public Transform2D ScaledLocal(Vector2 scale)
{
- x.x *= scale.x;
- x.y *= scale.y;
- y.x *= scale.x;
- y.y *= scale.y;
+ Transform2D copy = this;
+ copy.x *= scale;
+ copy.y *= scale;
+ return copy;
}
private real_t Tdotx(Vector2 with)
@@ -339,11 +362,23 @@ namespace Godot
}
/// <summary>
- /// Translates the transform by the given <paramref name="offset"/>,
- /// relative to the transform's basis vectors.
- ///
- /// Unlike <see cref="Rotated"/> and <see cref="Scaled"/>,
- /// this does not use matrix multiplication.
+ /// Translates the transform by the given <paramref name="offset"/>.
+ /// The operation is done in the parent/global frame, equivalent to
+ /// multiplying the matrix from the left.
+ /// </summary>
+ /// <param name="offset">The offset to translate by.</param>
+ /// <returns>The translated matrix.</returns>
+ public Transform2D Translated(Vector2 offset)
+ {
+ Transform2D copy = this;
+ copy.origin += offset;
+ return copy;
+ }
+
+ /// <summary>
+ /// Translates the transform by the given <paramref name="offset"/>.
+ /// The operation is done in the local frame, equivalent to
+ /// multiplying the matrix from the right.
/// </summary>
/// <param name="offset">The offset to translate by.</param>
/// <returns>The translated matrix.</returns>
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs
index 97b4a87713..9eaf4f3252 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs
@@ -186,8 +186,10 @@ namespace Godot
}
/// <summary>
- /// Rotates the transform around the given <paramref name="axis"/> by <paramref name="angle"/> (in radians),
- /// using matrix multiplication. The axis must be a normalized vector.
+ /// Rotates the transform around the given <paramref name="axis"/> by <paramref name="angle"/> (in radians).
+ /// The axis must be a normalized vector.
+ /// The operation is done in the parent/global frame, equivalent to
+ /// multiplying the matrix from the left.
/// </summary>
/// <param name="axis">The axis to rotate around. Must be normalized.</param>
/// <param name="angle">The angle to rotate, in radians.</param>
@@ -198,7 +200,24 @@ namespace Godot
}
/// <summary>
- /// Scales the transform by the given 3D scaling factor, using matrix multiplication.
+ /// Rotates the transform around the given <paramref name="axis"/> by <paramref name="angle"/> (in radians).
+ /// The axis must be a normalized vector.
+ /// The operation is done in the local frame, equivalent to
+ /// multiplying the matrix from the right.
+ /// </summary>
+ /// <param name="axis">The axis to rotate around. Must be normalized.</param>
+ /// <param name="angle">The angle to rotate, in radians.</param>
+ /// <returns>The rotated transformation matrix.</returns>
+ public Transform3D RotatedLocal(Vector3 axis, real_t angle)
+ {
+ Basis tmpBasis = new Basis(axis, angle);
+ return new Transform3D(basis * tmpBasis, origin);
+ }
+
+ /// <summary>
+ /// Scales the transform by the given 3D <paramref name="scale"/> factor.
+ /// The operation is done in the parent/global frame, equivalent to
+ /// multiplying the matrix from the left.
/// </summary>
/// <param name="scale">The scale to introduce.</param>
/// <returns>The scaled transformation matrix.</returns>
@@ -207,6 +226,19 @@ namespace Godot
return new Transform3D(basis.Scaled(scale), origin * scale);
}
+ /// <summary>
+ /// Scales the transform by the given 3D <paramref name="scale"/> factor.
+ /// The operation is done in the local frame, equivalent to
+ /// multiplying the matrix from the right.
+ /// </summary>
+ /// <param name="scale">The scale to introduce.</param>
+ /// <returns>The scaled transformation matrix.</returns>
+ public Transform3D ScaledLocal(Vector3 scale)
+ {
+ Basis tmpBasis = Basis.FromScale(scale);
+ return new Transform3D(basis * tmpBasis, origin);
+ }
+
private void SetLookAt(Vector3 eye, Vector3 target, Vector3 up)
{
// Make rotation matrix
@@ -231,11 +263,21 @@ namespace Godot
}
/// <summary>
- /// Translates the transform by the given <paramref name="offset"/>,
- /// relative to the transform's basis vectors.
- ///
- /// Unlike <see cref="Rotated"/> and <see cref="Scaled"/>,
- /// this does not use matrix multiplication.
+ /// Translates the transform by the given <paramref name="offset"/>.
+ /// The operation is done in the parent/global frame, equivalent to
+ /// multiplying the matrix from the left.
+ /// </summary>
+ /// <param name="offset">The offset to translate by.</param>
+ /// <returns>The translated matrix.</returns>
+ public Transform3D Translated(Vector3 offset)
+ {
+ return new Transform3D(basis, origin + offset);
+ }
+
+ /// <summary>
+ /// Translates the transform by the given <paramref name="offset"/>.
+ /// The operation is done in the local frame, equivalent to
+ /// multiplying the matrix from the right.
/// </summary>
/// <param name="offset">The offset to translate by.</param>
/// <returns>The translated matrix.</returns>
diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
index ec2e724b10..c3d5fbfdef 100644
--- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
+++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs
@@ -620,22 +620,6 @@ namespace Godot
);
}
- /// <summary>
- /// Returns a diagonal matrix with the vector as main diagonal.
- ///
- /// This is equivalent to a <see cref="Basis"/> with no rotation or shearing and
- /// this vector's components set as the scale.
- /// </summary>
- /// <returns>A <see cref="Basis"/> with the vector as its main diagonal.</returns>
- public Basis ToDiagonalMatrix()
- {
- return new Basis(
- x, 0, 0,
- 0, y, 0,
- 0, 0, z
- );
- }
-
// Constants
private static readonly Vector3 _zero = new Vector3(0, 0, 0);
private static readonly Vector3 _one = new Vector3(1, 1, 1);
diff --git a/modules/multiplayer/editor/replication_editor_plugin.cpp b/modules/multiplayer/editor/replication_editor_plugin.cpp
index c6484264d0..1f79b8c3e3 100644
--- a/modules/multiplayer/editor/replication_editor_plugin.cpp
+++ b/modules/multiplayer/editor/replication_editor_plugin.cpp
@@ -32,9 +32,12 @@
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
#include "editor/inspector_dock.h"
+#include "editor/scene_tree_editor.h"
#include "modules/multiplayer/multiplayer_synchronizer.h"
#include "scene/gui/dialogs.h"
+#include "scene/gui/separator.h"
#include "scene/gui/tree.h"
void ReplicationEditor::_pick_node_filter_text_changed(const String &p_newtext) {
diff --git a/modules/multiplayer/editor/replication_editor_plugin.h b/modules/multiplayer/editor/replication_editor_plugin.h
index 0bb2cb888d..5cc2bbe937 100644
--- a/modules/multiplayer/editor/replication_editor_plugin.h
+++ b/modules/multiplayer/editor/replication_editor_plugin.h
@@ -40,7 +40,9 @@
class ConfirmationDialog;
class MultiplayerSynchronizer;
+class SceneTreeDialog;
class Tree;
+class TreeItem;
class ReplicationEditor : public VBoxContainer {
GDCLASS(ReplicationEditor, VBoxContainer);
diff --git a/modules/regex/doc_classes/RegEx.xml b/modules/regex/doc_classes/RegEx.xml
index deabc5ccd3..52a7fe492f 100644
--- a/modules/regex/doc_classes/RegEx.xml
+++ b/modules/regex/doc_classes/RegEx.xml
@@ -62,6 +62,13 @@
Compiles and assign the search pattern to use. Returns [constant OK] if the compilation is successful. If an error is encountered, details are printed to standard output and an error is returned.
</description>
</method>
+ <method name="create_from_string" qualifiers="static">
+ <return type="RegEx" />
+ <argument index="0" name="pattern" type="String" />
+ <description>
+ Creates and compiles a new [RegEx] object.
+ </description>
+ </method>
<method name="get_group_count" qualifiers="const">
<return type="int" />
<description>
@@ -96,7 +103,7 @@
</description>
</method>
<method name="search_all" qualifiers="const">
- <return type="Array" />
+ <return type="RegExMatch[]" />
<argument index="0" name="subject" type="String" />
<argument index="1" name="offset" type="int" default="0" />
<argument index="2" name="end" type="int" default="-1" />
diff --git a/modules/regex/regex.cpp b/modules/regex/regex.cpp
index 67ce37219b..569066867a 100644
--- a/modules/regex/regex.cpp
+++ b/modules/regex/regex.cpp
@@ -159,6 +159,13 @@ void RegEx::_pattern_info(uint32_t what, void *where) const {
pcre2_pattern_info_32((pcre2_code_32 *)code, what, where);
}
+Ref<RegEx> RegEx::create_from_string(const String &p_pattern) {
+ Ref<RegEx> ret;
+ ret.instantiate();
+ ret->compile(p_pattern);
+ return ret;
+}
+
void RegEx::clear() {
if (code) {
pcre2_code_free_32((pcre2_code_32 *)code);
@@ -258,11 +265,11 @@ Ref<RegExMatch> RegEx::search(const String &p_subject, int p_offset, int p_end)
return result;
}
-Array RegEx::search_all(const String &p_subject, int p_offset, int p_end) const {
+TypedArray<RegExMatch> RegEx::search_all(const String &p_subject, int p_offset, int p_end) const {
ERR_FAIL_COND_V_MSG(p_offset < 0, Array(), "RegEx search offset must be >= 0");
int last_end = -1;
- Array result;
+ TypedArray<RegExMatch> result;
Ref<RegExMatch> match = search(p_subject, p_offset, p_end);
while (match.is_valid()) {
if (last_end == match->get_end(0)) {
@@ -384,6 +391,8 @@ RegEx::~RegEx() {
}
void RegEx::_bind_methods() {
+ ClassDB::bind_static_method("RegEx", D_METHOD("create_from_string", "pattern"), &RegEx::create_from_string);
+
ClassDB::bind_method(D_METHOD("clear"), &RegEx::clear);
ClassDB::bind_method(D_METHOD("compile", "pattern"), &RegEx::compile);
ClassDB::bind_method(D_METHOD("search", "subject", "offset", "end"), &RegEx::search, DEFVAL(0), DEFVAL(-1));
diff --git a/modules/regex/regex.h b/modules/regex/regex.h
index 1455188670..9296de929f 100644
--- a/modules/regex/regex.h
+++ b/modules/regex/regex.h
@@ -37,6 +37,7 @@
#include "core/templates/vector.h"
#include "core/variant/array.h"
#include "core/variant/dictionary.h"
+#include "core/variant/typed_array.h"
class RegExMatch : public RefCounted {
GDCLASS(RegExMatch, RefCounted);
@@ -81,11 +82,13 @@ protected:
static void _bind_methods();
public:
+ static Ref<RegEx> create_from_string(const String &p_pattern);
+
void clear();
Error compile(const String &p_pattern);
Ref<RegExMatch> search(const String &p_subject, int p_offset = 0, int p_end = -1) const;
- Array search_all(const String &p_subject, int p_offset = 0, int p_end = -1) const;
+ TypedArray<RegExMatch> search_all(const String &p_subject, int p_offset = 0, int p_end = -1) const;
String sub(const String &p_subject, const String &p_replacement, bool p_all = false, int p_offset = 0, int p_end = -1) const;
bool is_valid() const;
diff --git a/modules/text_server_adv/SCsub b/modules/text_server_adv/SCsub
index 93fd8fe45f..81b8e1ea5d 100644
--- a/modules/text_server_adv/SCsub
+++ b/modules/text_server_adv/SCsub
@@ -113,15 +113,18 @@ if env["builtin_harfbuzz"]:
if freetype_enabled:
thirdparty_sources += [
"src/hb-ft.cc",
- "src/hb-graphite2.cc",
]
+ if env["graphite"]:
+ thirdparty_sources += [
+ "src/hb-graphite2.cc",
+ ]
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
env_harfbuzz.Prepend(CPPPATH=["#thirdparty/harfbuzz/src"])
env_harfbuzz.Append(CCFLAGS=["-DHAVE_ICU"])
if env["builtin_icu"]:
- env_harfbuzz.Prepend(CPPPATH=["#thirdparty/icu4c/common/"])
+ env_harfbuzz.Prepend(CPPPATH=["#thirdparty/icu4c/common/", "#thirdparty/icu4c/i18n/"])
env_harfbuzz.Append(CCFLAGS=["-DU_HAVE_LIB_SUFFIX=1", "-DU_LIB_SUFFIX_C_NAME=_godot", "-DHAVE_ICU_BUILTIN"])
if freetype_enabled:
@@ -133,7 +136,7 @@ if env["builtin_harfbuzz"]:
)
if env["builtin_freetype"]:
env_harfbuzz.Prepend(CPPPATH=["#thirdparty/freetype/include"])
- if env["builtin_graphite"]:
+ if env["builtin_graphite"] and env["graphite"]:
env_harfbuzz.Prepend(CPPPATH=["#thirdparty/graphite/include"])
env_harfbuzz.Append(CCFLAGS=["-DGRAPHITE2_STATIC"])
@@ -165,7 +168,7 @@ if env["builtin_harfbuzz"]:
env.Append(LIBS=[lib])
-if env["builtin_graphite"] and freetype_enabled:
+if env["builtin_graphite"] and freetype_enabled and env["graphite"]:
env_graphite = env_modules.Clone()
env_graphite.disable_warnings()
@@ -439,6 +442,10 @@ if env["builtin_icu"]:
"common/uvectr32.cpp",
"common/uvectr64.cpp",
"common/wintz.cpp",
+ "i18n/scriptset.cpp",
+ "i18n/ucln_in.cpp",
+ "i18n/uspoof.cpp",
+ "i18n/uspoof_impl.cpp",
]
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
@@ -451,7 +458,7 @@ if env["builtin_icu"]:
else:
thirdparty_sources += ["icu_data/icudata_stub.cpp"]
- env_icu.Prepend(CPPPATH=["#thirdparty/icu4c/common/"])
+ env_icu.Prepend(CPPPATH=["#thirdparty/icu4c/common/", "#thirdparty/icu4c/i18n/"])
env_icu.Append(
CXXFLAGS=[
"-DU_STATIC_IMPLEMENTATION",
@@ -463,6 +470,7 @@ if env["builtin_icu"]:
"-DUCONFIG_NO_IDNA",
"-DUCONFIG_NO_FILE_IO",
"-DUCONFIG_NO_TRANSLITERATION",
+ "-DUCONFIG_NO_REGULAR_EXPRESSIONS",
"-DPKGDATA_MODE=static",
"-DU_ENABLE_DYLOAD=0",
"-DU_HAVE_LIB_SUFFIX=1",
@@ -480,7 +488,7 @@ if env["builtin_icu"]:
if env_text_server_adv["tools"]:
env_text_server_adv.Append(CXXFLAGS=["-DICU_STATIC_DATA"])
- env_text_server_adv.Prepend(CPPPATH=["#thirdparty/icu4c/common/"])
+ env_text_server_adv.Prepend(CPPPATH=["#thirdparty/icu4c/common/", "#thirdparty/icu4c/i18n/"])
lib = env_icu.add_library("icu_builtin", thirdparty_sources)
thirdparty_obj += lib
@@ -510,7 +518,7 @@ if env["builtin_freetype"] and freetype_enabled:
env_text_server_adv.Append(CPPDEFINES=["FT_CONFIG_OPTION_USE_BROTLI"])
env_text_server_adv.Prepend(CPPPATH=["#thirdparty/freetype/include"])
-if env["builtin_graphite"] and freetype_enabled:
+if env["builtin_graphite"] and freetype_enabled and env["graphite"]:
env_text_server_adv.Prepend(CPPPATH=["#thirdparty/graphite/include"])
env_text_server_adv.add_source_files(module_obj, "*.cpp")
diff --git a/modules/text_server_adv/config.py b/modules/text_server_adv/config.py
index 8c8df9b05e..179a2ff378 100644
--- a/modules/text_server_adv/config.py
+++ b/modules/text_server_adv/config.py
@@ -2,6 +2,14 @@ def can_build(env, platform):
return True
+def get_opts(platform):
+ from SCons.Variables import BoolVariable
+
+ return [
+ BoolVariable("graphite", "Enable SIL Graphite smart fonts support", True),
+ ]
+
+
def configure(env):
pass
diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp
index 64788bfeff..73dbf2f443 100644
--- a/modules/text_server_adv/text_server_adv.cpp
+++ b/modules/text_server_adv/text_server_adv.cpp
@@ -346,6 +346,8 @@ bool TextServerAdvanced::has_feature(Feature p_feature) const {
case FEATURE_FONT_VARIABLE:
case FEATURE_CONTEXT_SENSITIVE_CASE_CONVERSION:
case FEATURE_USE_SUPPORT_DATA:
+ case FEATURE_UNICODE_IDENTIFIERS:
+ case FEATURE_UNICODE_SECURITY:
return true;
default: {
}
@@ -4243,7 +4245,7 @@ void TextServerAdvanced::shaped_text_overrun_trim_to_width(const RID &p_shaped_l
Glyph *sd_glyphs = sd->glyphs.ptrw();
- if (p_trim_flags.has_flag(OVERRUN_TRIM) || sd_glyphs == nullptr || p_width <= 0 || !(sd->width > p_width || enforce_ellipsis)) {
+ if ((p_trim_flags & OVERRUN_TRIM) == OVERRUN_NO_TRIM || sd_glyphs == nullptr || p_width <= 0 || !(sd->width > p_width || enforce_ellipsis)) {
sd->overrun_trim_data.trim_pos = -1;
sd->overrun_trim_data.ellipsis_pos = -1;
return;
@@ -4704,7 +4706,7 @@ bool TextServerAdvanced::shaped_text_update_justification_ops(const RID &p_shape
for (int i = 0; i < sd_size; i++) {
if (sd_glyphs[i].count > 0) {
char32_t c = sd->text[sd_glyphs[i].start - sd->start];
- if (c == 0x0640) {
+ if (c == 0x0640 && sd_glyphs[i].start == sd_glyphs[i].end - 1) {
sd_glyphs[i].flags |= GRAPHEME_IS_ELONGATION;
}
if (sd->jstops.has(sd_glyphs[i].start)) {
@@ -4716,6 +4718,11 @@ bool TextServerAdvanced::shaped_text_update_justification_ops(const RID &p_shape
if (sd_glyphs[i].font_rid != RID()) {
Glyph gl = _shape_single_glyph(sd, 0x0640, HB_SCRIPT_ARABIC, HB_DIRECTION_RTL, sd->glyphs[i].font_rid, sd->glyphs[i].font_size);
if ((sd_glyphs[i].flags & GRAPHEME_IS_VALID) == GRAPHEME_IS_VALID) {
+#if HB_VERSION_ATLEAST(5, 1, 0)
+ if ((i > 0) && ((sd_glyphs[i - 1].flags & GRAPHEME_IS_SAFE_TO_INSERT_TATWEEL) != GRAPHEME_IS_SAFE_TO_INSERT_TATWEEL)) {
+ continue;
+ }
+#endif
gl.start = sd_glyphs[i].start;
gl.end = sd_glyphs[i].end;
gl.repeat = 0;
@@ -4906,11 +4913,16 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star
hb_buffer_clear_contents(p_sd->hb_buffer);
hb_buffer_set_direction(p_sd->hb_buffer, p_direction);
+ int flags = (p_start == 0 ? HB_BUFFER_FLAG_BOT : 0) | (p_end == p_sd->text.length() ? HB_BUFFER_FLAG_EOT : 0);
if (p_sd->preserve_control) {
- hb_buffer_set_flags(p_sd->hb_buffer, (hb_buffer_flags_t)(HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES | (p_start == 0 ? HB_BUFFER_FLAG_BOT : 0) | (p_end == p_sd->text.length() ? HB_BUFFER_FLAG_EOT : 0)));
+ flags |= HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES;
} else {
- hb_buffer_set_flags(p_sd->hb_buffer, (hb_buffer_flags_t)(HB_BUFFER_FLAG_DEFAULT | (p_start == 0 ? HB_BUFFER_FLAG_BOT : 0) | (p_end == p_sd->text.length() ? HB_BUFFER_FLAG_EOT : 0)));
+ flags |= HB_BUFFER_FLAG_DEFAULT;
}
+#if HB_VERSION_ATLEAST(5, 1, 0)
+ flags |= HB_BUFFER_FLAG_PRODUCE_SAFE_TO_INSERT_TATWEEL;
+#endif
+ hb_buffer_set_flags(p_sd->hb_buffer, (hb_buffer_flags_t)flags);
hb_buffer_set_script(p_sd->hb_buffer, p_script);
if (p_sd->spans[p_span].language.is_empty()) {
@@ -4974,10 +4986,16 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star
gl.font_rid = p_fonts[p_fb_index];
gl.font_size = fs;
- if (glyph_info[i].mask & HB_GLYPH_FLAG_DEFINED) {
+ if (glyph_info[i].mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK) {
gl.flags |= GRAPHEME_IS_CONNECTED;
}
+#if HB_VERSION_ATLEAST(5, 1, 0)
+ if (glyph_info[i].mask & HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL) {
+ gl.flags |= GRAPHEME_IS_SAFE_TO_INSERT_TATWEEL;
+ }
+#endif
+
gl.index = glyph_info[i].codepoint;
if (gl.index != 0) {
_ensure_glyph(fd, fss, gl.index);
@@ -5639,6 +5657,68 @@ String TextServerAdvanced::percent_sign(const String &p_language) const {
return "%";
}
+int TextServerAdvanced::is_confusable(const String &p_string, const PackedStringArray &p_dict) const {
+ UErrorCode status = U_ZERO_ERROR;
+ int match_index = -1;
+
+ Char16String utf16 = p_string.utf16();
+ Vector<UChar *> skeletons;
+ skeletons.resize(p_dict.size());
+
+ USpoofChecker *sc = uspoof_open(&status);
+ uspoof_setChecks(sc, USPOOF_CONFUSABLE, &status);
+ for (int i = 0; i < p_dict.size(); i++) {
+ Char16String word = p_dict[i].utf16();
+ int32_t len = uspoof_getSkeleton(sc, 0, word.get_data(), -1, NULL, 0, &status);
+ skeletons.write[i] = (UChar *)memalloc(++len * sizeof(UChar));
+ status = U_ZERO_ERROR;
+ uspoof_getSkeleton(sc, 0, word.get_data(), -1, skeletons.write[i], len, &status);
+ }
+
+ int32_t len = uspoof_getSkeleton(sc, 0, utf16.get_data(), -1, NULL, 0, &status);
+ UChar *skel = (UChar *)memalloc(++len * sizeof(UChar));
+ status = U_ZERO_ERROR;
+ uspoof_getSkeleton(sc, 0, utf16.get_data(), -1, skel, len, &status);
+ for (int i = 0; i < skeletons.size(); i++) {
+ if (u_strcmp(skel, skeletons[i]) == 0) {
+ match_index = i;
+ break;
+ }
+ }
+ memfree(skel);
+
+ for (int i = 0; i < skeletons.size(); i++) {
+ memfree(skeletons.write[i]);
+ }
+ uspoof_close(sc);
+
+ ERR_FAIL_COND_V_MSG(U_FAILURE(status), -1, u_errorName(status));
+
+ return match_index;
+}
+
+bool TextServerAdvanced::spoof_check(const String &p_string) const {
+ UErrorCode status = U_ZERO_ERROR;
+ Char16String utf16 = p_string.utf16();
+
+ USet *allowed = uset_openEmpty();
+ uset_addAll(allowed, uspoof_getRecommendedSet(&status));
+ uset_addAll(allowed, uspoof_getInclusionSet(&status));
+
+ USpoofChecker *sc = uspoof_open(&status);
+ uspoof_setAllowedChars(sc, allowed, &status);
+ uspoof_setRestrictionLevel(sc, USPOOF_MODERATELY_RESTRICTIVE);
+
+ int32_t bitmask = uspoof_check(sc, utf16.get_data(), -1, NULL, &status);
+
+ uspoof_close(sc);
+ uset_close(allowed);
+
+ ERR_FAIL_COND_V_MSG(U_FAILURE(status), false, u_errorName(status));
+
+ return (bitmask != 0);
+}
+
String TextServerAdvanced::strip_diacritics(const String &p_string) const {
UErrorCode err = U_ZERO_ERROR;
@@ -5757,6 +5837,191 @@ PackedInt32Array TextServerAdvanced::string_get_word_breaks(const String &p_stri
return ret;
}
+bool TextServerAdvanced::is_valid_identifier(const String &p_string) const {
+ enum UAX31SequenceStatus {
+ SEQ_NOT_STARTED,
+ SEQ_STARTED,
+ SEQ_STARTED_VIR,
+ SEQ_NEAR_END,
+ };
+
+ const char32_t *str = p_string.ptr();
+ int len = p_string.length();
+
+ if (len == 0) {
+ return false; // Empty string.
+ }
+
+ UErrorCode err = U_ZERO_ERROR;
+ Char16String utf16 = p_string.utf16();
+ const UNormalizer2 *norm_c = unorm2_getNFCInstance(&err);
+ if (U_FAILURE(err)) {
+ return false; // Failed to load normalizer.
+ }
+ bool isnurom = unorm2_isNormalized(norm_c, utf16.ptr(), utf16.length(), &err);
+ if (U_FAILURE(err) || !isnurom) {
+ return false; // Do not conform to Normalization Form C.
+ }
+
+ UAX31SequenceStatus A1_sequence_status = SEQ_NOT_STARTED;
+ UScriptCode A1_scr = USCRIPT_INHERITED;
+ UAX31SequenceStatus A2_sequence_status = SEQ_NOT_STARTED;
+ UScriptCode A2_scr = USCRIPT_INHERITED;
+ UAX31SequenceStatus B_sequence_status = SEQ_NOT_STARTED;
+ UScriptCode B_scr = USCRIPT_INHERITED;
+
+ for (int i = 0; i < len; i++) {
+ err = U_ZERO_ERROR;
+ UScriptCode scr = uscript_getScript(str[i], &err);
+ if (U_FAILURE(err)) {
+ return false; // Invalid script.
+ }
+ if (uscript_getUsage(scr) != USCRIPT_USAGE_RECOMMENDED) {
+ return false; // Not a recommended script.
+ }
+ uint8_t cat = u_charType(str[i]);
+ int32_t jt = u_getIntPropertyValue(str[i], UCHAR_JOINING_TYPE);
+
+ // UAX #31 section 2.3 subsections A1, A2 and B, check ZWNJ and ZWJ usage.
+ switch (A1_sequence_status) {
+ case SEQ_NEAR_END: {
+ if ((A1_scr > USCRIPT_INHERITED) && (scr > USCRIPT_INHERITED) && (scr != A1_scr)) {
+ return false; // Mixed script.
+ }
+ if (jt == U_JT_RIGHT_JOINING || jt == U_JT_DUAL_JOINING) {
+ A1_sequence_status = SEQ_NOT_STARTED; // Valid end of sequence, reset.
+ } else if (jt != U_JT_TRANSPARENT) {
+ return false; // Invalid end of sequence.
+ }
+ } break;
+ case SEQ_STARTED: {
+ if ((A1_scr > USCRIPT_INHERITED) && (scr > USCRIPT_INHERITED) && (scr != A1_scr)) {
+ A1_sequence_status = SEQ_NOT_STARTED; // Reset.
+ } else {
+ if (jt != U_JT_TRANSPARENT) {
+ if (str[i] == 0x200C /*ZWNJ*/) {
+ A1_sequence_status = SEQ_NEAR_END;
+ continue;
+ } else {
+ A1_sequence_status = SEQ_NOT_STARTED; // Reset.
+ }
+ }
+ }
+ } break;
+ default:
+ break;
+ }
+ if (A1_sequence_status == SEQ_NOT_STARTED) {
+ if (jt == U_JT_LEFT_JOINING || jt == U_JT_DUAL_JOINING) {
+ A1_sequence_status = SEQ_STARTED;
+ A1_scr = scr;
+ }
+ };
+
+ switch (A2_sequence_status) {
+ case SEQ_NEAR_END: {
+ if ((A2_scr > USCRIPT_INHERITED) && (scr > USCRIPT_INHERITED) && (scr != A2_scr)) {
+ return false; // Mixed script.
+ }
+ if (cat == U_UPPERCASE_LETTER || cat == U_LOWERCASE_LETTER || cat == U_TITLECASE_LETTER || cat == U_MODIFIER_LETTER || cat == U_OTHER_LETTER) {
+ A2_sequence_status = SEQ_NOT_STARTED; // Valid end of sequence, reset.
+ } else if (cat != U_MODIFIER_LETTER || u_getCombiningClass(str[i]) == 0) {
+ return false; // Invalid end of sequence.
+ }
+ } break;
+ case SEQ_STARTED_VIR: {
+ if ((A2_scr > USCRIPT_INHERITED) && (scr > USCRIPT_INHERITED) && (scr != A2_scr)) {
+ A2_sequence_status = SEQ_NOT_STARTED; // Reset.
+ } else {
+ if (str[i] == 0x200C /*ZWNJ*/) {
+ A2_sequence_status = SEQ_NEAR_END;
+ continue;
+ } else if (cat != U_MODIFIER_LETTER || u_getCombiningClass(str[i]) == 0) {
+ A2_sequence_status = SEQ_NOT_STARTED; // Reset.
+ }
+ }
+ } break;
+ case SEQ_STARTED: {
+ if ((A2_scr > USCRIPT_INHERITED) && (scr > USCRIPT_INHERITED) && (scr != A2_scr)) {
+ A2_sequence_status = SEQ_NOT_STARTED; // Reset.
+ } else {
+ if (u_getCombiningClass(str[i]) == 9 /*Virama Combining Class*/) {
+ A2_sequence_status = SEQ_STARTED_VIR;
+ } else if (cat != U_MODIFIER_LETTER) {
+ A2_sequence_status = SEQ_NOT_STARTED; // Reset.
+ }
+ }
+ } break;
+ default:
+ break;
+ }
+ if (A2_sequence_status == SEQ_NOT_STARTED) {
+ if (cat == U_UPPERCASE_LETTER || cat == U_LOWERCASE_LETTER || cat == U_TITLECASE_LETTER || cat == U_MODIFIER_LETTER || cat == U_OTHER_LETTER) {
+ A2_sequence_status = SEQ_STARTED;
+ A2_scr = scr;
+ }
+ }
+
+ switch (B_sequence_status) {
+ case SEQ_NEAR_END: {
+ if ((B_scr > USCRIPT_INHERITED) && (scr > USCRIPT_INHERITED) && (scr != B_scr)) {
+ return false; // Mixed script.
+ }
+ if (u_getIntPropertyValue(str[i], UCHAR_INDIC_SYLLABIC_CATEGORY) != U_INSC_VOWEL_DEPENDENT) {
+ B_sequence_status = SEQ_NOT_STARTED; // Valid end of sequence, reset.
+ } else {
+ return false; // Invalid end of sequence.
+ }
+ } break;
+ case SEQ_STARTED_VIR: {
+ if ((B_scr > USCRIPT_INHERITED) && (scr > USCRIPT_INHERITED) && (scr != B_scr)) {
+ B_sequence_status = SEQ_NOT_STARTED; // Reset.
+ } else {
+ if (str[i] == 0x200D /*ZWJ*/) {
+ B_sequence_status = SEQ_NEAR_END;
+ continue;
+ } else if (cat != U_MODIFIER_LETTER || u_getCombiningClass(str[i]) == 0) {
+ B_sequence_status = SEQ_NOT_STARTED; // Reset.
+ }
+ }
+ } break;
+ case SEQ_STARTED: {
+ if ((B_scr > USCRIPT_INHERITED) && (scr > USCRIPT_INHERITED) && (scr != B_scr)) {
+ B_sequence_status = SEQ_NOT_STARTED; // Reset.
+ } else {
+ if (u_getCombiningClass(str[i]) == 9 /*Virama Combining Class*/) {
+ B_sequence_status = SEQ_STARTED_VIR;
+ } else if (cat != U_MODIFIER_LETTER) {
+ B_sequence_status = SEQ_NOT_STARTED; // Reset.
+ }
+ }
+ } break;
+ default:
+ break;
+ }
+ if (B_sequence_status == SEQ_NOT_STARTED) {
+ if (cat == U_UPPERCASE_LETTER || cat == U_LOWERCASE_LETTER || cat == U_TITLECASE_LETTER || cat == U_MODIFIER_LETTER || cat == U_OTHER_LETTER) {
+ B_sequence_status = SEQ_STARTED;
+ B_scr = scr;
+ }
+ }
+
+ if (u_hasBinaryProperty(str[i], UCHAR_PATTERN_SYNTAX) || u_hasBinaryProperty(str[i], UCHAR_PATTERN_WHITE_SPACE) || u_hasBinaryProperty(str[i], UCHAR_NONCHARACTER_CODE_POINT)) {
+ return false; // Not a XID_Start or XID_Continue character.
+ }
+ if (i == 0) {
+ if (!(cat == U_LOWERCASE_LETTER || cat == U_UPPERCASE_LETTER || cat == U_TITLECASE_LETTER || cat == U_OTHER_LETTER || cat == U_MODIFIER_LETTER || cat == U_LETTER_NUMBER || str[0] == 0x2118 || str[0] == 0x212E || str[0] == 0x309B || str[0] == 0x309C || str[0] == 0x005F)) {
+ return false; // Not a XID_Start character.
+ }
+ } else {
+ if (!(cat == U_LOWERCASE_LETTER || cat == U_UPPERCASE_LETTER || cat == U_TITLECASE_LETTER || cat == U_OTHER_LETTER || cat == U_MODIFIER_LETTER || cat == U_LETTER_NUMBER || cat == U_NON_SPACING_MARK || cat == U_COMBINING_SPACING_MARK || cat == U_DECIMAL_DIGIT_NUMBER || cat == U_CONNECTOR_PUNCTUATION || str[i] == 0x2118 || str[i] == 0x212E || str[i] == 0x309B || str[i] == 0x309C || str[i] == 0x1369 || str[i] == 0x1371 || str[i] == 0x00B7 || str[i] == 0x0387 || str[i] == 0x19DA || str[i] == 0x0E33 || str[i] == 0x0EB3 || str[i] == 0xFF9E || str[i] == 0xFF9F)) {
+ return false; // Not a XID_Continue character.
+ }
+ }
+ }
+ return true;
+}
+
TextServerAdvanced::TextServerAdvanced() {
_insert_num_systems_lang();
_insert_feature_sets();
diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h
index 8852c40406..7ae329d616 100644
--- a/modules/text_server_adv/text_server_adv.h
+++ b/modules/text_server_adv/text_server_adv.h
@@ -101,6 +101,7 @@ using namespace godot;
#include <unicode/uloc.h>
#include <unicode/unorm2.h>
#include <unicode/uscript.h>
+#include <unicode/uspoof.h>
#include <unicode/ustring.h>
#include <unicode/utypes.h>
@@ -704,7 +705,11 @@ public:
virtual PackedInt32Array string_get_word_breaks(const String &p_string, const String &p_language = "") const override;
+ virtual int is_confusable(const String &p_string, const PackedStringArray &p_dict) const override;
+ virtual bool spoof_check(const String &p_string) const override;
+
virtual String strip_diacritics(const String &p_string) const override;
+ virtual bool is_valid_identifier(const String &p_string) const override;
virtual String string_to_upper(const String &p_string, const String &p_language = "") const override;
virtual String string_to_lower(const String &p_string, const String &p_language = "") const override;
diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp
index 50ea4677b1..55d912a10a 100644
--- a/modules/text_server_fb/text_server_fb.cpp
+++ b/modules/text_server_fb/text_server_fb.cpp
@@ -3204,7 +3204,7 @@ void TextServerFallback::shaped_text_overrun_trim_to_width(const RID &p_shaped_l
Glyph *sd_glyphs = sd->glyphs.ptrw();
- if (p_trim_flags.has_flag(OVERRUN_TRIM) || sd_glyphs == nullptr || p_width <= 0 || !(sd->width > p_width || enforce_ellipsis)) {
+ if ((p_trim_flags & OVERRUN_TRIM) == OVERRUN_NO_TRIM || sd_glyphs == nullptr || p_width <= 0 || !(sd->width > p_width || enforce_ellipsis)) {
sd->overrun_trim_data.trim_pos = -1;
sd->overrun_trim_data.ellipsis_pos = -1;
return;
diff --git a/modules/visual_script/editor/visual_script_editor.cpp b/modules/visual_script/editor/visual_script_editor.cpp
index 1e9755f45f..7f8e9d8254 100644
--- a/modules/visual_script/editor/visual_script_editor.cpp
+++ b/modules/visual_script/editor/visual_script_editor.cpp
@@ -42,10 +42,32 @@
#include "editor/editor_node.h"
#include "editor/editor_resource_preview.h"
#include "editor/editor_scale.h"
+#include "editor/editor_settings.h"
+#include "scene/gui/check_button.h"
+#include "scene/gui/graph_edit.h"
+#include "scene/gui/separator.h"
#include "scene/gui/view_panner.h"
#include "scene/main/window.h"
#ifdef TOOLS_ENABLED
+
+void VisualScriptEditedProperty::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_edited_property", "value"), &VisualScriptEditedProperty::set_edited_property);
+ ClassDB::bind_method(D_METHOD("get_edited_property"), &VisualScriptEditedProperty::get_edited_property);
+
+ ADD_PROPERTY(PropertyInfo(Variant::NIL, "edited_property", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT), "set_edited_property", "get_edited_property");
+}
+
+void VisualScriptEditedProperty::set_edited_property(Variant p_variant) {
+ edited_property = p_variant;
+}
+
+Variant VisualScriptEditedProperty::get_edited_property() const {
+ return edited_property;
+}
+
+/////////////////
+
class VisualScriptEditorSignalEdit : public Object {
GDCLASS(VisualScriptEditorSignalEdit, Object);
@@ -3898,14 +3920,14 @@ int VisualScriptEditor::_create_new_node_from_name(const String &p_text, const V
return new_id;
}
-void VisualScriptEditor::_default_value_changed() {
+void VisualScriptEditor::_default_value_changed(const StringName &p_property, const Variant &p_value, const String &p_field, bool p_changing) {
Ref<VisualScriptNode> vsn = script->get_node(editing_id);
if (vsn.is_null()) {
return;
}
undo_redo->create_action(TTR("Change Input Value"));
- undo_redo->add_do_method(vsn.ptr(), "set_default_input_value", editing_input, default_value_edit->get_variant());
+ undo_redo->add_do_method(vsn.ptr(), "set_default_input_value", editing_input, p_value);
undo_redo->add_undo_method(vsn.ptr(), "set_default_input_value", editing_input, vsn->get_default_input_value(editing_input));
undo_redo->add_do_method(this, "_update_graph", editing_id);
@@ -3928,9 +3950,6 @@ void VisualScriptEditor::_default_value_edited(Node *p_button, int p_id, int p_i
Variant::construct(pinfo.type, existing, &existingp, 1, ce);
}
- default_value_edit->set_position(Object::cast_to<Control>(p_button)->get_screen_position() + Vector2(0, Object::cast_to<Control>(p_button)->get_size().y) * graph->get_zoom());
- default_value_edit->reset_size();
-
if (pinfo.type == Variant::NODE_PATH) {
Node *edited_scene = get_tree()->get_edited_scene_root();
if (edited_scene) { // Fixing an old crash bug ( Visual Script Crashes on editing NodePath with an empty scene open).
@@ -3948,11 +3967,33 @@ void VisualScriptEditor::_default_value_edited(Node *p_button, int p_id, int p_i
}
}
- if (default_value_edit->edit(nullptr, pinfo.name, pinfo.type, existing, pinfo.hint, pinfo.hint_string)) {
- if (pinfo.hint == PROPERTY_HINT_MULTILINE_TEXT) {
- default_value_edit->popup_centered_ratio();
+ edited_default_property_holder->set_edited_property(existing);
+
+ if (default_property_editor) {
+ default_property_editor->disconnect("property_changed", callable_mp(this, &VisualScriptEditor::_default_value_changed));
+ default_property_editor_popup->remove_child(default_property_editor);
+ }
+
+ default_property_editor = EditorInspector::instantiate_property_editor(edited_default_property_holder.ptr(), pinfo.type, "edited_property", pinfo.hint, pinfo.hint_string, PROPERTY_USAGE_NONE);
+ if (default_property_editor) {
+ default_property_editor->set_object_and_property(edited_default_property_holder.ptr(), "edited_property");
+ default_property_editor->update_property();
+ default_property_editor->set_name_split_ratio(0);
+ default_property_editor_popup->add_child(default_property_editor);
+
+ default_property_editor->connect("property_changed", callable_mp(this, &VisualScriptEditor::_default_value_changed));
+
+ Button *button = Object::cast_to<Button>(p_button);
+ if (button) {
+ default_property_editor_popup->set_position(button->get_screen_position() + Vector2(0, button->get_size().height) * graph->get_zoom());
+ }
+
+ default_property_editor_popup->reset_size();
+
+ if (pinfo.hint == PROPERTY_HINT_MULTILINE_TEXT || !button) {
+ default_property_editor_popup->popup_centered_ratio();
} else {
- default_value_edit->popup();
+ default_property_editor_popup->popup();
}
}
@@ -4795,9 +4836,11 @@ VisualScriptEditor::VisualScriptEditor() {
set_process_input(true);
- default_value_edit = memnew(CustomPropertyEditor);
- add_child(default_value_edit);
- default_value_edit->connect("variant_changed", callable_mp(this, &VisualScriptEditor::_default_value_changed));
+ default_property_editor_popup = memnew(PopupPanel);
+ default_property_editor_popup->set_min_size(Size2i(180, 0) * EDSCALE);
+ add_child(default_property_editor_popup);
+
+ edited_default_property_holder.instantiate();
new_connect_node_select = memnew(VisualScriptPropertySelector);
add_child(new_connect_node_select);
diff --git a/modules/visual_script/editor/visual_script_editor.h b/modules/visual_script/editor/visual_script_editor.h
index a6df7bba73..6b337e52f6 100644
--- a/modules/visual_script/editor/visual_script_editor.h
+++ b/modules/visual_script/editor/visual_script_editor.h
@@ -34,15 +34,31 @@
#include "../visual_script.h"
#include "editor/create_dialog.h"
#include "editor/plugins/script_editor_plugin.h"
-#include "editor/property_editor.h"
-#include "scene/gui/graph_edit.h"
#include "visual_script_property_selector.h"
+class GraphEdit;
+
class VisualScriptEditorSignalEdit;
class VisualScriptEditorVariableEdit;
#ifdef TOOLS_ENABLED
+class VisualScriptEditedProperty : public RefCounted {
+ GDCLASS(VisualScriptEditedProperty, RefCounted);
+
+private:
+ Variant edited_property;
+
+protected:
+ static void _bind_methods();
+
+public:
+ void set_edited_property(Variant p_variant);
+ Variant get_edited_property() const;
+
+ VisualScriptEditedProperty() {}
+};
+
// TODO: Maybe this class should be refactored.
// See https://github.com/godotengine/godot/issues/51913
class VisualScriptEditor : public ScriptEditorBase {
@@ -115,7 +131,9 @@ class VisualScriptEditor : public ScriptEditorBase {
AcceptDialog *edit_variable_dialog = nullptr;
EditorInspector *edit_variable_edit = nullptr;
- CustomPropertyEditor *default_value_edit = nullptr;
+ PopupPanel *default_property_editor_popup = nullptr;
+ EditorProperty *default_property_editor = nullptr;
+ Ref<VisualScriptEditedProperty> edited_default_property_holder;
UndoRedo *undo_redo = nullptr;
@@ -276,7 +294,7 @@ class VisualScriptEditor : public ScriptEditorBase {
int data_disconnect_node = 0;
int data_disconnect_port = 0;
- void _default_value_changed();
+ void _default_value_changed(const StringName &p_property, const Variant &p_value, const String &p_field, bool p_changing);
void _default_value_edited(Node *p_button, int p_id, int p_input_port);
void _menu_option(int p_what);