diff options
-rw-r--r-- | editor/filesystem_dock.cpp | 27 | ||||
-rw-r--r-- | editor/plugins/node_3d_editor_plugin.cpp | 37 | ||||
-rw-r--r-- | scene/2d/physics_body_2d.cpp | 20 | ||||
-rw-r--r-- | scene/3d/physics_body_3d.cpp | 20 |
4 files changed, 75 insertions, 29 deletions
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index 4fdc3dc080..f279f402d9 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -2085,7 +2085,32 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data, } } if (!to_move.empty()) { - _move_operation_confirm(to_dir); + if (Input::get_singleton()->is_key_pressed(KEY_CONTROL)) { + for (int i = 0; i < to_move.size(); i++) { + String new_path; + String new_path_base; + + if (to_move[i].is_file) { + new_path = to_dir.plus_file(to_move[i].path.get_file()); + new_path_base = new_path.get_basename() + " (%d)." + new_path.get_extension(); + } else { + PackedStringArray path_split = to_move[i].path.split("/"); + new_path = to_dir.plus_file(path_split[path_split.size() - 2]); + new_path_base = new_path + " (%d)"; + } + + int exist_counter = 1; + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES); + while (da->file_exists(new_path) || da->dir_exists(new_path)) { + exist_counter++; + new_path = vformat(new_path_base, exist_counter); + } + _try_duplicate_item(to_move[i], new_path); + } + _rescan(); + } else { + _move_operation_confirm(to_dir); + } } } else if (favorite) { // Add the files from favorites. diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 796dd3f8b2..7bf8fd7d26 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -2583,14 +2583,14 @@ void Node3DEditorViewport::_notification(int p_what) { } } -static void draw_indicator_bar(Control &surface, real_t fill, Ref<Texture2D> icon) { +static void draw_indicator_bar(Control &surface, real_t fill, const Ref<Texture2D> icon, const Ref<Font> font, const String &text) { // Adjust bar size from control height - Vector2 surface_size = surface.get_size(); - real_t h = surface_size.y / 2.0; - real_t y = (surface_size.y - h) / 2.0; + const Vector2 surface_size = surface.get_size(); + const real_t h = surface_size.y / 2.0; + const real_t y = (surface_size.y - h) / 2.0; - Rect2 r(10, y, 6, h); - real_t sy = r.size.y * fill; + const Rect2 r(10 * EDSCALE, y, 6 * EDSCALE, h); + const real_t sy = r.size.y * fill; // Note: because this bar appears over the viewport, it has to stay readable for any background color // Draw both neutral dark and bright colors to account this @@ -2598,9 +2598,12 @@ static void draw_indicator_bar(Control &surface, real_t fill, Ref<Texture2D> ico surface.draw_rect(Rect2(r.position.x, r.position.y + r.size.y - sy, r.size.x, sy), Color(1, 1, 1, 0.6)); surface.draw_rect(r.grow(1), Color(0, 0, 0, 0.7), false, Math::round(EDSCALE)); - Vector2 icon_size = icon->get_size(); - Vector2 icon_pos = Vector2(r.position.x - (icon_size.x - r.size.x) / 2, r.position.y + r.size.y + 2); + const Vector2 icon_size = icon->get_size(); + const Vector2 icon_pos = Vector2(r.position.x - (icon_size.x - r.size.x) / 2, r.position.y + r.size.y + 2 * EDSCALE); surface.draw_texture(icon, icon_pos); + + // Draw text below the bar (for speed/zoom information). + surface.draw_string(font, Vector2(icon_pos.x, icon_pos.y + icon_size.y + 16 * EDSCALE), text); } void Node3DEditorViewport::_draw() { @@ -2697,7 +2700,14 @@ void Node3DEditorViewport::_draw() { logscale_t = 0.25 * Math::exp(4.0 * logscale_t - 1.0); } - draw_indicator_bar(*surface, 1.0 - logscale_t, get_theme_icon("ViewportSpeed", "EditorIcons")); + // Display the freelook speed to help the user get a better sense of scale. + const int precision = freelook_speed < 1.0 ? 2 : 1; + draw_indicator_bar( + *surface, + 1.0 - logscale_t, + get_theme_icon("ViewportSpeed", "EditorIcons"), + get_theme_font("font", "Label"), + vformat("%s u/s", String::num(freelook_speed).pad_decimals(precision))); } } else { @@ -2716,7 +2726,14 @@ void Node3DEditorViewport::_draw() { logscale_t = 0.25 * Math::exp(4.0 * logscale_t - 1.0); } - draw_indicator_bar(*surface, logscale_t, get_theme_icon("ViewportZoom", "EditorIcons")); + // Display the zoom center distance to help the user get a better sense of scale. + const int precision = cursor.distance < 1.0 ? 2 : 1; + draw_indicator_bar( + *surface, + logscale_t, + get_theme_icon("ViewportZoom", "EditorIcons"), + get_theme_font("font", "Label"), + vformat("%s u", String::num(cursor.distance).pad_decimals(precision))); } } } diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index ae448129bc..84560b843b 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -997,6 +997,7 @@ bool KinematicBody2D::move_and_collide(const Vector2 &p_motion, bool p_infinite_ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_up_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { Vector2 body_velocity = p_linear_velocity; Vector2 body_velocity_normal = body_velocity.normalized(); + Vector2 up_direction = p_up_direction.normalized(); Vector2 current_floor_velocity = floor_velocity; if (on_floor && on_floor_body.is_valid()) { @@ -1043,11 +1044,11 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const colliders.push_back(collision); motion = collision.remainder; - if (p_up_direction == Vector2()) { + if (up_direction == Vector2()) { //all is a wall on_wall = true; } else { - if (Math::acos(collision.normal.dot(p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor + if (Math::acos(collision.normal.dot(up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor on_floor = true; floor_normal = collision.normal; @@ -1055,14 +1056,14 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const floor_velocity = collision.collider_vel; if (p_stop_on_slope) { - if ((body_velocity_normal + p_up_direction).length() < 0.01 && collision.travel.length() < 1) { + if ((body_velocity_normal + up_direction).length() < 0.01 && collision.travel.length() < 1) { Transform2D gt = get_global_transform(); - gt.elements[2] -= collision.travel.slide(p_up_direction); + gt.elements[2] -= collision.travel.slide(up_direction); set_global_transform(gt); return Vector2(); } } - } else if (Math::acos(collision.normal.dot(-p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling + } else if (Math::acos(collision.normal.dot(-up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling on_ceiling = true; } else { on_wall = true; @@ -1085,9 +1086,10 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const } Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_velocity, const Vector2 &p_snap, const Vector2 &p_up_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { + Vector2 up_direction = p_up_direction.normalized(); bool was_on_floor = on_floor; - Vector2 ret = move_and_slide(p_linear_velocity, p_up_direction, p_stop_on_slope, p_max_slides, p_floor_max_angle, p_infinite_inertia); + Vector2 ret = move_and_slide(p_linear_velocity, up_direction, p_stop_on_slope, p_max_slides, p_floor_max_angle, p_infinite_inertia); if (!was_on_floor || p_snap == Vector2()) { return ret; } @@ -1097,8 +1099,8 @@ Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_veloci if (move_and_collide(p_snap, p_infinite_inertia, col, false, true)) { bool apply = true; - if (p_up_direction != Vector2()) { - if (Math::acos(p_up_direction.normalized().dot(col.normal)) < p_floor_max_angle) { + if (up_direction != Vector2()) { + if (Math::acos(col.normal.dot(up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { on_floor = true; floor_normal = col.normal; on_floor_body = col.collider_rid; @@ -1106,7 +1108,7 @@ Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_veloci if (p_stop_on_slope) { // move and collide may stray the object a bit because of pre un-stucking, // so only ensure that motion happens on floor direction in this case. - col.travel = p_up_direction * p_up_direction.dot(col.travel); + col.travel = up_direction * up_direction.dot(col.travel); } } else { diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index de8f1eea2e..6320af21eb 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -945,6 +945,7 @@ bool KinematicBody3D::move_and_collide(const Vector3 &p_motion, bool p_infinite_ Vector3 KinematicBody3D::move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_up_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { Vector3 body_velocity = p_linear_velocity; Vector3 body_velocity_normal = body_velocity.normalized(); + Vector3 up_direction = p_up_direction.normalized(); for (int i = 0; i < 3; i++) { if (locked_axis & (1 << i)) { @@ -988,11 +989,11 @@ Vector3 KinematicBody3D::move_and_slide(const Vector3 &p_linear_velocity, const colliders.push_back(collision); motion = collision.remainder; - if (p_up_direction == Vector3()) { + if (up_direction == Vector3()) { //all is a wall on_wall = true; } else { - if (Math::acos(collision.normal.dot(p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor + if (Math::acos(collision.normal.dot(up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor on_floor = true; floor_normal = collision.normal; @@ -1000,14 +1001,14 @@ Vector3 KinematicBody3D::move_and_slide(const Vector3 &p_linear_velocity, const floor_velocity = collision.collider_vel; if (p_stop_on_slope) { - if ((body_velocity_normal + p_up_direction).length() < 0.01 && collision.travel.length() < 1) { + if ((body_velocity_normal + up_direction).length() < 0.01 && collision.travel.length() < 1) { Transform gt = get_global_transform(); - gt.origin -= collision.travel.slide(p_up_direction); + gt.origin -= collision.travel.slide(up_direction); set_global_transform(gt); return Vector3(); } } - } else if (Math::acos(collision.normal.dot(-p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling + } else if (Math::acos(collision.normal.dot(-up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling on_ceiling = true; } else { on_wall = true; @@ -1036,9 +1037,10 @@ Vector3 KinematicBody3D::move_and_slide(const Vector3 &p_linear_velocity, const } Vector3 KinematicBody3D::move_and_slide_with_snap(const Vector3 &p_linear_velocity, const Vector3 &p_snap, const Vector3 &p_up_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { + Vector3 up_direction = p_up_direction.normalized(); bool was_on_floor = on_floor; - Vector3 ret = move_and_slide(p_linear_velocity, p_up_direction, p_stop_on_slope, p_max_slides, p_floor_max_angle, p_infinite_inertia); + Vector3 ret = move_and_slide(p_linear_velocity, up_direction, p_stop_on_slope, p_max_slides, p_floor_max_angle, p_infinite_inertia); if (!was_on_floor || p_snap == Vector3()) { return ret; } @@ -1048,8 +1050,8 @@ Vector3 KinematicBody3D::move_and_slide_with_snap(const Vector3 &p_linear_veloci if (move_and_collide(p_snap, p_infinite_inertia, col, false, true)) { bool apply = true; - if (p_up_direction != Vector3()) { - if (Math::acos(p_up_direction.normalized().dot(col.normal)) < p_floor_max_angle) { + if (up_direction != Vector3()) { + if (Math::acos(col.normal.dot(up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { on_floor = true; floor_normal = col.normal; on_floor_body = col.collider_rid; @@ -1057,7 +1059,7 @@ Vector3 KinematicBody3D::move_and_slide_with_snap(const Vector3 &p_linear_veloci if (p_stop_on_slope) { // move and collide may stray the object a bit because of pre un-stucking, // so only ensure that motion happens on floor direction in this case. - col.travel = col.travel.project(p_up_direction); + col.travel = col.travel.project(up_direction); } } else { apply = false; //snapped with floor direction, but did not snap to a floor, do not snap. |