From f4e3e5ab2add67e2f5730bafadfe06d6d70e787b Mon Sep 17 00:00:00 2001 From: adamgerhant <116332429+adamgerhant@users.noreply.github.com> Date: Tue, 9 Jul 2024 05:16:50 -0700 Subject: [PATCH] Add draggable upstream nodes feature (#1812) * drag upstream nodes, fix node deselection * Ignore bottom layer inputs * Fix amplified movement --------- Co-authored-by: Keavon Chambers --- .../document/node_graph/node_graph_message.rs | 1 + .../node_graph/node_graph_message_handler.rs | 43 +++++++++++++++---- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message.rs index 446dd0eb..a8052f60 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message.rs @@ -67,6 +67,7 @@ pub enum NodeGraphMessage { MoveSelectedNodes { displacement_x: i32, displacement_y: i32, + move_upstream: bool, }, PasteNodes { serialized_nodes: String, diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs index 0334e4b6..5b9f2627 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs @@ -62,6 +62,9 @@ pub struct NodeGraphMessageHandler { pub node_metadata: HashMap, /// Cache for the bounding box around all nodes in node graph space. pub bounding_box_subpath: Option>, + /// Index of selected node to be deselected on pointer up when shift clicking an already selected node + pub deselect_on_pointer_up: Option, + /// 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> 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> for NodeGrap warn!("No network"); return; }; - for node_id in selected_nodes.selected_nodes(network).cloned().collect::>() { + let mut nodes_to_move = selected_nodes.selected_nodes(network).cloned().collect::>(); + 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> 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> 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> 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> 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(), } }