@@ -363,6 +363,13 @@ pub struct SlidingPointInfo {
363363 connected_segments : [ SlidingSegmentData ; 2 ] ,
364364}
365365
366+ enum MouseDownIntent < ' a > {
367+ UpdatePoint { already_selected : bool , selection_info : Option < SelectedPointsInfo > } ,
368+ MoldSegment { segment : & ' a ClosestSegment } ,
369+ SelectLayer { layer : LayerNodeIdentifier } ,
370+ Draw ,
371+ }
372+
366373#[ derive( Clone , Copy , Debug , Default , PartialEq , Eq ) ]
367374enum PathToolFsmState {
368375 #[ default]
@@ -502,135 +509,148 @@ impl PathToolData {
502509
503510 let old_selection = shape_editor. selected_points ( ) . cloned ( ) . collect :: < Vec < _ > > ( ) ;
504511
505- // Check if the point is already selected; if not, select the first point within the threshold (in pixels)
506- // Don't select the points which are not shown currently in PathOverlayMode
507- if let Some ( ( already_selected, mut selection_info) ) = shape_editor. get_point_selection_state (
508- & document. network_interface ,
509- input. mouse . position ,
510- SELECTION_THRESHOLD ,
511- path_overlay_mode,
512- self . frontier_handles_info . clone ( ) ,
513- ) {
514- responses. add ( DocumentMessage :: StartTransaction ) ;
515-
516- self . last_clicked_point_was_selected = already_selected;
517-
518- // If the point is already selected and shift (`extend_selection`) is used, keep the selection unchanged.
519- // Otherwise, select the first point within the threshold.
520- if !( already_selected && extend_selection) {
521- if let Some ( updated_selection_info) = shape_editor. change_point_selection (
522- & document. network_interface ,
523- input. mouse . position ,
524- SELECTION_THRESHOLD ,
525- extend_selection,
526- path_overlay_mode,
527- self . frontier_handles_info . clone ( ) ,
528- ) {
529- selection_info = updated_selection_info;
530- }
512+ let mouse_down_intent = {
513+ // Check if the point is already selected; if not, select the first point within the threshold (in pixels)
514+ if let Some ( ( already_selected, selection_info) ) = shape_editor. get_point_selection_state (
515+ & document. network_interface ,
516+ input. mouse . position ,
517+ SELECTION_THRESHOLD ,
518+ path_overlay_mode,
519+ self . frontier_handles_info . clone ( ) ,
520+ ) {
521+ MouseDownIntent :: UpdatePoint { already_selected, selection_info }
522+ } else if lasso_select {
523+ MouseDownIntent :: Draw
524+ } else if let Some ( closed_segment) = & self . segment {
525+ MouseDownIntent :: MoldSegment { segment : closed_segment }
526+ } else if let Some ( layer) = document. click ( input) {
527+ MouseDownIntent :: SelectLayer { layer }
528+ } else {
529+ MouseDownIntent :: Draw
531530 }
531+ } ;
532532
533- if let Some ( selected_points) = selection_info {
534- self . drag_start_pos = input. mouse . position ;
533+ match mouse_down_intent {
534+ MouseDownIntent :: UpdatePoint { already_selected, mut selection_info } => {
535+ responses. add ( DocumentMessage :: StartTransaction ) ;
535536
536- // If selected points contain only handles and there was some selection before, then it is stored and becomes restored upon release
537- let mut dragging_only_handles = true ;
538- for point in & selected_points. points {
539- if matches ! ( point. point_id, ManipulatorPointId :: Anchor ( _) ) {
540- dragging_only_handles = false ;
541- break ;
537+ self . last_clicked_point_was_selected = already_selected;
538+
539+ // If the point is already selected and shift (`extend_selection`) is used, keep the selection unchanged.
540+ // Otherwise, select the first point within the threshold.
541+ if !( already_selected && extend_selection) {
542+ if let Some ( updated_selection_info) = shape_editor. change_point_selection (
543+ & document. network_interface ,
544+ input. mouse . position ,
545+ SELECTION_THRESHOLD ,
546+ extend_selection,
547+ path_overlay_mode,
548+ self . frontier_handles_info . clone ( ) ,
549+ ) {
550+ selection_info = updated_selection_info;
542551 }
543552 }
544- if dragging_only_handles && !self . handle_drag_toggle && !old_selection. is_empty ( ) {
545- self . saved_points_before_handle_drag = old_selection;
546- }
547553
548- if handle_drag_from_anchor {
549- if let Some ( ( layer, point) ) = shape_editor. find_nearest_point_indices ( & document. network_interface , input. mouse . position , SELECTION_THRESHOLD ) {
550- // Check that selected point is an anchor
551- if let ( Some ( point_id) , Some ( vector_data) ) = ( point. as_anchor ( ) , document. network_interface . compute_modified_vector ( layer) ) {
552- let handles = vector_data. all_connected ( point_id) . collect :: < Vec < _ > > ( ) ;
553- self . alt_clicked_on_anchor = true ;
554- for handle in & handles {
555- let modification_type = handle. set_relative_position ( DVec2 :: ZERO ) ;
556- responses. add ( GraphOperationMessage :: Vector { layer, modification_type } ) ;
557- for & handles in & vector_data. colinear_manipulators {
558- if handles. contains ( handle) {
559- let modification_type = VectorModificationType :: SetG1Continuous { handles, enabled : false } ;
560- responses. add ( GraphOperationMessage :: Vector { layer, modification_type } ) ;
554+ if let Some ( selected_points) = selection_info {
555+ self . drag_start_pos = input. mouse . position ;
556+
557+ // If selected points contain only handles and there was some selection before, then it is stored and becomes restored upon release
558+ let mut dragging_only_handles = true ;
559+ for point in & selected_points. points {
560+ if matches ! ( point. point_id, ManipulatorPointId :: Anchor ( _) ) {
561+ dragging_only_handles = false ;
562+ break ;
563+ }
564+ }
565+ if dragging_only_handles && !self . handle_drag_toggle && !old_selection. is_empty ( ) {
566+ self . saved_points_before_handle_drag = old_selection;
567+ }
568+
569+ if handle_drag_from_anchor {
570+ if let Some ( ( layer, point) ) = shape_editor. find_nearest_point_indices ( & document. network_interface , input. mouse . position , SELECTION_THRESHOLD ) {
571+ // Check that selected point is an anchor
572+ if let ( Some ( point_id) , Some ( vector_data) ) = ( point. as_anchor ( ) , document. network_interface . compute_modified_vector ( layer) ) {
573+ let handles = vector_data. all_connected ( point_id) . collect :: < Vec < _ > > ( ) ;
574+ self . alt_clicked_on_anchor = true ;
575+ for handle in & handles {
576+ let modification_type = handle. set_relative_position ( DVec2 :: ZERO ) ;
577+ responses. add ( GraphOperationMessage :: Vector { layer, modification_type } ) ;
578+ for & handles in & vector_data. colinear_manipulators {
579+ if handles. contains ( handle) {
580+ let modification_type = VectorModificationType :: SetG1Continuous { handles, enabled : false } ;
581+ responses. add ( GraphOperationMessage :: Vector { layer, modification_type } ) ;
582+ }
561583 }
562584 }
585+
586+ let manipulator_point_id = handles[ 0 ] . to_manipulator_point ( ) ;
587+ shape_editor. deselect_all_points ( ) ;
588+ shape_editor. select_points_by_manipulator_id ( & vec ! [ manipulator_point_id] ) ;
589+ responses. add ( PathToolMessage :: SelectedPointUpdated ) ;
563590 }
591+ }
592+ }
593+
594+ if let Some ( ( Some ( point) , Some ( vector_data) ) ) = shape_editor
595+ . find_nearest_point_indices ( & document. network_interface , input. mouse . position , SELECTION_THRESHOLD )
596+ . map ( |( layer, point) | ( point. as_anchor ( ) , document. network_interface . compute_modified_vector ( layer) ) )
597+ {
598+ let handles = vector_data
599+ . all_connected ( point)
600+ . filter ( |handle| handle. length ( & vector_data) < 1e-6 )
601+ . map ( |handle| handle. to_manipulator_point ( ) )
602+ . collect :: < Vec < _ > > ( ) ;
603+ let endpoint = vector_data. extendable_points ( false ) . any ( |anchor| point == anchor) ;
564604
565- let manipulator_point_id = handles[ 0 ] . to_manipulator_point ( ) ;
605+ if drag_zero_handle && ( handles. len ( ) == 1 && !endpoint ) {
566606 shape_editor. deselect_all_points ( ) ;
567- shape_editor. select_points_by_manipulator_id ( & vec ! [ manipulator_point_id ] ) ;
568- responses . add ( PathToolMessage :: SelectedPointUpdated ) ;
607+ shape_editor. select_points_by_manipulator_id ( & handles ) ;
608+ shape_editor . convert_selected_manipulators_to_colinear_handles ( responses , document ) ;
569609 }
570610 }
571- }
572611
573- if let Some ( ( Some ( point) , Some ( vector_data) ) ) = shape_editor
574- . find_nearest_point_indices ( & document. network_interface , input. mouse . position , SELECTION_THRESHOLD )
575- . map ( |( layer, point) | ( point. as_anchor ( ) , document. network_interface . compute_modified_vector ( layer) ) )
576- {
577- let handles = vector_data
578- . all_connected ( point)
579- . filter ( |handle| handle. length ( & vector_data) < 1e-6 )
580- . map ( |handle| handle. to_manipulator_point ( ) )
581- . collect :: < Vec < _ > > ( ) ;
582- let endpoint = vector_data. extendable_points ( false ) . any ( |anchor| point == anchor) ;
583-
584- if drag_zero_handle && ( handles. len ( ) == 1 && !endpoint) {
585- shape_editor. deselect_all_points ( ) ;
586- shape_editor. select_points_by_manipulator_id ( & handles) ;
587- shape_editor. convert_selected_manipulators_to_colinear_handles ( responses, document) ;
588- }
612+ self . start_dragging_point ( selected_points, input, document, shape_editor) ;
613+ responses. add ( OverlaysMessage :: Draw ) ;
589614 }
590-
591- self . start_dragging_point ( selected_points, input, document, shape_editor) ;
592- responses. add ( OverlaysMessage :: Draw ) ;
615+ PathToolFsmState :: Dragging ( self . dragging_state )
593616 }
594- PathToolFsmState :: Dragging ( self . dragging_state )
595- }
596- // We didn't find a point nearby, so we will see if there is a segment to insert a point on
597- else if let Some ( closed_segment) = & mut self . segment {
598- responses. add ( DocumentMessage :: StartTransaction ) ;
617+ MouseDownIntent :: MoldSegment { segment : closed_segment } => {
618+ responses. add ( DocumentMessage :: StartTransaction ) ;
599619
600- // Calculating and storing handle positions
601- let handle1 = ManipulatorPointId :: PrimaryHandle ( closed_segment. segment ( ) ) ;
602- let handle2 = ManipulatorPointId :: EndHandle ( closed_segment. segment ( ) ) ;
620+ // Calculating and storing handle positions
621+ let handle1 = ManipulatorPointId :: PrimaryHandle ( closed_segment. segment ( ) ) ;
622+ let handle2 = ManipulatorPointId :: EndHandle ( closed_segment. segment ( ) ) ;
603623
604- if let Some ( vector_data) = document. network_interface . compute_modified_vector ( closed_segment. layer ( ) ) {
605- if let ( Some ( pos1) , Some ( pos2) ) = ( handle1. get_position ( & vector_data) , handle2. get_position ( & vector_data) ) {
606- self . molding_info = Some ( ( pos1, pos2) )
624+ if let Some ( vector_data) = document. network_interface . compute_modified_vector ( closed_segment. layer ( ) ) {
625+ if let ( Some ( pos1) , Some ( pos2) ) = ( handle1. get_position ( & vector_data) , handle2. get_position ( & vector_data) ) {
626+ self . molding_info = Some ( ( pos1, pos2) )
627+ }
607628 }
629+ PathToolFsmState :: MoldingSegment
608630 }
631+ // We didn't find a segment, so consider selecting the nearest shape instead
632+ MouseDownIntent :: SelectLayer { layer } => {
633+ shape_editor. deselect_all_points ( ) ;
634+ if extend_selection {
635+ responses. add ( NodeGraphMessage :: SelectedNodesAdd { nodes : vec ! [ layer. to_node( ) ] } ) ;
636+ } else {
637+ responses. add ( NodeGraphMessage :: SelectedNodesSet { nodes : vec ! [ layer. to_node( ) ] } ) ;
638+ }
639+ self . drag_start_pos = input. mouse . position ;
640+ self . previous_mouse_position = document. metadata ( ) . document_to_viewport . inverse ( ) . transform_point2 ( input. mouse . position ) ;
609641
610- PathToolFsmState :: MoldingSegment
611- }
612- // We didn't find a segment, so consider selecting the nearest shape instead
613- else if let Some ( layer) = document. click ( input) {
614- shape_editor. deselect_all_points ( ) ;
615- if extend_selection {
616- responses. add ( NodeGraphMessage :: SelectedNodesAdd { nodes : vec ! [ layer. to_node( ) ] } ) ;
617- } else {
618- responses. add ( NodeGraphMessage :: SelectedNodesSet { nodes : vec ! [ layer. to_node( ) ] } ) ;
619- }
620- self . drag_start_pos = input. mouse . position ;
621- self . previous_mouse_position = document. metadata ( ) . document_to_viewport . inverse ( ) . transform_point2 ( input. mouse . position ) ;
622-
623- responses. add ( DocumentMessage :: StartTransaction ) ;
642+ responses. add ( DocumentMessage :: StartTransaction ) ;
624643
625- PathToolFsmState :: Dragging ( self . dragging_state )
626- }
627- // Start drawing
628- else {
629- self . drag_start_pos = input. mouse . position ;
630- self . previous_mouse_position = document. metadata ( ) . document_to_viewport . inverse ( ) . transform_point2 ( input. mouse . position ) ;
644+ PathToolFsmState :: Dragging ( self . dragging_state )
645+ }
646+ // Start drawing
647+ MouseDownIntent :: Draw => {
648+ self . drag_start_pos = input. mouse . position ;
649+ self . previous_mouse_position = document. metadata ( ) . document_to_viewport . inverse ( ) . transform_point2 ( input. mouse . position ) ;
631650
632- let selection_shape = if lasso_select { SelectionShapeType :: Lasso } else { SelectionShapeType :: Box } ;
633- PathToolFsmState :: Drawing { selection_shape }
651+ let selection_shape = if lasso_select { SelectionShapeType :: Lasso } else { SelectionShapeType :: Box } ;
652+ PathToolFsmState :: Drawing { selection_shape }
653+ }
634654 }
635655 }
636656
0 commit comments