11use super :: tool_prelude:: * ;
2- use crate :: consts:: { DEFAULT_STROKE_WIDTH , LINE_ROTATE_SNAP_ANGLE } ;
2+ use crate :: consts:: { BOUNDS_SELECT_THRESHOLD , DEFAULT_STROKE_WIDTH , LINE_ROTATE_SNAP_ANGLE } ;
33use crate :: messages:: portfolio:: document:: node_graph:: document_node_definitions:: resolve_document_node_type;
44use crate :: messages:: portfolio:: document:: overlays:: utility_types:: OverlayContext ;
55use crate :: messages:: portfolio:: document:: utility_types:: { document_metadata:: LayerNodeIdentifier , network_interface:: InputConnector } ;
66use crate :: messages:: tool:: common_functionality:: auto_panning:: AutoPanning ;
77use crate :: messages:: tool:: common_functionality:: color_selector:: { ToolColorOptions , ToolColorType } ;
8- use crate :: messages:: tool:: common_functionality:: graph_modification_utils;
8+ use crate :: messages:: tool:: common_functionality:: graph_modification_utils:: { self , NodeGraphLayer } ;
99use crate :: messages:: tool:: common_functionality:: snapping:: { SnapCandidatePoint , SnapConstraint , SnapData , SnapManager , SnapTypeConfiguration } ;
1010
1111use graph_craft:: document:: { value:: TaggedValue , NodeId , NodeInput } ;
@@ -142,15 +142,23 @@ enum LineToolFsmState {
142142 Drawing ,
143143}
144144
145+ #[ derive( Clone , Copy , Debug , PartialEq , Eq ) ]
146+ enum LineEnd {
147+ Start ,
148+ End ,
149+ }
150+
145151#[ derive( Clone , Debug , Default ) ]
146152struct LineToolData {
147153 drag_start : DVec2 ,
148154 drag_current : DVec2 ,
149155 angle : f64 ,
150156 weight : f64 ,
151- layer : Option < LayerNodeIdentifier > ,
157+ selected_layers_with_position : HashMap < LayerNodeIdentifier , [ DVec2 ; 2 ] > ,
158+ editing_layer : Option < LayerNodeIdentifier > ,
152159 snap_manager : SnapManager ,
153160 auto_panning : AutoPanning ,
161+ dragging_endpoint : Option < LineEnd > ,
154162}
155163
156164impl Fsm for LineToolFsmState {
@@ -166,13 +174,58 @@ impl Fsm for LineToolFsmState {
166174 match ( self , event) {
167175 ( _, LineToolMessage :: Overlays ( mut overlay_context) ) => {
168176 tool_data. snap_manager . draw_overlays ( SnapData :: new ( document, input) , & mut overlay_context) ;
177+
178+ tool_data. selected_layers_with_position = document
179+ . network_interface
180+ . selected_nodes ( & [ ] )
181+ . unwrap ( )
182+ . selected_visible_and_unlocked_layers ( & document. network_interface )
183+ . filter_map ( |layer| {
184+ let node_inputs = NodeGraphLayer :: new ( layer, & document. network_interface ) . find_node_inputs ( "Line" ) ?;
185+
186+ let ( Some ( & TaggedValue :: DVec2 ( start) ) , Some ( & TaggedValue :: DVec2 ( end) ) ) = ( node_inputs[ 1 ] . as_value ( ) , node_inputs[ 2 ] . as_value ( ) ) else {
187+ return None ;
188+ } ;
189+
190+ let [ viewport_start, viewport_end] = [ start, end] . map ( |point| document. metadata ( ) . transform_to_viewport ( layer) . transform_point2 ( point) ) ;
191+ if ( start. x - end. x ) . abs ( ) > f64:: EPSILON * 1000. && ( start. y - end. y ) . abs ( ) > f64:: EPSILON * 1000. {
192+ overlay_context. line ( viewport_start, viewport_end, None ) ;
193+ overlay_context. square ( viewport_start, Some ( 6. ) , None , None ) ;
194+ overlay_context. square ( viewport_end, Some ( 6. ) , None , None ) ;
195+ }
196+
197+ Some ( ( layer, [ start, end] ) )
198+ } )
199+ . collect :: < HashMap < LayerNodeIdentifier , [ DVec2 ; 2 ] > > ( ) ;
200+
169201 self
170202 }
171203 ( LineToolFsmState :: Ready , LineToolMessage :: DragStart ) => {
172204 let point = SnapCandidatePoint :: handle ( document. metadata ( ) . document_to_viewport . inverse ( ) . transform_point2 ( input. mouse . position ) ) ;
173205 let snapped = tool_data. snap_manager . free_snap ( & SnapData :: new ( document, input) , & point, SnapTypeConfiguration :: default ( ) ) ;
174206 tool_data. drag_start = snapped. snapped_point_document ;
175207
208+ for ( layer, [ document_start, document_end] ) in tool_data. selected_layers_with_position . iter ( ) {
209+ let transform = document. metadata ( ) . transform_to_viewport ( * layer) ;
210+ let viewport_x = transform. transform_vector2 ( DVec2 :: X ) . normalize_or_zero ( ) * BOUNDS_SELECT_THRESHOLD ;
211+ let viewport_y = transform. transform_vector2 ( DVec2 :: Y ) . normalize_or_zero ( ) * BOUNDS_SELECT_THRESHOLD ;
212+ let threshold_x = transform. inverse ( ) . transform_vector2 ( viewport_x) . length ( ) ;
213+ let threshold_y = transform. inverse ( ) . transform_vector2 ( viewport_y) . length ( ) ;
214+
215+ let drag_start = input. mouse . position ;
216+ let [ start, end] = [ document_start, document_end] . map ( |point| transform. transform_point2 ( * point) ) ;
217+
218+ let start_click = ( drag_start. y - start. y ) . abs ( ) < threshold_y && ( drag_start. x - start. x ) . abs ( ) < threshold_x;
219+ let end_click = ( drag_start. y - end. y ) . abs ( ) < threshold_y && ( drag_start. x - end. x ) . abs ( ) < threshold_x;
220+
221+ if start_click || end_click {
222+ tool_data. dragging_endpoint = Some ( if end_click { LineEnd :: End } else { LineEnd :: Start } ) ;
223+ tool_data. drag_start = if end_click { * document_start } else { * document_end } ;
224+ tool_data. editing_layer = Some ( * layer) ;
225+ return LineToolFsmState :: Drawing ;
226+ }
227+ }
228+
176229 responses. add ( DocumentMessage :: StartTransaction ) ;
177230
178231 let node_type = resolve_document_node_type ( "Line" ) . expect ( "Line node does not exist" ) ;
@@ -194,19 +247,39 @@ impl Fsm for LineToolFsmState {
194247
195248 tool_options. stroke . apply_stroke ( tool_options. line_weight , layer, responses) ;
196249
197- tool_data. layer = Some ( layer) ;
250+ tool_data. editing_layer = Some ( layer) ;
198251 tool_data. angle = 0. ;
199252 tool_data. weight = tool_options. line_weight ;
200253
201254 LineToolFsmState :: Drawing
202255 }
203256 ( LineToolFsmState :: Drawing , LineToolMessage :: PointerMove { center, snap_angle, lock_angle } ) => {
204- tool_data. drag_current = input. mouse . position ; // tool_data.snap_manager.snap_position(responses, document, input.mouse.position);
257+ let Some ( layer) = tool_data. editing_layer else { return LineToolFsmState :: Ready } ;
258+
259+ tool_data. drag_current = document. metadata ( ) . transform_to_viewport ( layer) . inverse ( ) . transform_point2 ( input. mouse . position ) ;
205260
206261 let keyboard = & input. keyboard ;
207- let ignore = if let Some ( layer ) = tool_data . layer { vec ! [ layer] } else { vec ! [ ] } ;
262+ let ignore = vec ! [ layer] ;
208263 let snap_data = SnapData :: ignore ( document, input, & ignore) ;
209- generate_line ( tool_data, snap_data, keyboard. key ( lock_angle) , keyboard. key ( snap_angle) , keyboard. key ( center) , responses) ;
264+ let mut document_points = generate_line ( tool_data, snap_data, keyboard. key ( lock_angle) , keyboard. key ( snap_angle) , keyboard. key ( center) ) ;
265+
266+ if tool_data. dragging_endpoint == Some ( LineEnd :: Start ) {
267+ document_points. swap ( 0 , 1 ) ;
268+ }
269+
270+ let Some ( node_id) = graph_modification_utils:: get_line_id ( layer, & document. network_interface ) else {
271+ return LineToolFsmState :: Ready ;
272+ } ;
273+
274+ responses. add ( NodeGraphMessage :: SetInput {
275+ input_connector : InputConnector :: node ( node_id, 1 ) ,
276+ input : NodeInput :: value ( TaggedValue :: DVec2 ( document_points[ 0 ] ) , false ) ,
277+ } ) ;
278+ responses. add ( NodeGraphMessage :: SetInput {
279+ input_connector : InputConnector :: node ( node_id, 2 ) ,
280+ input : NodeInput :: value ( TaggedValue :: DVec2 ( document_points[ 1 ] ) , false ) ,
281+ } ) ;
282+ responses. add ( NodeGraphMessage :: RunDocumentGraph ) ;
210283
211284 // Auto-panning
212285 let messages = [
@@ -240,14 +313,16 @@ impl Fsm for LineToolFsmState {
240313 }
241314 ( LineToolFsmState :: Drawing , LineToolMessage :: DragStop ) => {
242315 tool_data. snap_manager . cleanup ( responses) ;
316+ tool_data. editing_layer . take ( ) ;
243317 input. mouse . finish_transaction ( tool_data. drag_start , responses) ;
244- tool_data. layer = None ;
245318 LineToolFsmState :: Ready
246319 }
247320 ( LineToolFsmState :: Drawing , LineToolMessage :: Abort ) => {
248321 tool_data. snap_manager . cleanup ( responses) ;
249- responses. add ( DocumentMessage :: AbortTransaction ) ;
250- tool_data. layer = None ;
322+ tool_data. editing_layer . take ( ) ;
323+ if tool_data. dragging_endpoint . is_none ( ) {
324+ responses. add ( DocumentMessage :: AbortTransaction ) ;
325+ }
251326 LineToolFsmState :: Ready
252327 }
253328 ( _, LineToolMessage :: WorkingColorChanged ) => {
@@ -287,9 +362,8 @@ impl Fsm for LineToolFsmState {
287362 }
288363}
289364
290- fn generate_line ( tool_data : & mut LineToolData , snap_data : SnapData , lock_angle : bool , snap_angle : bool , center : bool , responses : & mut VecDeque < Message > ) {
291- let document_to_viewport = snap_data. document . metadata ( ) . document_to_viewport ;
292- let mut document_points = [ tool_data. drag_start , document_to_viewport. inverse ( ) . transform_point2 ( tool_data. drag_current ) ] ;
365+ fn generate_line ( tool_data : & mut LineToolData , snap_data : SnapData , lock_angle : bool , snap_angle : bool , center : bool ) -> [ DVec2 ; 2 ] {
366+ let mut document_points = [ tool_data. drag_start , tool_data. drag_current ] ;
293367
294368 let mut angle = -( document_points[ 1 ] - document_points[ 0 ] ) . angle_to ( DVec2 :: X ) ;
295369 let mut line_length = ( document_points[ 1 ] - document_points[ 0 ] ) . length ( ) ;
@@ -347,18 +421,5 @@ fn generate_line(tool_data: &mut LineToolData, snap_data: SnapData, lock_angle:
347421 snap. update_indicator ( snapped) ;
348422 }
349423
350- let Some ( node_id) = graph_modification_utils:: get_line_id ( tool_data. layer . unwrap ( ) , & snap_data. document . network_interface ) else {
351- return ;
352- } ;
353-
354- responses. add ( NodeGraphMessage :: SetInput {
355- input_connector : InputConnector :: node ( node_id, 1 ) ,
356- input : NodeInput :: value ( TaggedValue :: DVec2 ( document_points[ 0 ] ) , false ) ,
357- } ) ;
358- responses. add ( NodeGraphMessage :: SetInput {
359- input_connector : InputConnector :: node ( node_id, 2 ) ,
360- input : NodeInput :: value ( TaggedValue :: DVec2 ( document_points[ 1 ] ) , false ) ,
361- } ) ;
362-
363- responses. add ( NodeGraphMessage :: RunDocumentGraph ) ;
424+ document_points
364425}
0 commit comments