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>
This commit is contained in:
adamgerhant 2024-07-09 05:16:50 -07:00 committed by GitHub
parent 62f73df048
commit f4e3e5ab2a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 36 additions and 8 deletions

View File

@ -67,6 +67,7 @@ pub enum NodeGraphMessage {
MoveSelectedNodes {
displacement_x: i32,
displacement_y: i32,
move_upstream: bool,
},
PasteNodes {
serialized_nodes: String,

View File

@ -62,6 +62,9 @@ pub struct NodeGraphMessageHandler {
pub node_metadata: HashMap<NodeId, NodeMetadata>,
/// Cache for the bounding box around all nodes in node graph space.
pub bounding_box_subpath: Option<Subpath<PointId>>,
/// Index of selected node to be deselected on pointer up when shift clicking an already selected node
pub deselect_on_pointer_up: Option<usize>,
/// Adds the auto panning functionality to the node graph when dragging a node or selection box to the edge of the viewport.
auto_panning: AutoPanning,
}
@ -473,7 +476,11 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
responses.add(NodeGraphMessage::RunDocumentGraph);
responses.add(NodeGraphMessage::SendGraph);
}
NodeGraphMessage::MoveSelectedNodes { displacement_x, displacement_y } => {
NodeGraphMessage::MoveSelectedNodes {
displacement_x,
displacement_y,
move_upstream,
} => {
let network_path = if selected_nodes.selected_nodes_ref().iter().any(|node_id| document_network.nodes.contains_key(node_id)) {
Vec::new()
} else {
@ -484,7 +491,20 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
warn!("No network");
return;
};
for node_id in selected_nodes.selected_nodes(network).cloned().collect::<Vec<_>>() {
let mut nodes_to_move = selected_nodes.selected_nodes(network).cloned().collect::<HashSet<_>>();
if move_upstream {
for selected_node_id in selected_nodes.selected_nodes(network) {
let Some(selected_node) = network.nodes.get(selected_node_id) else {
log::error!("Could not get selected node from network");
continue;
};
// Only drag nodes that are children of the selected layer
if let Some(NodeInput::Node { node_id, .. }) = selected_node.inputs.get(1) {
nodes_to_move.extend(network.upstream_flow_back_from_nodes(vec![*node_id], FlowType::UpstreamFlow).map(|(_, node_id)| node_id))
};
}
}
for node_id in nodes_to_move {
if document_network.nested_network(&network_path).unwrap().exports_metadata.0 == node_id {
let network = document_network.nested_network_mut(&network_path).unwrap();
network.exports_metadata.1 += IVec2::new(displacement_x, displacement_y);
@ -761,12 +781,11 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
modified_selected = true;
let index = updated_selected.iter().enumerate().find_map(|(i, node_id)| if *node_id == clicked_id { Some(i) } else { None });
// Remove from selection if already selected
if let Some(index) = index {
updated_selected.remove(index);
}
// Remove from selection (on PointerUp) if already selected
self.deselect_on_pointer_up = index;
// Add to selection if not already selected. Necessary in order to drag multiple nodes
else {
if index.is_none() {
updated_selected.push(clicked_id);
};
}
@ -807,7 +826,6 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
}
self.box_selection_start = Some(UVec2::new(viewport_location.x.round().abs() as u32, viewport_location.y.round().abs() as u32));
}
// TODO: Alt+drag should move all upstream nodes as well
NodeGraphMessage::PointerMove { shift } => {
let Some(network) = document_network.nested_network(&self.network) else {
return;
@ -899,6 +917,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
responses.add(NodeGraphMessage::MoveSelectedNodes {
displacement_x: graph_delta.x - drag_start.round_x,
displacement_y: graph_delta.y - drag_start.round_y,
move_upstream: ipp.keyboard.get(shift as usize),
});
drag_start.round_x = graph_delta.x;
drag_start.round_y = graph_delta.y;
@ -943,6 +962,13 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
warn!("No network");
return;
};
if let Some(node_to_deselect) = self.deselect_on_pointer_up {
let mut new_selected_nodes = selected_nodes.selected_nodes_ref().clone();
new_selected_nodes.remove(node_to_deselect);
responses.add(NodeGraphMessage::SelectedNodesSet { nodes: new_selected_nodes });
self.deselect_on_pointer_up = None;
}
// Disconnect if the wire was previously connected to an input
let viewport_location = ipp.mouse.position;
let point = node_graph_to_viewport.inverse().transform_point2(viewport_location);
@ -2792,6 +2818,7 @@ impl Default for NodeGraphMessageHandler {
context_menu: None,
node_metadata: HashMap::new(),
bounding_box_subpath: None,
deselect_on_pointer_up: None,
auto_panning: Default::default(),
}
}