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:
parent
62f73df048
commit
f4e3e5ab2a
|
|
@ -67,6 +67,7 @@ pub enum NodeGraphMessage {
|
|||
MoveSelectedNodes {
|
||||
displacement_x: i32,
|
||||
displacement_y: i32,
|
||||
move_upstream: bool,
|
||||
},
|
||||
PasteNodes {
|
||||
serialized_nodes: String,
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue