Skip to content

Commit f4e3e5a

Browse files
adamgerhantKeavon
andauthored
Add draggable upstream nodes feature (#1812)
* drag upstream nodes, fix node deselection * Ignore bottom layer inputs * Fix amplified movement --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
1 parent 62f73df commit f4e3e5a

File tree

2 files changed

+36
-8
lines changed

2 files changed

+36
-8
lines changed

editor/src/messages/portfolio/document/node_graph/node_graph_message.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ pub enum NodeGraphMessage {
6767
MoveSelectedNodes {
6868
displacement_x: i32,
6969
displacement_y: i32,
70+
move_upstream: bool,
7071
},
7172
PasteNodes {
7273
serialized_nodes: String,

editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ pub struct NodeGraphMessageHandler {
6262
pub node_metadata: HashMap<NodeId, NodeMetadata>,
6363
/// Cache for the bounding box around all nodes in node graph space.
6464
pub bounding_box_subpath: Option<Subpath<PointId>>,
65+
/// Index of selected node to be deselected on pointer up when shift clicking an already selected node
66+
pub deselect_on_pointer_up: Option<usize>,
67+
/// Adds the auto panning functionality to the node graph when dragging a node or selection box to the edge of the viewport.
6568
auto_panning: AutoPanning,
6669
}
6770

@@ -473,7 +476,11 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
473476
responses.add(NodeGraphMessage::RunDocumentGraph);
474477
responses.add(NodeGraphMessage::SendGraph);
475478
}
476-
NodeGraphMessage::MoveSelectedNodes { displacement_x, displacement_y } => {
479+
NodeGraphMessage::MoveSelectedNodes {
480+
displacement_x,
481+
displacement_y,
482+
move_upstream,
483+
} => {
477484
let network_path = if selected_nodes.selected_nodes_ref().iter().any(|node_id| document_network.nodes.contains_key(node_id)) {
478485
Vec::new()
479486
} else {
@@ -484,7 +491,20 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
484491
warn!("No network");
485492
return;
486493
};
487-
for node_id in selected_nodes.selected_nodes(network).cloned().collect::<Vec<_>>() {
494+
let mut nodes_to_move = selected_nodes.selected_nodes(network).cloned().collect::<HashSet<_>>();
495+
if move_upstream {
496+
for selected_node_id in selected_nodes.selected_nodes(network) {
497+
let Some(selected_node) = network.nodes.get(selected_node_id) else {
498+
log::error!("Could not get selected node from network");
499+
continue;
500+
};
501+
// Only drag nodes that are children of the selected layer
502+
if let Some(NodeInput::Node { node_id, .. }) = selected_node.inputs.get(1) {
503+
nodes_to_move.extend(network.upstream_flow_back_from_nodes(vec![*node_id], FlowType::UpstreamFlow).map(|(_, node_id)| node_id))
504+
};
505+
}
506+
}
507+
for node_id in nodes_to_move {
488508
if document_network.nested_network(&network_path).unwrap().exports_metadata.0 == node_id {
489509
let network = document_network.nested_network_mut(&network_path).unwrap();
490510
network.exports_metadata.1 += IVec2::new(displacement_x, displacement_y);
@@ -761,12 +781,11 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
761781
modified_selected = true;
762782

763783
let index = updated_selected.iter().enumerate().find_map(|(i, node_id)| if *node_id == clicked_id { Some(i) } else { None });
764-
// Remove from selection if already selected
765-
if let Some(index) = index {
766-
updated_selected.remove(index);
767-
}
784+
// Remove from selection (on PointerUp) if already selected
785+
self.deselect_on_pointer_up = index;
786+
768787
// Add to selection if not already selected. Necessary in order to drag multiple nodes
769-
else {
788+
if index.is_none() {
770789
updated_selected.push(clicked_id);
771790
};
772791
}
@@ -807,7 +826,6 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
807826
}
808827
self.box_selection_start = Some(UVec2::new(viewport_location.x.round().abs() as u32, viewport_location.y.round().abs() as u32));
809828
}
810-
// TODO: Alt+drag should move all upstream nodes as well
811829
NodeGraphMessage::PointerMove { shift } => {
812830
let Some(network) = document_network.nested_network(&self.network) else {
813831
return;
@@ -899,6 +917,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
899917
responses.add(NodeGraphMessage::MoveSelectedNodes {
900918
displacement_x: graph_delta.x - drag_start.round_x,
901919
displacement_y: graph_delta.y - drag_start.round_y,
920+
move_upstream: ipp.keyboard.get(shift as usize),
902921
});
903922
drag_start.round_x = graph_delta.x;
904923
drag_start.round_y = graph_delta.y;
@@ -943,6 +962,13 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
943962
warn!("No network");
944963
return;
945964
};
965+
if let Some(node_to_deselect) = self.deselect_on_pointer_up {
966+
let mut new_selected_nodes = selected_nodes.selected_nodes_ref().clone();
967+
new_selected_nodes.remove(node_to_deselect);
968+
responses.add(NodeGraphMessage::SelectedNodesSet { nodes: new_selected_nodes });
969+
self.deselect_on_pointer_up = None;
970+
}
971+
946972
// Disconnect if the wire was previously connected to an input
947973
let viewport_location = ipp.mouse.position;
948974
let point = node_graph_to_viewport.inverse().transform_point2(viewport_location);
@@ -2792,6 +2818,7 @@ impl Default for NodeGraphMessageHandler {
27922818
context_menu: None,
27932819
node_metadata: HashMap::new(),
27942820
bounding_box_subpath: None,
2821+
deselect_on_pointer_up: None,
27952822
auto_panning: Default::default(),
27962823
}
27972824
}

0 commit comments

Comments
 (0)