diff --git a/editor/src/messages/tool/tool_messages/select_tool.rs b/editor/src/messages/tool/tool_messages/select_tool.rs index 7d24bcbba1..d559a595b2 100644 --- a/editor/src/messages/tool/tool_messages/select_tool.rs +++ b/editor/src/messages/tool/tool_messages/select_tool.rs @@ -512,7 +512,6 @@ struct SelectToolData { selected_layers_changed: bool, snap_candidates: Vec, auto_panning: AutoPanning, - drag_start_center: ViewportPosition, } impl SelectToolData { @@ -529,6 +528,15 @@ impl SelectToolData { } } + /// The center of the combined viewport-space bounding box of the layers currently being dragged. + fn dragging_layers_center(&self, document: &DocumentMessageHandler) -> Option { + self.layers_dragging + .iter() + .filter_map(|&layer| document.metadata().bounding_box_viewport(layer).map(Rect::from_box)) + .reduce(Rect::combine_bounds) + .map(|bounds| bounds.center()) + } + pub fn selection_quad(&self) -> Quad { let bbox = self.selection_box(); Quad::from_box(bbox) @@ -1021,7 +1029,18 @@ impl Fsm for SelectToolFsmState { let angle = -mouse_position.angle_to(DVec2::X); let snapped_angle = (angle / snap_resolution).round() * snap_resolution; - let origin = tool_data.drag_start_center; + // Anchor the guide to the dragged layers' center at the moment the drag began. It's computed live (rather than + // snapshotted at drag start) so it stays correct as the layers move and the viewport auto-pans: their current + // center minus the drag displacement recovers the start center in the present viewport frame. Sourcing it from + // the layers being dragged (not the prior selection's pivot) is what keeps it on the layer actually grabbed. + let origin = if matches!(self, Self::Dragging { .. }) { + tool_data + .dragging_layers_center(document) + .map(|center| center - (tool_data.drag_current - tool_data.drag_start)) + .unwrap_or_else(|| tool_data.pivot_gizmo().position(document)) + } else { + tool_data.pivot_gizmo().position(document) + }; let viewport_diagonal = viewport.size().into_dvec2().length(); let edge = DVec2::from_angle(snapped_angle).normalize_or(DVec2::X); @@ -1132,8 +1151,6 @@ impl Fsm for SelectToolFsmState { let position = tool_data.pivot_gizmo().position(document); let (resize, rotate, skew) = transforming_transform_cage(document, &mut tool_data.bounding_box_manager, input, responses, &mut tool_data.layers_dragging, Some(position)); - tool_data.drag_start_center = position; - // If the user is dragging the bounding box bounds, go into ResizingBounds mode. // If the user is dragging the rotate trigger, go into RotatingBounds mode. // If the user clicks on a layer that is in their current selection, go into the dragging mode.