@@ -72,7 +72,7 @@ pub enum SelectToolMessage {
7272
7373 // Tool-specific messages
7474 DragStart { extend_selection : Key , select_deepest : Key } ,
75- DragStop { remove_from_selection : Key } ,
75+ DragStop { remove_from_selection : Key , negative_box_selection : Key } ,
7676 EditLayer ,
7777 Enter ,
7878 PointerMove ( SelectToolPointerKeys ) ,
@@ -902,7 +902,7 @@ impl Fsm for SelectToolFsmState {
902902 let selection = tool_data. nested_selection_behavior ;
903903 SelectToolFsmState :: Ready { selection }
904904 }
905- ( SelectToolFsmState :: Dragging , SelectToolMessage :: DragStop { remove_from_selection } ) => {
905+ ( SelectToolFsmState :: Dragging , SelectToolMessage :: DragStop { remove_from_selection, .. } ) => {
906906 // Deselect layer if not snap dragging
907907 responses. add ( DocumentMessage :: EndTransaction ) ;
908908
@@ -1001,20 +1001,34 @@ impl Fsm for SelectToolFsmState {
10011001 let selection = tool_data. nested_selection_behavior ;
10021002 SelectToolFsmState :: Ready { selection }
10031003 }
1004- ( SelectToolFsmState :: DrawingBox { .. } , SelectToolMessage :: DragStop { .. } | SelectToolMessage :: Enter ) => {
1004+ (
1005+ SelectToolFsmState :: DrawingBox { .. } ,
1006+ SelectToolMessage :: DragStop {
1007+ remove_from_selection,
1008+ negative_box_selection,
1009+ } ,
1010+ ) => {
10051011 let quad = tool_data. selection_quad ( ) ;
10061012 let new_selected: HashSet < _ > = document. intersect_quad_no_artboards ( quad, input) . collect ( ) ;
10071013 let current_selected: HashSet < _ > = document. network_interface . selected_nodes ( & [ ] ) . unwrap ( ) . selected_layers ( document. metadata ( ) ) . collect ( ) ;
10081014 if new_selected != current_selected {
1009- let parent_selected: HashSet < _ > = new_selected
1010- . into_iter ( )
1011- . map ( |layer| {
1012- // Find the parent node
1013- layer. ancestors ( document. metadata ( ) ) . filter ( not_artboard ( document) ) . last ( ) . unwrap_or ( layer)
1014- } )
1015- . collect ( ) ;
1016-
1017- tool_data. layers_dragging . extend ( parent_selected. iter ( ) . copied ( ) ) ;
1015+ // Negative selection when both Shift and Ctrl are pressed
1016+ if input. keyboard . key ( remove_from_selection) && input. keyboard . key ( negative_box_selection) {
1017+ let updated_selection = current_selected
1018+ . into_iter ( )
1019+ . filter ( |layer| !new_selected. iter ( ) . any ( |selected| layer. starts_with ( * selected, document. metadata ( ) ) ) )
1020+ . collect ( ) ;
1021+ tool_data. layers_dragging = updated_selection;
1022+ } else {
1023+ let parent_selected: HashSet < _ > = new_selected
1024+ . into_iter ( )
1025+ . map ( |layer| {
1026+ // Find the parent node
1027+ layer. ancestors ( document. metadata ( ) ) . filter ( not_artboard ( document) ) . last ( ) . unwrap_or ( layer)
1028+ } )
1029+ . collect ( ) ;
1030+ tool_data. layers_dragging . extend ( parent_selected. iter ( ) . copied ( ) ) ;
1031+ }
10181032 responses. add ( NodeGraphMessage :: SelectedNodesSet {
10191033 nodes : tool_data
10201034 . layers_dragging
@@ -1143,9 +1157,13 @@ impl Fsm for SelectToolFsmState {
11431157 responses. add ( FrontendMessage :: UpdateInputHints { hint_data } ) ;
11441158 }
11451159 SelectToolFsmState :: DrawingBox { .. } => {
1146- // TODO: Add hint and implement functionality for holding Shift to extend the selection, thus preventing the prior selection from being cleared
1147- // TODO: Also fix the current functionality so canceling the box select doesn't clear the prior selection
1148- let hint_data = HintData ( vec ! [ HintGroup ( vec![ HintInfo :: mouse( MouseMotion :: Rmb , "" ) , HintInfo :: keys( [ Key :: Escape ] , "Cancel" ) . prepend_slash( ) ] ) ] ) ;
1160+ let hint_data = HintData ( vec ! [
1161+ HintGroup ( vec![ HintInfo :: mouse( MouseMotion :: Rmb , "" ) , HintInfo :: keys( [ Key :: Escape ] , "Cancel" ) . prepend_slash( ) ] ) ,
1162+ HintGroup ( vec![ HintInfo :: keys( [ Key :: Control , Key :: Shift ] , "Remove from Selection" ) . add_mac_keys( [ Key :: Command , Key :: Shift ] ) ] ) ,
1163+ // TODO: Re-select deselected layers during drag when Shift is pressed, and re-deselect if Shift is released before drag ends.
1164+ // TODO: (See https://discord.com/channels/731730685944922173/1216976541947531264/1321360311298818048)
1165+ // HintGroup(vec![HintInfo::keys([Key::Shift], "Extend Selection")])
1166+ ] ) ;
11491167 responses. add ( FrontendMessage :: UpdateInputHints { hint_data } ) ;
11501168 }
11511169 _ => { }
0 commit comments