Fix Alt-based quick measurement to show document space coordinates instead of viewport space (#2995)

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Vineet Puranik 2025-08-17 23:33:09 -07:00 committed by GitHub
parent 4da732dcc3
commit 0a4a822837
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 23 additions and 26 deletions

View File

@ -43,18 +43,19 @@ fn draw_line_with_length(line_start: DVec2, line_end: DVec2, transform: DAffine2
} }
} }
/// Draws a dashed outline around a rectangle to visualize the AABB /// Draws a dashed outline around the given rectangle (assumed to be in document space).
/// The provided transform is applied to convert coordinates (e.g., to viewport space) during rendering.
fn draw_dashed_rect_outline(rect: Rect, transform: DAffine2, overlay_context: &mut OverlayContext) { fn draw_dashed_rect_outline(rect: Rect, transform: DAffine2, overlay_context: &mut OverlayContext) {
let min = rect.min(); let min = rect.min();
let max = rect.max(); let max = rect.max();
// Create the four corners of the rectangle // Define corners in document space
let top_left = transform.transform_point2(DVec2::new(min.x, min.y)); let top_left = DVec2::new(min.x, min.y);
let top_right = transform.transform_point2(DVec2::new(max.x, min.y)); let top_right = DVec2::new(max.x, min.y);
let bottom_right = transform.transform_point2(DVec2::new(max.x, max.y)); let bottom_right = DVec2::new(max.x, max.y);
let bottom_left = transform.transform_point2(DVec2::new(min.x, max.y)); let bottom_left = DVec2::new(min.x, max.y);
// Draw the four sides as dashed lines // Draw each edge using document-space coordinates; transform is applied inside draw_dashed_line
draw_dashed_line(top_left, top_right, transform, overlay_context); draw_dashed_line(top_left, top_right, transform, overlay_context);
draw_dashed_line(top_right, bottom_right, transform, overlay_context); draw_dashed_line(top_right, bottom_right, transform, overlay_context);
draw_dashed_line(bottom_right, bottom_left, transform, overlay_context); draw_dashed_line(bottom_right, bottom_left, transform, overlay_context);

View File

@ -691,32 +691,28 @@ impl Fsm for SelectToolFsmState {
// Measure with Alt held down // Measure with Alt held down
// TODO: Don't use `Key::Alt` directly, instead take it as a variable from the input mappings list like in all other places // TODO: Don't use `Key::Alt` directly, instead take it as a variable from the input mappings list like in all other places
if overlay_context.visibility_settings.quick_measurement() && !matches!(self, Self::ResizingBounds { .. }) && input.keyboard.get(Key::Alt as usize) { if overlay_context.visibility_settings.quick_measurement() && !matches!(self, Self::ResizingBounds { .. }) && input.keyboard.get(Key::Alt as usize) {
// Get all selected layers and compute their viewport-aligned AABB // Compute document-space bounding box (AABB) of all selected visible & unlocked layers
let selected_bounds_viewport = document let selected_bounds_doc_space = document
.network_interface .network_interface
.selected_nodes() .selected_nodes()
.selected_visible_and_unlocked_layers(&document.network_interface) .selected_visible_and_unlocked_layers(&document.network_interface)
// Exclude layers that are artboards
.filter(|layer| !document.network_interface.is_artboard(&layer.to_node(), &[])) .filter(|layer| !document.network_interface.is_artboard(&layer.to_node(), &[]))
.filter_map(|layer| { // For each remaining layer, try to get its document-space bounding box and convert it to a Rect
// Get the layer's bounding box in its local space .filter_map(|layer| document.metadata().bounding_box_document(layer).map(Rect::from_box))
let local_bounds = document.metadata().bounding_box_with_transform(layer, DAffine2::IDENTITY)?; // Combine all individual bounding boxes into one overall bounding box that contains all selected layers
// Transform the bounds directly to viewport space
let viewport_quad = document.metadata().transform_to_viewport(layer) * Quad::from_box(local_bounds);
// Convert the quad to an AABB in viewport space
Some(Rect::from_box(viewport_quad.bounding_box()))
})
.reduce(Rect::combine_bounds); .reduce(Rect::combine_bounds);
// Get the hovered layer's viewport-aligned AABB // Compute document-space bounding box (AABB) of the currently hovered layer
let hovered_bounds_viewport = document.metadata().bounding_box_with_transform(layer, DAffine2::IDENTITY).map(|bounds| { let hovered_bounds_doc_space = document.metadata().bounding_box_document(layer);
let viewport_quad = document.metadata().transform_to_viewport(layer) * Quad::from_box(bounds);
Rect::from_box(viewport_quad.bounding_box())
});
// Use the viewport-aligned AABBs for measurement // If both selected and hovered bounds exist, overlay measurement lines
if let (Some(selected_bounds), Some(hovered_bounds)) = (selected_bounds_viewport, hovered_bounds_viewport) { if let (Some(selected_bounds), Some(hovered_bounds)) = (selected_bounds_doc_space, hovered_bounds_doc_space.map(Rect::from_box)) {
// Since we're already in viewport space, use identity transform // Both `selected_bounds` and `hovered_bounds` are in document space.
measure::overlay(selected_bounds, hovered_bounds, DAffine2::IDENTITY, DAffine2::IDENTITY, &mut overlay_context); // To correctly render overlay lines in the UI (which is in viewport space), we need to transform both rectangles from document to viewport space.
// Therefore, we pass `document_to_viewport` as both the `transform` and `document_to_viewport` parameters.
let document_to_viewport = document.metadata().document_to_viewport;
measure::overlay(selected_bounds, hovered_bounds, document_to_viewport, document_to_viewport, &mut overlay_context);
} }
} }
} }