@@ -10,7 +10,7 @@ use crate::messages::portfolio::document::node_graph::utility_types::{ContextMen
10
10
use crate :: messages:: portfolio:: document:: utility_types:: document_metadata:: LayerNodeIdentifier ;
11
11
use crate :: messages:: portfolio:: document:: utility_types:: misc:: GroupFolderType ;
12
12
use crate :: messages:: portfolio:: document:: utility_types:: network_interface:: {
13
- self , InputConnector , NodeNetworkInterface , NodeTemplate , NodeTypePersistentMetadata , OutputConnector , Previewing , TypeSource ,
13
+ self , FlowType , InputConnector , NodeNetworkInterface , NodeTemplate , NodeTypePersistentMetadata , OutputConnector , Previewing , TypeSource ,
14
14
} ;
15
15
use crate :: messages:: portfolio:: document:: utility_types:: nodes:: { CollapsedLayers , LayerPanelEntry } ;
16
16
use crate :: messages:: portfolio:: document:: utility_types:: wires:: { GraphWireStyle , WirePath , WirePathUpdate , build_vector_wire} ;
@@ -56,6 +56,8 @@ pub struct NodeGraphMessageHandler {
56
56
/// If dragging the selected nodes, this stores the starting position both in viewport and node graph coordinates,
57
57
/// plus a flag indicating if it has been dragged since the mousedown began.
58
58
pub drag_start : Option < ( DragStart , bool ) > ,
59
+ // Store the selected chain nodes on drag start so they can be reconnected if shaken
60
+ pub drag_start_chain_nodes : Vec < NodeId > ,
59
61
/// If dragging the background to create a box selection, this stores its starting point in node graph coordinates,
60
62
/// plus a flag indicating if it has been dragged since the mousedown began.
61
63
box_selection_start : Option < ( DVec2 , bool ) > ,
@@ -601,6 +603,9 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
601
603
NodeGraphMessage :: MoveNodeToChainStart { node_id, parent } => {
602
604
network_interface. move_node_to_chain_start ( & node_id, parent, selection_network_path) ;
603
605
}
606
+ NodeGraphMessage :: SetChainPosition { node_id } => {
607
+ network_interface. set_chain_position ( & node_id, selection_network_path) ;
608
+ }
604
609
NodeGraphMessage :: PasteNodes { serialized_nodes } => {
605
610
let data = match serde_json:: from_str :: < Vec < ( NodeId , NodeTemplate ) > > ( & serialized_nodes) {
606
611
Ok ( d) => d,
@@ -854,6 +859,20 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
854
859
} ;
855
860
856
861
self . drag_start = Some ( ( drag_start, false ) ) ;
862
+ let selected_chain_nodes = updated_selected
863
+ . iter ( )
864
+ . filter ( |node_id| network_interface. is_chain ( node_id, selection_network_path) )
865
+ . copied ( )
866
+ . collect :: < Vec < _ > > ( ) ;
867
+ self . drag_start_chain_nodes = selected_chain_nodes
868
+ . iter ( )
869
+ . flat_map ( |selected| {
870
+ network_interface
871
+ . upstream_flow_back_from_nodes ( vec ! [ * selected] , selection_network_path, FlowType :: PrimaryFlow )
872
+ . skip ( 1 )
873
+ . filter ( |node_id| network_interface. is_chain ( node_id, selection_network_path) )
874
+ } )
875
+ . collect :: < Vec < _ > > ( ) ;
857
876
self . begin_dragging = true ;
858
877
self . node_has_moved_in_drag = false ;
859
878
self . update_node_graph_hints ( responses) ;
@@ -1221,6 +1240,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
1221
1240
{
1222
1241
return None ;
1223
1242
}
1243
+ log:: debug!( "preferences.graph_wire_style: {:?}" , preferences. graph_wire_style) ;
1224
1244
let ( wire, is_stack) = network_interface. vector_wire_from_input ( & input, preferences. graph_wire_style , selection_network_path) ?;
1225
1245
wire. rectangle_intersections_exist ( bounding_box[ 0 ] , bounding_box[ 1 ] ) . then_some ( ( input, is_stack) )
1226
1246
} )
@@ -1303,6 +1323,135 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
1303
1323
self . auto_panning . stop ( & messages, responses) ;
1304
1324
}
1305
1325
}
1326
+ NodeGraphMessage :: ShakeNode => {
1327
+ let Some ( drag_start) = & self . drag_start else {
1328
+ log:: error!( "Drag start should be initialized when shaking a node" ) ;
1329
+ return ;
1330
+ } ;
1331
+
1332
+ let Some ( network_metadata) = network_interface. network_metadata ( selection_network_path) else {
1333
+ return ;
1334
+ } ;
1335
+
1336
+ let viewport_location = ipp. mouse . position ;
1337
+ let point = network_metadata
1338
+ . persistent_metadata
1339
+ . navigation_metadata
1340
+ . node_graph_to_viewport
1341
+ . inverse ( )
1342
+ . transform_point2 ( viewport_location) ;
1343
+
1344
+ // Collect the distance to move the shaken nodes after the undo
1345
+ let graph_delta = IVec2 :: new ( ( ( point. x - drag_start. 0 . start_x ) / 24. ) . round ( ) as i32 , ( ( point. y - drag_start. 0 . start_y ) / 24. ) . round ( ) as i32 ) ;
1346
+
1347
+ // Undo to the state of the graph before shaking
1348
+ responses. add ( DocumentMessage :: AbortTransaction ) ;
1349
+
1350
+ // Add a history step to abort to the state before shaking if right clicked
1351
+ responses. add ( DocumentMessage :: StartTransaction ) ;
1352
+
1353
+ let Some ( selected_nodes) = network_interface. selected_nodes_in_nested_network ( selection_network_path) else {
1354
+ log:: error!( "Could not get selected nodes in ShakeNode" ) ;
1355
+ return ;
1356
+ } ;
1357
+
1358
+ let mut all_selected_nodes = selected_nodes. 0 . iter ( ) . copied ( ) . collect :: < HashSet < _ > > ( ) ;
1359
+ for selected_layer in selected_nodes
1360
+ . 0
1361
+ . iter ( )
1362
+ . filter ( |selected_node| network_interface. is_layer ( selected_node, selection_network_path) )
1363
+ . copied ( )
1364
+ . collect :: < Vec < _ > > ( )
1365
+ {
1366
+ for sole_dependent in network_interface. upstream_nodes_below_layer ( & selected_layer, selection_network_path) {
1367
+ all_selected_nodes. insert ( sole_dependent) ;
1368
+ }
1369
+ }
1370
+
1371
+ for selected_node in & all_selected_nodes {
1372
+ // Handle inputs of selected node
1373
+ for input_index in 0 ..network_interface. number_of_inputs ( selected_node, selection_network_path) {
1374
+ let input_connector = InputConnector :: node ( * selected_node, input_index) ;
1375
+ // Only disconnect inputs to non selected nodes
1376
+ if network_interface
1377
+ . upstream_output_connector ( & input_connector, selection_network_path)
1378
+ . and_then ( |connector| connector. node_id ( ) )
1379
+ . is_some_and ( |node_id| !all_selected_nodes. contains ( & node_id) )
1380
+ {
1381
+ responses. add ( NodeGraphMessage :: DisconnectInput { input_connector } ) ;
1382
+ }
1383
+ }
1384
+
1385
+ let number_of_outputs = network_interface. number_of_outputs ( selected_node, selection_network_path) ;
1386
+ let first_deselected_upstream_node = network_interface
1387
+ . upstream_flow_back_from_nodes ( vec ! [ * selected_node] , selection_network_path, FlowType :: PrimaryFlow )
1388
+ . find ( |upstream_node| !all_selected_nodes. contains ( upstream_node) ) ;
1389
+ let Some ( outward_wires) = network_interface. outward_wires ( selection_network_path) else {
1390
+ log:: error!( "Could not get output wires in shake input" ) ;
1391
+ continue ;
1392
+ } ;
1393
+
1394
+ // Disconnect output wires to non selected nodes
1395
+ for output_index in 0 ..number_of_outputs {
1396
+ let output_connector = OutputConnector :: node ( * selected_node, output_index) ;
1397
+ if let Some ( downstream_connections) = outward_wires. get ( & output_connector) {
1398
+ for & input_connector in downstream_connections {
1399
+ if input_connector. node_id ( ) . is_some_and ( |downstream_node| !all_selected_nodes. contains ( & downstream_node) ) {
1400
+ responses. add ( NodeGraphMessage :: DisconnectInput { input_connector } ) ;
1401
+ }
1402
+ }
1403
+ }
1404
+ }
1405
+
1406
+ // Handle reconnection
1407
+ // Find first non selected upstream node by primary flow
1408
+ if let Some ( first_deselected_upstream_node) = first_deselected_upstream_node {
1409
+ let Some ( downstream_connections_to_first_output) = outward_wires. get ( & OutputConnector :: node ( * selected_node, 0 ) ) . cloned ( ) else {
1410
+ log:: error!( "Could not get downstream_connections_to_first_output in shake node" ) ;
1411
+ return ;
1412
+ } ;
1413
+ // Reconnect only if all downstream outputs are not selected
1414
+ if !downstream_connections_to_first_output
1415
+ . iter ( )
1416
+ . any ( |connector| connector. node_id ( ) . is_some_and ( |node_id| all_selected_nodes. contains ( & node_id) ) )
1417
+ {
1418
+ // Find what output on the deselected upstream node to reconnect to
1419
+ for output_index in 0 ..network_interface. number_of_outputs ( & first_deselected_upstream_node, selection_network_path) {
1420
+ let output_connector = & OutputConnector :: node ( first_deselected_upstream_node, output_index) ;
1421
+ let Some ( outward_wires) = network_interface. outward_wires ( selection_network_path) else {
1422
+ log:: error!( "Could not get output wires in shake input" ) ;
1423
+ continue ;
1424
+ } ;
1425
+ if let Some ( inputs) = outward_wires. get ( output_connector) {
1426
+ // This can only run once
1427
+ if inputs. iter ( ) . any ( |input_connector| {
1428
+ input_connector
1429
+ . node_id ( )
1430
+ . is_some_and ( |upstream_node| all_selected_nodes. contains ( & upstream_node) && input_connector. input_index ( ) == 0 )
1431
+ } ) {
1432
+ // Output index is the output of the deselected upstream node to reconnect to
1433
+ for downstream_connections_to_first_output in & downstream_connections_to_first_output {
1434
+ responses. add ( NodeGraphMessage :: CreateWire {
1435
+ output_connector : OutputConnector :: node ( first_deselected_upstream_node, output_index) ,
1436
+ input_connector : * downstream_connections_to_first_output,
1437
+ } ) ;
1438
+ }
1439
+ }
1440
+ }
1441
+
1442
+ // Set all chain nodes back to chain position
1443
+ // TODO: Fix
1444
+ // for chain_node_to_reset in std::mem::take(&mut self.drag_start_chain_nodes) {
1445
+ // responses.add(NodeGraphMessage::SetChainPosition { node_id: chain_node_to_reset });
1446
+ // }
1447
+ }
1448
+ }
1449
+ }
1450
+ }
1451
+ responses. add ( NodeGraphMessage :: ShiftSelectedNodesByAmount { graph_delta, rubber_band : false } ) ;
1452
+ responses. add ( NodeGraphMessage :: RunDocumentGraph ) ;
1453
+ responses. add ( NodeGraphMessage :: SendGraph ) ;
1454
+ }
1306
1455
NodeGraphMessage :: RemoveImport { import_index : usize } => {
1307
1456
network_interface. remove_import ( usize, selection_network_path) ;
1308
1457
responses. add ( NodeGraphMessage :: SendGraph ) ;
@@ -1823,6 +1972,12 @@ impl NodeGraphMessageHandler {
1823
1972
) ) ;
1824
1973
}
1825
1974
1975
+ if self . drag_start . is_some ( ) {
1976
+ common. extend ( actions ! ( NodeGraphMessageDiscriminant ;
1977
+ ShakeNode ,
1978
+ ) ) ;
1979
+ }
1980
+
1826
1981
common
1827
1982
}
1828
1983
@@ -2597,6 +2752,7 @@ impl Default for NodeGraphMessageHandler {
2597
2752
node_has_moved_in_drag : false ,
2598
2753
shift_without_push : false ,
2599
2754
box_selection_start : None ,
2755
+ drag_start_chain_nodes : Vec :: new ( ) ,
2600
2756
selection_before_pointer_down : Vec :: new ( ) ,
2601
2757
disconnecting : None ,
2602
2758
initial_disconnecting : false ,
0 commit comments