@@ -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
407408impl 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