summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/classes/Image.xml1
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp10
-rw-r--r--editor/plugins/mesh_instance_3d_editor_plugin.cpp7
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp27
-rw-r--r--modules/csg/csg_shape.cpp66
-rw-r--r--platform/android/export/export.cpp2
-rw-r--r--scene/2d/physics_body_2d.cpp3
7 files changed, 63 insertions, 53 deletions
diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml
index fd80841a63..37a96fef3d 100644
--- a/doc/classes/Image.xml
+++ b/doc/classes/Image.xml
@@ -465,6 +465,7 @@
</argument>
<description>
Saves the image as an EXR file to [code]path[/code]. If [code]grayscale[/code] is [code]true[/code] and the image has only one channel, it will be saved explicitly as monochrome rather than one red channel. This function will return [constant ERR_UNAVAILABLE] if Godot was compiled without the TinyEXR module.
+ [b]Note:[/b] The TinyEXR module is disabled in non-editor builds, which means [method save_exr] will return [constant ERR_UNAVAILABLE] when it is called from an exported project.
</description>
</method>
<method name="save_png" qualifiers="const">
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 869a582d96..9bbafcc79d 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -2921,7 +2921,7 @@ void CanvasItemEditor::_draw_ruler_tool() {
Point2 text_pos = (begin + end) / 2 - Vector2(text_width / 2, text_height / 2);
text_pos.x = CLAMP(text_pos.x, text_width / 2, viewport->get_rect().size.x - text_width * 1.5);
text_pos.y = CLAMP(text_pos.y, text_height * 1.5, viewport->get_rect().size.y - text_height * 1.5);
- viewport->draw_string(font, text_pos, TS->format_number(vformat("%.2f " + TTR("px"), length_vector.length())), HALIGN_LEFT, -1, font_size, font_color, outline_size, outline_color);
+ viewport->draw_string(font, text_pos, TS->format_number(vformat("%.1f px", length_vector.length())), HALIGN_LEFT, -1, font_size, font_color, outline_size, outline_color);
if (draw_secondary_lines) {
const float horizontal_angle_rad = atan2(length_vector.y, length_vector.x);
@@ -2931,16 +2931,16 @@ void CanvasItemEditor::_draw_ruler_tool() {
Point2 text_pos2 = text_pos;
text_pos2.x = begin.x < text_pos.x ? MIN(text_pos.x - text_width, begin.x - text_width / 2) : MAX(text_pos.x + text_width, begin.x - text_width / 2);
- viewport->draw_string(font, text_pos2, TS->format_number(vformat("%.2f " + TTR("px"), length_vector.y)), HALIGN_LEFT, -1, font_size, font_secondary_color, outline_size, outline_color);
+ viewport->draw_string(font, text_pos2, TS->format_number(vformat("%.1f px", length_vector.y)), HALIGN_LEFT, -1, font_size, font_secondary_color, outline_size, outline_color);
Point2 v_angle_text_pos = Point2();
v_angle_text_pos.x = CLAMP(begin.x - angle_text_width / 2, angle_text_width / 2, viewport->get_rect().size.x - angle_text_width);
v_angle_text_pos.y = begin.y < end.y ? MIN(text_pos2.y - 2 * text_height, begin.y - text_height * 0.5) : MAX(text_pos2.y + text_height * 3, begin.y + text_height * 1.5);
- viewport->draw_string(font, v_angle_text_pos, TS->format_number(vformat("%d " + TTR("deg"), vertical_angle)), HALIGN_LEFT, -1, font_size, font_secondary_color, outline_size, outline_color);
+ viewport->draw_string(font, v_angle_text_pos, TS->format_number(vformat(String::utf8("%d°"), vertical_angle)), HALIGN_LEFT, -1, font_size, font_secondary_color, outline_size, outline_color);
text_pos2 = text_pos;
text_pos2.y = end.y < text_pos.y ? MIN(text_pos.y - text_height * 2, end.y - text_height / 2) : MAX(text_pos.y + text_height * 2, end.y - text_height / 2);
- viewport->draw_string(font, text_pos2, TS->format_number(vformat("%.2f " + TTR("px"), length_vector.x)), HALIGN_LEFT, -1, font_size, font_secondary_color, outline_size, outline_color);
+ viewport->draw_string(font, text_pos2, TS->format_number(vformat("%.1f px", length_vector.x)), HALIGN_LEFT, -1, font_size, font_secondary_color, outline_size, outline_color);
Point2 h_angle_text_pos = Point2();
h_angle_text_pos.x = CLAMP(end.x - angle_text_width / 2, angle_text_width / 2, viewport->get_rect().size.x - angle_text_width);
@@ -2957,7 +2957,7 @@ void CanvasItemEditor::_draw_ruler_tool() {
h_angle_text_pos.y = MIN(text_pos.y - height_multiplier * text_height, MIN(end.y - text_height * 0.5, text_pos2.y - height_multiplier * text_height));
}
}
- viewport->draw_string(font, h_angle_text_pos, TS->format_number(vformat("%d " + TTR("deg"), horizontal_angle)), HALIGN_LEFT, -1, font_size, font_secondary_color, outline_size, outline_color);
+ viewport->draw_string(font, h_angle_text_pos, TS->format_number(vformat(String::utf8("%d°"), horizontal_angle)), HALIGN_LEFT, -1, font_size, font_secondary_color, outline_size, outline_color);
// Angle arcs
int arc_point_count = 8;
diff --git a/editor/plugins/mesh_instance_3d_editor_plugin.cpp b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
index 9ee1fcb325..9a2b222f21 100644
--- a/editor/plugins/mesh_instance_3d_editor_plugin.cpp
+++ b/editor/plugins/mesh_instance_3d_editor_plugin.cpp
@@ -332,7 +332,7 @@ void MeshInstance3DEditor::_create_uv_lines(int p_layer) {
Vector<Vector2> uv = a[p_layer == 0 ? Mesh::ARRAY_TEX_UV : Mesh::ARRAY_TEX_UV2];
if (uv.size() == 0) {
- err_dialog->set_text(TTR("Model has no UV in this layer"));
+ err_dialog->set_text(vformat(TTR("Mesh has no UV in layer %d."), p_layer + 1));
err_dialog->popup_centered();
return;
}
@@ -382,9 +382,10 @@ void MeshInstance3DEditor::_debug_uv_draw() {
}
debug_uv->set_clip_contents(true);
- debug_uv->draw_rect(Rect2(Vector2(), debug_uv->get_size()), Color(0.2, 0.2, 0.0));
+ debug_uv->draw_rect(Rect2(Vector2(), debug_uv->get_size()), get_theme_color(SNAME("dark_color_3"), SNAME("Editor")));
debug_uv->draw_set_transform(Vector2(), 0, debug_uv->get_size());
- debug_uv->draw_multiline(uv_lines, Color(1.0, 0.8, 0.7));
+ // Use a translucent color to allow overlapping triangles to be visible.
+ debug_uv->draw_multiline(uv_lines, get_theme_color(SNAME("mono_color"), SNAME("Editor")) * Color(1, 1, 1, 0.5), Math::round(EDSCALE));
}
void MeshInstance3DEditor::_create_outline_mesh() {
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index 3b9c0ff699..ebd6615ac1 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -942,14 +942,18 @@ bool Node3DEditorViewport::_transform_gizmo_select(const Vector2 &p_screenpos, b
Vector3 ivec2 = gt.basis.get_axis((i + 1) % 3).normalized();
Vector3 ivec3 = gt.basis.get_axis((i + 2) % 3).normalized();
- Vector3 grabber_pos = gt.origin + (ivec2 + ivec3) * gs * (GIZMO_PLANE_SIZE + GIZMO_PLANE_DST);
+ // Allow some tolerance to make the plane easier to click,
+ // even if the click is actually slightly outside the plane.
+ const Vector3 grabber_pos = gt.origin + (ivec2 + ivec3) * gs * (GIZMO_PLANE_SIZE + GIZMO_PLANE_DST * 0.6667);
Vector3 r;
Plane plane(gt.origin, gt.basis.get_axis(i).normalized());
if (plane.intersects_ray(ray_pos, ray, &r)) {
float dist = r.distance_to(grabber_pos);
- if (dist < (gs * GIZMO_PLANE_SIZE)) {
+ // Allow some tolerance to make the plane easier to click,
+ // even if the click is actually slightly outside the plane.
+ if (dist < (gs * GIZMO_PLANE_SIZE * 1.5)) {
float d = ray_pos.distance_to(r);
if (d < col_d) {
col_d = d;
@@ -1042,14 +1046,18 @@ bool Node3DEditorViewport::_transform_gizmo_select(const Vector2 &p_screenpos, b
Vector3 ivec2 = gt.basis.get_axis((i + 1) % 3).normalized();
Vector3 ivec3 = gt.basis.get_axis((i + 2) % 3).normalized();
- Vector3 grabber_pos = gt.origin + (ivec2 + ivec3) * gs * (GIZMO_PLANE_SIZE + GIZMO_PLANE_DST);
+ // Allow some tolerance to make the plane easier to click,
+ // even if the click is actually slightly outside the plane.
+ Vector3 grabber_pos = gt.origin + (ivec2 + ivec3) * gs * (GIZMO_PLANE_SIZE + GIZMO_PLANE_DST * 0.6667);
Vector3 r;
Plane plane(gt.origin, gt.basis.get_axis(i).normalized());
if (plane.intersects_ray(ray_pos, ray, &r)) {
float dist = r.distance_to(grabber_pos);
- if (dist < (gs * GIZMO_PLANE_SIZE)) {
+ // Allow some tolerance to make the plane easier to click,
+ // even if the click is actually slightly outside the plane.
+ if (dist < (gs * GIZMO_PLANE_SIZE * 1.5)) {
float d = ray_pos.distance_to(r);
if (d < col_d) {
col_d = d;
@@ -2909,9 +2917,7 @@ void Node3DEditorViewport::_draw() {
handle_color = get_theme_color(SNAME("accent_color"), SNAME("Editor"));
break;
}
- handle_color.a = 1.0;
- const float brightness = 1.3;
- handle_color *= Color(brightness, brightness, brightness);
+ handle_color = handle_color.from_hsv(handle_color.get_h(), 0.25, 1.0, 1);
RenderingServer::get_singleton()->canvas_item_add_line(
ci,
@@ -5638,8 +5644,7 @@ void fragment() {
gizmo_color[i] = mat;
Ref<StandardMaterial3D> mat_hl = mat->duplicate();
- const float brightness = 1.3;
- const Color albedo = Color(col.r * brightness, col.g * brightness, col.b * brightness);
+ const Color albedo = col.from_hsv(col.get_h(), 0.25, 1.0, 1);
mat_hl->set_albedo(albedo);
gizmo_color_hl[i] = mat_hl;
@@ -5746,7 +5751,7 @@ void fragment() {
surftool->begin(Mesh::PRIMITIVE_TRIANGLES);
int n = 128; // number of circle segments
- int m = 6; // number of thickness segments
+ int m = 3; // number of thickness segments
real_t step = Math_TAU / n;
for (int j = 0; j < n; ++j) {
@@ -5954,7 +5959,7 @@ void fragment() {
surftool->commit(scale_plane_gizmo[i]);
Ref<StandardMaterial3D> plane_mat_hl = plane_mat->duplicate();
- plane_mat_hl->set_albedo(Color(col.r * 1.3, col.g * 1.3, col.b * 1.3));
+ plane_mat_hl->set_albedo(col.from_hsv(col.get_h(), 0.25, 1.0, 1));
plane_gizmo_color_hl[i] = plane_mat_hl; // needed, so we can draw planes from both sides
}
}
diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp
index 73c1ba554c..b47fa35f1a 100644
--- a/modules/csg/csg_shape.cpp
+++ b/modules/csg/csg_shape.cpp
@@ -923,36 +923,40 @@ CSGBrush *CSGSphere3D::_build_brush() {
Ref<Material> *materialsw = materials.ptrw();
bool *invertw = invert.ptrw();
- const double lat_step = 1.0 / rings;
- const double lon_step = 1.0 / radial_segments;
+ // We want to follow an order that's convenient for UVs.
+ // For latitude step we start at the top and move down like in an image.
+ const double latitude_step = -Math_PI / rings;
+ const double longitude_step = Math_TAU / radial_segments;
int face = 0;
- for (int i = 1; i <= rings; i++) {
- double lat0 = Math_PI * (0.5 - (i - 1) * lat_step);
- double c0 = Math::cos(lat0);
- double s0 = Math::sin(lat0);
- double v0 = double(i - 1) / rings;
-
- double lat1 = Math_PI * (0.5 - i * lat_step);
- double c1 = Math::cos(lat1);
- double s1 = Math::sin(lat1);
- double v1 = double(i) / rings;
-
- for (int j = 1; j <= radial_segments; j++) {
- double lng0 = Math_TAU * (0.5 - (j - 1) * lon_step);
- double x0 = Math::cos(lng0);
- double y0 = Math::sin(lng0);
- double u0 = double(j - 1) / radial_segments;
-
- double lng1 = Math_TAU * (0.5 - j * lon_step);
- double x1 = Math::cos(lng1);
- double y1 = Math::sin(lng1);
- double u1 = double(j) / radial_segments;
+ for (int i = 0; i < rings; i++) {
+ double latitude0 = latitude_step * i + Math_TAU / 4;
+ double cos0 = Math::cos(latitude0);
+ double sin0 = Math::sin(latitude0);
+ double v0 = double(i) / rings;
+
+ double latitude1 = latitude_step * (i + 1) + Math_TAU / 4;
+ double cos1 = Math::cos(latitude1);
+ double sin1 = Math::sin(latitude1);
+ double v1 = double(i + 1) / rings;
+
+ for (int j = 0; j < radial_segments; j++) {
+ double longitude0 = longitude_step * j;
+ // We give sin to X and cos to Z on purpose.
+ // This allows UVs to be CCW on +X so it maps to images well.
+ double x0 = Math::sin(longitude0);
+ double z0 = Math::cos(longitude0);
+ double u0 = double(j) / radial_segments;
+
+ double longitude1 = longitude_step * (j + 1);
+ double x1 = Math::sin(longitude1);
+ double z1 = Math::cos(longitude1);
+ double u1 = double(j + 1) / radial_segments;
Vector3 v[4] = {
- Vector3(x0 * c0, s0, y0 * c0) * radius,
- Vector3(x1 * c0, s0, y1 * c0) * radius,
- Vector3(x1 * c1, s1, y1 * c1) * radius,
- Vector3(x0 * c1, s1, y0 * c1) * radius,
+ Vector3(x0 * cos0, sin0, z0 * cos0) * radius,
+ Vector3(x1 * cos0, sin0, z1 * cos0) * radius,
+ Vector3(x1 * cos1, sin1, z1 * cos1) * radius,
+ Vector3(x0 * cos1, sin1, z0 * cos1) * radius,
};
Vector2 u[4] = {
@@ -962,8 +966,8 @@ CSGBrush *CSGSphere3D::_build_brush() {
Vector2(u0, v1),
};
- if (i < rings) {
- //face 1
+ // Draw the first face, but skip this at the north pole (i == 0).
+ if (i > 0) {
facesw[face * 3 + 0] = v[0];
facesw[face * 3 + 1] = v[1];
facesw[face * 3 + 2] = v[2];
@@ -979,8 +983,8 @@ CSGBrush *CSGSphere3D::_build_brush() {
face++;
}
- if (i > 1) {
- //face 2
+ // Draw the second face, but skip this at the south pole (i == rings - 1).
+ if (i < rings - 1) {
facesw[face * 3 + 0] = v[2];
facesw[face * 3 + 1] = v[3];
facesw[face * 3 + 2] = v[0];
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index 956b59ce80..e5d1c2020a 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -2068,6 +2068,8 @@ public:
if (!installed_android_build_template) {
r_missing_templates = !exists_export_template("android_source.zip", &err);
err += TTR("Android build template not installed in the project. Install it from the Project menu.") + "\n";
+ } else {
+ r_missing_templates = false;
}
valid = installed_android_build_template && !r_missing_templates;
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index 561207c24c..9b4da2a77a 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -1187,9 +1187,6 @@ void CharacterBody2D::move_and_slide() {
}
void CharacterBody2D::_set_collision_direction(const PhysicsServer2D::MotionResult &p_result) {
- on_floor = false;
- on_ceiling = false;
- on_wall = false;
if (up_direction == Vector2()) {
//all is a wall
on_wall = true;