11use super :: tool_prelude:: * ;
2- use crate :: consts:: { COLOR_OVERLAY_BLUE , DEFAULT_STROKE_WIDTH , HIDE_HANDLE_DISTANCE , LINE_ROTATE_SNAP_ANGLE } ;
2+ use crate :: consts:: { COLOR_OVERLAY_BLUE , DEFAULT_STROKE_WIDTH , HIDE_HANDLE_DISTANCE , LINE_ROTATE_SNAP_ANGLE , SEGMENT_OVERLAY_SIZE } ;
33use crate :: messages:: input_mapper:: utility_types:: input_mouse:: MouseKeys ;
44use crate :: messages:: portfolio:: document:: node_graph:: document_node_definitions:: resolve_document_node_type;
55use crate :: messages:: portfolio:: document:: overlays:: utility_functions:: path_overlays;
@@ -361,6 +361,9 @@ struct PenToolData {
361361 current_layer : Option < LayerNodeIdentifier > ,
362362 prior_segment_endpoint : Option < PointId > ,
363363 prior_segment : Option < SegmentId > ,
364+
365+ /// For vector meshes, storing all the previous segments the last anchor point was connected to
366+ prior_segments : Option < Vec < SegmentId > > ,
364367 handle_type : TargetHandle ,
365368 handle_start_offset : Option < DVec2 > ,
366369 handle_end_offset : Option < DVec2 > ,
@@ -533,7 +536,15 @@ impl PenToolData {
533536 }
534537
535538 /// If the user places the anchor on top of the previous anchor, it becomes sharp and the outgoing handle may be dragged.
536- fn bend_from_previous_point ( & mut self , snap_data : SnapData , transform : DAffine2 , layer : LayerNodeIdentifier , preferences : & PreferencesMessageHandler ) {
539+ fn bend_from_previous_point (
540+ & mut self ,
541+ snap_data : SnapData ,
542+ transform : DAffine2 ,
543+ layer : LayerNodeIdentifier ,
544+ preferences : & PreferencesMessageHandler ,
545+ shape_editor : & mut ShapeState ,
546+ responses : & mut VecDeque < Message > ,
547+ ) {
537548 self . g1_continuous = true ;
538549 let document = snap_data. document ;
539550 self . next_handle_start = self . next_point ;
@@ -567,6 +578,43 @@ impl PenToolData {
567578 }
568579
569580 // Closing path
581+ let closing_path_on_point = self . close_path_on_point ( snap_data, & vector_data, document, preferences, id, & transform) ;
582+ if !closing_path_on_point && preferences. vector_meshes {
583+ // Attempt to find nearest segment and close path on segment by creating an anchor point on it
584+ let tolerance = crate :: consts:: SNAP_POINT_TOLERANCE ;
585+ if let Some ( closest_segment) = shape_editor. upper_closest_segment ( & document. network_interface , transform. transform_point2 ( self . next_point ) , tolerance) {
586+ let ( point, _) = closest_segment. adjusted_insert ( responses) ;
587+
588+ self . update_handle_type ( TargetHandle :: PreviewInHandle ) ;
589+ self . handle_end_offset = None ;
590+ self . path_closed = true ;
591+ self . next_handle_start = self . next_point ;
592+
593+ self . prior_segment_endpoint = Some ( point) ;
594+ self . prior_segment_layer = Some ( closest_segment. layer ( ) ) ;
595+ self . prior_segments = None ;
596+ self . prior_segment = None ;
597+
598+ // Should also update the SnapCache here?
599+
600+ self . handle_mode = HandleMode :: Free ;
601+ if let ( true , Some ( prior_endpoint) ) = ( self . modifiers . lock_angle , self . prior_segment_endpoint ) {
602+ self . set_lock_angle ( & vector_data, prior_endpoint, self . prior_segment ) ;
603+ self . switch_to_free_on_ctrl_release = true ;
604+ }
605+ }
606+ }
607+ }
608+
609+ fn close_path_on_point (
610+ & mut self ,
611+ snap_data : SnapData ,
612+ vector_data : & VectorData ,
613+ document : & DocumentMessageHandler ,
614+ preferences : & PreferencesMessageHandler ,
615+ id : PointId ,
616+ transform : & DAffine2 ,
617+ ) -> bool {
570618 for id in vector_data. extendable_points ( preferences. vector_meshes ) . filter ( |& point| point != id) {
571619 let Some ( pos) = vector_data. point_domain . position_from_id ( id) else { continue } ;
572620 let transformed_distance_between_squared = transform. transform_point2 ( pos) . distance_squared ( transform. transform_point2 ( self . next_point ) ) ;
@@ -577,14 +625,16 @@ impl PenToolData {
577625 self . handle_end_offset = None ;
578626 self . path_closed = true ;
579627 self . next_handle_start = self . next_point ;
580- self . store_clicked_endpoint ( document, & transform, snap_data. input , preferences) ;
628+ self . store_clicked_endpoint ( document, transform, snap_data. input , preferences) ;
581629 self . handle_mode = HandleMode :: Free ;
582630 if let ( true , Some ( prior_endpoint) ) = ( self . modifiers . lock_angle , self . prior_segment_endpoint ) {
583- self . set_lock_angle ( & vector_data, prior_endpoint, self . prior_segment ) ;
631+ self . set_lock_angle ( vector_data, prior_endpoint, self . prior_segment ) ;
584632 self . switch_to_free_on_ctrl_release = true ;
585633 }
634+ return true ;
586635 }
587636 }
637+ false
588638 }
589639
590640 fn finish_placing_handle ( & mut self , snap_data : SnapData , transform : DAffine2 , preferences : & PreferencesMessageHandler , responses : & mut VecDeque < Message > ) -> Option < PenToolFsmState > {
@@ -1122,6 +1172,7 @@ impl PenToolData {
11221172 transform. inverse ( ) . transform_point2 ( document_pos)
11231173 }
11241174
1175+ #[ allow( clippy:: too_many_arguments) ]
11251176 fn create_initial_point (
11261177 & mut self ,
11271178 document : & DocumentMessageHandler ,
@@ -1130,6 +1181,7 @@ impl PenToolData {
11301181 tool_options : & PenOptions ,
11311182 append : bool ,
11321183 preferences : & PreferencesMessageHandler ,
1184+ shape_editor : & mut ShapeState ,
11331185 ) {
11341186 let point = SnapCandidatePoint :: handle ( document. metadata ( ) . document_to_viewport . inverse ( ) . transform_point2 ( input. mouse . position ) ) ;
11351187 let snapped = self . snap_manager . free_snap ( & SnapData :: new ( document, input) , & point, SnapTypeConfiguration :: default ( ) ) ;
@@ -1145,6 +1197,20 @@ impl PenToolData {
11451197 self . current_layer = Some ( layer) ;
11461198 self . extend_existing_path ( document, layer, point, position) ;
11471199 return ;
1200+ } else if preferences. vector_meshes {
1201+ if let Some ( closest_segment) = shape_editor. upper_closest_segment ( & document. network_interface , viewport, tolerance) {
1202+ let ( point, segments) = closest_segment. adjusted_insert ( responses) ;
1203+ let layer = closest_segment. layer ( ) ;
1204+ let position = closest_segment. closest_point_document ( ) ;
1205+
1206+ // Setting any one of the new segments created as the previous segment
1207+ self . prior_segment_endpoint = Some ( point) ;
1208+ self . prior_segment_layer = Some ( layer) ;
1209+ self . prior_segments = Some ( segments. to_vec ( ) ) ;
1210+
1211+ self . extend_existing_path ( document, layer, point, position) ;
1212+ return ;
1213+ }
11481214 }
11491215
11501216 if append {
@@ -1186,6 +1252,7 @@ impl PenToolData {
11861252 tool_options. fill . apply_fill ( layer, responses) ;
11871253 tool_options. stroke . apply_stroke ( tool_options. line_weight , layer, responses) ;
11881254 self . prior_segment = None ;
1255+ self . prior_segments = None ;
11891256 responses. add ( NodeGraphMessage :: SelectedNodesSet { nodes : vec ! [ layer. to_node( ) ] } ) ;
11901257
11911258 // This causes the following message to be run only after the next graph evaluation runs and the transforms are updated
@@ -1266,6 +1333,7 @@ impl PenToolData {
12661333 self . prior_segment = None ;
12671334 self . prior_segment_endpoint = None ;
12681335 self . prior_segment_layer = None ;
1336+ self . prior_segments = None ;
12691337
12701338 if let Some ( ( layer, point, _position) ) = closest_point ( document, viewport, tolerance, document. metadata ( ) . all_layers ( ) , |_| false , preferences) {
12711339 self . prior_segment_endpoint = Some ( point) ;
@@ -1493,6 +1561,22 @@ impl Fsm for PenToolFsmState {
14931561 path_overlays ( document, DrawHandles :: None , shape_editor, & mut overlay_context) ;
14941562 }
14951563 }
1564+ // Check if there is an anchor within threshold
1565+ // If not check if there is a closest segment within threshold, if yes then draw overlay
1566+ let tolerance = crate :: consts:: SNAP_POINT_TOLERANCE ;
1567+ let point = SnapCandidatePoint :: handle ( document. metadata ( ) . document_to_viewport . inverse ( ) . transform_point2 ( input. mouse . position ) ) ;
1568+ let snapped = tool_data. snap_manager . free_snap ( & SnapData :: new ( document, input) , & point, SnapTypeConfiguration :: default ( ) ) ;
1569+ let viewport = document. metadata ( ) . document_to_viewport . transform_point2 ( snapped. snapped_point_document ) ;
1570+
1571+ let close_to_point = closest_point ( document, viewport, tolerance, document. metadata ( ) . all_layers ( ) , |_| false , preferences) . is_some ( ) ;
1572+ if preferences. vector_meshes && !close_to_point {
1573+ if let Some ( closest_segment) = shape_editor. upper_closest_segment ( & document. network_interface , viewport, tolerance) {
1574+ let pos = closest_segment. closest_point_to_viewport ( ) ;
1575+ let perp = closest_segment. calculate_perp ( document) ;
1576+ overlay_context. manipulator_anchor ( pos, true , None ) ;
1577+ overlay_context. line ( pos - perp * SEGMENT_OVERLAY_SIZE , pos + perp * SEGMENT_OVERLAY_SIZE , Some ( COLOR_OVERLAY_BLUE ) , None ) ;
1578+ }
1579+ }
14961580 tool_data. snap_manager . draw_overlays ( SnapData :: new ( document, input) , & mut overlay_context) ;
14971581 self
14981582 }
@@ -1530,13 +1614,20 @@ impl Fsm for PenToolFsmState {
15301614 // Draw the line between the currently-being-placed anchor and its currently-being-dragged-out outgoing handle (opposite the one currently being dragged out)
15311615 overlay_context. line ( next_anchor, next_handle_start, None , None ) ;
15321616 }
1617+
15331618 match tool_options. pen_overlay_mode {
15341619 PenOverlayMode :: AllHandles => {
15351620 path_overlays ( document, DrawHandles :: All , shape_editor, & mut overlay_context) ;
15361621 }
15371622 PenOverlayMode :: FrontierHandles => {
15381623 if let Some ( latest_segment) = tool_data. prior_segment {
15391624 path_overlays ( document, DrawHandles :: SelectedAnchors ( vec ! [ latest_segment] ) , shape_editor, & mut overlay_context) ;
1625+ }
1626+ // If a vector mesh then there can be more than one prior segments
1627+ else if let Some ( segments) = tool_data. prior_segments . clone ( ) {
1628+ if preferences. vector_meshes {
1629+ path_overlays ( document, DrawHandles :: SelectedAnchors ( segments) , shape_editor, & mut overlay_context) ;
1630+ }
15401631 } else {
15411632 path_overlays ( document, DrawHandles :: None , shape_editor, & mut overlay_context) ;
15421633 } ;
@@ -1598,6 +1689,22 @@ impl Fsm for PenToolFsmState {
15981689 overlay_context. manipulator_anchor ( next_anchor, false , None ) ;
15991690 }
16001691
1692+ if self == PenToolFsmState :: PlacingAnchor && preferences. vector_meshes {
1693+ let tolerance = crate :: consts:: SNAP_POINT_TOLERANCE ;
1694+ let point = SnapCandidatePoint :: handle ( document. metadata ( ) . document_to_viewport . inverse ( ) . transform_point2 ( input. mouse . position ) ) ;
1695+ let snapped = tool_data. snap_manager . free_snap ( & SnapData :: new ( document, input) , & point, SnapTypeConfiguration :: default ( ) ) ;
1696+ let viewport = document. metadata ( ) . document_to_viewport . transform_point2 ( snapped. snapped_point_document ) ;
1697+ let close_to_point = closest_point ( document, viewport, tolerance, document. metadata ( ) . all_layers ( ) , |_| false , preferences) . is_some ( ) ;
1698+ if !close_to_point {
1699+ if let Some ( closest_segment) = shape_editor. upper_closest_segment ( & document. network_interface , viewport, tolerance) {
1700+ let pos = closest_segment. closest_point_to_viewport ( ) ;
1701+ let perp = closest_segment. calculate_perp ( document) ;
1702+ overlay_context. manipulator_anchor ( pos, true , None ) ;
1703+ overlay_context. line ( pos - perp * SEGMENT_OVERLAY_SIZE , pos + perp * SEGMENT_OVERLAY_SIZE , Some ( COLOR_OVERLAY_BLUE ) , None ) ;
1704+ }
1705+ }
1706+ }
1707+
16011708 // Display a filled overlay of the shape if the new point closes the path
16021709 if let Some ( latest_point) = tool_data. latest_point ( ) {
16031710 let handle_start = latest_point. handle_start ;
@@ -1663,8 +1770,10 @@ impl Fsm for PenToolFsmState {
16631770 tool_data. handle_mode = HandleMode :: Free ;
16641771
16651772 // Get the closest point and the segment it is on
1773+ let append = input. keyboard . key ( append_to_selected) ;
1774+
16661775 tool_data. store_clicked_endpoint ( document, & transform, input, preferences) ;
1667- tool_data. create_initial_point ( document, input, responses, tool_options, input . keyboard . key ( append_to_selected ) , preferences) ;
1776+ tool_data. create_initial_point ( document, input, responses, tool_options, append , preferences, shape_editor ) ;
16681777
16691778 // Enter the dragging handle state while the mouse is held down, allowing the user to move the mouse and position the handle
16701779 PenToolFsmState :: DraggingHandle ( tool_data. handle_mode )
@@ -1688,7 +1797,7 @@ impl Fsm for PenToolFsmState {
16881797 if let Some ( layer) = layer {
16891798 tool_data. buffering_merged_vector = false ;
16901799 tool_data. handle_mode = HandleMode :: ColinearLocked ;
1691- tool_data. bend_from_previous_point ( SnapData :: new ( document, input) , transform, layer, preferences) ;
1800+ tool_data. bend_from_previous_point ( SnapData :: new ( document, input) , transform, layer, preferences, shape_editor , responses ) ;
16921801 tool_data. place_anchor ( SnapData :: new ( document, input) , transform, input. mouse . position , preferences, responses) ;
16931802 }
16941803 tool_data. buffering_merged_vector = false ;
0 commit comments