Improve quick measurement overlays with better number alignment and decimal rounding (#2155)

* Tidy up number text alignment and decimal precision for quick measurement overlays

* Tidy up number text alignment and decimal precision for quick measurement overlays

* Tidy up number text alignment and decimal precision for quick measurement overlays

* Tidy up number text alignment and decimal precision for quick measurement overlays

* Tidy up number text alignment and decimal precision for quick measurement overlays

* Tidy up number text alignment and decimal precision for quick measurement overlays

* Tidy up number text alignment and decimal precision for quick measurement overlays

* Tidy up number text alignment and decimal precision for quick measurement overlays

* Formatting changes

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Utsav Singh 2024-12-28 14:15:26 +05:30 committed by GitHub
parent b81f48385a
commit 6d737f15ee
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 105 additions and 43 deletions

View File

@ -11,23 +11,33 @@ fn draw_dashed_line(line_start: DVec2, line_end: DVec2, transform: DAffine2, ove
overlay_context.dashed_line(min_viewport, max_viewport, None, Some(2.), Some(3.));
}
/// Draws a solid line with a length annotation between two points transformed by the given affine transformations.
fn draw_line_with_length(line_start: DVec2, line_end: DVec2, transform: DAffine2, document_to_viewport: DAffine2, overlay_context: &mut OverlayContext) {
fn draw_line_with_length(line_start: DVec2, line_end: DVec2, transform: DAffine2, document_to_viewport: DAffine2, overlay_context: &mut OverlayContext, label_alignment: LabelAlignment) {
let transform_to_document = document_to_viewport.inverse() * transform;
let min_viewport = transform.transform_point2(line_start);
let max_viewport = transform.transform_point2(line_end);
overlay_context.line(min_viewport, max_viewport, None);
let length = format!("{:.2}", transform_to_document.transform_vector2(line_end - line_start).length());
overlay_context.text(
&length,
COLOR_OVERLAY_BLUE,
None,
DAffine2::from_translation((min_viewport + max_viewport) / 2.),
5.,
[Pivot::Middle, Pivot::Start],
);
// Remove trailing zeros from the formatted string
let length = format!("{:.2}", transform_to_document.transform_vector2(line_end - line_start).length())
.trim_end_matches('0')
.trim_end_matches('.')
.to_string();
const TEXT_PADDING: f64 = 5.;
// Calculate midpoint of the line
let midpoint = (min_viewport + max_viewport) / 2.;
// Adjust text position based on line orientation and flags
// Determine text position based on line orientation and flags
let (pivot_x, pivot_y) = match (label_alignment.is_vertical_line, label_alignment.text_on_left, label_alignment.text_on_top) {
(true, true, _) => (Pivot::End, Pivot::Middle), // Vertical line, text on the left
(true, false, _) => (Pivot::Start, Pivot::Middle), // Vertical line, text on the right
(false, _, true) => (Pivot::Middle, Pivot::End), // Horizontal line, text on top
(false, _, false) => (Pivot::Middle, Pivot::Start), // Horizontal line, text on bottom
};
overlay_context.text(&length, COLOR_OVERLAY_BLUE, None, DAffine2::from_translation(midpoint), TEXT_PADDING, [pivot_x, pivot_y]);
}
/// Checks if the selected bounds overlap with the hovered bounds on the Y-axis.
@ -56,7 +66,8 @@ fn draw_zero_axis_crossings(selected_bounds: Rect, hovered_bounds: Rect, transfo
// Draw horizontal solid line with length
let line_start = DVec2::new(selected_x, selected_y);
let line_end = DVec2::new(hovered_x, selected_y);
draw_line_with_length(line_start, line_end, transform, document_to_viewport, overlay_context);
let label_alignment = LabelAlignment::new(false, false, !selected_on_bottom);
draw_line_with_length(line_start, line_end, transform, document_to_viewport, overlay_context, label_alignment);
// Draw horizontal dashed line
let line_start = DVec2::new(selected_x, hovered_y);
@ -66,7 +77,8 @@ fn draw_zero_axis_crossings(selected_bounds: Rect, hovered_bounds: Rect, transfo
// Draw vertical solid line with length
let line_start = DVec2::new(selected_x, selected_y);
let line_end = DVec2::new(selected_x, hovered_y);
draw_line_with_length(line_start, line_end, transform, document_to_viewport, overlay_context);
let label_alignment = LabelAlignment::new(true, !selected_on_right, false);
draw_line_with_length(line_start, line_end, transform, document_to_viewport, overlay_context, label_alignment);
// Draw vertical dashed line
let line_start = DVec2::new(hovered_x, selected_y);
@ -82,6 +94,8 @@ fn draw_single_axis_zero_crossings(selected_bounds: Rect, hovered_bounds: Rect,
let overlap_y = does_overlap_y(selected_bounds, hovered_bounds);
let overlap_x = does_overlap_x(selected_bounds, hovered_bounds);
let selected_on_bottom = selected_bounds.center().y > hovered_bounds.center().y;
let selected_on_right = selected_bounds.center().x > hovered_bounds.center().x;
if overlap_y {
let selected_facing_edge = if hovered_max.y < selected_min.y { selected_min.y } else { selected_max.y };
let hovered_facing_edge = if hovered_max.y < selected_min.y { hovered_max.y } else { hovered_min.y };
@ -91,12 +105,14 @@ fn draw_single_axis_zero_crossings(selected_bounds: Rect, hovered_bounds: Rect,
// Draw horizontal solid line with length
let line_start = DVec2::new(f64::min(hovered_max.x, selected_max.x), selected_facing_edge);
let line_end = DVec2::new(f64::max(hovered_min.x, selected_min.x), selected_facing_edge);
draw_line_with_length(line_start, line_end, transform, document_to_viewport, overlay_context);
let label_alignment = LabelAlignment::new(false, false, selected_on_bottom);
draw_line_with_length(line_start, line_end, transform, document_to_viewport, overlay_context, label_alignment);
// Draw vertical solid line with length
let line_start = DVec2::new(vertical_line_start_x, selected_facing_edge);
let line_end = DVec2::new(vertical_line_start_x, hovered_facing_edge);
draw_line_with_length(line_start, line_end, transform, document_to_viewport, overlay_context);
let label_alignment = LabelAlignment::new(true, !selected_on_right, false);
draw_line_with_length(line_start, line_end, transform, document_to_viewport, overlay_context, label_alignment);
// Draw vertical dashed line
let dashed_line_start = DVec2::new(dashed_vertical_line_start_x, selected_facing_edge);
@ -111,12 +127,14 @@ fn draw_single_axis_zero_crossings(selected_bounds: Rect, hovered_bounds: Rect,
// Draw vertical solid line with length
let line_start = DVec2::new(selected_facing_edge, f64::min(hovered_max.y, selected_max.y));
let line_end = DVec2::new(selected_facing_edge, f64::max(hovered_min.y, selected_min.y));
draw_line_with_length(line_start, line_end, transform, document_to_viewport, overlay_context);
let label_alignment = LabelAlignment::new(true, selected_on_right, false);
draw_line_with_length(line_start, line_end, transform, document_to_viewport, overlay_context, label_alignment);
// Draw horizontal solid line with length
let line_start = DVec2::new(selected_facing_edge, horizontal_line_start_y);
let line_end = DVec2::new(hovered_facing_edge, horizontal_line_start_y);
draw_line_with_length(line_start, line_end, transform, document_to_viewport, overlay_context);
let label_alignment = LabelAlignment::new(false, false, !selected_on_bottom);
draw_line_with_length(line_start, line_end, transform, document_to_viewport, overlay_context, label_alignment);
// Draw horizontal dashed line
let dashed_line_start = DVec2::new(selected_facing_edge, dashed_horizontal_line_start_y);
@ -148,7 +166,8 @@ fn draw_single_axis_one_crossings(selected_bounds: Rect, hovered_bounds: Rect, t
// Draw vertical solid line with length
let line_start = DVec2::new(vertical_line_start, selected_facing_edge);
let line_end = DVec2::new(vertical_line_start, hovered_facing_edge);
draw_line_with_length(line_start, line_end, transform, document_to_viewport, overlay_context);
let label_alignment = LabelAlignment::new(true, true, false);
draw_line_with_length(line_start, line_end, transform, document_to_viewport, overlay_context, label_alignment);
} else if overlap_x {
let selected_facing_edge = if hovered_max.x < selected_min.x { selected_min.x } else { selected_max.x };
let hovered_facing_edge = if hovered_max.x < selected_min.x { hovered_max.x } else { hovered_min.x };
@ -161,7 +180,8 @@ fn draw_single_axis_one_crossings(selected_bounds: Rect, hovered_bounds: Rect, t
// Draw horizontal solid line with length
let line_start = DVec2::new(selected_facing_edge, horizontal_line_start_y);
let line_end = DVec2::new(hovered_facing_edge, horizontal_line_start_y);
draw_line_with_length(line_start, line_end, transform, document_to_viewport, overlay_context);
let label_alignment = LabelAlignment::new(false, false, true);
draw_line_with_length(line_start, line_end, transform, document_to_viewport, overlay_context, label_alignment);
}
}
@ -186,20 +206,24 @@ fn draw_two_axis_one_one_crossing(selected_bounds: Rect, hovered_bounds: Rect, t
// Draw horizontal solid lines with length
let top_x_start = DVec2::new(f64::min(selected_max.x, hovered_max.x), top_y_bound);
let top_x_end = DVec2::new(f64::max(selected_max.x, hovered_max.x), top_y_bound);
draw_line_with_length(top_x_start, top_x_end, transform, document_to_viewport, overlay_context);
let label_alignment = LabelAlignment::new(false, false, true);
draw_line_with_length(top_x_start, top_x_end, transform, document_to_viewport, overlay_context, label_alignment);
let bottom_x_start = DVec2::new(f64::min(selected_min.x, hovered_min.x), bottom_y_bound);
let bottom_x_end = DVec2::new(f64::max(selected_min.x, hovered_min.x), bottom_y_bound);
draw_line_with_length(bottom_x_start, bottom_x_end, transform, document_to_viewport, overlay_context);
let label_alignment = LabelAlignment::new(false, false, false);
draw_line_with_length(bottom_x_start, bottom_x_end, transform, document_to_viewport, overlay_context, label_alignment);
// Draw vertical solid lines with length
let top_y_start = DVec2::new(top_x_bound, f64::min(selected_min.y, hovered_min.y));
let top_y_end = DVec2::new(top_x_bound, f64::max(selected_min.y, hovered_min.y));
draw_line_with_length(top_y_start, top_y_end, transform, document_to_viewport, overlay_context);
let label_alignment = LabelAlignment::new(true, false, false);
draw_line_with_length(top_y_start, top_y_end, transform, document_to_viewport, overlay_context, label_alignment);
let bottom_y_start = DVec2::new(bottom_x_bound, f64::min(selected_max.y, hovered_max.y));
let bottom_y_end = DVec2::new(bottom_x_bound, f64::max(selected_max.y, hovered_max.y));
draw_line_with_length(bottom_y_start, bottom_y_end, transform, document_to_viewport, overlay_context);
let label_alignment = LabelAlignment::new(true, true, false);
draw_line_with_length(bottom_y_start, bottom_y_end, transform, document_to_viewport, overlay_context, label_alignment);
}
/// Draws measurements for partial overlaps with two vertical or horizontal edge intersections.
@ -225,11 +249,13 @@ fn draw_two_axis_one_one_two_zero_crossing(
// Draw vertical solid lines with length
let y_start_left = DVec2::new(hovered_min.x, f64::min(selected_bound_edge, hovered_bound_edge));
let y_end_left = DVec2::new(hovered_min.x, f64::max(selected_bound_edge, hovered_bound_edge));
draw_line_with_length(y_start_left, y_end_left, transform, document_to_viewport, overlay_context);
let label_alignment = LabelAlignment::new(true, true, false);
draw_line_with_length(y_start_left, y_end_left, transform, document_to_viewport, overlay_context, label_alignment);
let y_start_right = DVec2::new(hovered_max.x, f64::min(selected_bound_edge, hovered_bound_edge));
let y_end_right = DVec2::new(hovered_max.x, f64::max(selected_bound_edge, hovered_bound_edge));
draw_line_with_length(y_start_right, y_end_right, transform, document_to_viewport, overlay_context);
let label_alignment = LabelAlignment::new(true, false, false);
draw_line_with_length(y_start_right, y_end_right, transform, document_to_viewport, overlay_context, label_alignment);
// Draw horizontal solid lines with length
let horizontal_line_y_bound = if selected_bounds.center().y >= hovered_bounds.center().y {
@ -240,11 +266,13 @@ fn draw_two_axis_one_one_two_zero_crossing(
let x_start_left = DVec2::new(hovered_min.x, horizontal_line_y_bound);
let x_end_left = DVec2::new(selected_min.x, horizontal_line_y_bound);
draw_line_with_length(x_start_left, x_end_left, transform, document_to_viewport, overlay_context);
let label_alignment = LabelAlignment::new(false, false, false);
draw_line_with_length(x_start_left, x_end_left, transform, document_to_viewport, overlay_context, label_alignment);
let x_start_right = DVec2::new(hovered_max.x, horizontal_line_y_bound);
let x_end_right = DVec2::new(selected_max.x, horizontal_line_y_bound);
draw_line_with_length(x_start_right, x_end_right, transform, document_to_viewport, overlay_context);
let label_alignment = LabelAlignment::new(false, false, false);
draw_line_with_length(x_start_right, x_end_right, transform, document_to_viewport, overlay_context, label_alignment);
} else {
let selected_bound_edge = if selected_bounds.center().x >= hovered_bounds.center().x {
selected_max.x
@ -263,11 +291,13 @@ fn draw_two_axis_one_one_two_zero_crossing(
// Draw vertical solid lines with length
let y_start_up = DVec2::new(vertical_line_x, selected_min.y);
let y_end_up = DVec2::new(vertical_line_x, hovered_min.y);
draw_line_with_length(y_start_up, y_end_up, transform, document_to_viewport, overlay_context);
let label_alignment = LabelAlignment::new(true, false, false);
draw_line_with_length(y_start_up, y_end_up, transform, document_to_viewport, overlay_context, label_alignment);
let y_start_down = DVec2::new(vertical_line_x, selected_max.y);
let y_end_down = DVec2::new(vertical_line_x, hovered_max.y);
draw_line_with_length(y_start_down, y_end_down, transform, document_to_viewport, overlay_context);
let label_alignment = LabelAlignment::new(true, false, false);
draw_line_with_length(y_start_down, y_end_down, transform, document_to_viewport, overlay_context, label_alignment);
// Draw horizontal solid lines with length
let horizontal_line_inner_x = if selected_bounds.center().x >= hovered_bounds.center().x {
@ -277,11 +307,13 @@ fn draw_two_axis_one_one_two_zero_crossing(
};
let x_start_up = DVec2::new(vertical_line_x, f64::min(selected_min.y, hovered_min.y));
let x_end_up = DVec2::new(horizontal_line_inner_x, f64::min(selected_min.y, hovered_min.y));
draw_line_with_length(x_start_up, x_end_up, transform, document_to_viewport, overlay_context);
let label_alignment = LabelAlignment::new(false, false, true);
draw_line_with_length(x_start_up, x_end_up, transform, document_to_viewport, overlay_context, label_alignment);
let x_start_down = DVec2::new(vertical_line_x, f64::max(selected_max.y, hovered_max.y));
let x_end_down = DVec2::new(horizontal_line_inner_x, f64::max(selected_max.y, hovered_max.y));
draw_line_with_length(x_start_down, x_end_down, transform, document_to_viewport, overlay_context);
let label_alignment = LabelAlignment::new(false, false, false);
draw_line_with_length(x_start_down, x_end_down, transform, document_to_viewport, overlay_context, label_alignment);
}
}
@ -293,36 +325,46 @@ fn draw_two_axis_two_zero_zero_two(selected_bounds: Rect, hovered_bounds: Rect,
// Draw vertical solid lines with length
let y_start_left_top = DVec2::new(f64::min(hovered_min.x, selected_min.x), f64::min(hovered_min.y, selected_min.y));
let y_end_left_top = DVec2::new(f64::min(hovered_min.x, selected_min.x), f64::max(hovered_min.y, selected_min.y));
draw_line_with_length(y_start_left_top, y_end_left_top, transform, document_to_viewport, overlay_context);
let label_alignment = LabelAlignment::new(true, true, false);
draw_line_with_length(y_start_left_top, y_end_left_top, transform, document_to_viewport, overlay_context, label_alignment);
let label_alignment = LabelAlignment::new(true, true, false);
draw_line_with_length(y_start_left_top, y_end_left_top, transform, document_to_viewport, overlay_context, label_alignment);
let y_start_left_bottom = DVec2::new(f64::min(hovered_min.x, selected_min.x), f64::min(hovered_max.y, selected_max.y));
let y_end_left_bottom = DVec2::new(f64::min(hovered_min.x, selected_min.x), f64::max(hovered_max.y, selected_max.y));
draw_line_with_length(y_start_left_bottom, y_end_left_bottom, transform, document_to_viewport, overlay_context);
let label_alignment = LabelAlignment::new(true, true, false);
draw_line_with_length(y_start_left_bottom, y_end_left_bottom, transform, document_to_viewport, overlay_context, label_alignment);
let y_start_right_top = DVec2::new(f64::max(hovered_max.x, selected_max.x), f64::min(hovered_min.y, selected_min.y));
let y_end_right_top = DVec2::new(f64::max(hovered_max.x, selected_max.x), f64::max(hovered_min.y, selected_min.y));
draw_line_with_length(y_start_right_top, y_end_right_top, transform, document_to_viewport, overlay_context);
let label_alignment = LabelAlignment::new(true, false, false);
draw_line_with_length(y_start_right_top, y_end_right_top, transform, document_to_viewport, overlay_context, label_alignment);
let y_start_right_bottom = DVec2::new(f64::max(hovered_max.x, selected_max.x), f64::min(hovered_max.y, selected_max.y));
let y_end_right_bottom = DVec2::new(f64::max(hovered_max.x, selected_max.x), f64::max(hovered_max.y, selected_max.y));
draw_line_with_length(y_start_right_bottom, y_end_right_bottom, transform, document_to_viewport, overlay_context);
let label_alignment = LabelAlignment::new(true, false, false);
draw_line_with_length(y_start_right_bottom, y_end_right_bottom, transform, document_to_viewport, overlay_context, label_alignment);
// Draw horizontal solid lines with length
let x_start_left_top = DVec2::new(f64::min(hovered_min.x, selected_min.x), f64::min(hovered_min.y, selected_min.y));
let x_end_left_top = DVec2::new(f64::max(hovered_min.x, selected_min.x), f64::min(hovered_min.y, selected_min.y));
draw_line_with_length(x_start_left_top, x_end_left_top, transform, document_to_viewport, overlay_context);
let label_alignment = LabelAlignment::new(false, false, true);
draw_line_with_length(x_start_left_top, x_end_left_top, transform, document_to_viewport, overlay_context, label_alignment);
let x_start_right_top = DVec2::new(f64::min(hovered_max.x, selected_max.x), f64::min(hovered_min.y, selected_min.y));
let x_end_right_top = DVec2::new(f64::max(hovered_max.x, selected_max.x), f64::min(hovered_min.y, selected_min.y));
draw_line_with_length(x_start_right_top, x_end_right_top, transform, document_to_viewport, overlay_context);
let label_alignment = LabelAlignment::new(false, false, true);
draw_line_with_length(x_start_right_top, x_end_right_top, transform, document_to_viewport, overlay_context, label_alignment);
let x_start_left_bottom = DVec2::new(f64::min(hovered_min.x, selected_min.x), f64::max(hovered_max.y, selected_max.y));
let x_end_left_bottom = DVec2::new(f64::max(hovered_min.x, selected_min.x), f64::max(hovered_max.y, selected_max.y));
draw_line_with_length(x_start_left_bottom, x_end_left_bottom, transform, document_to_viewport, overlay_context);
let label_alignment = LabelAlignment::new(false, false, false);
draw_line_with_length(x_start_left_bottom, x_end_left_bottom, transform, document_to_viewport, overlay_context, label_alignment);
let x_start_right_bottom = DVec2::new(f64::min(hovered_max.x, selected_max.x), f64::max(hovered_max.y, selected_max.y));
let x_end_right_bottom = DVec2::new(f64::max(hovered_max.x, selected_max.x), f64::max(hovered_max.y, selected_max.y));
draw_line_with_length(x_start_right_bottom, x_end_right_bottom, transform, document_to_viewport, overlay_context);
let label_alignment = LabelAlignment::new(false, false, false);
draw_line_with_length(x_start_right_bottom, x_end_right_bottom, transform, document_to_viewport, overlay_context, label_alignment);
}
/// Draws measurements where selected and hovered bounds have two vertical edges crossing each other.
@ -333,20 +375,24 @@ fn draw_two_axis_two_zero_two_zero(selected_bounds: Rect, hovered_bounds: Rect,
// Draw horizontal solid lines with length
let x_start_left = DVec2::new(f64::max(hovered_min.x, selected_min.x), selected_bounds.center().y);
let x_end_left = DVec2::new(f64::min(hovered_min.x, selected_min.x), selected_bounds.center().y);
draw_line_with_length(x_start_left, x_end_left, transform, document_to_viewport, overlay_context);
let label_alignment = LabelAlignment::new(false, false, true);
draw_line_with_length(x_start_left, x_end_left, transform, document_to_viewport, overlay_context, label_alignment);
let x_start_right = DVec2::new(f64::min(hovered_max.x, selected_max.x), selected_bounds.center().y);
let x_end_right = DVec2::new(f64::max(hovered_max.x, selected_max.x), selected_bounds.center().y);
draw_line_with_length(x_start_right, x_end_right, transform, document_to_viewport, overlay_context);
let label_alignment = LabelAlignment::new(false, false, true);
draw_line_with_length(x_start_right, x_end_right, transform, document_to_viewport, overlay_context, label_alignment);
// Draw vertical solid lines with length
let y_start_top = DVec2::new(selected_bounds.center().x, f64::max(hovered_min.y, selected_min.y));
let y_end_top = DVec2::new(selected_bounds.center().x, f64::min(hovered_min.y, selected_min.y));
draw_line_with_length(y_start_top, y_end_top, transform, document_to_viewport, overlay_context);
let label_alignment = LabelAlignment::new(true, false, false);
draw_line_with_length(y_start_top, y_end_top, transform, document_to_viewport, overlay_context, label_alignment);
let y_start_bottom = DVec2::new(selected_bounds.center().x, f64::min(hovered_max.y, selected_max.y));
let y_end_bottom = DVec2::new(selected_bounds.center().x, f64::max(hovered_max.y, selected_max.y));
draw_line_with_length(y_start_bottom, y_end_bottom, transform, document_to_viewport, overlay_context);
let label_alignment = LabelAlignment::new(true, false, false);
draw_line_with_length(y_start_bottom, y_end_bottom, transform, document_to_viewport, overlay_context, label_alignment);
}
/// Handles overlapping scenarios involving two axes between selected and hovered bounds.
@ -411,3 +457,19 @@ pub fn overlay(selected_bounds: Rect, hovered_bounds: Rect, transform: DAffine2,
_ => (), // Fallback case, should not typically happen
}
}
struct LabelAlignment {
is_vertical_line: bool,
text_on_left: bool,
text_on_top: bool,
}
impl LabelAlignment {
fn new(is_vertical_line: bool, text_on_left: bool, text_on_top: bool) -> Self {
Self {
is_vertical_line,
text_on_left,
text_on_top,
}
}
}