@@ -52,10 +52,12 @@ enum ConnectionStyle {DIRECT, BEZIER, ROUNDED, MANHATTAN, DIAGONAL}
5252var connection_line_style : int = ConnectionStyle .BEZIER
5353
5454@onready var drag_cut_cursor = preload ("res://material_maker/icons/knife.png" )
55- var connections_to_cut : Array [Dictionary ]
56- var drag_cut_line : PackedVector2Array
57- var valid_drag_cut_entry : bool = false
58- const CURSOR_HOT_SPOT : Vector2 = Vector2 (1.02 , 17.34 )
55+ @onready var drag_reroute_cursor = preload ("res://material_maker/icons/cross.png" )
56+ const DRAG_CUT_CURSOR_HOT_SPOT : Vector2 = Vector2 (1.02 , 17.34 )
57+
58+ var drag_line : PackedVector2Array
59+ enum DragLineGesture {CUT , REROUTE , NONE }
60+ var drag_line_mode : int = DragLineGesture .NONE
5961
6062var lasso_points : PackedVector2Array
6163
@@ -71,7 +73,7 @@ func _ready() -> void:
7173 for t in range (41 ):
7274 add_valid_connection_type (t , 42 )
7375 add_valid_connection_type (42 , t )
74- node_popup .about_to_popup .connect (func (): valid_drag_cut_entry = false )
76+ node_popup .about_to_popup .connect (func (): drag_line_mode = DragLineGesture . NONE )
7577
7678func _exit_tree ():
7779 remove_crash_recovery_file ()
@@ -163,22 +165,45 @@ func _gui_input(event) -> void:
163165 accept_event ()
164166 node_popup .position = Vector2i (get_screen_transform ()* get_local_mouse_position ())
165167 node_popup .show_popup ()
166- elif event .is_action_released ("ui_cut_drag" ):
167- var conns : Array [Dictionary ]
168- for p in len (drag_cut_line ) - 1 :
169- var rect : Rect2
170- rect .position = drag_cut_line [p ]
171- rect .end = drag_cut_line [p + 1 ]
172- conns = get_connections_intersecting_with_rect (rect .abs ())
173- if conns .size ():
174- connections_to_cut .append_array (conns )
175- if connections_to_cut .size ():
176- on_cut_connections (connections_to_cut )
177- connections_to_cut .clear ()
178- Input .set_custom_mouse_cursor (null )
179- drag_cut_line .clear ()
180- conns .clear ()
181- queue_redraw ()
168+ elif event .is_action_released ("ui_cut_drag" ) or event .is_action_released ("ui_reroute_drag" ):
169+ match drag_line_mode :
170+ DragLineGesture .CUT :
171+ var connections_to_cut : Array [Dictionary ]
172+ var links : Array [Dictionary ]
173+ for p in len (drag_line ) - 1 :
174+ var rect : Rect2
175+ rect .position = drag_line [p ]
176+ rect .end = drag_line [p + 1 ]
177+ links = get_connections_intersecting_with_rect (rect .abs ())
178+ if links .size ():
179+ connections_to_cut .append_array (links )
180+ if connections_to_cut .size ():
181+ on_cut_connections (connections_to_cut )
182+ connections_to_cut .clear ()
183+ Input .set_custom_mouse_cursor (null )
184+ drag_line .clear ()
185+ links .clear ()
186+ queue_redraw ()
187+ DragLineGesture .REROUTE :
188+ if drag_line .size () >= 2 :
189+ var drag_reroute_line := Curve2D .new ()
190+ for p : Vector2 in drag_line :
191+ drag_reroute_line .add_point (p )
192+ var points := drag_reroute_line .tessellate_even_length (5 , connection_lines_thickness )
193+ var target_connections : Array [Dictionary ]
194+ for p : Vector2 in points :
195+ var link := get_closest_connection_at_point (p , connection_lines_thickness )
196+ if not link .is_empty () and target_connections .find_custom (func (d ):
197+ return (d .from_node == link .from_node and d .from_port == link .from_port
198+ and d .to_node == link .to_node and d .to_port == link .to_port )) == - 1 :
199+ link .position = p
200+ target_connections .append (link )
201+ if target_connections .size ():
202+ on_reroute_connections (target_connections )
203+ target_connections .clear ()
204+ Input .set_custom_mouse_cursor (null )
205+ drag_line .clear ()
206+ queue_redraw ()
182207 elif event .is_action_released ("ui_lasso_select" , true ):
183208 for node in get_children ():
184209 if node is GraphElement :
@@ -219,7 +244,7 @@ func _gui_input(event) -> void:
219244 event .control = true
220245 do_zoom (1.0 / 1.1 )
221246 elif event .button_index == MOUSE_BUTTON_RIGHT and event .is_pressed ():
222- valid_drag_cut_entry = true
247+ drag_line_mode = DragLineGesture . CUT
223248 if event .shift_pressed :
224249 add_reroute_under_mouse ()
225250
@@ -319,14 +344,24 @@ func _gui_input(event) -> void:
319344 if rect .has_point (get_global_mouse_position ()):
320345 mm_globals .set_tip_text ("Space/#RMB: Nodes menu, Arrow keys: Pan, Mouse wheel: Zoom" , 3 )
321346
322- if (event .button_mask & MOUSE_BUTTON_MASK_RIGHT ) != 0 and valid_drag_cut_entry :
323- if event .ctrl_pressed :
324- Input .set_custom_mouse_cursor (
325- drag_cut_cursor , Input .CURSOR_ARROW , CURSOR_HOT_SPOT )
326- drag_cut_line .append (get_local_mouse_position ())
347+ # drag line gesture (cut/reroute)
348+ if (event .button_mask & MOUSE_BUTTON_MASK_RIGHT ) != 0 :
349+ if drag_line_mode != DragLineGesture .NONE :
350+ drag_line .append (get_local_mouse_position ())
327351 queue_redraw ()
328- elif drag_cut_line .size ():
329- drag_cut_line .append (get_local_mouse_position ())
352+ if event .ctrl_pressed :
353+ drag_line_mode = DragLineGesture .CUT
354+ Input .set_custom_mouse_cursor (drag_cut_cursor ,
355+ Input .CURSOR_ARROW , DRAG_CUT_CURSOR_HOT_SPOT )
356+ elif event .shift_pressed :
357+ drag_line_mode = DragLineGesture .REROUTE
358+ Input .set_custom_mouse_cursor (drag_reroute_cursor ,
359+ Input .CURSOR_ARROW , drag_reroute_cursor .get_size () * 0.5 )
360+ else :
361+ drag_line_mode = DragLineGesture .NONE
362+ Input .set_custom_mouse_cursor (null )
363+ if drag_line .size ():
364+ drag_line .clear ()
330365 queue_redraw ()
331366
332367 # lasso selection
@@ -347,8 +382,8 @@ func get_padded_node_rect(graph_node:GraphNode) -> Rect2:
347382 return Rect2 (rect .position , rect .size )
348383
349384func _draw () -> void :
350- if drag_cut_line .size () > 1 :
351- draw_polyline (drag_cut_line , get_theme_color ("connection_knife " , "GraphEdit" ), 1.0 )
385+ if drag_line .size () > 1 :
386+ draw_polyline (drag_line , get_theme_color ("line_gesture " , "GraphEdit" ), 1.0 )
352387 if lasso_points .size () > 1 :
353388 draw_polyline (lasso_points + PackedVector2Array ([lasso_points [0 ]]),
354389 get_theme_color ("lasso_stroke" , "GraphEdit" ), 1.0 )
@@ -471,6 +506,40 @@ func do_disconnect_node(from : String, from_slot : int, to : String, to_slot : i
471506 return true
472507 return false
473508
509+ func on_reroute_connections (target_connections : Array [Dictionary ]) -> void :
510+ var prev : Dictionary = generator .serialize ()
511+ var grouped_connections : Dictionary [String , Array ]
512+
513+ # group connections by their source node/port
514+ for link : Dictionary in target_connections :
515+ var key := "%s _%d " % [link .from_node , link .from_port ]
516+ if not grouped_connections .has (key ):
517+ grouped_connections [key ] = []
518+ grouped_connections [key ].append (link )
519+
520+ for group : String in grouped_connections :
521+ # find connection group center
522+ var group_rect := Rect2 (grouped_connections [group ][0 ].position , Vector2 .ZERO )
523+ for group_link : Dictionary in grouped_connections [group ]:
524+ group_rect = group_rect .expand (group_link .position )
525+ var group_center := (group_rect .abs ().get_center () + scroll_offset ) / zoom
526+
527+ # create reroute node
528+ var reroute : Array = await do_create_nodes ({nodes = [{name = "reroute" , type = "reroute" ,
529+ node_position = {x = group_center .x , y = group_center .y }}], connections = []})
530+ var group_reroute : GraphNode = reroute [0 ]
531+ group_reroute .position_offset -= group_reroute .size * 0.5
532+
533+ # reroute connections
534+ for link : Dictionary in grouped_connections [group ]:
535+ do_disconnect_node (link .from_node , link .from_port , link .to_node , link .to_port )
536+ do_connect_node (link .from_node , link .from_port , group_reroute .name , 0 )
537+ do_connect_node (group_reroute .name , 0 , link .to_node , link .to_port )
538+
539+ # undo/redo
540+ var next : Dictionary = generator .serialize ()
541+ undoredo_create_step ("Reroute multiple connections" , generator .get_hier_name (), prev , next )
542+
474543func on_cut_connections (connections_to_be_cut : Array ):
475544 var generator_hier_name : String = generator .get_hier_name ()
476545 var conns : Array = []
@@ -487,7 +556,6 @@ func on_cut_connections(connections_to_be_cut : Array):
487556 ]
488557 undoredo .add ("Cut node connections" , undo_actions , redo_actions )
489558
490-
491559func on_disconnect_node (from : String , from_slot : int , to : String , to_slot : int ) -> void :
492560 var from_gen = get_node (from ).generator
493561 var to_gen = get_node (to ).generator
0 commit comments