From 0a4a822837b0f2d88fe99375902813be47f05c28 Mon Sep 17 00:00:00 2001 From: Vineet Puranik <40868710+vineetpuranik@users.noreply.github.com> Date: Sun, 17 Aug 2025 23:33:09 -0700 Subject: [PATCH] Fix Alt-based quick measurement to show document space coordinates instead of viewport space (#2995) Co-authored-by: Keavon Chambers --- .../tool/common_functionality/measure.rs | 15 ++++---- .../tool/tool_messages/select_tool.rs | 34 ++++++++----------- 2 files changed, 23 insertions(+), 26 deletions(-) diff --git a/editor/src/messages/tool/common_functionality/measure.rs b/editor/src/messages/tool/common_functionality/measure.rs index 5a76a5bd..1ad5ae70 100644 --- a/editor/src/messages/tool/common_functionality/measure.rs +++ b/editor/src/messages/tool/common_functionality/measure.rs @@ -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); diff --git a/editor/src/messages/tool/tool_messages/select_tool.rs b/editor/src/messages/tool/tool_messages/select_tool.rs index a14ad14f..62935748 100644 --- a/editor/src/messages/tool/tool_messages/select_tool.rs +++ b/editor/src/messages/tool/tool_messages/select_tool.rs @@ -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); } } }