From aecb0f5031678c6b9ba73579802f3ca261fb3360 Mon Sep 17 00:00:00 2001 From: setzer22 Date: Sun, 29 May 2022 18:35:30 +0200 Subject: [PATCH 1/3] Send disconnect event on node delete --- egui_node_graph/src/editor_ui.rs | 12 +++++++++++- egui_node_graph/src/graph_impls.rs | 12 +++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/egui_node_graph/src/editor_ui.rs b/egui_node_graph/src/editor_ui.rs index 5a725cb..e2b949c 100644 --- a/egui_node_graph/src/editor_ui.rs +++ b/egui_node_graph/src/editor_ui.rs @@ -168,6 +168,10 @@ where /* Handle responses from drawing nodes */ + // Some responses generate additional responses when processed. These + // are stored here to report them back to the user. + let mut extra_responses : Vec> = Vec::new(); + for response in delayed_responses.iter().copied() { match response { NodeResponse::ConnectEventStarted(node_id, port) => { @@ -199,7 +203,8 @@ where self.selected_node = Some(node_id); } NodeResponse::DeleteNode(node_id) => { - self.graph.remove_node(node_id); + let (ins, _) = self.graph.remove_node(node_id); + extra_responses.extend(ins.into_iter().map(NodeResponse::DisconnectEvent)); self.node_positions.remove(node_id); // Make sure to not leave references to old nodes hanging if self.selected_node.map(|x| x == node_id).unwrap_or(false) { @@ -232,6 +237,11 @@ where } } + // Push any responses that were generated during response handling. + // These are only informative for the end-user and need no special + // treatment here. + delayed_responses.extend(extra_responses); + /* Mouse input handling */ // This locks the context, so don't hold on to it for too long. diff --git a/egui_node_graph/src/graph_impls.rs b/egui_node_graph/src/graph_impls.rs index 7f898a6..42cd96e 100644 --- a/egui_node_graph/src/graph_impls.rs +++ b/egui_node_graph/src/graph_impls.rs @@ -63,18 +63,20 @@ impl Graph { output_id } - pub fn remove_node(&mut self, node_id: NodeId) { + /// Returns the list of input and output ids that were disconnected. + pub fn remove_node(&mut self, node_id: NodeId) -> (SVec, SVec) { self.connections .retain(|i, o| !(self.outputs[*o].node == node_id || self.inputs[i].node == node_id)); let inputs: SVec<_> = self[node_id].input_ids().collect(); - for input in inputs { - self.inputs.remove(input); + for input in &inputs { + self.inputs.remove(*input); } let outputs: SVec<_> = self[node_id].output_ids().collect(); - for output in outputs { - self.outputs.remove(output); + for output in &outputs { + self.outputs.remove(*output); } self.nodes.remove(node_id); + (inputs, outputs) } pub fn remove_connection(&mut self, input_id: InputId) -> Option { From 2ca80217877bc576f3bb67b44940bc6e732abc8c Mon Sep 17 00:00:00 2001 From: setzer22 Date: Sun, 29 May 2022 18:37:39 +0200 Subject: [PATCH 2/3] Cargo fmt --- egui_node_graph/src/editor_ui.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/egui_node_graph/src/editor_ui.rs b/egui_node_graph/src/editor_ui.rs index e2b949c..4896b04 100644 --- a/egui_node_graph/src/editor_ui.rs +++ b/egui_node_graph/src/editor_ui.rs @@ -170,7 +170,7 @@ where // Some responses generate additional responses when processed. These // are stored here to report them back to the user. - let mut extra_responses : Vec> = Vec::new(); + let mut extra_responses: Vec> = Vec::new(); for response in delayed_responses.iter().copied() { match response { From 7204ac79c5c6e05fd0e121c96c459d59ecd8743d Mon Sep 17 00:00:00 2001 From: Setzer22 Date: Tue, 7 Jun 2022 21:44:51 +0200 Subject: [PATCH 3/3] Address review comments --- egui_node_graph/src/editor_ui.rs | 10 ++++++-- egui_node_graph/src/graph_impls.rs | 38 +++++++++++++++++++++--------- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/egui_node_graph/src/editor_ui.rs b/egui_node_graph/src/editor_ui.rs index 4896b04..03bb537 100644 --- a/egui_node_graph/src/editor_ui.rs +++ b/egui_node_graph/src/editor_ui.rs @@ -203,8 +203,14 @@ where self.selected_node = Some(node_id); } NodeResponse::DeleteNode(node_id) => { - let (ins, _) = self.graph.remove_node(node_id); - extra_responses.extend(ins.into_iter().map(NodeResponse::DisconnectEvent)); + let removed = self.graph.remove_node(node_id); + extra_responses.extend( + removed + .into_iter() + .map(|x| x.0) + .into_iter() + .map(NodeResponse::DisconnectEvent), + ); self.node_positions.remove(node_id); // Make sure to not leave references to old nodes hanging if self.selected_node.map(|x| x == node_id).unwrap_or(false) { diff --git a/egui_node_graph/src/graph_impls.rs b/egui_node_graph/src/graph_impls.rs index 42cd96e..9c26881 100644 --- a/egui_node_graph/src/graph_impls.rs +++ b/egui_node_graph/src/graph_impls.rs @@ -63,20 +63,36 @@ impl Graph { output_id } - /// Returns the list of input and output ids that were disconnected. - pub fn remove_node(&mut self, node_id: NodeId) -> (SVec, SVec) { - self.connections - .retain(|i, o| !(self.outputs[*o].node == node_id || self.inputs[i].node == node_id)); - let inputs: SVec<_> = self[node_id].input_ids().collect(); - for input in &inputs { - self.inputs.remove(*input); + /// Removes a node from the graph with given `node_id`. This also removes + /// any incoming or outgoing connections from that node + /// + /// This function returns the list of connections that has been removed + /// after deleting this node as input-output pairs. Note that one of the two + /// ids in the pair (the one on `node_id`'s end) will be invalid after + /// calling this function. + pub fn remove_node(&mut self, node_id: NodeId) -> Vec<(InputId, OutputId)> { + let mut disconnect_events = vec![]; + + self.connections.retain(|i, o| { + if self.outputs[*o].node == node_id || self.inputs[i].node == node_id { + disconnect_events.push((i, *o)); + false + } else { + true + } + }); + + // NOTE: Collect is needed because we can't borrow the input ids while + // we remove them inside the loop. + for input in self[node_id].input_ids().collect::>() { + self.inputs.remove(input); } - let outputs: SVec<_> = self[node_id].output_ids().collect(); - for output in &outputs { - self.outputs.remove(*output); + for output in self[node_id].output_ids().collect::>() { + self.outputs.remove(output); } self.nodes.remove(node_id); - (inputs, outputs) + + disconnect_events } pub fn remove_connection(&mut self, input_id: InputId) -> Option {