diff options
-rw-r--r-- | doc/classes/Image.xml | 1 | ||||
-rw-r--r-- | editor/plugins/canvas_item_editor_plugin.cpp | 10 | ||||
-rw-r--r-- | editor/plugins/mesh_instance_3d_editor_plugin.cpp | 7 | ||||
-rw-r--r-- | editor/plugins/node_3d_editor_plugin.cpp | 27 | ||||
-rw-r--r-- | modules/csg/csg_shape.cpp | 66 | ||||
-rw-r--r-- | platform/android/export/export.cpp | 2 | ||||
-rw-r--r-- | scene/2d/physics_body_2d.cpp | 3 |
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; |