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) {
let min = rect.min();
let max = rect.max();
// Create the four corners of the rectangle
let top_left = transform.transform_point2(DVec2::new(min.x, min.y));
let top_right = transform.transform_point2(DVec2::new(max.x, min.y));
let bottom_right = transform.transform_point2(DVec2::new(max.x, max.y));
let bottom_left = transform.transform_point2(DVec2::new(min.x, max.y));
// Define corners in document space
let top_left = DVec2::new(min.x, min.y);
let top_right = DVec2::new(max.x, min.y);
let bottom_right = DVec2::new(max.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_right, bottom_right, 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
// 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) {
// Get all selected layers and compute their viewport-aligned AABB
let selected_bounds_viewport = document
// Compute document-space bounding box (AABB) of all selected visible & unlocked layers
let selected_bounds_doc_space = document
.network_interface
.selected_nodes()
.selected_visible_and_unlocked_layers(&document.network_interface)
// Exclude layers that are artboards
.filter(|layer| !document.network_interface.is_artboard(&layer.to_node(), &[]))
.filter_map(|layer| {
// Get the layer's bounding box in its local space
let local_bounds = document.metadata().bounding_box_with_transform(layer, DAffine2::IDENTITY)?;
// 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()))
})
// For each remaining layer, try to get its document-space bounding box and convert it to a Rect
.filter_map(|layer| document.metadata().bounding_box_document(layer).map(Rect::from_box))
// Combine all individual bounding boxes into one overall bounding box that contains all selected layers
.reduce(Rect::combine_bounds);
// Get the hovered layer's viewport-aligned AABB
let hovered_bounds_viewport = document.metadata().bounding_box_with_transform(layer, DAffine2::IDENTITY).map(|bounds| {
let viewport_quad = document.metadata().transform_to_viewport(layer) * Quad::from_box(bounds);
Rect::from_box(viewport_quad.bounding_box())
});
// Compute document-space bounding box (AABB) of the currently hovered layer
let hovered_bounds_doc_space = document.metadata().bounding_box_document(layer);
// Use the viewport-aligned AABBs for measurement
if let (Some(selected_bounds), Some(hovered_bounds)) = (selected_bounds_viewport, hovered_bounds_viewport) {
// Since we're already in viewport space, use identity transform
measure::overlay(selected_bounds, hovered_bounds, DAffine2::IDENTITY, DAffine2::IDENTITY, &mut overlay_context);
// If both selected and hovered bounds exist, overlay measurement lines
if let (Some(selected_bounds), Some(hovered_bounds)) = (selected_bounds_doc_space, hovered_bounds_doc_space.map(Rect::from_box)) {
// Both `selected_bounds` and `hovered_bounds` are in document space.
// 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);
}
}
}