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 {
|
MoveSelectedNodes {
|
||||||
displacement_x: i32,
|
displacement_x: i32,
|
||||||
displacement_y: i32,
|
displacement_y: i32,
|
||||||
|
move_upstream: bool,
|
||||||
},
|
},
|
||||||
PasteNodes {
|
PasteNodes {
|
||||||
serialized_nodes: String,
|
serialized_nodes: String,
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,9 @@ pub struct NodeGraphMessageHandler {
|
||||||
pub node_metadata: HashMap<NodeId, NodeMetadata>,
|
pub node_metadata: HashMap<NodeId, NodeMetadata>,
|
||||||
/// Cache for the bounding box around all nodes in node graph space.
|
/// Cache for the bounding box around all nodes in node graph space.
|
||||||
pub bounding_box_subpath: Option<Subpath<PointId>>,
|
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,
|
auto_panning: AutoPanning,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -473,7 +476,11 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
|
||||||
responses.add(NodeGraphMessage::RunDocumentGraph);
|
responses.add(NodeGraphMessage::RunDocumentGraph);
|
||||||
responses.add(NodeGraphMessage::SendGraph);
|
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)) {
|
let network_path = if selected_nodes.selected_nodes_ref().iter().any(|node_id| document_network.nodes.contains_key(node_id)) {
|
||||||
Vec::new()
|
Vec::new()
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -484,7 +491,20 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
|
||||||
warn!("No network");
|
warn!("No network");
|
||||||
return;
|
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 {
|
if document_network.nested_network(&network_path).unwrap().exports_metadata.0 == node_id {
|
||||||
let network = document_network.nested_network_mut(&network_path).unwrap();
|
let network = document_network.nested_network_mut(&network_path).unwrap();
|
||||||
network.exports_metadata.1 += IVec2::new(displacement_x, displacement_y);
|
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;
|
modified_selected = true;
|
||||||
|
|
||||||
let index = updated_selected.iter().enumerate().find_map(|(i, node_id)| if *node_id == clicked_id { Some(i) } else { None });
|
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
|
// Remove from selection (on PointerUp) if already selected
|
||||||
if let Some(index) = index {
|
self.deselect_on_pointer_up = index;
|
||||||
updated_selected.remove(index);
|
|
||||||
}
|
|
||||||
// Add to selection if not already selected. Necessary in order to drag multiple nodes
|
// Add to selection if not already selected. Necessary in order to drag multiple nodes
|
||||||
else {
|
if index.is_none() {
|
||||||
updated_selected.push(clicked_id);
|
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));
|
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 } => {
|
NodeGraphMessage::PointerMove { shift } => {
|
||||||
let Some(network) = document_network.nested_network(&self.network) else {
|
let Some(network) = document_network.nested_network(&self.network) else {
|
||||||
return;
|
return;
|
||||||
|
|
@ -899,6 +917,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
|
||||||
responses.add(NodeGraphMessage::MoveSelectedNodes {
|
responses.add(NodeGraphMessage::MoveSelectedNodes {
|
||||||
displacement_x: graph_delta.x - drag_start.round_x,
|
displacement_x: graph_delta.x - drag_start.round_x,
|
||||||
displacement_y: graph_delta.y - drag_start.round_y,
|
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_x = graph_delta.x;
|
||||||
drag_start.round_y = graph_delta.y;
|
drag_start.round_y = graph_delta.y;
|
||||||
|
|
@ -943,6 +962,13 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
|
||||||
warn!("No network");
|
warn!("No network");
|
||||||
return;
|
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
|
// Disconnect if the wire was previously connected to an input
|
||||||
let viewport_location = ipp.mouse.position;
|
let viewport_location = ipp.mouse.position;
|
||||||
let point = node_graph_to_viewport.inverse().transform_point2(viewport_location);
|
let point = node_graph_to_viewport.inverse().transform_point2(viewport_location);
|
||||||
|
|
@ -2792,6 +2818,7 @@ impl Default for NodeGraphMessageHandler {
|
||||||
context_menu: None,
|
context_menu: None,
|
||||||
node_metadata: HashMap::new(),
|
node_metadata: HashMap::new(),
|
||||||
bounding_box_subpath: None,
|
bounding_box_subpath: None,
|
||||||
|
deselect_on_pointer_up: None,
|
||||||
auto_panning: Default::default(),
|
auto_panning: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue