From 27f9e3f00e8d012598bdbc688cb7266b6afbfe56 Mon Sep 17 00:00:00 2001 From: Keavon Chambers Date: Wed, 27 Mar 2024 05:17:08 -0700 Subject: [PATCH] Move node visibility flag from NodeNetwork to DocumentNode (#1708) * protonode -> proto node * Move node visibility flag from NodeNetwork to DocumentNode * Add serde default for new field * Logic improvements --- .../messages/input_mapper/default_mapping.rs | 2 +- .../document/document_message_handler.rs | 13 +-- .../document/node_graph/node_graph_message.rs | 8 +- .../node_graph/node_graph_message_handler.rs | 92 ++++++++++--------- .../document/node_graph/utility_types.rs | 2 +- .../document/utility_types/clipboards.rs | 4 +- .../utility_types/document_metadata.rs | 43 ++++++--- .../portfolio/document/utility_types/nodes.rs | 16 ++-- .../portfolio/portfolio_message_handler.rs | 10 +- .../tool/common_functionality/pivot.rs | 6 +- .../tool/common_functionality/snapping.rs | 2 +- .../tool/tool_messages/gradient_tool.rs | 6 +- .../tool/tool_messages/select_tool.rs | 8 +- .../messages/tool/tool_messages/text_tool.rs | 2 +- editor/src/node_graph_executor.rs | 4 +- frontend/.eslintrc.cjs | 4 +- frontend/src/components/panels/Layers.svelte | 4 +- frontend/src/components/views/Graph.svelte | 8 +- frontend/src/wasm-communication/messages.ts | 4 +- frontend/wasm/src/editor_api.rs | 4 +- node-graph/README.md | 4 +- node-graph/compilation-client/src/main.rs | 1 - node-graph/graph-craft/src/document.rs | 36 ++++---- node-graph/graph-craft/src/proto.rs | 4 +- .../src/dynamic_executor.rs | 10 +- website/.eslintrc.js | 2 +- website/other/bezier-rs-demos/.eslintrc.cjs | 2 +- 27 files changed, 161 insertions(+), 140 deletions(-) diff --git a/editor/src/messages/input_mapper/default_mapping.rs b/editor/src/messages/input_mapper/default_mapping.rs index ff353efb7f..4920f8d72a 100644 --- a/editor/src/messages/input_mapper/default_mapping.rs +++ b/editor/src/messages/input_mapper/default_mapping.rs @@ -57,7 +57,7 @@ pub fn default_mapping() -> Mapping { entry!(KeyDown(KeyX); modifiers=[Accel], action_dispatch=NodeGraphMessage::Cut), entry!(KeyDown(KeyC); modifiers=[Accel], action_dispatch=NodeGraphMessage::Copy), entry!(KeyDown(KeyD); modifiers=[Accel], action_dispatch=NodeGraphMessage::DuplicateSelectedNodes), - entry!(KeyDown(KeyH); modifiers=[Accel], action_dispatch=NodeGraphMessage::ToggleSelectedHidden), + entry!(KeyDown(KeyH); modifiers=[Accel], action_dispatch=NodeGraphMessage::ToggleSelectedVisibility), // // TransformLayerMessage entry!(KeyDown(Enter); action_dispatch=TransformLayerMessage::ApplyTransformOperation), diff --git a/editor/src/messages/portfolio/document/document_message_handler.rs b/editor/src/messages/portfolio/document/document_message_handler.rs index b6a29247ff..de705a3f02 100644 --- a/editor/src/messages/portfolio/document/document_message_handler.rs +++ b/editor/src/messages/portfolio/document/document_message_handler.rs @@ -822,7 +822,7 @@ impl DocumentMessageHandler { self.metadata .root() .descendants(&self.metadata) - .filter(|&layer| self.selected_nodes.layer_visible(layer, self.network(), self.metadata())) + .filter(|&layer| self.selected_nodes.layer_visible(layer, self.metadata())) .filter(|&layer| !is_artboard(layer, network)) .filter_map(|layer| self.metadata.click_target(layer).map(|targets| (layer, targets))) .filter(move |(layer, target)| target.iter().any(move |target| target.intersect_rectangle(document_quad, self.metadata.transform_to_document(*layer)))) @@ -835,7 +835,7 @@ impl DocumentMessageHandler { self.metadata .root() .descendants(&self.metadata) - .filter(|&layer| self.selected_nodes.layer_visible(layer, self.network(), self.metadata())) + .filter(|&layer| self.selected_nodes.layer_visible(layer, self.metadata())) .filter_map(|layer| self.metadata.click_target(layer).map(|targets| (layer, targets))) .filter(move |(layer, target)| target.iter().any(|target: &ClickTarget| target.intersect_point(point, self.metadata.transform_to_document(*layer)))) .map(|(layer, _)| layer) @@ -849,7 +849,7 @@ impl DocumentMessageHandler { /// Get the combined bounding box of the click targets of the selected visible layers in viewport space pub fn selected_visible_layers_bounding_box_viewport(&self) -> Option<[DVec2; 2]> { self.selected_nodes - .selected_visible_layers(self.network(), self.metadata()) + .selected_visible_layers(self.metadata()) .filter_map(|layer| self.metadata.bounding_box_viewport(layer)) .reduce(graphene_core::renderer::Quad::combine_bounds) } @@ -887,13 +887,6 @@ impl DocumentMessageHandler { Ok(document) } - /// Returns the bounding boxes for all visible layers. - pub fn bounding_boxes(&self) -> impl Iterator + '_ { - // TODO: Remove this function entirely? - // self.visible_layers().filter_map(|path| self.document_legacy.viewport_bounding_box(path, font_cache).ok()?) - std::iter::empty() - } - /// Called recursively by the entry function [`serialize_root`]. fn serialize_structure(&self, folder: LayerNodeIdentifier, structure_section: &mut Vec, data_section: &mut Vec, path: &mut Vec) { let mut space = 0; diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message.rs index b22d1535e8..7769be0019 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message.rs @@ -89,13 +89,13 @@ pub enum NodeGraphMessage { ShiftNode { node_id: NodeId, }, - ToggleSelectedHidden, - ToggleHidden { + ToggleSelectedVisibility, + ToggleVisibility { node_id: NodeId, }, - SetHidden { + SetVisibility { node_id: NodeId, - hidden: bool, + visible: bool, }, SetName { node_id: NodeId, diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs index a0a8333489..a1f7173c11 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler.rs @@ -59,8 +59,8 @@ impl<'a> MessageHandler> for NodeGrap load_network_structure(document_network, document_metadata, selected_nodes, collapsed); } NodeGraphMessage::SelectedNodesUpdated => { - self.update_selection_action_buttons(document_network, selected_nodes, responses); - self.update_selected(document_network, selected_nodes, responses); + self.update_selection_action_buttons(document_network, document_metadata, selected_nodes, responses); + self.update_selected(document_network, document_metadata, selected_nodes, responses); if selected_nodes.selected_layers(document_metadata).count() <= 1 { responses.add(DocumentMessage::SetRangeSelectionLayer { new_layer: selected_nodes.selected_layers(document_metadata).next(), @@ -195,7 +195,7 @@ impl<'a> MessageHandler> for NodeGrap if let Some(network) = document_network.nested_network(&self.network) { self.send_graph(network, graph_view_overlay_open, document_metadata, selected_nodes, collapsed, responses); } - self.update_selected(document_network, selected_nodes, responses); + self.update_selected(document_network, document_metadata, selected_nodes, responses); } NodeGraphMessage::DuplicateSelectedNodes => { if let Some(network) = document_network.nested_network(&self.network) { @@ -221,7 +221,7 @@ impl<'a> MessageHandler> for NodeGrap responses.add(NodeGraphMessage::InsertNode { node_id, document_node }); } - self.update_selected(document_network, selected_nodes, responses); + self.update_selected(document_network, document_metadata, selected_nodes, responses); } } NodeGraphMessage::ExitNestedNetwork { depth_of_nesting } => { @@ -234,7 +234,7 @@ impl<'a> MessageHandler> for NodeGrap if let Some(network) = document_network.nested_network(&self.network) { self.send_graph(network, graph_view_overlay_open, document_metadata, selected_nodes, collapsed, responses); } - self.update_selected(document_network, selected_nodes, responses); + self.update_selected(document_network, document_metadata, selected_nodes, responses); } NodeGraphMessage::ExposeInput { node_id, input_index, new_exposed } => { let Some(network) = document_network.nested_network(&self.network) else { @@ -447,36 +447,46 @@ impl<'a> MessageHandler> for NodeGrap self.send_graph(network, graph_view_overlay_open, document_metadata, selected_nodes, collapsed, responses); } - NodeGraphMessage::ToggleSelectedHidden => { - if let Some(network) = document_network.nested_network(&self.network) { - responses.add(DocumentMessage::StartTransaction); + NodeGraphMessage::ToggleSelectedVisibility => { + responses.add(DocumentMessage::StartTransaction); - let new_hidden = !selected_nodes.selected_nodes().any(|id| network.disabled.contains(id)); - for &node_id in selected_nodes.selected_nodes() { - responses.add(NodeGraphMessage::SetHidden { node_id, hidden: new_hidden }); - } + // If any of the selected nodes are hidden, show them all. Otherwise, hide them all. + let visible = selected_nodes.selected_nodes().all(|&node_id| document_metadata.node_is_visible(node_id)); + let visible = !visible; + + for &node_id in selected_nodes.selected_nodes() { + responses.add(NodeGraphMessage::SetVisibility { node_id, visible }); } } - NodeGraphMessage::ToggleHidden { node_id } => { - if let Some(network) = document_network.nested_network(&self.network) { - let new_hidden = !network.disabled.contains(&node_id); - responses.add(NodeGraphMessage::SetHidden { node_id, hidden: new_hidden }); - } + NodeGraphMessage::ToggleVisibility { node_id } => { + let visible = document_metadata.node_is_visible(node_id); + let visible = !visible; + + responses.add(NodeGraphMessage::SetVisibility { node_id, visible }); } - NodeGraphMessage::SetHidden { node_id, hidden } => { - if let Some(network) = document_network.nested_network_mut(&self.network) { - if !hidden { - network.disabled.retain(|&id| node_id != id); - } else if !network.imports.contains(&node_id) && !network.original_outputs().iter().any(|output| output.node_id == node_id) { - network.disabled.push(node_id); - } + NodeGraphMessage::SetVisibility { node_id, visible } => { + (|| { + let Some(network) = document_network.nested_network_mut(&self.network) else { return }; + + let input_or_output = network.imports.contains(&node_id) || network.original_outputs().iter().any(|output| output.node_id == node_id); + let visibility = if visible { + true + } else if !input_or_output { + false + } else { + return; + }; + + // Set what we determined shall be the visibility of the node + let Some(node) = network.nodes.get_mut(&node_id) else { return }; + node.visible = visibility; // Only generate node graph if one of the selected nodes is connected to the output if network.connected_to_output(node_id) { responses.add(NodeGraphMessage::RunDocumentGraph); } - } - self.update_selection_action_buttons(document_network, selected_nodes, responses); + })(); + self.update_selection_action_buttons(document_network, document_metadata, selected_nodes, responses); } NodeGraphMessage::SetName { node_id, name } => { responses.add(DocumentMessage::StartTransaction); @@ -508,7 +518,7 @@ impl<'a> MessageHandler> for NodeGrap } } - self.update_selection_action_buttons(document_network, selected_nodes, responses); + self.update_selection_action_buttons(document_network, document_metadata, selected_nodes, responses); responses.add(NodeGraphMessage::RunDocumentGraph); } @@ -522,7 +532,7 @@ impl<'a> MessageHandler> for NodeGrap let node_types = document_node_types::collect_node_types(); responses.add(FrontendMessage::UpdateNodeTypes { node_types }); } - self.update_selected(document_network, selected_nodes, responses); + self.update_selected(document_network, document_metadata, selected_nodes, responses); } NodeGraphMessage::UpdateTypes { resolved_types, node_graph_errors } => { self.resolved_types = resolved_types; @@ -540,7 +550,7 @@ impl<'a> MessageHandler> for NodeGrap impl NodeGraphMessageHandler { pub fn actions_with_node_graph_open(&self, graph_open: bool) -> ActionList { if self.has_selection && graph_open { - actions!(NodeGraphMessageDiscriminant; DeleteSelectedNodes, Cut, Copy, DuplicateSelectedNodes, ToggleSelectedHidden) + actions!(NodeGraphMessageDiscriminant; DeleteSelectedNodes, Cut, Copy, DuplicateSelectedNodes, ToggleSelectedVisibility) } else { actions!(NodeGraphMessageDiscriminant;) } @@ -554,8 +564,8 @@ impl NodeGraphMessageHandler { }); } - /// Updates the buttons for disable and preview - fn update_selection_action_buttons(&mut self, document_network: &NodeNetwork, selected_nodes: &SelectedNodes, responses: &mut VecDeque) { + /// Updates the buttons for visibility and preview + fn update_selection_action_buttons(&mut self, document_network: &NodeNetwork, document_metadata: &DocumentMetadata, selected_nodes: &SelectedNodes, responses: &mut VecDeque) { if let Some(network) = document_network.nested_network(&self.network) { let mut widgets = Vec::new(); @@ -565,18 +575,18 @@ impl NodeGraphMessageHandler { // If there is at least one other selected node then show the hide or show button if selection.next().is_some() { // Check if any of the selected nodes are disabled - let is_hidden = selected_nodes.selected_nodes().any(|id| network.disabled.contains(id)); + let all_visible = selected_nodes.selected_nodes().all(|&id| document_metadata.node_is_visible(id)); // Check if multiple nodes are selected let multiple_nodes = selection.next().is_some(); - // Generate the enable or disable button accordingly - let (hide_show_label, hide_show_icon) = if is_hidden { ("Make Visible", "EyeHidden") } else { ("Make Hidden", "EyeVisible") }; + // Generate the visible/hidden button accordingly + let (hide_show_label, hide_show_icon) = if all_visible { ("Make Hidden", "EyeVisible") } else { ("Make Visible", "EyeHidden") }; let hide_button = TextButton::new(hide_show_label) .icon(Some(hide_show_icon.to_string())) - .tooltip(if is_hidden { "Show selected nodes/layers" } else { "Hide selected nodes/layers" }.to_string() + if multiple_nodes { "s" } else { "" }) - .tooltip_shortcut(action_keys!(NodeGraphMessageDiscriminant::ToggleSelectedHidden)) - .on_update(move |_| NodeGraphMessage::ToggleSelectedHidden.into()) + .tooltip(if all_visible { "Hide selected nodes/layers" } else { "Show selected nodes/layers" }.to_string() + if multiple_nodes { "s" } else { "" }) + .tooltip_shortcut(action_keys!(NodeGraphMessageDiscriminant::ToggleSelectedVisibility)) + .on_update(move |_| NodeGraphMessage::ToggleSelectedVisibility.into()) .widget_holder(); widgets.push(hide_button); @@ -745,7 +755,7 @@ impl NodeGraphMessageHandler { exposed_outputs, position: node.metadata.position.into(), previewed: network.outputs_contain(node_id), - disabled: network.disabled.contains(&node_id), + visible: node.visible, errors: errors.map(|e| format!("{e:?}")), }); } @@ -774,7 +784,7 @@ impl NodeGraphMessageHandler { parent_id: layer.parent(metadata).map(|parent| parent.to_node()), name: network.nodes.get(&node_id).map(|node| node.alias.clone()).unwrap_or_default(), tooltip: if cfg!(debug_assertions) { format!("Layer ID: {node_id}") } else { "".into() }, - disabled: network.disabled.contains(&node_id), + visible: node.visible, }; responses.add(FrontendMessage::UpdateDocumentLayerDetails { data }); } @@ -795,8 +805,8 @@ impl NodeGraphMessageHandler { } /// Updates the frontend's selection state in line with the backend - fn update_selected(&mut self, document_network: &NodeNetwork, selected_nodes: &SelectedNodes, responses: &mut VecDeque) { - self.update_selection_action_buttons(document_network, selected_nodes, responses); + fn update_selected(&mut self, document_network: &NodeNetwork, document_metadata: &DocumentMetadata, selected_nodes: &SelectedNodes, responses: &mut VecDeque) { + self.update_selection_action_buttons(document_network, document_metadata, selected_nodes, responses); responses.add(FrontendMessage::UpdateNodeGraphSelection { selected: selected_nodes.selected_nodes_ref().clone(), }); diff --git a/editor/src/messages/portfolio/document/node_graph/utility_types.rs b/editor/src/messages/portfolio/document/node_graph/utility_types.rs index d528b377bf..6bf6ff5383 100644 --- a/editor/src/messages/portfolio/document/node_graph/utility_types.rs +++ b/editor/src/messages/portfolio/document/node_graph/utility_types.rs @@ -84,7 +84,7 @@ pub struct FrontendNode { #[serde(rename = "exposedOutputs")] pub exposed_outputs: Vec, pub position: (i32, i32), - pub disabled: bool, + pub visible: bool, pub previewed: bool, pub errors: Option, } diff --git a/editor/src/messages/portfolio/document/utility_types/clipboards.rs b/editor/src/messages/portfolio/document/utility_types/clipboards.rs index 549fd48279..a9db421147 100644 --- a/editor/src/messages/portfolio/document/utility_types/clipboards.rs +++ b/editor/src/messages/portfolio/document/utility_types/clipboards.rs @@ -8,7 +8,7 @@ use std::collections::HashMap; pub enum Clipboard { Internal, - _InternalClipboardCount, // Keep this as the last entry in internal clipboards since it is used for counting the number of enum variants + _InternalClipboardCount, // Keep this as the last entry of **internal** clipboards since it is used for counting the number of enum variants Device, } @@ -19,7 +19,7 @@ pub const INTERNAL_CLIPBOARD_COUNT: u8 = Clipboard::_InternalClipboardCount as u pub struct CopyBufferEntry { pub nodes: HashMap, pub selected: bool, - pub disabled: bool, + pub visible: bool, pub collapsed: bool, pub alias: String, } diff --git a/editor/src/messages/portfolio/document/utility_types/document_metadata.rs b/editor/src/messages/portfolio/document/utility_types/document_metadata.rs index d148de1efc..944675290a 100644 --- a/editor/src/messages/portfolio/document/utility_types/document_metadata.rs +++ b/editor/src/messages/portfolio/document/utility_types/document_metadata.rs @@ -14,12 +14,15 @@ use std::num::NonZeroU64; // DocumentMetadata // ================ +// TODO: To avoid storing a stateful snapshot of some other system's state (which is easily to accidentally get out of sync), +// TODO: it might be better to have a system that can query the state of the node network on demand. #[derive(Debug, Clone)] pub struct DocumentMetadata { upstream_transforms: HashMap, structure: HashMap, artboards: HashSet, folders: HashSet, + hidden: HashSet, click_targets: HashMap>, /// Transform from document space to viewport space. pub document_to_viewport: DAffine2, @@ -29,10 +32,11 @@ impl Default for DocumentMetadata { fn default() -> Self { Self { upstream_transforms: HashMap::new(), - click_targets: HashMap::new(), structure: HashMap::from_iter([(LayerNodeIdentifier::ROOT, NodeRelations::default())]), artboards: HashSet::new(), folders: HashSet::new(), + hidden: HashSet::new(), + click_targets: HashMap::new(), document_to_viewport: DAffine2::IDENTITY, } } @@ -118,6 +122,10 @@ impl DocumentMetadata { self.artboards.contains(&layer) } + pub fn node_is_visible(&self, layer: NodeId) -> bool { + !self.hidden.contains(&layer) + } + /// Folders sorted from most nested to least nested pub fn folders_sorted_by_most_nested(&self, layers: impl Iterator) -> Vec { let mut folders: Vec<_> = layers.filter(|layer| self.folders.contains(layer)).collect(); @@ -138,8 +146,9 @@ impl DocumentMetadata { } self.structure = HashMap::from_iter([(LayerNodeIdentifier::ROOT, NodeRelations::default())]); - self.folders = HashSet::new(); self.artboards = HashSet::new(); + self.folders = HashSet::new(); + self.hidden = HashSet::new(); let id = graph.exports[0].node_id; let Some(output_node) = graph.nodes.get(&id) else { @@ -150,22 +159,26 @@ impl DocumentMetadata { }; let parent = LayerNodeIdentifier::ROOT; let mut stack = vec![(layer_node, node_id, parent)]; - while let Some((node, id, parent)) = stack.pop() { - let mut current = Some((node, id)); - while let Some(&(current_node, current_id)) = current.as_ref() { - let current_identifier = LayerNodeIdentifier::new_unchecked(current_id); - if !self.structure.contains_key(¤t_identifier) { - parent.push_child(self, current_identifier); + while let Some((node, node_id, parent)) = stack.pop() { + let mut current = Some((node, node_id)); + while let Some(&(current_node, current_node_id)) = current.as_ref() { + let current_layer_id = LayerNodeIdentifier::new_unchecked(current_node_id); + if !self.structure.contains_key(¤t_layer_id) { + parent.push_child(self, current_layer_id); if let Some((child_node, child_id)) = first_child_layer(graph, current_node) { - stack.push((child_node, child_id, current_identifier)); + stack.push((child_node, child_id, current_layer_id)); } - if is_artboard(current_identifier, graph) { - self.artboards.insert(current_identifier); + if is_artboard(current_layer_id, graph) { + self.artboards.insert(current_layer_id); } - if is_folder(current_identifier, graph) { - self.folders.insert(current_identifier); + if is_folder(current_layer_id, graph) { + self.folders.insert(current_layer_id); + } + + if !current_node.visible { + self.hidden.insert(current_node_id); } } @@ -532,9 +545,9 @@ impl<'a> Iterator for AxisIter<'a> { } } -// ============== +// =============== // DescendantsIter -// ============== +// =============== #[derive(Clone)] pub struct DescendantsIter<'a> { diff --git a/editor/src/messages/portfolio/document/utility_types/nodes.rs b/editor/src/messages/portfolio/document/utility_types/nodes.rs index ffeb5cd5b4..f3e788b829 100644 --- a/editor/src/messages/portfolio/document/utility_types/nodes.rs +++ b/editor/src/messages/portfolio/document/utility_types/nodes.rs @@ -1,9 +1,9 @@ -use graph_craft::document::{NodeId, NodeNetwork}; +use super::document_metadata::{DocumentMetadata, LayerNodeIdentifier}; + +use graph_craft::document::NodeId; use serde::ser::SerializeStruct; -use super::document_metadata::{DocumentMetadata, LayerNodeIdentifier}; - #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq, specta::Type)] pub struct RawBuffer(Vec); @@ -46,7 +46,7 @@ pub struct LayerPanelEntry { #[serde(rename = "layerClassification")] pub layer_classification: LayerClassification, pub expanded: bool, - pub disabled: bool, + pub visible: bool, #[serde(rename = "parentId")] pub parent_id: Option, pub depth: usize, @@ -56,12 +56,12 @@ pub struct LayerPanelEntry { pub struct SelectedNodes(pub Vec); impl SelectedNodes { - pub fn layer_visible(&self, layer: LayerNodeIdentifier, network: &NodeNetwork, metadata: &DocumentMetadata) -> bool { - !layer.ancestors(metadata).any(|layer| network.disabled.contains(&layer.to_node())) + pub fn layer_visible(&self, layer: LayerNodeIdentifier, metadata: &DocumentMetadata) -> bool { + layer.ancestors(metadata).all(|layer| metadata.node_is_visible(layer.to_node())) } - pub fn selected_visible_layers<'a>(&'a self, network: &'a NodeNetwork, metadata: &'a DocumentMetadata) -> impl Iterator + '_ { - self.selected_layers(metadata).filter(move |&layer| self.layer_visible(layer, network, metadata)) + pub fn selected_visible_layers<'a>(&'a self, metadata: &'a DocumentMetadata) -> impl Iterator + '_ { + self.selected_layers(metadata).filter(move |&layer| self.layer_visible(layer, metadata)) } pub fn selected_layers<'a>(&'a self, metadata: &'a DocumentMetadata) -> impl Iterator + '_ { diff --git a/editor/src/messages/portfolio/portfolio_message_handler.rs b/editor/src/messages/portfolio/portfolio_message_handler.rs index 8e8737a669..d6042afd71 100644 --- a/editor/src/messages/portfolio/portfolio_message_handler.rs +++ b/editor/src/messages/portfolio/portfolio_message_handler.rs @@ -202,7 +202,7 @@ impl MessageHandler> for PortfolioMes ) .collect(), selected: active_document.selected_nodes.selected_layers_contains(layer, active_document.metadata()), - disabled: !active_document.selected_nodes.layer_visible(layer, active_document.network(), active_document.metadata()), + visible: active_document.selected_nodes.layer_visible(layer, active_document.metadata()), collapsed: false, alias: previous_alias, }); @@ -388,8 +388,8 @@ impl MessageHandler> for PortfolioMes if entry.selected { responses.add(NodeGraphMessage::SelectedNodesAdd { nodes: vec![id] }); } - if entry.disabled { - responses.add(NodeGraphMessage::SetHidden { node_id: id, hidden: entry.disabled }); + if !entry.visible { + responses.add(NodeGraphMessage::SetVisibility { node_id: id, visible: false }); } } }; @@ -419,8 +419,8 @@ impl MessageHandler> for PortfolioMes if entry.selected { responses.add(NodeGraphMessage::SelectedNodesAdd { nodes: vec![id] }); } - if entry.disabled { - responses.add(NodeGraphMessage::SetHidden { node_id: id, hidden: entry.disabled }); + if !entry.visible { + responses.add(NodeGraphMessage::SetVisibility { node_id: id, visible: false }); } } diff --git a/editor/src/messages/tool/common_functionality/pivot.rs b/editor/src/messages/tool/common_functionality/pivot.rs index 614bf9b4e8..c762ca50b1 100644 --- a/editor/src/messages/tool/common_functionality/pivot.rs +++ b/editor/src/messages/tool/common_functionality/pivot.rs @@ -45,7 +45,7 @@ impl Pivot { /// Recomputes the pivot position and transform. fn recalculate_pivot(&mut self, document: &DocumentMessageHandler) { - let mut layers = document.selected_nodes.selected_visible_layers(document.network(), document.metadata()); + let mut layers = document.selected_nodes.selected_visible_layers(document.metadata()); let Some(first) = layers.next() else { // If no layers are selected then we revert things back to default self.normalized_pivot = DVec2::splat(0.5); @@ -66,7 +66,7 @@ impl Pivot { // If more than one layer is selected we use the AABB with the mean of the pivots let xy_summation = document .selected_nodes - .selected_visible_layers(document.network(), document.metadata()) + .selected_visible_layers(document.metadata()) .map(|layer| graph_modification_utils::get_viewport_pivot(layer, &document.network, &document.metadata)) .reduce(|a, b| a + b) .unwrap_or_default(); @@ -101,7 +101,7 @@ impl Pivot { /// Sets the viewport position of the pivot for all selected layers. pub fn set_viewport_position(&self, position: DVec2, document: &DocumentMessageHandler, responses: &mut VecDeque) { - for layer in document.selected_nodes.selected_visible_layers(document.network(), document.metadata()) { + for layer in document.selected_nodes.selected_visible_layers(document.metadata()) { let transform = Self::get_layer_pivot_transform(layer, document); let pivot = transform.inverse().transform_point2(position); // Only update the pivot when computed position is finite. Infinite can happen when scale is 0. diff --git a/editor/src/messages/tool/common_functionality/snapping.rs b/editor/src/messages/tool/common_functionality/snapping.rs index 7eb95cdf41..57f5c50e29 100644 --- a/editor/src/messages/tool/common_functionality/snapping.rs +++ b/editor/src/messages/tool/common_functionality/snapping.rs @@ -255,7 +255,7 @@ impl SnapManager { if candidates.len() > 10 { return; } - if !document.selected_nodes.layer_visible(layer, &document.network, &document.metadata) { + if !document.selected_nodes.layer_visible(layer, &document.metadata) { return; } if snap_data.ignore.contains(&layer) { diff --git a/editor/src/messages/tool/tool_messages/gradient_tool.rs b/editor/src/messages/tool/tool_messages/gradient_tool.rs index dd1487b70f..0b7d8bc855 100644 --- a/editor/src/messages/tool/tool_messages/gradient_tool.rs +++ b/editor/src/messages/tool/tool_messages/gradient_tool.rs @@ -247,7 +247,7 @@ impl Fsm for GradientToolFsmState { (_, GradientToolMessage::Overlays(mut overlay_context)) => { let selected = tool_data.selected_gradient.as_ref(); - for layer in document.selected_nodes.selected_visible_layers(document.network(), document.metadata()) { + for layer in document.selected_nodes.selected_visible_layers(document.metadata()) { let Some(gradient) = get_gradient(layer, &document.network) else { continue }; let transform = gradient_space_transform(layer, document); let dragging = selected.filter(|selected| selected.layer == layer).map(|selected| selected.dragging); @@ -318,7 +318,7 @@ impl Fsm for GradientToolFsmState { self } (_, GradientToolMessage::InsertStop) => { - for layer in document.selected_nodes.selected_visible_layers(document.network(), document.metadata()) { + for layer in document.selected_nodes.selected_visible_layers(document.metadata()) { let Some(mut gradient) = get_gradient(layer, &document.network) else { continue }; let transform = gradient_space_transform(layer, document); @@ -357,7 +357,7 @@ impl Fsm for GradientToolFsmState { let tolerance = (MANIPULATOR_GROUP_MARKER_SIZE * 2.).powi(2); let mut dragging = false; - for layer in document.selected_nodes.selected_visible_layers(document.network(), document.metadata()) { + for layer in document.selected_nodes.selected_visible_layers(document.metadata()) { let Some(gradient) = get_gradient(layer, &document.network) else { continue }; let transform = gradient_space_transform(layer, document); diff --git a/editor/src/messages/tool/tool_messages/select_tool.rs b/editor/src/messages/tool/tool_messages/select_tool.rs index 728a9205f1..5894dd04a4 100644 --- a/editor/src/messages/tool/tool_messages/select_tool.rs +++ b/editor/src/messages/tool/tool_messages/select_tool.rs @@ -391,7 +391,7 @@ impl Fsm for SelectToolFsmState { tool_data.selected_layers_count = selected_layers_count; // Outline selected layers - for layer in document.selected_nodes.selected_visible_layers(document.network(), document.metadata()) { + for layer in document.selected_nodes.selected_visible_layers(document.metadata()) { overlay_context.outline(document.metadata().layer_outline(layer), document.metadata().transform_to_viewport(layer)); } @@ -405,13 +405,13 @@ impl Fsm for SelectToolFsmState { // Update bounds let transform = document .selected_nodes - .selected_visible_layers(document.network(), document.metadata()) + .selected_visible_layers(document.metadata()) .next() .map(|layer| document.metadata().transform_to_viewport(layer)); let transform = transform.unwrap_or(DAffine2::IDENTITY); let bounds = document .selected_nodes - .selected_visible_layers(document.network(), document.metadata()) + .selected_visible_layers(document.metadata()) .filter_map(|layer| { document .metadata() @@ -472,7 +472,7 @@ impl Fsm for SelectToolFsmState { .map(|bounding_box| bounding_box.check_rotate(input.mouse.position)) .unwrap_or_default(); - let mut selected: Vec<_> = document.selected_nodes.selected_visible_layers(document.network(), document.metadata()).collect(); + let mut selected: Vec<_> = document.selected_nodes.selected_visible_layers(document.metadata()).collect(); let intersection = document.click(input.mouse.position, &document.network); // If the user is dragging the bounding box bounds, go into ResizingBounds mode. diff --git a/editor/src/messages/tool/tool_messages/text_tool.rs b/editor/src/messages/tool/tool_messages/text_tool.rs index 1ec71f7edd..6f1c0c1c56 100644 --- a/editor/src/messages/tool/tool_messages/text_tool.rs +++ b/editor/src/messages/tool/tool_messages/text_tool.rs @@ -215,7 +215,7 @@ impl TextToolData { /// Set the editing state of the currently modifying layer fn set_editing(&self, editable: bool, font_cache: &FontCache, document: &DocumentMessageHandler, responses: &mut VecDeque) { if let Some(node_id) = graph_modification_utils::get_fill_id(self.layer, &document.network) { - responses.add(NodeGraphMessage::SetHidden { node_id, hidden: editable }); + responses.add(NodeGraphMessage::SetVisibility { node_id, visible: !editable }); } if let Some(editing_text) = self.editing_text.as_ref().filter(|_| editable) { diff --git a/editor/src/node_graph_executor.rs b/editor/src/node_graph_executor.rs index d6a9cf5287..7f5ada86ce 100644 --- a/editor/src/node_graph_executor.rs +++ b/editor/src/node_graph_executor.rs @@ -190,7 +190,7 @@ impl NodeRuntime { image_frame: None, }; - // Required to ensure that the appropriate protonodes are reinserted when the Editor API changes. + // Required to ensure that the appropriate proto nodes are reinserted when the Editor API changes. let mut graph_input_hash = DefaultHasher::new(); editor_api.font_cache.hash(&mut graph_input_hash); let font_hash_code = graph_input_hash.finish(); @@ -218,7 +218,7 @@ impl NodeRuntime { Err(e) => return Err(e), }; - assert_ne!(proto_network.nodes.len(), 0, "No protonodes exist?"); + assert_ne!(proto_network.nodes.len(), 0, "No proto nodes exist?"); if let Err(e) = self.executor.update(proto_network).await { self.node_graph_errors = e; } else { diff --git a/frontend/.eslintrc.cjs b/frontend/.eslintrc.cjs index b8b9123a3e..32485f10bf 100644 --- a/frontend/.eslintrc.cjs +++ b/frontend/.eslintrc.cjs @@ -50,7 +50,7 @@ module.exports = { camelcase: ["error", { properties: "always" }], "linebreak-style": ["error", "unix"], "eol-last": ["error", "always"], - "max-len": ["error", { code: 200, tabWidth: 4 }], + "max-len": ["error", { code: 200, tabWidth: 4, ignorePattern: `d="([\\s\\S]*?)"` }], "prefer-destructuring": "off", "no-console": "warn", "no-debugger": "warn", @@ -81,6 +81,8 @@ module.exports = { // Import plugin config (for intelligently validating module import statements) "import/no-unresolved": "error", + // `no-duplicates` disabled due to . Reenable if that issue gets fixed. + "import/no-duplicates": "off", "import/prefer-default-export": "off", "import/no-relative-packages": "error", "import/order": [ diff --git a/frontend/src/components/panels/Layers.svelte b/frontend/src/components/panels/Layers.svelte index df5bc5a729..f1ca23cc73 100644 --- a/frontend/src/components/panels/Layers.svelte +++ b/frontend/src/components/panels/Layers.svelte @@ -417,8 +417,8 @@ class={"visibility"} action={(e) => (toggleLayerVisibility(listing.entry.id), e?.stopPropagation())} size={24} - icon={listing.entry.disabled ? "EyeHidden" : "EyeVisible"} - tooltip={listing.entry.disabled ? "Disabled" : "Enabled"} + icon={listing.entry.visible ? "EyeVisible" : "EyeHidden"} + tooltip={listing.entry.visible ? "Visible" : "Hidden"} /> {/each} diff --git a/frontend/src/components/views/Graph.svelte b/frontend/src/components/views/Graph.svelte index 74bbb35d55..bec9870926 100644 --- a/frontend/src/components/views/Graph.svelte +++ b/frontend/src/components/views/Graph.svelte @@ -795,7 +795,7 @@ class="layer" class:selected={showSelected($nodeGraph.selected, boxSelection, node.id, nodeIndex)} class:previewed={node.previewed} - class:disabled={node.disabled} + class:disabled={!node.visible} style:--offset-left={(node.position?.x || 0) + ($nodeGraph.selected.includes(node.id) ? draggingNodes?.roundX || 0 : 0)} style:--offset-top={(node.position?.y || 0) + ($nodeGraph.selected.includes(node.id) ? draggingNodes?.roundY || 0 : 0)} style:--clip-path-id={`url(#${clipPathId})`} @@ -891,8 +891,8 @@ class={"visibility"} action={(e) => (toggleLayerVisibility(node.id), e?.stopPropagation())} size={24} - icon={node.disabled ? "EyeHidden" : "EyeVisible"} - tooltip={node.disabled ? "Disabled" : "Enabled"} + icon={node.visible ? "EyeVisible" : "EyeHidden"} + tooltip={node.visible ? "Visible" : "Hidden"} /> @@ -913,7 +913,7 @@ class="node" class:selected={showSelected($nodeGraph.selected, boxSelection, node.id, nodeIndex)} class:previewed={node.previewed} - class:disabled={node.disabled} + class:disabled={!node.visible} style:--offset-left={(node.position?.x || 0) + ($nodeGraph.selected.includes(node.id) ? draggingNodes?.roundX || 0 : 0)} style:--offset-top={(node.position?.y || 0) + ($nodeGraph.selected.includes(node.id) ? draggingNodes?.roundY || 0 : 0)} style:--clip-path-id={`url(#${clipPathId})`} diff --git a/frontend/src/wasm-communication/messages.ts b/frontend/src/wasm-communication/messages.ts index 3df903e1f2..704be65f26 100644 --- a/frontend/src/wasm-communication/messages.ts +++ b/frontend/src/wasm-communication/messages.ts @@ -124,7 +124,7 @@ export class FrontendNode { readonly previewed!: boolean; - readonly disabled!: boolean; + readonly visible!: boolean; readonly errors!: string | undefined; } @@ -613,7 +613,7 @@ export class LayerPanelEntry { expanded!: boolean; - disabled!: boolean; + visible!: boolean; parentId!: bigint | undefined; diff --git a/frontend/wasm/src/editor_api.rs b/frontend/wasm/src/editor_api.rs index 99631d0426..f79344c6da 100644 --- a/frontend/wasm/src/editor_api.rs +++ b/frontend/wasm/src/editor_api.rs @@ -757,8 +757,8 @@ impl JsEditorHandle { /// Toggle visibility of a layer from the layer list #[wasm_bindgen(js_name = toggleLayerVisibility)] pub fn toggle_layer_visibility(&self, id: u64) { - let id = NodeId(id); - let message = NodeGraphMessage::ToggleHidden { node_id: id }; + let node_id = NodeId(id); + let message = NodeGraphMessage::ToggleVisibility { node_id }; self.dispatch(message); } diff --git a/node-graph/README.md b/node-graph/README.md index a19a96e41a..629d4ba3d6 100644 --- a/node-graph/README.md +++ b/node-graph/README.md @@ -60,7 +60,7 @@ pub fn multiply_opacity(document_node: &DocumentNode, node_id: NodeId, _context: } ``` -## Graphene (protonode executor) +## Graphene (proto node executor) The graphene crate (found in `gcore/`) and the graphene standard library (found in `gstd/`) is where actual implementation for nodes are located. @@ -100,7 +100,7 @@ fn test_opacity_node() { The `graphene_core::value::CopiedNode` is a node that, when evaluated, copies `10_f32` and returns it. -## Creating a new protonode +## Creating a new proto node Instead of manually implementing the `Node` trait with complex generics, one can use the `node_fn` macro, which can be applied to a function like `opacity_node` with an attribute of the name of the node: diff --git a/node-graph/compilation-client/src/main.rs b/node-graph/compilation-client/src/main.rs index 72f1593f07..a07a808901 100644 --- a/node-graph/compilation-client/src/main.rs +++ b/node-graph/compilation-client/src/main.rs @@ -39,7 +39,6 @@ fn add_network() -> NodeNetwork { NodeNetwork { imports: vec![], exports: vec![NodeOutput::new(NodeId(0), 0)], - disabled: vec![], previous_outputs: None, nodes: [DocumentNode { name: "Blend Image".into(), diff --git a/node-graph/graph-craft/src/document.rs b/node-graph/graph-craft/src/document.rs index dddfc08662..09c3a98b40 100644 --- a/node-graph/graph-craft/src/document.rs +++ b/node-graph/graph-craft/src/document.rs @@ -152,18 +152,24 @@ pub struct DocumentNode { /// Now, the call from `F` directly reaches the `CacheNode` and the `CacheNode` can decide whether to call `G.eval(input_from_f)` /// in the event of a cache miss or just return the cached data in the event of a cache hit. pub manual_composition: Option, + // TODO: Remove once this references its definition instead (see above TODO). + /// Indicates to the UI if a primary output should be drawn for this node. + /// True for most nodes, but the Split Channels node is an example of a node that has multiple secondary outputs but no primary output. #[serde(default = "return_true")] pub has_primary_output: bool, // A nested document network or a proto-node identifier. pub implementation: DocumentNodeImplementation, + /// Represents the eye icon for hiding/showing the node in the graph UI. When hidden, a node gets replaced with an identity node during the graph flattening step. + #[serde(default = "return_true")] + pub visible: bool, /// Metadata about the node including its position in the graph UI. pub metadata: DocumentNodeMetadata, - /// When two different protonodes hash to the same value (e.g. two value nodes each containing `2_u32` or two multiply nodes that have the same node IDs as input), the duplicates are removed. + /// When two different proto nodes hash to the same value (e.g. two value nodes each containing `2_u32` or two multiply nodes that have the same node IDs as input), the duplicates are removed. /// See [`crate::proto::ProtoNetwork::generate_stable_node_ids`] for details. /// However sometimes this is not desirable, for example in the case of a [`graphene_core::memo::MonitorNode`] that needs to be accessed outside of the graph. #[serde(default)] pub skip_deduplication: bool, - /// Used as a hash of the graph input where applicable. This ensures that protonodes that depend on the graph's input are always regenerated. + /// Used as a hash of the graph input where applicable. This ensures that proto nodes that depend on the graph's input are always regenerated. #[serde(default)] pub world_state_hash: u64, /// The path to this node and its inputs and outputs as of when [`NodeNetwork::generate_node_paths`] was called. @@ -185,7 +191,7 @@ pub struct Source { pub struct OriginalLocation { /// The original location to the document node - e.g. [grandparent_id, parent_id, node_id]. pub path: Option>, - /// Each document input source maps to one protonode input (however one protonode input may come from several sources) + /// Each document input source maps to one proto node input (however one proto node input may come from several sources) pub inputs_source: HashMap, /// A list of document sources for the node's output pub outputs_source: HashMap, @@ -203,6 +209,7 @@ impl Default for DocumentNode { manual_composition: Default::default(), has_primary_output: true, implementation: Default::default(), + visible: true, metadata: Default::default(), skip_deduplication: Default::default(), world_state_hash: Default::default(), @@ -272,7 +279,7 @@ impl DocumentNode { (ProtoNodeInput::None, ConstructionArgs::Value(tagged_value)) } NodeInput::Node { node_id, output_index, lambda } => { - assert_eq!(output_index, 0, "Outputs should be flattened before converting to protonode. {:#?}", self.name); + assert_eq!(output_index, 0, "Outputs should be flattened before converting to proto node. {:#?}", self.name); let node = if lambda { ProtoNodeInput::NodeLambda(node_id) } else { ProtoNodeInput::Node(node_id) }; (node, ConstructionArgs::Nodes(vec![])) } @@ -445,9 +452,9 @@ pub enum DocumentNodeImplementation { /// /// A nested [`NodeNetwork`] that is flattened by the [`NodeNetwork::flatten`] function. Network(NodeNetwork), - /// This describes a (document) node implemented as a protonode. + /// This describes a (document) node implemented as a proto node. /// - /// A protonode identifier which can be found in `node_registry.rs`. + /// A proto node identifier which can be found in `node_registry.rs`. ProtoNode(ProtoNodeIdentifier), /// The Extract variant is a tag which tells the compilation process to do something special. It invokes language-level functionality built for use by the ExtractNode to enable metaprogramming. /// When the ExtractNode is compiled, it gets replaced by a value node containing a representation of the source code for the function/lambda of the document node that's fed into the ExtractNode @@ -523,9 +530,6 @@ pub struct NodeNetwork { pub exports: Vec, /// The list of all nodes in this network. pub nodes: HashMap, - /// Nodes that the user has disabled/hidden with the visibility eye icon. - /// These nodes get replaced with Identity nodes during the graph flattening step. - pub disabled: Vec, /// In the case when another node is previewed (chosen by the user as a temporary output), this stores what it previously was so it can be restored later. pub previous_outputs: Option>, } @@ -540,7 +544,6 @@ impl std::hash::Hash for NodeNetwork { id.hash(state); node.hash(state); } - self.disabled.hash(state); self.previous_outputs.hash(state); } } @@ -567,7 +570,6 @@ impl NodeNetwork { imports: node.inputs.iter().filter(|input| matches!(input, NodeInput::Network(_))).map(|_| NodeId(0)).collect(), exports: vec![NodeOutput::new(NodeId(0), 0)], nodes: [(NodeId(0), node)].into_iter().collect(), - disabled: vec![], previous_outputs: None, } } @@ -815,7 +817,6 @@ impl NodeNetwork { pub fn map_ids(&mut self, f: impl Fn(NodeId) -> NodeId + Copy) { self.imports.iter_mut().for_each(|id| *id = f(*id)); self.exports.iter_mut().for_each(|output| output.node_id = f(output.node_id)); - self.disabled.iter_mut().for_each(|id| *id = f(*id)); self.previous_outputs .iter_mut() .for_each(|nodes| nodes.iter_mut().for_each(|output| output.node_id = f(output.node_id))); @@ -843,7 +844,7 @@ impl NodeNetwork { outwards_links } - /// Populate the [`DocumentNode::path`], which stores the location of the document node to allow for matching the resulting protonodes to the document node for the purposes of typing and finding monitor nodes. + /// Populate the [`DocumentNode::path`], which stores the location of the document node to allow for matching the resulting proto nodes to the document node for the purposes of typing and finding monitor nodes. pub fn generate_node_paths(&mut self, prefix: &[NodeId]) { for (node_id, node) in &mut self.nodes { let mut new_path = prefix.to_vec(); @@ -930,8 +931,11 @@ impl NodeNetwork { return; }; - if node.implementation != DocumentNodeImplementation::ProtoNode("graphene_core::ops::IdentityNode".into()) && self.disabled.contains(&id) { - node.implementation = DocumentNodeImplementation::ProtoNode("graphene_core::ops::IdentityNode".into()); + // If the node is hidden, replace it with an identity node + let identity_node = DocumentNodeImplementation::ProtoNode("graphene_core::ops::IdentityNode".into()); + if !node.visible && node.implementation != identity_node { + node.implementation = identity_node; + if node.is_layer() { // Connect layer node to the graphic group below node.inputs.drain(..1); @@ -939,6 +943,7 @@ impl NodeNetwork { node.inputs.drain(1..); } self.nodes.insert(id, node); + return; } @@ -983,7 +988,6 @@ impl NodeNetwork { let new_nodes = inner_network.nodes.keys().cloned().collect::>(); // Copy nodes from the inner network into the parent network self.nodes.extend(inner_network.nodes); - self.disabled.extend(inner_network.disabled); let mut network_offsets = HashMap::new(); assert_eq!( diff --git a/node-graph/graph-craft/src/proto.rs b/node-graph/graph-craft/src/proto.rs index 8983cab932..89553f3136 100644 --- a/node-graph/graph-craft/src/proto.rs +++ b/node-graph/graph-craft/src/proto.rs @@ -200,7 +200,7 @@ impl ConstructionArgs { #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[derive(Debug, Clone, PartialEq, Hash, Eq)] -/// A protonode is an intermediate step between the `DocumentNode` and the boxed struct that actually runs the node (found in the [`BorrowTree`]). It has one primary input and several secondary inputs in [`ConstructionArgs`]. +/// A proto node is an intermediate step between the `DocumentNode` and the boxed struct that actually runs the node (found in the [`BorrowTree`]). It has one primary input and several secondary inputs in [`ConstructionArgs`]. pub struct ProtoNode { pub construction_args: ConstructionArgs, pub input: ProtoNodeInput, @@ -718,7 +718,7 @@ impl TypingContext { ConstructionArgs::Inline(ref inline) => vec![inline.ty.clone()], }; - // Get the node input type from the protonode declaration + // Get the node input type from the proto node declaration let input = match node.input { ProtoNodeInput::None => concrete!(()), ProtoNodeInput::ManualComposition(ref ty) => ty.clone(), diff --git a/node-graph/interpreted-executor/src/dynamic_executor.rs b/node-graph/interpreted-executor/src/dynamic_executor.rs index f9410cfd05..b34baa8048 100644 --- a/node-graph/interpreted-executor/src/dynamic_executor.rs +++ b/node-graph/interpreted-executor/src/dynamic_executor.rs @@ -17,7 +17,7 @@ pub struct DynamicExecutor { output: NodeId, /// Stores all of the dynamic node structs. tree: BorrowTree, - /// Stores the types of the protonodes. + /// Stores the types of the proto nodes. typing_context: TypingContext, // This allows us to keep the nodes around for one more frame which is used for introspection orphaned_nodes: Vec, @@ -111,11 +111,11 @@ impl<'a, I: StaticType + 'a> Executor for &'a DynamicExecutor { pub struct BorrowTree { /// A hashmap of node IDs and dynamically typed nodes. nodes: HashMap, - /// A hashmap from the document path to the protonode ID. + /// A hashmap from the document path to the proto node ID. source_map: HashMap, NodeId>, - /// Each document input source maps to one protonode input (however one protonode input may come from several sources) + /// Each document input source maps to one proto node input (however one proto node input may come from several sources) inputs_source_map: HashMap, - /// A mapping of document input sources to the (single) protonode output + /// A mapping of document input sources to the (single) proto node output outputs_source_map: HashMap, } @@ -193,7 +193,7 @@ impl BorrowTree { .extend((0..params).flat_map(|i| proto_node.original_location.inputs(i).map(move |source| (source, (id, i))))); self.outputs_source_map.extend(proto_node.original_location.outputs(0).map(|source| (source, id))); for x in proto_node.original_location.outputs_source.values() { - assert_eq!(*x, 0, "protonodes should refer to output index 0"); + assert_eq!(*x, 0, "Proto nodes should refer to output index 0"); } match &proto_node.construction_args { diff --git a/website/.eslintrc.js b/website/.eslintrc.js index e4f6d915b1..5cbe47b71c 100644 --- a/website/.eslintrc.js +++ b/website/.eslintrc.js @@ -38,7 +38,7 @@ module.exports = { camelcase: ["error", { properties: "always" }], "linebreak-style": ["error", "unix"], "eol-last": ["error", "always"], - "max-len": ["error", { code: 200, tabWidth: 4 }], + "max-len": ["error", { code: 200, tabWidth: 4, ignorePattern: `d="([\\s\\S]*?)"` }], "prefer-destructuring": "off", "no-console": "warn", "no-debugger": "warn", diff --git a/website/other/bezier-rs-demos/.eslintrc.cjs b/website/other/bezier-rs-demos/.eslintrc.cjs index 50241be8b1..a079a10499 100644 --- a/website/other/bezier-rs-demos/.eslintrc.cjs +++ b/website/other/bezier-rs-demos/.eslintrc.cjs @@ -35,7 +35,7 @@ module.exports = { camelcase: ["error", { properties: "always" }], "linebreak-style": ["error", "unix"], "eol-last": ["error", "always"], - "max-len": ["error", { code: 200, tabWidth: 4 }], + "max-len": ["error", { code: 200, tabWidth: 4, ignorePattern: `d="([\\s\\S]*?)"` }], "prefer-destructuring": "off", "no-console": "warn", "no-debugger": "warn",