Merge branch 'master' into bugfix-ios-export

This commit is contained in:
Larry Tran 2022-08-05 18:47:20 -05:00 committed by GitHub
commit 2ea4baae0a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 1290 additions and 1367 deletions

View File

@ -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)

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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>

View File

@ -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" />

View File

@ -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" />

View File

@ -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;

View File

@ -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)));

View File

@ -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;

View File

@ -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));

View File

@ -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;
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}

View File

@ -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

View File

@ -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());

File diff suppressed because it is too large Load Diff

View File

@ -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();

View File

@ -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"])

View File

@ -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

View File

@ -5,6 +5,37 @@ def can_build(env, platform):
return not env["arch"].startswith("rv")
def get_opts(platform):
from SCons.Variables import BoolVariable, PathVariable
default_mono_static = platform in ["ios", "javascript"]
default_mono_bundles_zlib = platform in ["javascript"]
return [
PathVariable(
"mono_prefix",
"Path to the Mono installation directory for the target platform and architecture",
"",
PathVariable.PathAccept,
),
PathVariable(
"mono_bcl",
"Path to a custom Mono BCL (Base Class Library) directory for the target platform",
"",
PathVariable.PathAccept,
),
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"]
@ -13,45 +44,6 @@ def configure(env):
env.add_module_version_string("mono")
from SCons.Script import BoolVariable, PathVariable, Variables, Help
default_mono_static = platform in ["ios", "javascript"]
default_mono_bundles_zlib = platform in ["javascript"]
envvars = Variables()
envvars.Add(
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_bundles_zlib", "Specify if the Mono runtime was built with bundled zlib", default_mono_bundles_zlib
)
)
envvars.Update(env)
Help(envvars.GenerateHelpText(env))
if env["mono_bundles_zlib"]:
# Mono may come with zlib bundled for WASM or on newer version when built with MinGW.
print("This Mono runtime comes with zlib bundled. Disabling 'builtin_zlib'...")

View File

@ -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")

View File

@ -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

View File

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

View File

@ -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

View File

@ -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")

View File

@ -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
/*************************************************************************/

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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()) {
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);
if (no_line) {
arrow_size = target_position.length();
} else {
draw_line(Vector2(), target_position - target_position.normalized() * arrow_size, draw_col, line_width);
}
Transform2D xf;
xf.rotate(target_position.angle());
xf.translate_local(Vector2(target_position.length(), 0));
draw_line(Vector2(), target_position, draw_col, 2);
float tsize = 8;
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() {

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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^