diff --git a/doc/classes/Curve2D.xml b/doc/classes/Curve2D.xml
index f6679439b19..d2d94e6a88d 100644
--- a/doc/classes/Curve2D.xml
+++ b/doc/classes/Curve2D.xml
@@ -17,7 +17,7 @@
- Adds a point to a curve at [code]position[/code], with control points [code]in[/code] and [code]out[/code].
+ Adds a point to a curve at [code]position[/code] relative to the [Curve2D]'s position, with control points [code]in[/code] and [code]out[/code].
If [code]at_position[/code] is given, the point is inserted before the point number [code]at_position[/code], moving that point (and every point after) after the inserted point. If [code]at_position[/code] is not given, or is an illegal value ([code]at_position <0[/code] or [code]at_position >= [method get_point_count][/code]), the point will be appended at the end of the point list.
diff --git a/doc/classes/Curve3D.xml b/doc/classes/Curve3D.xml
index 76e4ece6fe2..7fbd309f338 100644
--- a/doc/classes/Curve3D.xml
+++ b/doc/classes/Curve3D.xml
@@ -17,7 +17,7 @@
- Adds a point to a curve at [code]position[/code], with control points [code]in[/code] and [code]out[/code].
+ Adds a point to a curve at [code]position[/code] relative to the [Curve3D]'s position, with control points [code]in[/code] and [code]out[/code].
If [code]at_position[/code] is given, the point is inserted before the point number [code]at_position[/code], moving that point (and every point after) after the inserted point. If [code]at_position[/code] is not given, or is an illegal value ([code]at_position <0[/code] or [code]at_position >= [method get_point_count][/code]), the point will be appended at the end of the point list.
diff --git a/doc/classes/Environment.xml b/doc/classes/Environment.xml
index ecef1ef4a69..b5971741d5b 100644
--- a/doc/classes/Environment.xml
+++ b/doc/classes/Environment.xml
@@ -302,7 +302,8 @@
- Keeps on screen every pixel drawn in the background. This is the fastest background mode, but it can only be safely used in fully-interior scenes (no visible sky or sky reflections). If enabled in a scene where the background is visible, "ghost trail" artifacts will be visible when moving the camera.
+ Keeps on screen every pixel drawn in the background. Only select this mode if you really need to keep the old data. On modern GPUs it will generally not be faster than clearing the background, and can be significantly slower, particularly on mobile.
+ It can only be safely used in fully-interior scenes (no visible sky or sky reflections). If enabled in a scene where the background is visible, "ghost trail" artifacts will be visible when moving the camera.
Clears the background using the clear color defined in [member ProjectSettings.rendering/environment/default_clear_color].
diff --git a/doc/classes/HeightMapShape.xml b/doc/classes/HeightMapShape.xml
index 46dc1cd9328..ea14356f306 100644
--- a/doc/classes/HeightMapShape.xml
+++ b/doc/classes/HeightMapShape.xml
@@ -15,10 +15,10 @@
Height map data, pool array must be of [member map_width] * [member map_depth] size.
- Depth of the height map data. Changing this will resize the [member map_data].
+ Number of vertices in the depth of the height map. Changing this will resize the [member map_data].
- Width of the height map data. Changing this will resize the [member map_data].
+ Number of vertices in the width of the height map. Changing this will resize the [member map_data].
diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp
index 5c891bd53f6..d2d85daebe3 100644
--- a/drivers/gles2/rasterizer_storage_gles2.cpp
+++ b/drivers/gles2/rasterizer_storage_gles2.cpp
@@ -1952,7 +1952,7 @@ void RasterizerStorageGLES2::_update_material(Material *p_material) {
if (p_material->shader && p_material->shader->mode == VS::SHADER_SPATIAL) {
if (p_material->shader->spatial.blend_mode == Shader::Spatial::BLEND_MODE_MIX &&
- (!p_material->shader->spatial.uses_alpha || p_material->shader->spatial.depth_draw_mode == Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS)) {
+ (!(p_material->shader->spatial.uses_alpha && !p_material->shader->spatial.uses_alpha_scissor) || p_material->shader->spatial.depth_draw_mode == Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS)) {
can_cast_shadow = true;
}
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index 2a3631fdb87..b8050fd3ca9 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -3153,7 +3153,7 @@ void RasterizerStorageGLES3::_update_material(Material *material) {
if (material->shader && material->shader->mode == VS::SHADER_SPATIAL) {
if (material->shader->spatial.blend_mode == Shader::Spatial::BLEND_MODE_MIX &&
- (!material->shader->spatial.uses_alpha || material->shader->spatial.depth_draw_mode == Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS)) {
+ (!(material->shader->spatial.uses_alpha && !material->shader->spatial.uses_alpha_scissor) || material->shader->spatial.depth_draw_mode == Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS)) {
can_cast_shadow = true;
}
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index abd30fa39ee..3f1615f0a12 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -1241,6 +1241,8 @@ bool CanvasItemEditor::_gui_input_rulers_and_guides(const Ref &p_eve
}
}
}
+ snap_target[0] = SNAP_TARGET_NONE;
+ snap_target[1] = SNAP_TARGET_NONE;
drag_type = DRAG_NONE;
viewport->update();
return true;
diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp
index bc312f1d321..64164f55f57 100644
--- a/modules/csg/csg_shape.cpp
+++ b/modules/csg/csg_shape.cpp
@@ -273,7 +273,7 @@ void CSGShape::mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, const f
}
void CSGShape::_update_shape() {
- if (parent || !is_inside_tree()) {
+ if (parent) {
return;
}
@@ -296,17 +296,19 @@ void CSGShape::_update_shape() {
ERR_CONTINUE(mat < -1 || mat >= face_count.size());
int idx = mat == -1 ? face_count.size() - 1 : mat;
- Plane p(n->faces[i].vertices[0], n->faces[i].vertices[1], n->faces[i].vertices[2]);
+ if (n->faces[i].smooth) {
+ Plane p(n->faces[i].vertices[0], n->faces[i].vertices[1], n->faces[i].vertices[2]);
- for (int j = 0; j < 3; j++) {
- Vector3 v = n->faces[i].vertices[j];
- Vector3 add;
- if (vec_map.lookup(v, add)) {
- add += p.normal;
- } else {
- add = p.normal;
+ for (int j = 0; j < 3; j++) {
+ Vector3 v = n->faces[i].vertices[j];
+ Vector3 add;
+ if (vec_map.lookup(v, add)) {
+ add += p.normal;
+ } else {
+ add = p.normal;
+ }
+ vec_map.set(v, add);
}
- vec_map.set(v, add);
}
face_count.write[idx]++;
@@ -1577,6 +1579,9 @@ CSGBrush *CSGTorus::_build_brush() {
for (int i = 0; i < sides; i++) {
float inci = float(i) / sides;
float inci_n = float((i + 1)) / sides;
+ if (i == sides - 1) {
+ inci_n = 0;
+ }
float angi = inci * Math_PI * 2.0;
float angi_n = inci_n * Math_PI * 2.0;
@@ -1587,6 +1592,9 @@ CSGBrush *CSGTorus::_build_brush() {
for (int j = 0; j < ring_sides; j++) {
float incj = float(j) / ring_sides;
float incj_n = float((j + 1)) / ring_sides;
+ if (j == ring_sides - 1) {
+ incj_n = 0;
+ }
float angj = incj * Math_PI * 2.0;
float angj_n = incj_n * Math_PI * 2.0;
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index 87217274193..91dd605c97d 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -3758,9 +3758,11 @@ static String get_mountpoint(const String &p_path) {
}
Error OS_X11::move_to_trash(const String &p_path) {
+ String path = p_path.rstrip("/"); // Strip trailing slash when path points to a directory
+
int err_code;
List args;
- args.push_back(p_path);
+ args.push_back(path);
args.push_front("trash"); // The command is `gio trash ` so we need to add it to args.
Error result = execute("gio", args, true, nullptr, nullptr, &err_code); // For GNOME based machines.
if (result == OK && !err_code) {
@@ -3790,14 +3792,14 @@ Error OS_X11::move_to_trash(const String &p_path) {
// If the commands `kioclient5`, `gio` or `gvfs-trash` don't exist on the system we do it manually.
String trash_path = "";
- String mnt = get_mountpoint(p_path);
+ String mnt = get_mountpoint(path);
// If there is a directory "[Mountpoint]/.Trash-[UID], use it as the trash can.
if (mnt != "") {
- String path(mnt + "/.Trash-" + itos(getuid()));
+ String mountpoint_trash_path(mnt + "/.Trash-" + itos(getuid()));
struct stat s;
- if (!stat(path.utf8().get_data(), &s)) {
- trash_path = path;
+ if (!stat(mountpoint_trash_path.utf8().get_data(), &s)) {
+ trash_path = mountpoint_trash_path;
}
}
@@ -3828,18 +3830,15 @@ Error OS_X11::move_to_trash(const String &p_path) {
// Issue an error if trash can is not created proprely.
ERR_FAIL_COND_V_MSG(err != OK, err, "Could not create the trash path \"" + trash_path + "\"");
err = dir_access->make_dir_recursive(trash_path + "/files");
- ERR_FAIL_COND_V_MSG(err != OK, err, "Could not create the trash path \"" + trash_path + "\"/files");
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Could not create the trash path \"" + trash_path + "/files\"");
err = dir_access->make_dir_recursive(trash_path + "/info");
- ERR_FAIL_COND_V_MSG(err != OK, err, "Could not create the trash path \"" + trash_path + "\"/info");
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Could not create the trash path \"" + trash_path + "/info\"");
}
// The trash can is successfully created, now we check that we don't exceed our file name length limit.
// If the file name is too long trim it so we can add the identifying number and ".trashinfo".
// Assumes that the file name length limit is 255 characters.
- String file_name = p_path.get_file();
- if (file_name.length() == 0) {
- file_name = p_path.get_base_dir().get_file();
- }
+ String file_name = path.get_file();
if (file_name.length() > 240) {
file_name = file_name.substr(0, file_name.length() - 15);
}
@@ -3862,29 +3861,31 @@ Error OS_X11::move_to_trash(const String &p_path) {
}
file_name = fn;
+ String renamed_path = path.get_base_dir() + "/" + file_name;
+
// Generates the .trashinfo file
OS::Date date = OS::get_singleton()->get_date(false);
OS::Time time = OS::get_singleton()->get_time(false);
String timestamp = vformat("%04d-%02d-%02dT%02d:%02d:", date.year, (int)date.month, date.day, time.hour, time.min);
timestamp = vformat("%s%02d", timestamp, time.sec); // vformat only supports up to 6 arguments.
- String trash_info = "[Trash Info]\nPath=" + p_path.http_escape() + "\nDeletionDate=" + timestamp + "\n";
+ String trash_info = "[Trash Info]\nPath=" + path.http_escape() + "\nDeletionDate=" + timestamp + "\n";
{
Error err;
FileAccessRef file = FileAccess::open(trash_path + "/info/" + file_name + ".trashinfo", FileAccess::WRITE, &err);
- ERR_FAIL_COND_V_MSG(err != OK, err, "Can't create trashinfo file:" + trash_path + "/info/" + file_name + ".trashinfo");
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Can't create trashinfo file: \"" + trash_path + "/info/" + file_name + ".trashinfo\"");
file->store_string(trash_info);
file->close();
// Rename our resource before moving it to the trash can.
DirAccessRef dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- err = dir_access->rename(p_path, p_path.get_base_dir() + "/" + file_name);
- ERR_FAIL_COND_V_MSG(err != OK, err, "Can't rename file \"" + p_path + "\"");
+ err = dir_access->rename(path, renamed_path);
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Can't rename file \"" + path + "\" to \"" + renamed_path + "\"");
}
// Move the given resource to the trash can.
// Do not use DirAccess:rename() because it can't move files across multiple mountpoints.
List mv_args;
- mv_args.push_back(p_path.get_base_dir() + "/" + file_name);
+ mv_args.push_back(renamed_path);
mv_args.push_back(trash_path + "/files");
{
int retval;
@@ -3892,11 +3893,11 @@ Error OS_X11::move_to_trash(const String &p_path) {
// Issue an error if "mv" failed to move the given resource to the trash can.
if (err != OK || retval != 0) {
- ERR_PRINT("move_to_trash: Could not move the resource \"" + p_path + "\" to the trash can \"" + trash_path + "/files\"");
+ ERR_PRINT("move_to_trash: Could not move the resource \"" + path + "\" to the trash can \"" + trash_path + "/files\"");
DirAccess *dir_access = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- err = dir_access->rename(p_path.get_base_dir() + "/" + file_name, p_path);
+ err = dir_access->rename(renamed_path, path);
memdelete(dir_access);
- ERR_FAIL_COND_V_MSG(err != OK, err, "Could not rename " + p_path.get_base_dir() + "/" + file_name + " back to its original name:" + p_path);
+ ERR_FAIL_COND_V_MSG(err != OK, err, "Could not rename \"" + renamed_path + "\" back to its original name: \"" + path + "\"");
return FAILED;
}
}
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index f5a0ee38521..b7a6adad4af 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -591,21 +591,24 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
draw_rect(Rect2(p_ofs.x + pofs, p_ofs.y + y, cw, lh), selection_bg);
}
- if (p_font_color_shadow.a > 0) {
+ const Color char_color = selected && override_selected_font_color ? selection_fg : fx_color;
+ const Color shadow_color = p_font_color_shadow * Color(1, 1, 1, char_color.a);
+
+ if (shadow_color.a > 0) {
const Point2 shadow_base_pos = p_ofs + Point2(align_ofs + pofs, y + lh - line_descent);
- font->draw_char(ci, shadow_base_pos + shadow_ofs + fx_offset, fx_char, c[i + 1], p_font_color_shadow);
+ font->draw_char(ci, shadow_base_pos + shadow_ofs + fx_offset, fx_char, c[i + 1], shadow_color);
if (p_shadow_as_outline) {
- font->draw_char(ci, shadow_base_pos + Vector2(-shadow_ofs.x, shadow_ofs.y) + fx_offset, fx_char, c[i + 1], p_font_color_shadow);
- font->draw_char(ci, shadow_base_pos + Vector2(shadow_ofs.x, -shadow_ofs.y) + fx_offset, fx_char, c[i + 1], p_font_color_shadow);
- font->draw_char(ci, shadow_base_pos + Vector2(-shadow_ofs.x, -shadow_ofs.y) + fx_offset, fx_char, c[i + 1], p_font_color_shadow);
+ font->draw_char(ci, shadow_base_pos + Vector2(-shadow_ofs.x, shadow_ofs.y) + fx_offset, fx_char, c[i + 1], shadow_color);
+ font->draw_char(ci, shadow_base_pos + Vector2(shadow_ofs.x, -shadow_ofs.y) + fx_offset, fx_char, c[i + 1], shadow_color);
+ font->draw_char(ci, shadow_base_pos + Vector2(-shadow_ofs.x, -shadow_ofs.y) + fx_offset, fx_char, c[i + 1], shadow_color);
}
}
if (selected) {
- drawer.draw_char(ci, p_ofs + Point2(align_ofs + pofs, y + lh - line_descent), fx_char, c[i + 1], override_selected_font_color ? selection_fg : fx_color);
+ drawer.draw_char(ci, p_ofs + Point2(align_ofs + pofs, y + lh - line_descent), fx_char, c[i + 1], char_color);
} else {
- cw = drawer.draw_char(ci, p_ofs + Point2(align_ofs + pofs, y + lh - line_descent) + fx_offset, fx_char, c[i + 1], fx_color);
+ cw = drawer.draw_char(ci, p_ofs + Point2(align_ofs + pofs, y + lh - line_descent) + fx_offset, fx_char, c[i + 1], char_color);
}
} else if (previously_visible && c[i] != '\t') {
backtrack += font->get_char_size(fx_char, c[i + 1]).x;