Skip to content

Commit 9297b83

Browse files
committed
Add imports/exports
1 parent bbca6a2 commit 9297b83

File tree

7 files changed

+258
-13
lines changed

7 files changed

+258
-13
lines changed

editor/src/messages/frontend/frontend_message.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,10 @@ pub enum FrontendMessage {
126126
UpdateImportsExports {
127127
imports: Vec<(FrontendGraphOutput, i32, i32)>,
128128
exports: Vec<(FrontendGraphInput, i32, i32)>,
129+
#[serde(rename = "addImport")]
130+
add_import: (i32, i32),
131+
#[serde(rename = "addExport")]
132+
add_export: (i32, i32),
129133
},
130134
UpdateInSelectedNetwork {
131135
#[serde(rename = "inSelectedNetwork")]

editor/src/messages/portfolio/document/document_message_handler.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1227,11 +1227,36 @@ impl MessageHandler<DocumentMessage, DocumentMessageData<'_>> for DocumentMessag
12271227
self.network_interface.set_transform(transform, &self.breadcrumb_network_path);
12281228
let imports = self.network_interface.frontend_imports(&self.breadcrumb_network_path).unwrap_or_default();
12291229
let exports = self.network_interface.frontend_exports(&self.breadcrumb_network_path).unwrap_or_default();
1230+
let add_import = self
1231+
.network_interface
1232+
.modify_import_export(&self.breadcrumb_network_path)
1233+
.and_then(|modify_import_export_click_target| {
1234+
modify_import_export_click_target
1235+
.add_import
1236+
.bounding_box()
1237+
.map(|bounding_box| (bounding_box[0].x as i32, bounding_box[0].y as i32))
1238+
})
1239+
.unwrap_or((0, 0));
1240+
let add_export = self
1241+
.network_interface
1242+
.modify_import_export(&self.breadcrumb_network_path)
1243+
.and_then(|modify_import_export_click_target| {
1244+
modify_import_export_click_target
1245+
.add_export
1246+
.bounding_box()
1247+
.map(|bounding_box| (bounding_box[0].x as i32, bounding_box[0].y as i32))
1248+
})
1249+
.unwrap_or((0, 0));
12301250
responses.add(DocumentMessage::RenderRulers);
12311251
responses.add(DocumentMessage::RenderScrollbars);
12321252
responses.add(NodeGraphMessage::UpdateEdges);
12331253
responses.add(NodeGraphMessage::UpdateBoxSelection);
1234-
responses.add(FrontendMessage::UpdateImportsExports { imports, exports });
1254+
responses.add(FrontendMessage::UpdateImportsExports {
1255+
imports,
1256+
exports,
1257+
add_import,
1258+
add_export,
1259+
});
12351260
responses.add(FrontendMessage::UpdateNodeGraphTransform {
12361261
transform: Transform {
12371262
scale: transform.matrix2.x_axis.x,

editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,23 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
545545

546546
let node_graph_point = network_metadata.persistent_metadata.navigation_metadata.node_graph_to_viewport.inverse().transform_point2(click);
547547

548+
let Some(modify_import_export) = network_interface.modify_import_export(selection_network_path) else {
549+
log::error!("Could not get modify import export in PointerDown");
550+
return;
551+
};
552+
553+
if modify_import_export.add_export.intersect_point_no_stroke(node_graph_point) {
554+
responses.add(DocumentMessage::AddTransaction);
555+
responses.add(NodeGraphMessage::AddExport);
556+
responses.add(NodeGraphMessage::SendGraph);
557+
return;
558+
} else if modify_import_export.add_import.intersect_point_no_stroke(node_graph_point) {
559+
responses.add(DocumentMessage::AddTransaction);
560+
responses.add(NodeGraphMessage::AddImport);
561+
responses.add(NodeGraphMessage::SendGraph);
562+
return;
563+
}
564+
548565
if network_interface
549566
.layer_click_target_from_click(click, network_interface::LayerClickTargetTypes::Grip, selection_network_path)
550567
.is_some()
@@ -1201,7 +1218,30 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
12011218
let (layer_widths, chain_widths) = network_interface.collect_layer_widths(breadcrumb_network_path);
12021219
let imports = network_interface.frontend_imports(breadcrumb_network_path).unwrap_or_default();
12031220
let exports = network_interface.frontend_exports(breadcrumb_network_path).unwrap_or_default();
1204-
responses.add(FrontendMessage::UpdateImportsExports { imports, exports });
1221+
let add_import = network_interface
1222+
.modify_import_export(breadcrumb_network_path)
1223+
.and_then(|modify_import_export_click_target| {
1224+
modify_import_export_click_target
1225+
.add_import
1226+
.bounding_box()
1227+
.map(|bounding_box| (bounding_box[0].x as i32, bounding_box[0].y as i32))
1228+
})
1229+
.unwrap_or((0, 0));
1230+
let add_export = network_interface
1231+
.modify_import_export(breadcrumb_network_path)
1232+
.and_then(|modify_import_export_click_target| {
1233+
modify_import_export_click_target
1234+
.add_export
1235+
.bounding_box()
1236+
.map(|bounding_box| (bounding_box[0].x as i32, bounding_box[0].y as i32))
1237+
})
1238+
.unwrap_or((0, 0));
1239+
responses.add(FrontendMessage::UpdateImportsExports {
1240+
imports,
1241+
exports,
1242+
add_import,
1243+
add_export,
1244+
});
12051245
responses.add(FrontendMessage::UpdateNodeGraph { nodes, wires });
12061246
responses.add(FrontendMessage::UpdateLayerWidths { layer_widths, chain_widths });
12071247
responses.add(NodeGraphMessage::SendSelectedNodes);
@@ -1213,7 +1253,30 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
12131253
// Send the new edges to the frontend
12141254
let imports = network_interface.frontend_imports(breadcrumb_network_path).unwrap_or_default();
12151255
let exports = network_interface.frontend_exports(breadcrumb_network_path).unwrap_or_default();
1216-
responses.add(FrontendMessage::UpdateImportsExports { imports, exports });
1256+
let add_import = network_interface
1257+
.modify_import_export(breadcrumb_network_path)
1258+
.and_then(|modify_import_export_click_target| {
1259+
modify_import_export_click_target
1260+
.add_import
1261+
.bounding_box()
1262+
.map(|bounding_box| (bounding_box[0].x as i32, bounding_box[0].y as i32))
1263+
})
1264+
.unwrap_or((0, 0));
1265+
let add_export = network_interface
1266+
.modify_import_export(breadcrumb_network_path)
1267+
.and_then(|modify_import_export_click_target| {
1268+
modify_import_export_click_target
1269+
.add_export
1270+
.bounding_box()
1271+
.map(|bounding_box| (bounding_box[0].x as i32, bounding_box[0].y as i32))
1272+
})
1273+
.unwrap_or((0, 0));
1274+
responses.add(FrontendMessage::UpdateImportsExports {
1275+
imports,
1276+
exports,
1277+
add_import,
1278+
add_export,
1279+
});
12171280
}
12181281
}
12191282
NodeGraphMessage::SetInputValue { node_id, input_index, value } => {

editor/src/messages/portfolio/document/utility_types/network_interface.rs

Lines changed: 137 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ impl NodeNetworkInterface {
256256
encapsulating_node.inputs.len()
257257
} else {
258258
// There is one(?) import to the document network, but the imports are not displayed
259+
// I think this is zero now that the scope system has been added
259260
1
260261
}
261262
}
@@ -1896,6 +1897,109 @@ impl NodeNetworkInterface {
18961897
network_metadata.transient_metadata.import_export_ports.unload();
18971898
}
18981899

1900+
pub fn modify_import_export(&mut self, network_path: &[NodeId]) -> Option<&ModifyImportExportClickTarget> {
1901+
let Some(network_metadata) = self.network_metadata(network_path) else {
1902+
log::error!("Could not get nested network_metadata in modify_import_export");
1903+
return None;
1904+
};
1905+
if !network_metadata.transient_metadata.modify_import_export.is_loaded() {
1906+
self.load_modify_import_export(network_path);
1907+
}
1908+
let Some(network_metadata) = self.network_metadata(network_path) else {
1909+
log::error!("Could not get nested network_metadata in modify_import_export");
1910+
return None;
1911+
};
1912+
let TransientMetadata::Loaded(click_targets) = &network_metadata.transient_metadata.modify_import_export else {
1913+
log::error!("could not load modify import export ports");
1914+
return None;
1915+
};
1916+
Some(click_targets)
1917+
}
1918+
1919+
pub fn load_modify_import_export(&mut self, network_path: &[NodeId]) {
1920+
let Some(all_nodes_bounding_box) = self.all_nodes_bounding_box(network_path).cloned() else {
1921+
log::error!("Could not get all nodes bounding box in load_export_ports");
1922+
return;
1923+
};
1924+
let Some(rounded_network_edge_distance) = self.rounded_network_edge_distance(network_path).cloned() else {
1925+
log::error!("Could not get rounded_network_edge_distance in load_export_ports");
1926+
return;
1927+
};
1928+
let Some(network_metadata) = self.network_metadata(network_path) else {
1929+
log::error!("Could not get nested network_metadata in load_export_ports");
1930+
return;
1931+
};
1932+
let Some(network) = self.network(network_path) else {
1933+
log::error!("Could not get current network in load_export_ports");
1934+
return;
1935+
};
1936+
1937+
let viewport_top_right = network_metadata
1938+
.persistent_metadata
1939+
.navigation_metadata
1940+
.node_graph_to_viewport
1941+
.inverse()
1942+
.transform_point2(rounded_network_edge_distance.exports_to_edge_distance);
1943+
let offset_from_top_right = if network
1944+
.exports
1945+
.first()
1946+
.is_some_and(|export| export.as_node().is_some_and(|export_node| self.is_layer(&export_node, network_path)))
1947+
{
1948+
DVec2::new(2. * GRID_SIZE as f64, -2. * GRID_SIZE as f64)
1949+
} else {
1950+
DVec2::new(4. * GRID_SIZE as f64, 0.)
1951+
};
1952+
1953+
let bounding_box_top_right = DVec2::new((all_nodes_bounding_box[1].x / 24. + 0.5).floor() * 24., (all_nodes_bounding_box[0].y / 24. + 0.5).floor() * 24.) + offset_from_top_right;
1954+
let export_top_right = DVec2::new(viewport_top_right.x.max(bounding_box_top_right.x), viewport_top_right.y.min(bounding_box_top_right.y));
1955+
let add_export_center = export_top_right + DVec2::new(0., network.exports.len() as f64 * 24.);
1956+
let add_export = ClickTarget::new(Subpath::new_ellipse(add_export_center - DVec2::new(8., 8.), add_export_center + DVec2::new(8., 8.)), 0.);
1957+
1958+
let viewport_top_left = network_metadata
1959+
.persistent_metadata
1960+
.navigation_metadata
1961+
.node_graph_to_viewport
1962+
.inverse()
1963+
.transform_point2(rounded_network_edge_distance.imports_to_edge_distance);
1964+
1965+
let offset_from_top_left = if network
1966+
.exports
1967+
.first()
1968+
.is_some_and(|export| export.as_node().is_some_and(|export_node| self.is_layer(&export_node, network_path)))
1969+
{
1970+
DVec2::new(-4. * GRID_SIZE as f64, -2. * GRID_SIZE as f64)
1971+
} else {
1972+
DVec2::new(-4. * GRID_SIZE as f64, 0.)
1973+
};
1974+
1975+
let bounding_box_top_left = DVec2::new((all_nodes_bounding_box[0].x / 24. + 0.5).floor() * 24., (all_nodes_bounding_box[0].y / 24. + 0.5).floor() * 24.) + offset_from_top_left;
1976+
let import_top_left = DVec2::new(viewport_top_left.x.min(bounding_box_top_left.x), viewport_top_left.y.min(bounding_box_top_left.y));
1977+
let add_import_center = import_top_left + DVec2::new(0., self.number_of_displayed_imports(network_path) as f64 * 24.);
1978+
let add_import = ClickTarget::new(Subpath::new_ellipse(add_import_center - DVec2::new(8., 8.), add_import_center + DVec2::new(8., 8.)), 0.);
1979+
1980+
let Some(network_metadata) = self.network_metadata_mut(network_path) else {
1981+
log::error!("Could not get current network in load_modify_import_export");
1982+
return;
1983+
};
1984+
1985+
network_metadata.transient_metadata.modify_import_export = TransientMetadata::Loaded(ModifyImportExportClickTarget {
1986+
add_export,
1987+
add_import,
1988+
remove_imports: Vec::new(),
1989+
remove_exports: Vec::new(),
1990+
move_import: Vec::new(),
1991+
move_export: Vec::new(),
1992+
});
1993+
}
1994+
1995+
fn unload_modify_import_export(&mut self, network_path: &[NodeId]) {
1996+
let Some(network_metadata) = self.network_metadata_mut(network_path) else {
1997+
log::error!("Could not get nested network_metadata in unload_export_ports");
1998+
return;
1999+
};
2000+
network_metadata.transient_metadata.modify_import_export.unload();
2001+
}
2002+
18992003
pub fn rounded_network_edge_distance(&mut self, network_path: &[NodeId]) -> Option<&NetworkEdgeDistance> {
19002004
let Some(network_metadata) = self.network_metadata(network_path) else {
19012005
log::error!("Could not get nested network_metadata in rounded_network_edge_distance");
@@ -2981,6 +3085,7 @@ impl NodeNetworkInterface {
29813085
};
29823086
network_metadata.persistent_metadata.navigation_metadata.node_graph_to_viewport = transform;
29833087
self.unload_import_export_ports(network_path);
3088+
self.unload_modify_import_export(network_path);
29843089
}
29853090

29863091
// This should be run whenever the pan ends, a zoom occurs, or the network is opened
@@ -2992,6 +3097,7 @@ impl NodeNetworkInterface {
29923097
network_metadata.persistent_metadata.navigation_metadata.node_graph_top_right = node_graph_top_right;
29933098
self.unload_rounded_network_edge_distance(network_path);
29943099
self.unload_import_export_ports(network_path);
3100+
self.unload_modify_import_export(network_path);
29953101
}
29963102

29973103
pub fn vector_modify(&mut self, node_id: &NodeId, modification_type: VectorModificationType) {
@@ -3045,6 +3151,7 @@ impl NodeNetworkInterface {
30453151

30463152
// Update the export ports and outward wires for the current network
30473153
self.unload_import_export_ports(network_path);
3154+
self.unload_modify_import_export(network_path);
30483155
self.unload_outward_wires(network_path);
30493156

30503157
// Update the outward wires and bounding box for all nodes in the encapsulating network
@@ -3066,17 +3173,17 @@ impl NodeNetworkInterface {
30663173

30673174
/// Inserts a new input at insert index. If the insert index is -1 it is inserted at the end. The output_name is used by the encapsulating node.
30683175
pub fn add_import(&mut self, default_value: TaggedValue, exposed: bool, insert_index: isize, input_name: String, network_path: &[NodeId]) {
3069-
let mut network_path = network_path.to_vec();
3070-
let Some(node_id) = network_path.pop() else {
3176+
let mut encapsulating_network_path = network_path.to_vec();
3177+
let Some(node_id) = encapsulating_network_path.pop() else {
30713178
log::error!("Cannot add import for document network");
30723179
return;
30733180
};
30743181
// Set the node to be a non layer if it is no longer eligible to be a layer
3075-
if !self.is_eligible_to_be_layer(&node_id, &network_path) && self.is_layer(&node_id, &network_path) {
3076-
self.set_to_node_or_layer(&node_id, &network_path, false);
3182+
if !self.is_eligible_to_be_layer(&node_id, &encapsulating_network_path) && self.is_layer(&node_id, &encapsulating_network_path) {
3183+
self.set_to_node_or_layer(&node_id, &encapsulating_network_path, false);
30773184
}
30783185

3079-
let Some(network) = self.network_mut(&network_path) else {
3186+
let Some(network) = self.network_mut(&encapsulating_network_path) else {
30803187
log::error!("Could not get nested network in insert_input");
30813188
return;
30823189
};
@@ -3094,7 +3201,7 @@ impl NodeNetworkInterface {
30943201

30953202
self.transaction_modified();
30963203

3097-
let Some(node_metadata) = self.node_metadata_mut(&node_id, &network_path) else {
3204+
let Some(node_metadata) = self.node_metadata_mut(&node_id, &encapsulating_network_path) else {
30983205
log::error!("Could not get node_metadata in insert_input");
30993206
return;
31003207
};
@@ -3111,14 +3218,18 @@ impl NodeNetworkInterface {
31113218
}
31123219

31133220
// Update the click targets for the node
3114-
self.unload_node_click_targets(&node_id, &network_path);
3221+
self.unload_node_click_targets(&node_id, &encapsulating_network_path);
31153222

31163223
// Update the transient network metadata bounding box for all nodes and outward wires
3117-
self.unload_all_nodes_bounding_box(&network_path);
3118-
self.unload_outward_wires(&network_path);
3224+
self.unload_all_nodes_bounding_box(&encapsulating_network_path);
3225+
3226+
// Unload the metadata for the nested network
3227+
self.unload_outward_wires(network_path);
3228+
self.unload_import_export_ports(network_path);
3229+
self.unload_modify_import_export(network_path);
31193230

31203231
// If the input is inserted as the first input, then it may have affected the document metadata structure
3121-
if network_path.is_empty() && (insert_index == 0 || insert_index == 1) {
3232+
if encapsulating_network_path.is_empty() && (insert_index == 0 || insert_index == 1) {
31223233
self.load_structure();
31233234
}
31243235
}
@@ -3915,6 +4026,7 @@ impl NodeNetworkInterface {
39154026
self.unload_upstream_node_click_targets(vec![*node_id], network_path);
39164027
self.unload_all_nodes_bounding_box(network_path);
39174028
self.unload_import_export_ports(network_path);
4029+
self.unload_modify_import_export(network_path);
39184030
self.load_structure();
39194031
}
39204032

@@ -5341,10 +5453,25 @@ pub struct NodeNetworkTransientMetadata {
53415453
// pub wire_paths: Vec<WirePath>
53425454
/// All export connector click targets
53435455
pub import_export_ports: TransientMetadata<Ports>,
5456+
/// Click targets for adding, removing, and moving import/export ports
5457+
pub modify_import_export: TransientMetadata<ModifyImportExportClickTarget>,
53445458
// Distance to the edges of the network, where the import/export ports are displayed. Rounded to nearest grid space when the panning ends.
53455459
pub rounded_network_edge_distance: TransientMetadata<NetworkEdgeDistance>,
53465460
}
53475461

5462+
#[derive(Debug, Clone)]
5463+
pub struct ModifyImportExportClickTarget {
5464+
// Plus icon that appears below all imports/exports
5465+
pub add_import: ClickTarget,
5466+
pub add_export: ClickTarget,
5467+
// Subtract icon that appears when hovering over an import/export
5468+
pub remove_imports: Vec<ClickTarget>,
5469+
pub remove_exports: Vec<ClickTarget>,
5470+
// Grip drag icon that appears when hovering over an import/export
5471+
pub move_import: Vec<ClickTarget>,
5472+
pub move_export: Vec<ClickTarget>,
5473+
}
5474+
53485475
#[derive(Debug, Clone)]
53495476
pub struct NetworkEdgeDistance {
53505477
/// The viewport pixel distance between the left edge of the node graph and the exports.

0 commit comments

Comments
 (0)