Add mitigation for inability to connect graph import directly to export by auto-inserting a Passthrough node (#3449)

insert passthrough
This commit is contained in:
Adam Gerhant 2025-12-07 11:19:55 -08:00 committed by GitHub
parent 9fc98cf03f
commit bba771bd08
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 55 additions and 28 deletions

View file

@ -203,8 +203,30 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
}
NodeGraphMessage::CreateWire { output_connector, input_connector } => {
// TODO: Add support for flattening NodeInput::Import exports in flatten_with_fns https://github.com/GraphiteEditor/Graphite/issues/1762
if matches!(input_connector, InputConnector::Export(_)) && matches!(output_connector, OutputConnector::Import { .. }) {
// We return early for now until this case becomes supported, then we can remove this
if let (InputConnector::Export(_), OutputConnector::Import(_)) = (input_connector, output_connector) {
let mid_point = (network_interface.get_output_center(&output_connector, breadcrumb_network_path).unwrap()
+ network_interface.get_input_center(&input_connector, breadcrumb_network_path).unwrap())
/ 2.;
let node_template = Box::new(document_node_definitions::resolve_document_node_type("Passthrough").unwrap().default_node_template());
let node_id = NodeId::new();
responses.add(NodeGraphMessage::InsertNode { node_id, node_template });
responses.add(NodeGraphMessage::ShiftNodePosition {
node_id,
x: (mid_point.x / 24.) as i32,
y: (mid_point.y / 24.) as i32,
});
let node_input_connector = InputConnector::node(node_id, 0);
let node_output_connector = OutputConnector::node(node_id, 0);
responses.add(NodeGraphMessage::CreateWire {
output_connector,
input_connector: node_input_connector,
});
responses.add(NodeGraphMessage::CreateWire {
output_connector: node_output_connector,
input_connector,
});
return;
}
network_interface.create_wire(&output_connector, &input_connector, selection_network_path);
@ -745,7 +767,6 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphMessageContext<'a>> for NodeG
let clicked_input = network_interface.input_connector_from_click(click, selection_network_path);
let clicked_output = network_interface.output_connector_from_click(click, selection_network_path);
let network_metadata = network_interface.network_metadata(selection_network_path).unwrap();
// Create the add node popup on right click, then exit
if right_click {
// Abort dragging a node

View file

@ -2704,15 +2704,23 @@ impl NodeNetworkInterface {
log::error!("Could not get nested network_metadata in collect_frontend_click_targets");
return FrontendClickTargets::default();
};
network_metadata.persistent_metadata.node_metadata.keys().copied().collect::<Vec<_>>().into_iter().for_each(|node_id| {
if let (Some(import_export_click_targets), Some(node_click_targets)) = (self.import_export_ports(network_path).cloned(), self.node_click_targets(&node_id, network_path)) {
let nodes = network_metadata.persistent_metadata.node_metadata.keys().copied().collect::<Vec<_>>();
if let Some(import_export_click_targets) = self.import_export_ports(network_path).cloned() {
for port in import_export_click_targets.click_targets() {
if let ClickTargetType::Subpath(subpath) = port.target_type() {
connector_click_targets.push(subpath.to_bezpath().to_svg());
}
}
}
nodes.into_iter().for_each(|node_id| {
if let Some(node_click_targets) = self.node_click_targets(&node_id, network_path) {
let mut node_path = String::new();
if let ClickTargetType::Subpath(subpath) = node_click_targets.node_click_target.target_type() {
node_path.push_str(subpath.to_bezpath().to_svg().as_str())
}
all_node_click_targets.push((node_id, node_path));
for port in node_click_targets.port_click_targets.click_targets().chain(import_export_click_targets.click_targets()) {
for port in node_click_targets.port_click_targets.click_targets() {
if let ClickTargetType::Subpath(subpath) = port.target_type() {
connector_click_targets.push(subpath.to_bezpath().to_svg());
}
@ -2879,19 +2887,18 @@ impl NodeNetworkInterface {
.collect::<Vec<_>>()
.iter()
.filter_map(|node_id| {
self.node_click_targets(node_id, network_path)
.and_then(|transient_node_metadata| {
transient_node_metadata
.port_click_targets
.clicked_input_port_from_point(point)
.map(|port| InputConnector::node(*node_id, port))
})
.or_else(|| {
self.import_export_ports(network_path)
.and_then(|import_export_ports| import_export_ports.clicked_input_port_from_point(point).map(InputConnector::Export))
})
self.node_click_targets(node_id, network_path).and_then(|transient_node_metadata| {
transient_node_metadata
.port_click_targets
.clicked_input_port_from_point(point)
.map(|port| InputConnector::node(*node_id, port))
})
})
.next()
.or_else(|| {
self.import_export_ports(network_path)
.and_then(|import_export_ports| import_export_ports.clicked_input_port_from_point(point).map(InputConnector::Export))
})
}
pub fn output_connector_from_click(&mut self, click: DVec2, network_path: &[NodeId]) -> Option<OutputConnector> {
@ -2909,19 +2916,18 @@ impl NodeNetworkInterface {
nodes
.iter()
.filter_map(|node_id| {
self.node_click_targets(node_id, network_path)
.and_then(|transient_node_metadata| {
transient_node_metadata
.port_click_targets
.clicked_output_port_from_point(point)
.map(|output_index| OutputConnector::node(*node_id, output_index))
})
.or_else(|| {
self.import_export_ports(network_path)
.and_then(|import_export_ports| import_export_ports.clicked_output_port_from_point(point).map(OutputConnector::Import))
})
self.node_click_targets(node_id, network_path).and_then(|transient_node_metadata| {
transient_node_metadata
.port_click_targets
.clicked_output_port_from_point(point)
.map(|output_index| OutputConnector::node(*node_id, output_index))
})
})
.next()
.or_else(|| {
self.import_export_ports(network_path)
.and_then(|import_export_ports| import_export_ports.clicked_output_port_from_point(point).map(OutputConnector::Import))
})
}
pub fn input_position(&mut self, input_connector: &InputConnector, network_path: &[NodeId]) -> Option<DVec2> {