Parcourir la source

Merge branch 'master' into bugfix-ios-export

Larry Tran il y a 3 ans
Parent
commit
2ea4baae0a

+ 12 - 6
SConstruct

@@ -337,21 +337,27 @@ for path in module_search_paths:
 
 # Add module options.
 for name, path in modules_detected.items():
+    sys.path.insert(0, path)
+    import config
+
     if env_base["modules_enabled_by_default"]:
         enabled = True
-
-        sys.path.insert(0, path)
-        import config
-
         try:
             enabled = config.is_enabled()
         except AttributeError:
             pass
-        sys.path.remove(path)
-        sys.modules.pop("config")
     else:
         enabled = False
 
+    # Add module-specific options.
+    try:
+        for opt in config.get_opts(selected_platform):
+            opts.Add(opt)
+    except AttributeError:
+        pass
+
+    sys.path.remove(path)
+    sys.modules.pop("config")
     opts.Add(BoolVariable("module_" + name + "_enabled", "Enable module '%s'" % (name,), enabled))
 
 methods.write_modules(modules_detected)

+ 2 - 0
core/io/dir_access.h

@@ -108,6 +108,8 @@ public:
 			if (da->remove(p_path) != OK) {
 				ERR_FAIL_MSG("Cannot remove file or directory: " + p_path);
 			}
+		} else {
+			ERR_FAIL_MSG("Cannot remove non-existent file or directory: " + p_path);
 		}
 	}
 

+ 2 - 0
core/variant/variant_op.cpp

@@ -341,6 +341,8 @@ void Variant::_register_variant_operators() {
 	register_op<OperatorEvaluatorXFormInv<Vector3, Vector3, Transform3D>>(Variant::OP_MULTIPLY, Variant::VECTOR3, Variant::TRANSFORM3D);
 	register_op<OperatorEvaluatorXForm<::AABB, Transform3D, ::AABB>>(Variant::OP_MULTIPLY, Variant::TRANSFORM3D, Variant::AABB);
 	register_op<OperatorEvaluatorXFormInv<::AABB, ::AABB, Transform3D>>(Variant::OP_MULTIPLY, Variant::AABB, Variant::TRANSFORM3D);
+	register_op<OperatorEvaluatorXForm<Plane, Transform3D, Plane>>(Variant::OP_MULTIPLY, Variant::TRANSFORM3D, Variant::PLANE);
+	register_op<OperatorEvaluatorXFormInv<Plane, Plane, Transform3D>>(Variant::OP_MULTIPLY, Variant::PLANE, Variant::TRANSFORM3D);
 	register_op<OperatorEvaluatorXForm<Vector<Vector3>, Transform3D, Vector<Vector3>>>(Variant::OP_MULTIPLY, Variant::TRANSFORM3D, Variant::PACKED_VECTOR3_ARRAY);
 	register_op<OperatorEvaluatorXFormInv<Vector<Vector3>, Vector<Vector3>, Transform3D>>(Variant::OP_MULTIPLY, Variant::PACKED_VECTOR3_ARRAY, Variant::TRANSFORM3D);
 

+ 1 - 1
doc/classes/Camera3D.xml

@@ -144,7 +144,7 @@
 				# This code block is part of a script that inherits from Node3D.
 				# `control` is a reference to a node inheriting from Control.
 				control.visible = not get_viewport().get_camera_3d().is_position_behind(global_transform.origin)
-				control.rect_position = get_viewport().get_camera_3d().unproject_position(global_transform.origin)
+				control.position = get_viewport().get_camera_3d().unproject_position(global_transform.origin)
 				[/codeblock]
 			</description>
 		</method>

+ 7 - 0
doc/classes/Plane.xml

@@ -179,6 +179,13 @@
 				[b]Note:[/b] Due to floating-point precision errors, consider using [method is_equal_approx] instead, which is more reliable.
 			</description>
 		</operator>
+		<operator name="operator *">
+			<return type="Plane" />
+			<argument index="0" name="right" type="Transform3D" />
+			<description>
+				Inversely transforms (multiplies) the [Plane] by the given [Transform3D] transformation matrix.
+			</description>
+		</operator>
 		<operator name="operator ==">
 			<return type="bool" />
 			<argument index="0" name="right" type="Plane" />

+ 7 - 0
doc/classes/Transform3D.xml

@@ -215,6 +215,13 @@
 				Transforms (multiplies) each element of the [Vector3] array by the given [Transform3D] matrix.
 			</description>
 		</operator>
+		<operator name="operator *">
+			<return type="Plane" />
+			<argument index="0" name="right" type="Plane" />
+			<description>
+				Transforms (multiplies) the [Plane] by the given [Transform3D] transformation matrix.
+			</description>
+		</operator>
 		<operator name="operator *">
 			<return type="Transform3D" />
 			<argument index="0" name="right" type="Transform3D" />

+ 59 - 7
drivers/vulkan/rendering_device_vulkan.cpp

@@ -2004,6 +2004,9 @@ RID RenderingDeviceVulkan::texture_create(const TextureFormat &p_format, const T
 	}
 
 	RID id = texture_owner.make_rid(texture);
+#ifdef DEV_ENABLED
+	set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
 
 	if (p_data.size()) {
 		for (uint32_t i = 0; i < image_create_info.arrayLayers; i++) {
@@ -2133,6 +2136,9 @@ RID RenderingDeviceVulkan::texture_create_shared(const TextureView &p_view, RID
 
 	texture.owner = p_with_texture;
 	RID id = texture_owner.make_rid(texture);
+#ifdef DEV_ENABLED
+	set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
 	_add_dependency(id, p_with_texture);
 
 	return id;
@@ -2252,6 +2258,9 @@ RID RenderingDeviceVulkan::texture_create_from_extension(TextureType p_type, Dat
 	}
 
 	RID id = texture_owner.make_rid(texture);
+#ifdef DEV_ENABLED
+	set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
 
 	return id;
 }
@@ -2377,6 +2386,9 @@ RID RenderingDeviceVulkan::texture_create_shared_from_slice(const TextureView &p
 
 	texture.owner = p_with_texture;
 	RID id = texture_owner.make_rid(texture);
+#ifdef DEV_ENABLED
+	set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
 	_add_dependency(id, p_with_texture);
 
 	return id;
@@ -4082,7 +4094,11 @@ RID RenderingDeviceVulkan::framebuffer_create_empty(const Size2i &p_size, Textur
 	framebuffer.size = p_size;
 	framebuffer.view_count = 1;
 
-	return framebuffer_owner.make_rid(framebuffer);
+	RID id = framebuffer_owner.make_rid(framebuffer);
+#ifdef DEV_ENABLED
+	set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
+	return id;
 }
 
 RID RenderingDeviceVulkan::framebuffer_create(const Vector<RID> &p_texture_attachments, FramebufferFormatID p_format_check, uint32_t p_view_count) {
@@ -4162,6 +4178,9 @@ RID RenderingDeviceVulkan::framebuffer_create_multipass(const Vector<RID> &p_tex
 	framebuffer.view_count = p_view_count;
 
 	RID id = framebuffer_owner.make_rid(framebuffer);
+#ifdef DEV_ENABLED
+	set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
 
 	for (int i = 0; i < p_texture_attachments.size(); i++) {
 		if (p_texture_attachments[i].is_valid()) {
@@ -4239,7 +4258,11 @@ RID RenderingDeviceVulkan::sampler_create(const SamplerState &p_state) {
 	VkResult res = vkCreateSampler(device, &sampler_create_info, nullptr, &sampler);
 	ERR_FAIL_COND_V_MSG(res, RID(), "vkCreateSampler failed with error " + itos(res) + ".");
 
-	return sampler_owner.make_rid(sampler);
+	RID id = sampler_owner.make_rid(sampler);
+#ifdef DEV_ENABLED
+	set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
+	return id;
 }
 
 /**********************/
@@ -4268,7 +4291,11 @@ RID RenderingDeviceVulkan::vertex_buffer_create(uint32_t p_size_bytes, const Vec
 		_buffer_memory_barrier(buffer.buffer, 0, data_size, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, false);
 	}
 
-	return vertex_buffer_owner.make_rid(buffer);
+	RID id = vertex_buffer_owner.make_rid(buffer);
+#ifdef DEV_ENABLED
+	set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
+	return id;
 }
 
 // Internally reference counted, this ID is warranted to be unique for the same description, but needs to be freed as many times as it was allocated
@@ -4429,7 +4456,11 @@ RID RenderingDeviceVulkan::index_buffer_create(uint32_t p_index_count, IndexBuff
 		_buffer_update(&index_buffer, 0, r, data_size);
 		_buffer_memory_barrier(index_buffer.buffer, 0, data_size, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_INDEX_READ_BIT, false);
 	}
-	return index_buffer_owner.make_rid(index_buffer);
+	RID id = index_buffer_owner.make_rid(index_buffer);
+#ifdef DEV_ENABLED
+	set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
+	return id;
 }
 
 RID RenderingDeviceVulkan::index_array_create(RID p_index_buffer, uint32_t p_index_offset, uint32_t p_index_count) {
@@ -5526,7 +5557,11 @@ RID RenderingDeviceVulkan::shader_create_from_bytecode(const Vector<uint8_t> &p_
 		ERR_FAIL_V_MSG(RID(), error_text);
 	}
 
-	return shader_owner.make_rid(shader);
+	RID id = shader_owner.make_rid(shader);
+#ifdef DEV_ENABLED
+	set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
+	return id;
 }
 
 uint32_t RenderingDeviceVulkan::shader_get_vertex_input_attribute_mask(RID p_shader) {
@@ -5559,7 +5594,11 @@ RID RenderingDeviceVulkan::uniform_buffer_create(uint32_t p_size_bytes, const Ve
 		_buffer_update(&buffer, 0, r, data_size);
 		_buffer_memory_barrier(buffer.buffer, 0, data_size, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_UNIFORM_READ_BIT, false);
 	}
-	return uniform_buffer_owner.make_rid(buffer);
+	RID id = uniform_buffer_owner.make_rid(buffer);
+#ifdef DEV_ENABLED
+	set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
+	return id;
 }
 
 RID RenderingDeviceVulkan::storage_buffer_create(uint32_t p_size_bytes, const Vector<uint8_t> &p_data, uint32_t p_usage) {
@@ -5630,7 +5669,11 @@ RID RenderingDeviceVulkan::texture_buffer_create(uint32_t p_size_elements, DataF
 	}
 
 	//allocate the view
-	return texture_buffer_owner.make_rid(texture_buffer);
+	RID id = texture_buffer_owner.make_rid(texture_buffer);
+#ifdef DEV_ENABLED
+	set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
+	return id;
 }
 
 RenderingDeviceVulkan::DescriptorPool *RenderingDeviceVulkan::_descriptor_pool_allocate(const DescriptorPoolKey &p_key) {
@@ -6209,6 +6252,9 @@ RID RenderingDeviceVulkan::uniform_set_create(const Vector<Uniform> &p_uniforms,
 	uniform_set.shader_id = p_shader;
 
 	RID id = uniform_set_owner.make_rid(uniform_set);
+#ifdef DEV_ENABLED
+	set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
 	//add dependencies
 	_add_dependency(id, p_shader);
 	for (uint32_t i = 0; i < uniform_count; i++) {
@@ -6831,6 +6877,9 @@ RID RenderingDeviceVulkan::render_pipeline_create(RID p_shader, FramebufferForma
 #endif
 	//create ID to associate with this pipeline
 	RID id = render_pipeline_owner.make_rid(pipeline);
+#ifdef DEV_ENABLED
+	set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
 	//now add all the dependencies
 	_add_dependency(id, p_shader);
 	return id;
@@ -6920,6 +6969,9 @@ RID RenderingDeviceVulkan::compute_pipeline_create(RID p_shader, const Vector<Pi
 
 	//create ID to associate with this pipeline
 	RID id = compute_pipeline_owner.make_rid(pipeline);
+#ifdef DEV_ENABLED
+	set_resource_name(id, "RID:" + itos(id.get_id()));
+#endif
 	//now add all the dependencies
 	_add_dependency(id, p_shader);
 	return id;

+ 116 - 14
editor/editor_build_profile.cpp

@@ -46,19 +46,68 @@ const char *EditorBuildProfile::build_option_identifiers[BUILD_OPTION_MAX] = {
 	"disable_3d_physics",
 	"disable_navigation",
 	"openxr",
+	"rendering_device", // FIXME: there's no scons option to disable rendering device
 	"opengl3",
 	"vulkan",
+	"module_text_server_fb_enabled",
+	"module_text_server_adv_enabled",
+	"module_freetype_enabled",
+	"brotli",
+	"graphite",
+	"module_msdfgen_enabled"
+};
+
+const bool EditorBuildProfile::build_option_disabled_by_default[BUILD_OPTION_MAX] = {
+	// This maps to SCons build options.
+	false, // 3D
+	false, // PHYSICS_2D
+	false, // PHYSICS_3D
+	false, // NAVIGATION
+	false, // XR
+	false, // RENDERING_DEVICE
+	false, // OPENGL
+	false, // VULKAN
+	true, // TEXT_SERVER_FALLBACK
+	false, // TEXT_SERVER_COMPLEX
+	false, // DYNAMIC_FONTS
+	false, // WOFF2_FONTS
+	false, // GRPAHITE_FONTS
+	false, // MSDFGEN
 };
 
 const bool EditorBuildProfile::build_option_disable_values[BUILD_OPTION_MAX] = {
 	// This maps to SCons build options.
-	true,
-	true,
-	true,
-	true,
-	false,
-	false,
-	false
+	true, // 3D
+	true, // PHYSICS_2D
+	true, // PHYSICS_3D
+	true, // NAVIGATION
+	false, // XR
+	false, // RENDERING_DEVICE
+	false, // OPENGL
+	false, // VULKAN
+	false, // TEXT_SERVER_FALLBACK
+	false, // TEXT_SERVER_COMPLEX
+	false, // DYNAMIC_FONTS
+	false, // WOFF2_FONTS
+	false, // GRPAHITE_FONTS
+	false, // MSDFGEN
+};
+
+const EditorBuildProfile::BuildOptionCategory EditorBuildProfile::build_option_category[BUILD_OPTION_MAX] = {
+	BUILD_OPTION_CATEGORY_GENERAL, // 3D
+	BUILD_OPTION_CATEGORY_GENERAL, // PHYSICS_2D
+	BUILD_OPTION_CATEGORY_GENERAL, // PHYSICS_3D
+	BUILD_OPTION_CATEGORY_GENERAL, // NAVIGATION
+	BUILD_OPTION_CATEGORY_GENERAL, // XR
+	BUILD_OPTION_CATEGORY_GENERAL, // RENDERING_DEVICE
+	BUILD_OPTION_CATEGORY_GENERAL, // OPENGL
+	BUILD_OPTION_CATEGORY_GENERAL, // VULKAN
+	BUILD_OPTION_CATEGORY_TEXT_SERVER, // TEXT_SERVER_FALLBACK
+	BUILD_OPTION_CATEGORY_TEXT_SERVER, // TEXT_SERVER_COMPLEX
+	BUILD_OPTION_CATEGORY_TEXT_SERVER, // DYNAMIC_FONTS
+	BUILD_OPTION_CATEGORY_TEXT_SERVER, // WOFF2_FONTS
+	BUILD_OPTION_CATEGORY_TEXT_SERVER, // GRPAHITE_FONTS
+	BUILD_OPTION_CATEGORY_TEXT_SERVER, // MSDFGEN
 };
 
 void EditorBuildProfile::set_disable_class(const StringName &p_class, bool p_disabled) {
@@ -127,6 +176,12 @@ String EditorBuildProfile::get_build_option_name(BuildOption p_build_option) {
 		TTRC("RenderingDevice"),
 		TTRC("OpenGL"),
 		TTRC("Vulkan"),
+		TTRC("Text Server: Fallback"),
+		TTRC("Text Server: Advanced"),
+		TTRC("TTF, OTF, Type 1, WOFF1 Fonts"),
+		TTRC("WOFF2 Fonts"),
+		TTRC("SIL Graphite Fonts"),
+		TTRC("Multi-channel Signed Distance Field Font Rendering"),
 	};
 	return TTRGET(build_option_names[p_build_option]);
 }
@@ -143,11 +198,33 @@ String EditorBuildProfile::get_build_option_description(BuildOption p_build_opti
 		TTRC("RenderingDevice based rendering (if disabled, the OpenGL back-end is required)."),
 		TTRC("OpenGL back-end (if disabled, the RenderingDevice back-end is required)."),
 		TTRC("Vulkan back-end of RenderingDevice."),
+		TTRC("Fallback implementation of Text Server\nSupports basic text layouts."),
+		TTRC("Text Server implementation powered by ICU and HarfBuzz libraries.\nSupports complex text layouts, BiDi, and contextual OpenType font features."),
+		TTRC("TrueType, OpenType, Type 1, and WOFF1 font format support using FreeType library (if disabled, WOFF2 support is also disabled)."),
+		TTRC("WOFF2 font format support using FreeType and Brotli libraries."),
+		TTRC("SIL Graphite smart font technology support (supported by Advanced Text Server only)."),
+		TTRC("Multi-channel signed distance field font rendering support using msdfgen library (pre-rendered MSDF fonts can be used even if this option disabled)."),
 	};
 
 	return TTRGET(build_option_descriptions[p_build_option]);
 }
 
+EditorBuildProfile::BuildOptionCategory EditorBuildProfile::get_build_option_category(BuildOption p_build_option) {
+	ERR_FAIL_INDEX_V(p_build_option, BUILD_OPTION_MAX, BUILD_OPTION_CATEGORY_GENERAL);
+	return build_option_category[p_build_option];
+}
+
+String EditorBuildProfile::get_build_option_category_name(BuildOptionCategory p_build_option_category) {
+	ERR_FAIL_INDEX_V(p_build_option_category, BUILD_OPTION_CATEGORY_MAX, String());
+
+	const char *build_option_subcategories[BUILD_OPTION_CATEGORY_MAX]{
+		TTRC("General Features:"),
+		TTRC("Text Rendering and Font Options:"),
+	};
+
+	return TTRGET(build_option_subcategories[p_build_option_category]);
+}
+
 Error EditorBuildProfile::save_to_file(const String &p_path) {
 	Dictionary data;
 	data["type"] = "build_profile";
@@ -160,8 +237,12 @@ Error EditorBuildProfile::save_to_file(const String &p_path) {
 
 	Dictionary dis_build_options;
 	for (int i = 0; i < BUILD_OPTION_MAX; i++) {
-		if (build_options_disabled[i]) {
-			dis_build_options[build_option_identifiers[i]] = build_option_disable_values[i];
+		if (build_options_disabled[i] != build_option_disabled_by_default[i]) {
+			if (build_options_disabled[i]) {
+				dis_build_options[build_option_identifiers[i]] = build_option_disable_values[i];
+			} else {
+				dis_build_options[build_option_identifiers[i]] = !build_option_disable_values[i];
+			}
 		}
 	}
 
@@ -211,7 +292,7 @@ Error EditorBuildProfile::load_from_file(const String &p_path) {
 	}
 
 	for (int i = 0; i < BUILD_OPTION_MAX; i++) {
-		build_options_disabled[i] = false;
+		build_options_disabled[i] = build_option_disabled_by_default[i];
 	}
 
 	if (data.has("disabled_build_options")) {
@@ -259,10 +340,24 @@ void EditorBuildProfile::_bind_methods() {
 	BIND_ENUM_CONSTANT(BUILD_OPTION_RENDERING_DEVICE);
 	BIND_ENUM_CONSTANT(BUILD_OPTION_OPENGL);
 	BIND_ENUM_CONSTANT(BUILD_OPTION_VULKAN);
+	BIND_ENUM_CONSTANT(BUILD_OPTION_TEXT_SERVER_FALLBACK);
+	BIND_ENUM_CONSTANT(BUILD_OPTION_TEXT_SERVER_ADVANCED);
+	BIND_ENUM_CONSTANT(BUILD_OPTION_DYNAMIC_FONTS);
+	BIND_ENUM_CONSTANT(BUILD_OPTION_WOFF2_FONTS);
+	BIND_ENUM_CONSTANT(BUILD_OPTION_GRPAHITE_FONTS);
+	BIND_ENUM_CONSTANT(BUILD_OPTION_MSDFGEN);
 	BIND_ENUM_CONSTANT(BUILD_OPTION_MAX);
+
+	BIND_ENUM_CONSTANT(BUILD_OPTION_CATEGORY_GENERAL);
+	BIND_ENUM_CONSTANT(BUILD_OPTION_CATEGORY_TEXT_SERVER);
+	BIND_ENUM_CONSTANT(BUILD_OPTION_CATEGORY_MAX);
 }
 
-EditorBuildProfile::EditorBuildProfile() {}
+EditorBuildProfile::EditorBuildProfile() {
+	for (int i = 0; i < EditorBuildProfile::BUILD_OPTION_MAX; i++) {
+		build_options_disabled[i] = build_option_disabled_by_default[i];
+	}
+}
 
 //////////////////////////
 
@@ -633,11 +728,18 @@ void EditorBuildProfileManager::_update_edited_profile() {
 
 	TreeItem *root = class_list->create_item();
 
-	TreeItem *build_options = class_list->create_item(root);
-	build_options->set_text(0, TTR("General Features:"));
+	HashMap<EditorBuildProfile::BuildOptionCategory, TreeItem *> subcats;
+	for (int i = 0; i < EditorBuildProfile::BUILD_OPTION_CATEGORY_MAX; i++) {
+		TreeItem *build_cat;
+		build_cat = class_list->create_item(root);
+
+		build_cat->set_text(0, EditorBuildProfile::get_build_option_category_name(EditorBuildProfile::BuildOptionCategory(i)));
+		subcats[EditorBuildProfile::BuildOptionCategory(i)] = build_cat;
+	}
+
 	for (int i = 0; i < EditorBuildProfile::BUILD_OPTION_MAX; i++) {
 		TreeItem *build_option;
-		build_option = class_list->create_item(build_options);
+		build_option = class_list->create_item(subcats[EditorBuildProfile::get_build_option_category(EditorBuildProfile::BuildOption(i))]);
 
 		build_option->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
 		build_option->set_text(0, EditorBuildProfile::get_build_option_name(EditorBuildProfile::BuildOption(i)));

+ 19 - 1
editor/editor_build_profile.h

@@ -53,7 +53,19 @@ public:
 		BUILD_OPTION_RENDERING_DEVICE,
 		BUILD_OPTION_OPENGL,
 		BUILD_OPTION_VULKAN,
-		BUILD_OPTION_MAX
+		BUILD_OPTION_TEXT_SERVER_FALLBACK,
+		BUILD_OPTION_TEXT_SERVER_ADVANCED,
+		BUILD_OPTION_DYNAMIC_FONTS,
+		BUILD_OPTION_WOFF2_FONTS,
+		BUILD_OPTION_GRPAHITE_FONTS,
+		BUILD_OPTION_MSDFGEN,
+		BUILD_OPTION_MAX,
+	};
+
+	enum BuildOptionCategory {
+		BUILD_OPTION_CATEGORY_GENERAL,
+		BUILD_OPTION_CATEGORY_TEXT_SERVER,
+		BUILD_OPTION_CATEGORY_MAX,
 	};
 
 private:
@@ -65,7 +77,9 @@ private:
 
 	bool build_options_disabled[BUILD_OPTION_MAX] = {};
 	static const char *build_option_identifiers[BUILD_OPTION_MAX];
+	static const bool build_option_disabled_by_default[BUILD_OPTION_MAX];
 	static const bool build_option_disable_values[BUILD_OPTION_MAX];
+	static const BuildOptionCategory build_option_category[BUILD_OPTION_MAX];
 
 	String _get_build_option_name(BuildOption p_build_option) { return get_build_option_name(p_build_option); }
 
@@ -93,11 +107,15 @@ public:
 	static String get_build_option_name(BuildOption p_build_option);
 	static String get_build_option_description(BuildOption p_build_option);
 	static bool get_build_option_disable_value(BuildOption p_build_option);
+	static BuildOptionCategory get_build_option_category(BuildOption p_build_option);
+
+	static String get_build_option_category_name(BuildOptionCategory p_build_option_category);
 
 	EditorBuildProfile();
 };
 
 VARIANT_ENUM_CAST(EditorBuildProfile::BuildOption)
+VARIANT_ENUM_CAST(EditorBuildProfile::BuildOptionCategory)
 
 class EditorFileSystemDirectory;
 

+ 2 - 2
editor/editor_node.cpp

@@ -141,6 +141,7 @@
 #include "editor/plugins/bone_map_editor_plugin.h"
 #include "editor/plugins/camera_3d_editor_plugin.h"
 #include "editor/plugins/canvas_item_editor_plugin.h"
+#include "editor/plugins/cast_2d_editor_plugin.h"
 #include "editor/plugins/collision_polygon_2d_editor_plugin.h"
 #include "editor/plugins/collision_shape_2d_editor_plugin.h"
 #include "editor/plugins/control_editor_plugin.h"
@@ -176,7 +177,6 @@
 #include "editor/plugins/physical_bone_3d_editor_plugin.h"
 #include "editor/plugins/polygon_2d_editor_plugin.h"
 #include "editor/plugins/polygon_3d_editor_plugin.h"
-#include "editor/plugins/ray_cast_2d_editor_plugin.h"
 #include "editor/plugins/resource_preloader_editor_plugin.h"
 #include "editor/plugins/root_motion_editor_plugin.h"
 #include "editor/plugins/script_editor_plugin.h"
@@ -7192,7 +7192,7 @@ EditorNode::EditorNode() {
 	add_editor_plugin(memnew(NavigationPolygonEditorPlugin));
 	add_editor_plugin(memnew(Path2DEditorPlugin));
 	add_editor_plugin(memnew(Polygon2DEditorPlugin));
-	add_editor_plugin(memnew(RayCast2DEditorPlugin));
+	add_editor_plugin(memnew(Cast2DEditorPlugin));
 	add_editor_plugin(memnew(Skeleton2DEditorPlugin));
 	add_editor_plugin(memnew(Sprite2DEditorPlugin));
 	add_editor_plugin(memnew(TilesEditorPlugin));

+ 22 - 5
editor/editor_properties.cpp

@@ -133,6 +133,11 @@ void EditorPropertyMultilineText::_text_changed() {
 void EditorPropertyMultilineText::_open_big_text() {
 	if (!big_text_dialog) {
 		big_text = memnew(TextEdit);
+		if (expression) {
+			big_text->set_syntax_highlighter(text->get_syntax_highlighter());
+			big_text->add_theme_font_override("font", get_theme_font(SNAME("expression"), SNAME("EditorFonts")));
+			big_text->add_theme_font_size_override("font_size", get_theme_font_size(SNAME("expression_size"), SNAME("EditorFonts")));
+		}
 		big_text->connect("text_changed", callable_mp(this, &EditorPropertyMultilineText::_big_text_changed));
 		big_text->set_line_wrapping_mode(TextEdit::LineWrappingMode::LINE_WRAPPING_BOUNDARY);
 		big_text_dialog = memnew(AcceptDialog);
@@ -162,12 +167,24 @@ void EditorPropertyMultilineText::_notification(int p_what) {
 		case NOTIFICATION_ENTER_TREE: {
 			Ref<Texture2D> df = get_theme_icon(SNAME("DistractionFree"), SNAME("EditorIcons"));
 			open_big_text->set_icon(df);
-			Ref<Font> font = get_theme_font(SNAME("font"), SNAME("Label"));
-			int font_size = get_theme_font_size(SNAME("font_size"), SNAME("Label"));
-			text->set_custom_minimum_size(Vector2(0, font->get_height(font_size) * 6));
-			text->add_theme_font_override("font", get_theme_font("expression", "EditorFonts"));
-			text->add_theme_font_size_override("font_size", get_theme_font_size("expression_size", "EditorFonts"));
 
+			Ref<Font> font;
+			int font_size;
+			if (expression) {
+				font = get_theme_font(SNAME("expression"), SNAME("EditorFonts"));
+				font_size = get_theme_font_size(SNAME("expression_size"), SNAME("EditorFonts"));
+
+				text->add_theme_font_override("font", font);
+				text->add_theme_font_size_override("font_size", font_size);
+				if (big_text) {
+					big_text->add_theme_font_override("font", font);
+					big_text->add_theme_font_size_override("font_size", font_size);
+				}
+			} else {
+				font = get_theme_font(SNAME("font"), SNAME("TextEdit"));
+				font_size = get_theme_font_size(SNAME("font_size"), SNAME("TextEdit"));
+			}
+			text->set_custom_minimum_size(Vector2(0, font->get_height(font_size) * 6));
 		} break;
 	}
 }

+ 3 - 3
editor/plugins/canvas_item_editor_plugin.cpp

@@ -4237,13 +4237,13 @@ void CanvasItemEditor::_insert_animation_keys(bool p_location, bool p_rotation,
 			Control *ctrl = Object::cast_to<Control>(canvas_item);
 
 			if (key_pos) {
-				te->insert_node_value_key(ctrl, "rect_position", ctrl->get_position(), p_on_existing);
+				te->insert_node_value_key(ctrl, "position", ctrl->get_position(), p_on_existing);
 			}
 			if (key_rot) {
-				te->insert_node_value_key(ctrl, "rect_rotation", ctrl->get_rotation(), p_on_existing);
+				te->insert_node_value_key(ctrl, "rotation", ctrl->get_rotation(), p_on_existing);
 			}
 			if (key_scale) {
-				te->insert_node_value_key(ctrl, "rect_size", ctrl->get_size(), p_on_existing);
+				te->insert_node_value_key(ctrl, "size", ctrl->get_size(), p_on_existing);
 			}
 		}
 	}

+ 30 - 26
editor/plugins/ray_cast_2d_editor_plugin.cpp → editor/plugins/cast_2d_editor_plugin.cpp

@@ -1,5 +1,5 @@
 /*************************************************************************/
-/*  ray_cast_2d_editor_plugin.cpp                                        */
+/*  cast_2d_editor_plugin.cpp                                            */
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
@@ -28,30 +28,32 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 
-#include "ray_cast_2d_editor_plugin.h"
+#include "cast_2d_editor_plugin.h"
 
 #include "canvas_item_editor_plugin.h"
 #include "editor/editor_node.h"
+#include "scene/2d/ray_cast_2d.h"
+#include "scene/2d/shape_cast_2d.h"
 
-void RayCast2DEditor::_notification(int p_what) {
+void Cast2DEditor::_notification(int p_what) {
 	switch (p_what) {
 		case NOTIFICATION_ENTER_TREE: {
-			get_tree()->connect("node_removed", callable_mp(this, &RayCast2DEditor::_node_removed));
+			get_tree()->connect("node_removed", callable_mp(this, &Cast2DEditor::_node_removed));
 		} break;
 
 		case NOTIFICATION_EXIT_TREE: {
-			get_tree()->disconnect("node_removed", callable_mp(this, &RayCast2DEditor::_node_removed));
+			get_tree()->disconnect("node_removed", callable_mp(this, &Cast2DEditor::_node_removed));
 		} break;
 	}
 }
 
-void RayCast2DEditor::_node_removed(Node *p_node) {
+void Cast2DEditor::_node_removed(Node *p_node) {
 	if (p_node == node) {
 		node = nullptr;
 	}
 }
 
-bool RayCast2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
+bool Cast2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
 	if (!node || !node->is_visible_in_tree()) {
 		return false;
 	}
@@ -60,10 +62,12 @@ bool RayCast2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
 
 	Ref<InputEventMouseButton> mb = p_event;
 	if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT) {
+		Vector2 target_position = node->get("target_position");
+
 		if (mb->is_pressed()) {
-			if (xform.xform(node->get_target_position()).distance_to(mb->get_position()) < 8) {
+			if (xform.xform(target_position).distance_to(mb->get_position()) < 8) {
 				pressed = true;
-				original_target_position = node->get_target_position();
+				original_target_position = target_position;
 
 				return true;
 			} else {
@@ -73,9 +77,9 @@ bool RayCast2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
 			}
 		} else if (pressed) {
 			undo_redo->create_action(TTR("Set target_position"));
-			undo_redo->add_do_method(node, "set_target_position", node->get_target_position());
+			undo_redo->add_do_property(node, "target_position", target_position);
 			undo_redo->add_do_method(canvas_item_editor, "update_viewport");
-			undo_redo->add_undo_method(node, "set_target_position", original_target_position);
+			undo_redo->add_undo_property(node, "target_position", original_target_position);
 			undo_redo->add_undo_method(canvas_item_editor, "update_viewport");
 			undo_redo->commit_action();
 
@@ -90,7 +94,7 @@ bool RayCast2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
 		Vector2 point = canvas_item_editor->snap_point(canvas_item_editor->get_canvas_transform().affine_inverse().xform(mm->get_position()));
 		point = node->get_global_transform().affine_inverse().xform(point);
 
-		node->set_target_position(point);
+		node->set("target_position", point);
 		canvas_item_editor->update_viewport();
 		node->notify_property_list_changed();
 
@@ -100,7 +104,7 @@ bool RayCast2DEditor::forward_canvas_gui_input(const Ref<InputEvent> &p_event) {
 	return false;
 }
 
-void RayCast2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
+void Cast2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
 	if (!node || !node->is_visible_in_tree()) {
 		return;
 	}
@@ -108,16 +112,16 @@ void RayCast2DEditor::forward_canvas_draw_over_viewport(Control *p_overlay) {
 	Transform2D gt = canvas_item_editor->get_canvas_transform() * node->get_global_transform();
 
 	const Ref<Texture2D> handle = get_theme_icon(SNAME("EditorHandle"), SNAME("EditorIcons"));
-	p_overlay->draw_texture(handle, gt.xform(node->get_target_position()) - handle->get_size() / 2);
+	p_overlay->draw_texture(handle, gt.xform((Vector2)node->get("target_position")) - handle->get_size() / 2);
 }
 
-void RayCast2DEditor::edit(Node *p_node) {
+void Cast2DEditor::edit(Node2D *p_node) {
 	if (!canvas_item_editor) {
 		canvas_item_editor = CanvasItemEditor::get_singleton();
 	}
 
-	if (p_node) {
-		node = Object::cast_to<RayCast2D>(p_node);
+	if (Object::cast_to<RayCast2D>(p_node) || Object::cast_to<ShapeCast2D>(p_node)) {
+		node = p_node;
 	} else {
 		node = nullptr;
 	}
@@ -125,27 +129,27 @@ void RayCast2DEditor::edit(Node *p_node) {
 	canvas_item_editor->update_viewport();
 }
 
-RayCast2DEditor::RayCast2DEditor() {
+Cast2DEditor::Cast2DEditor() {
 	undo_redo = EditorNode::get_singleton()->get_undo_redo();
 }
 
 ///////////////////////
 
-void RayCast2DEditorPlugin::edit(Object *p_object) {
-	ray_cast_2d_editor->edit(Object::cast_to<RayCast2D>(p_object));
+void Cast2DEditorPlugin::edit(Object *p_object) {
+	cast_2d_editor->edit(Object::cast_to<Node2D>(p_object));
 }
 
-bool RayCast2DEditorPlugin::handles(Object *p_object) const {
-	return Object::cast_to<RayCast2D>(p_object) != nullptr;
+bool Cast2DEditorPlugin::handles(Object *p_object) const {
+	return Object::cast_to<RayCast2D>(p_object) != nullptr || Object::cast_to<ShapeCast2D>(p_object) != nullptr;
 }
 
-void RayCast2DEditorPlugin::make_visible(bool p_visible) {
+void Cast2DEditorPlugin::make_visible(bool p_visible) {
 	if (!p_visible) {
 		edit(nullptr);
 	}
 }
 
-RayCast2DEditorPlugin::RayCast2DEditorPlugin() {
-	ray_cast_2d_editor = memnew(RayCast2DEditor);
-	EditorNode::get_singleton()->get_gui_base()->add_child(ray_cast_2d_editor);
+Cast2DEditorPlugin::Cast2DEditorPlugin() {
+	cast_2d_editor = memnew(Cast2DEditor);
+	EditorNode::get_singleton()->get_gui_base()->add_child(cast_2d_editor);
 }

+ 17 - 17
editor/plugins/ray_cast_2d_editor_plugin.h → editor/plugins/cast_2d_editor_plugin.h

@@ -1,5 +1,5 @@
 /*************************************************************************/
-/*  ray_cast_2d_editor_plugin.h                                          */
+/*  cast_2d_editor_plugin.h                                              */
 /*************************************************************************/
 /*                       This file is part of:                           */
 /*                           GODOT ENGINE                                */
@@ -28,20 +28,20 @@
 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
 /*************************************************************************/
 
-#ifndef RAY_CAST_2D_EDITOR_PLUGIN_H
-#define RAY_CAST_2D_EDITOR_PLUGIN_H
+#ifndef CAST_2D_EDITOR_PLUGIN_H
+#define CAST_2D_EDITOR_PLUGIN_H
 
 #include "editor/editor_plugin.h"
-#include "scene/2d/ray_cast_2d.h"
+#include "scene/2d/node_2d.h"
 
 class CanvasItemEditor;
 
-class RayCast2DEditor : public Control {
-	GDCLASS(RayCast2DEditor, Control);
+class Cast2DEditor : public Control {
+	GDCLASS(Cast2DEditor, Control);
 
 	UndoRedo *undo_redo = nullptr;
 	CanvasItemEditor *canvas_item_editor = nullptr;
-	RayCast2D *node;
+	Node2D *node;
 
 	bool pressed = false;
 	Point2 original_target_position;
@@ -53,27 +53,27 @@ protected:
 public:
 	bool forward_canvas_gui_input(const Ref<InputEvent> &p_event);
 	void forward_canvas_draw_over_viewport(Control *p_overlay);
-	void edit(Node *p_node);
+	void edit(Node2D *p_node);
 
-	RayCast2DEditor();
+	Cast2DEditor();
 };
 
-class RayCast2DEditorPlugin : public EditorPlugin {
-	GDCLASS(RayCast2DEditorPlugin, EditorPlugin);
+class Cast2DEditorPlugin : public EditorPlugin {
+	GDCLASS(Cast2DEditorPlugin, EditorPlugin);
 
-	RayCast2DEditor *ray_cast_2d_editor = nullptr;
+	Cast2DEditor *cast_2d_editor = nullptr;
 
 public:
-	virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) override { return ray_cast_2d_editor->forward_canvas_gui_input(p_event); }
-	virtual void forward_canvas_draw_over_viewport(Control *p_overlay) override { ray_cast_2d_editor->forward_canvas_draw_over_viewport(p_overlay); }
+	virtual bool forward_canvas_gui_input(const Ref<InputEvent> &p_event) override { return cast_2d_editor->forward_canvas_gui_input(p_event); }
+	virtual void forward_canvas_draw_over_viewport(Control *p_overlay) override { cast_2d_editor->forward_canvas_draw_over_viewport(p_overlay); }
 
-	virtual String get_name() const override { return "RayCast2D"; }
+	virtual String get_name() const override { return "Cast2D"; }
 	bool has_main_screen() const override { return false; }
 	virtual void edit(Object *p_object) override;
 	virtual bool handles(Object *p_object) const override;
 	virtual void make_visible(bool visible) override;
 
-	RayCast2DEditorPlugin();
+	Cast2DEditorPlugin();
 };
 
-#endif // RAY_CAST_2D_EDITOR_PLUGIN_H
+#endif // CAST_2D_EDITOR_PLUGIN_H

+ 3 - 0
editor/plugins/script_editor_plugin.cpp

@@ -1853,10 +1853,12 @@ void ScriptEditor::_update_members_overview_visibility() {
 
 	if (members_overview_enabled && se->show_members_overview()) {
 		members_overview_alphabeta_sort_button->set_visible(true);
+		filter_methods->set_visible(true);
 		members_overview->set_visible(true);
 		overview_vbox->set_visible(true);
 	} else {
 		members_overview_alphabeta_sort_button->set_visible(false);
+		filter_methods->set_visible(false);
 		members_overview->set_visible(false);
 		overview_vbox->set_visible(false);
 	}
@@ -1911,6 +1913,7 @@ void ScriptEditor::_update_help_overview_visibility() {
 
 	if (help_overview_enabled) {
 		members_overview_alphabeta_sort_button->set_visible(false);
+		filter_methods->set_visible(false);
 		help_overview->set_visible(true);
 		overview_vbox->set_visible(true);
 		filename->set_text(se->get_name());

Fichier diff supprimé car celui-ci est trop grand
+ 514 - 884
editor/project_converter_3_to_4.cpp


+ 10 - 3
editor/project_converter_3_to_4.h

@@ -37,17 +37,23 @@
 #include "core/string/ustring.h"
 
 class ProjectConverter3To4 {
+public:
+	class RegExContainer;
+
+private:
 	void rename_enums(String &file_content);
 	Vector<String> check_for_rename_enums(Vector<String> &file_content);
 
 	void rename_classes(String &file_content);
 	Vector<String> check_for_rename_classes(Vector<String> &file_content);
 
-	void rename_gdscript_functions(String &file_content);
-	Vector<String> check_for_rename_gdscript_functions(Vector<String> &file_content);
+	void rename_gdscript_functions(String &file_content, const RegExContainer &reg_container, bool builtin);
+	Vector<String> check_for_rename_gdscript_functions(Vector<String> &file_content, const RegExContainer &reg_container, bool builtin);
+	void process_gdscript_line(String &line, const RegExContainer &reg_container, bool builtin);
 
 	void rename_csharp_functions(String &file_content);
 	Vector<String> check_for_rename_csharp_functions(Vector<String> &file_content);
+	void process_csharp_line(String &line);
 
 	void rename_gdscript_keywords(String &file_content);
 	Vector<String> check_for_rename_gdscript_keywords(Vector<String> &file_content);
@@ -71,9 +77,10 @@ class ProjectConverter3To4 {
 
 	bool test_single_array(const char *array[][2], bool ignore_second_check = false);
 	bool test_conversion_single_additional(String name, String expected, void (ProjectConverter3To4::*func)(String &), String what);
+	bool test_conversion_single_additional_builtin(String name, String expected, void (ProjectConverter3To4::*func)(String &, const RegExContainer &, bool), String what, const RegExContainer &reg_container, bool builtin);
 	bool test_conversion_single_normal(String name, String expected, const char *array[][2], String what);
 	bool test_array_names();
-	bool test_conversion();
+	bool test_conversion(const RegExContainer &reg_container);
 
 public:
 	int validate_conversion();

+ 17 - 16
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"])

+ 8 - 0
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

+ 21 - 29
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.

+ 8 - 4
modules/text_server_adv/SCsub

@@ -113,8 +113,11 @@ 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"])
@@ -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()
 
@@ -512,9 +515,10 @@ if env["builtin_msdfgen"] and msdfgen_enabled:
     env_text_server_adv.Prepend(CPPPATH=["#thirdparty/msdfgen"])
 
 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")

+ 8 - 0
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
 

+ 1 - 1
modules/text_server_adv/text_server_adv.cpp

@@ -4706,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)) {

+ 4 - 1
modules/text_server_adv/text_server_adv.h

@@ -113,7 +113,10 @@ using namespace godot;
 #include FT_ADVANCES_H
 #include FT_MULTIPLE_MASTERS_H
 #include FT_BBOX_H
-
+#include FT_CONFIG_OPTIONS_H
+#if !defined(FT_CONFIG_OPTION_USE_BROTLI) && !defined(_MSC_VER)
+#warning FreeType is configured without Brotli support, built-in fonts will not be available.
+#endif
 #include <hb-ft.h>
 #include <hb-ot.h>
 #endif

+ 1 - 0
modules/text_server_fb/SCsub

@@ -12,6 +12,7 @@ if env["builtin_msdfgen"] and msdfgen_enabled:
     env_text_server_fb.Prepend(CPPPATH=["#thirdparty/msdfgen"])
 
 if env["builtin_freetype"] and freetype_enabled:
+    env_text_server_fb.Append(CPPDEFINES=["FT_CONFIG_OPTION_USE_BROTLI"])
     env_text_server_fb.Prepend(CPPPATH=["#thirdparty/freetype/include"])
 
 env_text_server_fb.add_source_files(env.modules_sources, "*.cpp")

+ 4 - 0
modules/text_server_fb/text_server_fb.h

@@ -98,6 +98,10 @@ using namespace godot;
 #include FT_ADVANCES_H
 #include FT_MULTIPLE_MASTERS_H
 #include FT_BBOX_H
+#include FT_CONFIG_OPTIONS_H
+#if !defined(FT_CONFIG_OPTION_USE_BROTLI) && !defined(_MSC_VER)
+#warning FreeType is configured without Brotli support, built-in fonts will not be available.
+#endif
 #endif
 
 /*************************************************************************/

+ 1 - 0
platform/macos/display_server_macos.h

@@ -303,6 +303,7 @@ public:
 	virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
 	virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
 	virtual void screen_set_keep_on(bool p_enable) override;
+	virtual bool screen_is_kept_on() const override;
 
 	virtual Vector<int> get_window_list() const override;
 

+ 4 - 0
platform/macos/display_server_macos.mm

@@ -1892,6 +1892,10 @@ float DisplayServerMacOS::screen_get_refresh_rate(int p_screen) const {
 	return SCREEN_REFRESH_RATE_FALLBACK;
 }
 
+bool DisplayServerMacOS::screen_is_kept_on() const {
+	return (screen_keep_on_assertion);
+}
+
 void DisplayServerMacOS::screen_set_keep_on(bool p_enable) {
 	if (screen_keep_on_assertion) {
 		IOPMAssertionRelease(screen_keep_on_assertion);

+ 40 - 1
platform/windows/display_server_windows.cpp

@@ -531,10 +531,43 @@ DisplayServer::ScreenOrientation DisplayServerWindows::screen_get_orientation(in
 }
 
 void DisplayServerWindows::screen_set_keep_on(bool p_enable) {
+	if (keep_screen_on == p_enable) {
+		return;
+	}
+
+	if (p_enable) {
+		const String reason = "Godot Engine running with display/window/energy_saving/keep_screen_on = true";
+		Char16String reason_utf16 = reason.utf16();
+
+		REASON_CONTEXT context;
+		context.Version = POWER_REQUEST_CONTEXT_VERSION;
+		context.Flags = POWER_REQUEST_CONTEXT_SIMPLE_STRING;
+		context.Reason.SimpleReasonString = (LPWSTR)(reason_utf16.ptrw());
+		power_request = PowerCreateRequest(&context);
+		if (power_request == INVALID_HANDLE_VALUE) {
+			print_error("Failed to enable screen_keep_on.");
+			return;
+		}
+		if (PowerSetRequest(power_request, POWER_REQUEST_TYPE::PowerRequestSystemRequired) == 0) {
+			print_error("Failed to request system sleep override.");
+			return;
+		}
+		if (PowerSetRequest(power_request, POWER_REQUEST_TYPE::PowerRequestDisplayRequired) == 0) {
+			print_error("Failed to request display timeout override.");
+			return;
+		}
+	} else {
+		PowerClearRequest(power_request, POWER_REQUEST_TYPE::PowerRequestSystemRequired);
+		PowerClearRequest(power_request, POWER_REQUEST_TYPE::PowerRequestDisplayRequired);
+		CloseHandle(power_request);
+		power_request = nullptr;
+	}
+
+	keep_screen_on = p_enable;
 }
 
 bool DisplayServerWindows::screen_is_kept_on() const {
-	return false;
+	return keep_screen_on;
 }
 
 Vector<DisplayServer::WindowID> DisplayServerWindows::get_window_list() const {
@@ -3619,6 +3652,9 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
 	// Init TTS
 	tts = memnew(TTS_Windows);
 
+	// Enforce default keep screen on value.
+	screen_set_keep_on(GLOBAL_DEF("display/window/energy_saving/keep_screen_on", true));
+
 	// Note: Wacom WinTab driver API for pen input, for devices incompatible with Windows Ink.
 	HMODULE wintab_lib = LoadLibraryW(L"wintab32.dll");
 	if (wintab_lib) {
@@ -3822,6 +3858,9 @@ DisplayServerWindows::~DisplayServerWindows() {
 		SetWindowLongPtr(windows[MAIN_WINDOW_ID].hWnd, GWLP_WNDPROC, (LONG_PTR)user_proc);
 	}
 
+	// Close power request handle.
+	screen_set_keep_on(false);
+
 #ifdef GLES3_ENABLED
 	// destroy windows .. NYI?
 	// FIXME wglDeleteContext is never called

+ 2 - 0
platform/windows/display_server_windows.h

@@ -331,6 +331,8 @@ class DisplayServerWindows : public DisplayServer {
 	HINSTANCE hInstance; // Holds The Instance Of The Application
 	String rendering_driver;
 	bool app_focused = false;
+	bool keep_screen_on = false;
+	HANDLE power_request;
 
 	TTS_Windows *tts = nullptr;
 

+ 22 - 9
scene/2d/shape_cast_2d.cpp

@@ -217,7 +217,7 @@ void ShapeCast2D::_notification(int p_what) {
 			if (shape.is_null()) {
 				break;
 			}
-			Color draw_col = get_tree()->get_debug_collisions_color();
+			Color draw_col = collided ? Color(1.0, 0.01, 0) : get_tree()->get_debug_collisions_color();
 			if (!enabled) {
 				float g = draw_col.get_v();
 				draw_col.r = g;
@@ -235,18 +235,25 @@ void ShapeCast2D::_notification(int p_what) {
 
 			// Draw an arrow indicating where the ShapeCast is pointing to.
 			if (target_position != Vector2()) {
-				Transform2D xf;
-				xf.rotate(target_position.angle());
-				xf.translate_local(Vector2(target_position.length(), 0));
+				const real_t max_arrow_size = 6;
+				const real_t line_width = 1.4;
+				bool no_line = target_position.length() < line_width;
+				real_t arrow_size = CLAMP(target_position.length() * 2 / 3, line_width, max_arrow_size);
 
-				draw_line(Vector2(), target_position, draw_col, 2);
+				if (no_line) {
+					arrow_size = target_position.length();
+				} else {
+					draw_line(Vector2(), target_position - target_position.normalized() * arrow_size, draw_col, line_width);
+				}
 
-				float tsize = 8;
+				Transform2D xf;
+				xf.rotate(target_position.angle());
+				xf.translate_local(Vector2(no_line ? 0 : target_position.length() - arrow_size, 0));
 
 				Vector<Vector2> pts = {
-					xf.xform(Vector2(tsize, 0)),
-					xf.xform(Vector2(0, Math_SQRT12 * tsize)),
-					xf.xform(Vector2(0, -Math_SQRT12 * tsize))
+					xf.xform(Vector2(arrow_size, 0)),
+					xf.xform(Vector2(0, 0.5 * arrow_size)),
+					xf.xform(Vector2(0, -0.5 * arrow_size))
 				};
 
 				Vector<Color> cols = { draw_col, draw_col, draw_col };
@@ -291,6 +298,8 @@ void ShapeCast2D::_update_shapecast_state() {
 	collision_safe_fraction = 0.0;
 	collision_unsafe_fraction = 0.0;
 
+	bool prev_collision_state = collided;
+
 	if (target_position != Vector2()) {
 		dss->cast_motion(params, collision_safe_fraction, collision_unsafe_fraction);
 		if (collision_unsafe_fraction < 1.0) {
@@ -314,6 +323,10 @@ void ShapeCast2D::_update_shapecast_state() {
 		}
 	}
 	collided = !result.is_empty();
+
+	if (prev_collision_state != collided) {
+		update();
+	}
 }
 
 void ShapeCast2D::force_shapecast_update() {

+ 2 - 2
scene/gui/color_mode.cpp

@@ -159,7 +159,7 @@ void ColorModeHSV::slider_draw(int p_which) {
 	} else if (p_which == 0) {
 		Ref<Texture2D> hue = color_picker->get_theme_icon(SNAME("color_hue"), SNAME("ColorPicker"));
 		slider->draw_set_transform(Point2(), -Math_PI / 2, Size2(1.0, 1.0));
-		slider->draw_texture_rect(hue, Rect2(Vector2(margin * -2, 0), Vector2(slider->get_size().x, margin)), false, Color(1, 1, 1), true);
+		slider->draw_texture_rect(hue, Rect2(Vector2(margin * -2, 0), Vector2(margin, size.x)), false);
 		return;
 	} else {
 		Color s_col;
@@ -306,7 +306,7 @@ void ColorModeOKHSL::slider_draw(int p_which) {
 	} else if (p_which == 0) {
 		Ref<Texture2D> hue = color_picker->get_theme_icon(SNAME("color_hue"), SNAME("ColorPicker"));
 		slider->draw_set_transform(Point2(), -Math_PI / 2, Size2(1.0, 1.0));
-		slider->draw_texture_rect(hue, Rect2(Vector2(margin * -2, 0), Vector2(slider->get_size().x, margin)), false, Color(1, 1, 1), true);
+		slider->draw_texture_rect(hue, Rect2(Vector2(margin * -2, 0), Vector2(margin, size.x)), false);
 		return;
 	} else {
 		Color s_col;

+ 1 - 1
scene/gui/graph_node.cpp

@@ -450,7 +450,7 @@ void GraphNode::_validate_property(PropertyInfo &property) const {
 	Control::_validate_property(property);
 	GraphEdit *graph = Object::cast_to<GraphEdit>(get_parent());
 	if (graph) {
-		if (property.name == "rect_position") {
+		if (property.name == "position") {
 			property.usage |= PROPERTY_USAGE_READ_ONLY;
 		}
 	}

+ 120 - 78
tests/servers/test_text_server.h

@@ -44,7 +44,7 @@ TEST_SUITE("[TextServer]") {
 		SUBCASE("[TextServer] Loading fonts") {
 			for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
 				Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i);
-				TEST_FAIL_COND(ts.is_null(), "Invalid TS interface.");
+				CHECK_FALSE_MESSAGE(ts.is_null(), "Invalid TS interface.");
 
 				if (!ts->has_feature(TextServer::FEATURE_FONT_DYNAMIC)) {
 					continue;
@@ -52,7 +52,7 @@ TEST_SUITE("[TextServer]") {
 
 				RID font = ts->create_font();
 				ts->font_set_data_ptr(font, _font_NotoSans_Regular, _font_NotoSans_Regular_size);
-				TEST_FAIL_COND(font == RID(), "Loading font failed.");
+				CHECK_FALSE_MESSAGE(font == RID(), "Loading font failed.");
 				ts->free_rid(font);
 			}
 		}
@@ -60,7 +60,7 @@ TEST_SUITE("[TextServer]") {
 		SUBCASE("[TextServer] Text layout: Font fallback") {
 			for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
 				Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i);
-				TEST_FAIL_COND(ts.is_null(), "Invalid TS interface.");
+				CHECK_FALSE_MESSAGE(ts.is_null(), "Invalid TS interface.");
 
 				if (!ts->has_feature(TextServer::FEATURE_FONT_DYNAMIC) || !ts->has_feature(TextServer::FEATURE_SIMPLE_LAYOUT)) {
 					continue;
@@ -79,26 +79,26 @@ TEST_SUITE("[TextServer]") {
 				//                 6^       17^
 
 				RID ctx = ts->create_shaped_text();
-				TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed.");
+				CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed.");
 				bool ok = ts->shaped_text_add_string(ctx, test, font, 16);
-				TEST_FAIL_COND(!ok, "Adding text to the buffer failed.");
+				CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed.");
 
 				const Glyph *glyphs = ts->shaped_text_get_glyphs(ctx);
 				int gl_size = ts->shaped_text_get_glyph_count(ctx);
-				TEST_FAIL_COND(gl_size == 0, "Shaping failed");
+				CHECK_FALSE_MESSAGE(gl_size == 0, "Shaping failed");
 				for (int j = 0; j < gl_size; j++) {
 					if (glyphs[j].start < 6) {
-						TEST_FAIL_COND(glyphs[j].font_rid != font[1], "Incorrect font selected.");
+						CHECK_FALSE_MESSAGE(glyphs[j].font_rid != font[1], "Incorrect font selected.");
 					}
 					if ((glyphs[j].start > 6) && (glyphs[j].start < 16)) {
-						TEST_FAIL_COND(glyphs[j].font_rid != font[0], "Incorrect font selected.");
+						CHECK_FALSE_MESSAGE(glyphs[j].font_rid != font[0], "Incorrect font selected.");
 					}
 					if (glyphs[j].start > 16) {
-						TEST_FAIL_COND(glyphs[j].font_rid != RID(), "Incorrect font selected.");
-						TEST_FAIL_COND(glyphs[j].index != test[glyphs[j].start], "Incorrect glyph index.");
+						CHECK_FALSE_MESSAGE(glyphs[j].font_rid != RID(), "Incorrect font selected.");
+						CHECK_FALSE_MESSAGE(glyphs[j].index != test[glyphs[j].start], "Incorrect glyph index.");
 					}
-					TEST_FAIL_COND((glyphs[j].start < 0 || glyphs[j].end > test.length()), "Incorrect glyph range.");
-					TEST_FAIL_COND(glyphs[j].font_size != 16, "Incorrect glyph font size.");
+					CHECK_FALSE_MESSAGE((glyphs[j].start < 0 || glyphs[j].end > test.length()), "Incorrect glyph range.");
+					CHECK_FALSE_MESSAGE(glyphs[j].font_size != 16, "Incorrect glyph font size.");
 				}
 
 				ts->free_rid(ctx);
@@ -113,7 +113,7 @@ TEST_SUITE("[TextServer]") {
 		SUBCASE("[TextServer] Text layout: BiDi") {
 			for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
 				Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i);
-				TEST_FAIL_COND(ts.is_null(), "Invalid TS interface.");
+				CHECK_FALSE_MESSAGE(ts.is_null(), "Invalid TS interface.");
 
 				if (!ts->has_feature(TextServer::FEATURE_FONT_DYNAMIC) || !ts->has_feature(TextServer::FEATURE_BIDI_LAYOUT)) {
 					continue;
@@ -132,23 +132,23 @@ TEST_SUITE("[TextServer]") {
 				//                    7^      26^
 
 				RID ctx = ts->create_shaped_text();
-				TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed.");
+				CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed.");
 				bool ok = ts->shaped_text_add_string(ctx, test, font, 16);
-				TEST_FAIL_COND(!ok, "Adding text to the buffer failed.");
+				CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed.");
 
 				const Glyph *glyphs = ts->shaped_text_get_glyphs(ctx);
 				int gl_size = ts->shaped_text_get_glyph_count(ctx);
-				TEST_FAIL_COND(gl_size == 0, "Shaping failed");
+				CHECK_FALSE_MESSAGE(gl_size == 0, "Shaping failed");
 				for (int j = 0; j < gl_size; j++) {
 					if (glyphs[j].count > 0) {
 						if (glyphs[j].start < 7) {
-							TEST_FAIL_COND(((glyphs[j].flags & TextServer::GRAPHEME_IS_RTL) == TextServer::GRAPHEME_IS_RTL), "Incorrect direction.");
+							CHECK_FALSE_MESSAGE(((glyphs[j].flags & TextServer::GRAPHEME_IS_RTL) == TextServer::GRAPHEME_IS_RTL), "Incorrect direction.");
 						}
 						if ((glyphs[j].start > 8) && (glyphs[j].start < 23)) {
-							TEST_FAIL_COND(((glyphs[j].flags & TextServer::GRAPHEME_IS_RTL) != TextServer::GRAPHEME_IS_RTL), "Incorrect direction.");
+							CHECK_FALSE_MESSAGE(((glyphs[j].flags & TextServer::GRAPHEME_IS_RTL) != TextServer::GRAPHEME_IS_RTL), "Incorrect direction.");
 						}
 						if (glyphs[j].start > 26) {
-							TEST_FAIL_COND(((glyphs[j].flags & TextServer::GRAPHEME_IS_RTL) == TextServer::GRAPHEME_IS_RTL), "Incorrect direction.");
+							CHECK_FALSE_MESSAGE(((glyphs[j].flags & TextServer::GRAPHEME_IS_RTL) == TextServer::GRAPHEME_IS_RTL), "Incorrect direction.");
 						}
 					}
 				}
@@ -165,7 +165,7 @@ TEST_SUITE("[TextServer]") {
 		SUBCASE("[TextServer] Text layout: Line break and align points") {
 			for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
 				Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i);
-				TEST_FAIL_COND(ts.is_null(), "Invalid TS interface.");
+				CHECK_FALSE_MESSAGE(ts.is_null(), "Invalid TS interface.");
 
 				if (!ts->has_feature(TextServer::FEATURE_FONT_DYNAMIC) || !ts->has_feature(TextServer::FEATURE_SIMPLE_LAYOUT)) {
 					continue;
@@ -186,16 +186,16 @@ TEST_SUITE("[TextServer]") {
 				{
 					String test = U"Test test long text long text\n";
 					RID ctx = ts->create_shaped_text();
-					TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed.");
+					CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed.");
 					bool ok = ts->shaped_text_add_string(ctx, test, font, 16);
-					TEST_FAIL_COND(!ok, "Adding text to the buffer failed.");
+					CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed.");
 					ts->shaped_text_update_breaks(ctx);
 					ts->shaped_text_update_justification_ops(ctx);
 
 					const Glyph *glyphs = ts->shaped_text_get_glyphs(ctx);
 					int gl_size = ts->shaped_text_get_glyph_count(ctx);
 
-					TEST_FAIL_COND(gl_size != 30, "Invalid glyph count.");
+					CHECK_FALSE_MESSAGE(gl_size != 30, "Invalid glyph count.");
 					for (int j = 0; j < gl_size; j++) {
 						bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD;
 						bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT;
@@ -203,11 +203,11 @@ TEST_SUITE("[TextServer]") {
 						bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL;
 						bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION;
 						if (j == 4 || j == 9 || j == 14 || j == 19 || j == 24) {
-							TEST_FAIL_COND((!soft || !space || hard || virt || elo), "Invalid glyph flags.");
+							CHECK_FALSE_MESSAGE((!soft || !space || hard || virt || elo), "Invalid glyph flags.");
 						} else if (j == 29) {
-							TEST_FAIL_COND((soft || !space || !hard || virt || elo), "Invalid glyph flags.");
+							CHECK_FALSE_MESSAGE((soft || !space || !hard || virt || elo), "Invalid glyph flags.");
 						} else {
-							TEST_FAIL_COND((soft || space || hard || virt || elo), "Invalid glyph flags.");
+							CHECK_FALSE_MESSAGE((soft || space || hard || virt || elo), "Invalid glyph flags.");
 						}
 					}
 					ts->free_rid(ctx);
@@ -216,21 +216,63 @@ TEST_SUITE("[TextServer]") {
 				{
 					String test = U"الحمـد";
 					RID ctx = ts->create_shaped_text();
-					TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed.");
+					CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed.");
 					bool ok = ts->shaped_text_add_string(ctx, test, font, 16);
-					TEST_FAIL_COND(!ok, "Adding text to the buffer failed.");
+					CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed.");
 					ts->shaped_text_update_breaks(ctx);
 
 					const Glyph *glyphs = ts->shaped_text_get_glyphs(ctx);
 					int gl_size = ts->shaped_text_get_glyph_count(ctx);
-					TEST_FAIL_COND(gl_size != 6, "Invalid glyph count.");
+					CHECK_FALSE_MESSAGE(gl_size != 6, "Invalid glyph count.");
 					for (int j = 0; j < gl_size; j++) {
 						bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD;
 						bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT;
 						bool space = (glyphs[j].flags & TextServer::GRAPHEME_IS_SPACE) == TextServer::GRAPHEME_IS_SPACE;
 						bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL;
 						bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION;
-						TEST_FAIL_COND((soft || space || hard || virt || elo), "Invalid glyph flags.");
+						CHECK_FALSE_MESSAGE((soft || space || hard || virt || elo), "Invalid glyph flags.");
+					}
+					if (ts->has_feature(TextServer::FEATURE_KASHIDA_JUSTIFICATION)) {
+						ts->shaped_text_update_justification_ops(ctx);
+
+						glyphs = ts->shaped_text_get_glyphs(ctx);
+						gl_size = ts->shaped_text_get_glyph_count(ctx);
+
+						CHECK_FALSE_MESSAGE(gl_size != 6, "Invalid glyph count.");
+						for (int j = 0; j < gl_size; j++) {
+							bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD;
+							bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT;
+							bool space = (glyphs[j].flags & TextServer::GRAPHEME_IS_SPACE) == TextServer::GRAPHEME_IS_SPACE;
+							bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL;
+							bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION;
+							if (j == 1) {
+								CHECK_FALSE_MESSAGE((soft || space || hard || virt || !elo), "Invalid glyph flags.");
+							} else {
+								CHECK_FALSE_MESSAGE((soft || space || hard || virt || elo), "Invalid glyph flags.");
+							}
+						}
+					}
+					ts->free_rid(ctx);
+				}
+
+				{
+					String test = U"الحمد";
+					RID ctx = ts->create_shaped_text();
+					CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed.");
+					bool ok = ts->shaped_text_add_string(ctx, test, font, 16);
+					CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed.");
+					ts->shaped_text_update_breaks(ctx);
+
+					const Glyph *glyphs = ts->shaped_text_get_glyphs(ctx);
+					int gl_size = ts->shaped_text_get_glyph_count(ctx);
+					CHECK_FALSE_MESSAGE(gl_size != 5, "Invalid glyph count.");
+					for (int j = 0; j < gl_size; j++) {
+						bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD;
+						bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT;
+						bool space = (glyphs[j].flags & TextServer::GRAPHEME_IS_SPACE) == TextServer::GRAPHEME_IS_SPACE;
+						bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL;
+						bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION;
+						CHECK_FALSE_MESSAGE((soft || space || hard || virt || elo), "Invalid glyph flags.");
 					}
 
 					if (ts->has_feature(TextServer::FEATURE_KASHIDA_JUSTIFICATION)) {
@@ -239,7 +281,7 @@ TEST_SUITE("[TextServer]") {
 						glyphs = ts->shaped_text_get_glyphs(ctx);
 						gl_size = ts->shaped_text_get_glyph_count(ctx);
 
-						TEST_FAIL_COND(gl_size != 6, "Invalid glyph count.");
+						CHECK_FALSE_MESSAGE(gl_size != 6, "Invalid glyph count.");
 						for (int j = 0; j < gl_size; j++) {
 							bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD;
 							bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT;
@@ -247,9 +289,9 @@ TEST_SUITE("[TextServer]") {
 							bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL;
 							bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION;
 							if (j == 1) {
-								TEST_FAIL_COND((soft || space || hard || virt || !elo), "Invalid glyph flags.");
+								CHECK_FALSE_MESSAGE((soft || space || hard || !virt || !elo), "Invalid glyph flags.");
 							} else {
-								TEST_FAIL_COND((soft || space || hard || virt || elo), "Invalid glyph flags.");
+								CHECK_FALSE_MESSAGE((soft || space || hard || virt || elo), "Invalid glyph flags.");
 							}
 						}
 					}
@@ -259,15 +301,15 @@ TEST_SUITE("[TextServer]") {
 				{
 					String test = U"الحمـد الرياضي العربي";
 					RID ctx = ts->create_shaped_text();
-					TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed.");
+					CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed.");
 					bool ok = ts->shaped_text_add_string(ctx, test, font, 16);
-					TEST_FAIL_COND(!ok, "Adding text to the buffer failed.");
+					CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed.");
 					ts->shaped_text_update_breaks(ctx);
 
 					const Glyph *glyphs = ts->shaped_text_get_glyphs(ctx);
 					int gl_size = ts->shaped_text_get_glyph_count(ctx);
 
-					TEST_FAIL_COND(gl_size != 21, "Invalid glyph count.");
+					CHECK_FALSE_MESSAGE(gl_size != 21, "Invalid glyph count.");
 					for (int j = 0; j < gl_size; j++) {
 						bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD;
 						bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT;
@@ -275,9 +317,9 @@ TEST_SUITE("[TextServer]") {
 						bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL;
 						bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION;
 						if (j == 6 || j == 14) {
-							TEST_FAIL_COND((!soft || !space || hard || virt || elo), "Invalid glyph flags.");
+							CHECK_FALSE_MESSAGE((!soft || !space || hard || virt || elo), "Invalid glyph flags.");
 						} else {
-							TEST_FAIL_COND((soft || space || hard || virt || elo), "Invalid glyph flags.");
+							CHECK_FALSE_MESSAGE((soft || space || hard || virt || elo), "Invalid glyph flags.");
 						}
 					}
 
@@ -287,7 +329,7 @@ TEST_SUITE("[TextServer]") {
 						glyphs = ts->shaped_text_get_glyphs(ctx);
 						gl_size = ts->shaped_text_get_glyph_count(ctx);
 
-						TEST_FAIL_COND(gl_size != 23, "Invalid glyph count.");
+						CHECK_FALSE_MESSAGE(gl_size != 23, "Invalid glyph count.");
 						for (int j = 0; j < gl_size; j++) {
 							bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD;
 							bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT;
@@ -295,13 +337,13 @@ TEST_SUITE("[TextServer]") {
 							bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL;
 							bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION;
 							if (j == 7 || j == 16) {
-								TEST_FAIL_COND((!soft || !space || hard || virt || elo), "Invalid glyph flags.");
+								CHECK_FALSE_MESSAGE((!soft || !space || hard || virt || elo), "Invalid glyph flags.");
 							} else if (j == 3 || j == 9) {
-								TEST_FAIL_COND((soft || space || hard || !virt || !elo), "Invalid glyph flags.");
+								CHECK_FALSE_MESSAGE((soft || space || hard || !virt || !elo), "Invalid glyph flags.");
 							} else if (j == 18) {
-								TEST_FAIL_COND((soft || space || hard || virt || !elo), "Invalid glyph flags.");
+								CHECK_FALSE_MESSAGE((soft || space || hard || virt || !elo), "Invalid glyph flags.");
 							} else {
-								TEST_FAIL_COND((soft || space || hard || virt || elo), "Invalid glyph flags.");
+								CHECK_FALSE_MESSAGE((soft || space || hard || virt || elo), "Invalid glyph flags.");
 							}
 						}
 					}
@@ -312,16 +354,16 @@ TEST_SUITE("[TextServer]") {
 				{
 					String test = U"เป็น ภาษา ราชการ และ ภาษา";
 					RID ctx = ts->create_shaped_text();
-					TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed.");
+					CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed.");
 					bool ok = ts->shaped_text_add_string(ctx, test, font, 16);
-					TEST_FAIL_COND(!ok, "Adding text to the buffer failed.");
+					CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed.");
 					ts->shaped_text_update_breaks(ctx);
 					ts->shaped_text_update_justification_ops(ctx);
 
 					const Glyph *glyphs = ts->shaped_text_get_glyphs(ctx);
 					int gl_size = ts->shaped_text_get_glyph_count(ctx);
 
-					TEST_FAIL_COND(gl_size != 25, "Invalid glyph count.");
+					CHECK_FALSE_MESSAGE(gl_size != 25, "Invalid glyph count.");
 					for (int j = 0; j < gl_size; j++) {
 						bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD;
 						bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT;
@@ -329,9 +371,9 @@ TEST_SUITE("[TextServer]") {
 						bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL;
 						bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION;
 						if (j == 4 || j == 9 || j == 16 || j == 20) {
-							TEST_FAIL_COND((!soft || !space || hard || virt || elo), "Invalid glyph flags.");
+							CHECK_FALSE_MESSAGE((!soft || !space || hard || virt || elo), "Invalid glyph flags.");
 						} else {
-							TEST_FAIL_COND((soft || space || hard || virt || elo), "Invalid glyph flags.");
+							CHECK_FALSE_MESSAGE((soft || space || hard || virt || elo), "Invalid glyph flags.");
 						}
 					}
 					ts->free_rid(ctx);
@@ -340,16 +382,16 @@ TEST_SUITE("[TextServer]") {
 				if (ts->has_feature(TextServer::FEATURE_BREAK_ITERATORS)) {
 					String test = U"เป็นภาษาราชการและภาษา";
 					RID ctx = ts->create_shaped_text();
-					TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed.");
+					CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed.");
 					bool ok = ts->shaped_text_add_string(ctx, test, font, 16);
-					TEST_FAIL_COND(!ok, "Adding text to the buffer failed.");
+					CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed.");
 					ts->shaped_text_update_breaks(ctx);
 					ts->shaped_text_update_justification_ops(ctx);
 
 					const Glyph *glyphs = ts->shaped_text_get_glyphs(ctx);
 					int gl_size = ts->shaped_text_get_glyph_count(ctx);
 
-					TEST_FAIL_COND(gl_size != 25, "Invalid glyph count.");
+					CHECK_FALSE_MESSAGE(gl_size != 25, "Invalid glyph count.");
 					for (int j = 0; j < gl_size; j++) {
 						bool hard = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_HARD) == TextServer::GRAPHEME_IS_BREAK_HARD;
 						bool soft = (glyphs[j].flags & TextServer::GRAPHEME_IS_BREAK_SOFT) == TextServer::GRAPHEME_IS_BREAK_SOFT;
@@ -357,9 +399,9 @@ TEST_SUITE("[TextServer]") {
 						bool virt = (glyphs[j].flags & TextServer::GRAPHEME_IS_VIRTUAL) == TextServer::GRAPHEME_IS_VIRTUAL;
 						bool elo = (glyphs[j].flags & TextServer::GRAPHEME_IS_ELONGATION) == TextServer::GRAPHEME_IS_ELONGATION;
 						if (j == 4 || j == 9 || j == 16 || j == 20) {
-							TEST_FAIL_COND((!soft || !space || hard || !virt || elo), "Invalid glyph flags.");
+							CHECK_FALSE_MESSAGE((!soft || !space || hard || !virt || elo), "Invalid glyph flags.");
 						} else {
-							TEST_FAIL_COND((soft || space || hard || virt || elo), "Invalid glyph flags.");
+							CHECK_FALSE_MESSAGE((soft || space || hard || virt || elo), "Invalid glyph flags.");
 						}
 					}
 					ts->free_rid(ctx);
@@ -375,7 +417,7 @@ TEST_SUITE("[TextServer]") {
 		SUBCASE("[TextServer] Text layout: Line breaking") {
 			for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
 				Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i);
-				TEST_FAIL_COND(ts.is_null(), "Invalid TS interface.");
+				CHECK_FALSE_MESSAGE(ts.is_null(), "Invalid TS interface.");
 
 				if (!ts->has_feature(TextServer::FEATURE_FONT_DYNAMIC) || !ts->has_feature(TextServer::FEATURE_SIMPLE_LAYOUT)) {
 					continue;
@@ -394,21 +436,21 @@ TEST_SUITE("[TextServer]") {
 				font.push_back(font2);
 
 				RID ctx = ts->create_shaped_text();
-				TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed.");
+				CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed.");
 				bool ok = ts->shaped_text_add_string(ctx, test_1, font, 16);
-				TEST_FAIL_COND(!ok, "Adding text to the buffer failed.");
+				CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed.");
 
 				PackedInt32Array brks = ts->shaped_text_get_line_breaks(ctx, 1);
-				TEST_FAIL_COND(brks.size() != 6, "Invalid line breaks number.");
+				CHECK_FALSE_MESSAGE(brks.size() != 6, "Invalid line breaks number.");
 				if (brks.size() == 6) {
-					TEST_FAIL_COND(brks[0] != 0, "Invalid line break position.");
-					TEST_FAIL_COND(brks[1] != 5, "Invalid line break position.");
+					CHECK_FALSE_MESSAGE(brks[0] != 0, "Invalid line break position.");
+					CHECK_FALSE_MESSAGE(brks[1] != 5, "Invalid line break position.");
 
-					TEST_FAIL_COND(brks[2] != 5, "Invalid line break position.");
-					TEST_FAIL_COND(brks[3] != 10, "Invalid line break position.");
+					CHECK_FALSE_MESSAGE(brks[2] != 5, "Invalid line break position.");
+					CHECK_FALSE_MESSAGE(brks[3] != 10, "Invalid line break position.");
 
-					TEST_FAIL_COND(brks[4] != 10, "Invalid line break position.");
-					TEST_FAIL_COND(brks[5] != 14, "Invalid line break position.");
+					CHECK_FALSE_MESSAGE(brks[4] != 10, "Invalid line break position.");
+					CHECK_FALSE_MESSAGE(brks[5] != 14, "Invalid line break position.");
 				}
 
 				ts->free_rid(ctx);
@@ -423,7 +465,7 @@ TEST_SUITE("[TextServer]") {
 		SUBCASE("[TextServer] Text layout: Justification") {
 			for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
 				Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i);
-				TEST_FAIL_COND(ts.is_null(), "Invalid TS interface.");
+				CHECK_FALSE_MESSAGE(ts.is_null(), "Invalid TS interface.");
 
 				if (!ts->has_feature(TextServer::FEATURE_FONT_DYNAMIC) || !ts->has_feature(TextServer::FEATURE_SIMPLE_LAYOUT)) {
 					continue;
@@ -448,40 +490,40 @@ TEST_SUITE("[TextServer]") {
 				float width_old, width;
 				if (ts->has_feature(TextServer::FEATURE_KASHIDA_JUSTIFICATION)) {
 					ctx = ts->create_shaped_text();
-					TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed.");
+					CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed.");
 					ok = ts->shaped_text_add_string(ctx, test_1, font, 16);
-					TEST_FAIL_COND(!ok, "Adding text to the buffer failed.");
+					CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed.");
 
 					width_old = ts->shaped_text_get_width(ctx);
 					width = ts->shaped_text_fit_to_width(ctx, 100, TextServer::JUSTIFICATION_WORD_BOUND);
-					TEST_FAIL_COND((width != width_old), "Invalid fill width.");
+					CHECK_FALSE_MESSAGE((width != width_old), "Invalid fill width.");
 					width = ts->shaped_text_fit_to_width(ctx, 100, TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA);
-					TEST_FAIL_COND((width <= width_old || width > 100), "Invalid fill width.");
+					CHECK_FALSE_MESSAGE((width <= width_old || width > 100), "Invalid fill width.");
 
 					ts->free_rid(ctx);
 
 					ctx = ts->create_shaped_text();
-					TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed.");
+					CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed.");
 					ok = ts->shaped_text_add_string(ctx, test_2, font, 16);
-					TEST_FAIL_COND(!ok, "Adding text to the buffer failed.");
+					CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed.");
 
 					width_old = ts->shaped_text_get_width(ctx);
 					width = ts->shaped_text_fit_to_width(ctx, 100, TextServer::JUSTIFICATION_WORD_BOUND);
-					TEST_FAIL_COND((width <= width_old || width > 100), "Invalid fill width.");
+					CHECK_FALSE_MESSAGE((width <= width_old || width > 100), "Invalid fill width.");
 					width = ts->shaped_text_fit_to_width(ctx, 100, TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA);
-					TEST_FAIL_COND((width <= width_old || width > 100), "Invalid fill width.");
+					CHECK_FALSE_MESSAGE((width <= width_old || width > 100), "Invalid fill width.");
 
 					ts->free_rid(ctx);
 				}
 
 				ctx = ts->create_shaped_text();
-				TEST_FAIL_COND(ctx == RID(), "Creating text buffer failed.");
+				CHECK_FALSE_MESSAGE(ctx == RID(), "Creating text buffer failed.");
 				ok = ts->shaped_text_add_string(ctx, test_3, font, 16);
-				TEST_FAIL_COND(!ok, "Adding text to the buffer failed.");
+				CHECK_FALSE_MESSAGE(!ok, "Adding text to the buffer failed.");
 
 				width_old = ts->shaped_text_get_width(ctx);
 				width = ts->shaped_text_fit_to_width(ctx, 100, TextServer::JUSTIFICATION_WORD_BOUND);
-				TEST_FAIL_COND((width <= width_old || width > 100), "Invalid fill width.");
+				CHECK_FALSE_MESSAGE((width <= width_old || width > 100), "Invalid fill width.");
 
 				ts->free_rid(ctx);
 
@@ -495,7 +537,7 @@ TEST_SUITE("[TextServer]") {
 		SUBCASE("[TextServer] Unicode identifiers") {
 			for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
 				Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i);
-				TEST_FAIL_COND(ts.is_null(), "Invalid TS interface.");
+				CHECK_FALSE_MESSAGE(ts.is_null(), "Invalid TS interface.");
 
 				static const char32_t *data[19] = { U"-30", U"100", U"10.1", U"10,1", U"1e2", U"1e-2", U"1e2e3", U"0xAB", U"AB", U"Test1", U"1Test", U"Test*1", U"test_testeT", U"test_tes teT", U"عَلَيْكُمْ", U"عَلَيْكُمْTest", U"ӒӖӚӜ", U"_test", U"ÂÃÄÅĀĂĄÇĆĈĊ" };
 				static bool isid[19] = { false, false, false, false, false, false, false, false, true, true, false, false, true, false, true, true, true, true, true };
@@ -516,7 +558,7 @@ TEST_SUITE("[TextServer]") {
 		SUBCASE("[TextServer] Strip Diacritics") {
 			for (int i = 0; i < TextServerManager::get_singleton()->get_interface_count(); i++) {
 				Ref<TextServer> ts = TextServerManager::get_singleton()->get_interface(i);
-				TEST_FAIL_COND(ts.is_null(), "Invalid TS interface.");
+				CHECK_FALSE_MESSAGE(ts.is_null(), "Invalid TS interface.");
 
 				if (ts->has_feature(TextServer::FEATURE_SHAPING)) {
 					CHECK(ts->strip_diacritics(U"ٱلسَّلَامُ عَلَيْكُمْ") == U"ٱلسلام عليكم");
@@ -544,7 +586,7 @@ TEST_SUITE("[TextServer]") {
 					continue;
 				}
 
-				TEST_FAIL_COND(ts.is_null(), "Invalid TS interface.");
+				CHECK_FALSE_MESSAGE(ts.is_null(), "Invalid TS interface.");
 				{
 					String text1 = U"linguistically similar and effectively form";
 					//                           14^     22^ 26^         38^

Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff