Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions editor/src/messages/tool/common_functionality/measure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
34 changes: 15 additions & 19 deletions editor/src/messages/tool/tool_messages/select_tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -689,32 +689,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);
}
}
}
Expand Down