Skip to content

Commit e044f13

Browse files
committed
fixed Box selection with the Select tool and Path tool to follow canvas while panning
1 parent 3f999bf commit e044f13

File tree

1 file changed

+29
-18
lines changed

1 file changed

+29
-18
lines changed

editor/src/messages/tool/tool_messages/select_tool.rs

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,7 @@ struct SelectToolData {
402402
snap_candidates: Vec<SnapCandidatePoint>,
403403
auto_panning: AutoPanning,
404404
drag_start_center: ViewportPosition,
405+
drag_start_document: Option<DVec2>,
405406
}
406407

407408
impl SelectToolData {
@@ -418,13 +419,13 @@ impl SelectToolData {
418419
}
419420
}
420421

421-
pub fn selection_quad(&self) -> Quad {
422-
let bbox = self.selection_box();
422+
pub fn selection_quad(&self, metadata: &DocumentMetadata) -> Quad {
423+
let bbox = self.selection_box(metadata);
423424
Quad::from_box(bbox)
424425
}
425426

426-
pub fn calculate_selection_mode_from_direction(&mut self) -> SelectionMode {
427-
let bbox: [DVec2; 2] = self.selection_box();
427+
pub fn calculate_selection_mode_from_direction(&mut self, metadata: &DocumentMetadata) -> SelectionMode {
428+
let bbox: [DVec2; 2] = self.selection_box(metadata);
428429
let above_threshold = bbox[1].distance_squared(bbox[0]) > DRAG_DIRECTION_MODE_DETERMINATION_THRESHOLD.powi(2);
429430

430431
if self.selection_mode.is_none() && above_threshold {
@@ -440,12 +441,19 @@ impl SelectToolData {
440441
self.selection_mode.unwrap_or(SelectionMode::Touched)
441442
}
442443

443-
pub fn selection_box(&self) -> [DVec2; 2] {
444-
if self.drag_current == self.drag_start {
444+
pub fn selection_box(&self, metadata: &DocumentMetadata) -> [DVec2; 2] {
445+
// If we have a document-anchored start point, transform it to viewport
446+
let start_viewport = if let Some(start_doc) = self.drag_start_document {
447+
metadata.document_to_viewport.transform_point2(start_doc)
448+
} else {
449+
self.drag_start
450+
};
451+
452+
if self.drag_current == start_viewport {
445453
let tolerance = DVec2::splat(SELECTION_TOLERANCE);
446-
[self.drag_start - tolerance, self.drag_start + tolerance]
454+
[start_viewport - tolerance, start_viewport + tolerance]
447455
} else {
448-
[self.drag_start, self.drag_current]
456+
[start_viewport, self.drag_current]
449457
}
450458
}
451459

@@ -938,10 +946,10 @@ impl Fsm for SelectToolFsmState {
938946
// Check if the tool is in selection mode
939947
if let Self::Drawing { selection_shape, .. } = self {
940948
// Get the updated selection box bounds
941-
let quad = Quad::from_box([tool_data.drag_start, tool_data.drag_current]);
949+
let quad = tool_data.selection_quad(document.metadata());
942950

943951
let current_selection_mode = match tool_action_data.preferences.get_selection_mode() {
944-
SelectionMode::Directional => tool_data.calculate_selection_mode_from_direction(),
952+
SelectionMode::Directional => tool_data.calculate_selection_mode_from_direction(document.metadata()),
945953
SelectionMode::Touched => SelectionMode::Touched,
946954
SelectionMode::Enclosed => SelectionMode::Enclosed,
947955
};
@@ -1140,6 +1148,8 @@ impl Fsm for SelectToolFsmState {
11401148
}
11411149
} else {
11421150
let selection_shape = if input.keyboard.key(lasso_select) { SelectionShapeType::Lasso } else { SelectionShapeType::Box };
1151+
// Anchor the drag start to document coordinates so panning/zooming doesn't move the start point
1152+
tool_data.drag_start_document = Some(document.metadata().document_to_viewport.inverse().transform_point2(tool_data.drag_start));
11431153
SelectToolFsmState::Drawing { selection_shape, has_drawn: false }
11441154
}
11451155
};
@@ -1380,10 +1390,8 @@ impl Fsm for SelectToolFsmState {
13801390
self
13811391
}
13821392
(SelectToolFsmState::Drawing { .. }, SelectToolMessage::PointerOutsideViewport { .. }) => {
1383-
// Auto-panning
1384-
if let Some(shift) = tool_data.auto_panning.shift_viewport(input, viewport, responses) {
1385-
tool_data.drag_start += shift;
1386-
}
1393+
// Auto-panning - the start is anchored to document space, so no need to shift `drag_start` here
1394+
let _ = tool_data.auto_panning.shift_viewport(input, viewport, responses);
13871395

13881396
self
13891397
}
@@ -1404,8 +1412,8 @@ impl Fsm for SelectToolFsmState {
14041412

14051413
if !has_dragged && input.keyboard.key(remove_from_selection) && tool_data.layer_selected_on_start.is_none() {
14061414
// When you click on the layer with remove from selection key (shift) pressed, we deselect all nodes that are children.
1407-
let quad = tool_data.selection_quad();
1408-
let intersection = document.intersect_quad_no_artboards(quad, viewport);
1415+
let quad = tool_data.selection_quad(document.metadata());
1416+
let intersection: Vec<_> = document.intersect_quad_no_artboards(quad, viewport).collect();
14091417

14101418
if let Some(path) = intersection.last() {
14111419
let replacement_selected_layers: Vec<_> = document
@@ -1504,10 +1512,10 @@ impl Fsm for SelectToolFsmState {
15041512
SelectToolFsmState::Ready { selection }
15051513
}
15061514
(SelectToolFsmState::Drawing { selection_shape, .. }, SelectToolMessage::DragStop { remove_from_selection }) => {
1507-
let quad = tool_data.selection_quad();
1515+
let quad = tool_data.selection_quad(document.metadata());
15081516

15091517
let selection_mode = match tool_action_data.preferences.get_selection_mode() {
1510-
SelectionMode::Directional => tool_data.calculate_selection_mode_from_direction(),
1518+
SelectionMode::Directional => tool_data.calculate_selection_mode_from_direction(document.metadata()),
15111519
selection_mode => selection_mode,
15121520
};
15131521

@@ -1572,6 +1580,9 @@ impl Fsm for SelectToolFsmState {
15721580

15731581
tool_data.lasso_polygon.clear();
15741582

1583+
// Clear the document-anchored drag start when finishing drawing
1584+
tool_data.drag_start_document = None;
1585+
15751586
responses.add(OverlaysMessage::Draw);
15761587

15771588
let selection = tool_data.nested_selection_behavior;

0 commit comments

Comments
 (0)