diff --git a/editor/src/application.rs b/editor/src/application.rs index 37e2af4bf3..5ca6ae7fed 100644 --- a/editor/src/application.rs +++ b/editor/src/application.rs @@ -68,7 +68,7 @@ mod test { preferences: r#"{"imaginate_server_hostname":"https://exchange-encoding-watched-insured.trycloudflare.com/","imaginate_refresh_frequency":1,"zoom_with_scroll":false}"#.to_string(), }), PortfolioMessage::OpenDocumentFileWithId { - document_id: 0, + document_id: DocumentId(0), document_name: "".into(), document_is_auto_saved: true, document_is_saved: true, diff --git a/editor/src/dispatcher.rs b/editor/src/dispatcher.rs index e6751ac460..00052593b0 100644 --- a/editor/src/dispatcher.rs +++ b/editor/src/dispatcher.rs @@ -256,7 +256,7 @@ impl Dispatcher { mod test { use crate::application::Editor; use crate::messages::portfolio::document::utility_types::clipboards::Clipboard; - use crate::messages::portfolio::document::utility_types::document_metadata::{self, LayerNodeIdentifier}; + use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; use crate::messages::prelude::*; use crate::messages::tool::tool_messages::tool_prelude::ToolType; use crate::test_utils::EditorTestUtils; @@ -359,7 +359,7 @@ mod test { fn copy_paste_folder() { let mut editor = create_editor_with_three_layers(); - const FOLDER_ID: NodeId = 3; + const FOLDER_ID: NodeId = NodeId(3); editor.handle_message(GraphOperationMessage::NewCustomLayer { id: FOLDER_ID, @@ -369,9 +369,6 @@ mod test { }); editor.handle_message(NodeGraphMessage::SelectedNodesSet { nodes: vec![FOLDER_ID] }); - let document_before_added_shapes = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().unwrap().clone(); - let folder_layer = LayerNodeIdentifier::new(FOLDER_ID, &document_before_added_shapes.network); - editor.drag_tool(ToolType::Line, 0., 0., 10., 10.); editor.drag_tool(ToolType::Freehand, 10., 20., 30., 40.); @@ -388,19 +385,20 @@ mod test { let document_after_copy = editor.dispatcher.message_handlers.portfolio_message_handler.active_document().unwrap().clone(); - let layers_before_added_shapes = document_before_added_shapes.metadata.all_layers().collect::>(); let layers_before_copy = document_before_copy.metadata.all_layers().collect::>(); let layers_after_copy = document_after_copy.metadata.all_layers().collect::>(); let [original_folder, original_freehand, original_line, original_ellipse, original_polygon, original_rect] = layers_before_copy[..] else { panic!("Layers before incorrect"); }; - let [duplicated_folder, freehand_dup, line_dup, folder, freehand, line, ellipse, polygon, rect] = layers_after_copy[..] else { + let [_, _, _, folder, freehand, line, ellipse, polygon, rect] = layers_after_copy[..] else { panic!("Layers after incorrect"); }; assert_eq!(original_folder, folder); + assert_eq!(original_freehand, freehand); + assert_eq!(original_line, line); assert_eq!(original_ellipse, ellipse); - assert_eq!(original_rect, rect); assert_eq!(original_polygon, polygon); + assert_eq!(original_rect, rect); } #[test] diff --git a/editor/src/messages/dialog/new_document_dialog/new_document_dialog_message_handler.rs b/editor/src/messages/dialog/new_document_dialog/new_document_dialog_message_handler.rs index 747cb7fcf9..809eab2edf 100644 --- a/editor/src/messages/dialog/new_document_dialog/new_document_dialog_message_handler.rs +++ b/editor/src/messages/dialog/new_document_dialog/new_document_dialog_message_handler.rs @@ -1,6 +1,7 @@ use crate::messages::layout::utility_types::widget_prelude::*; use crate::messages::prelude::*; +use graph_craft::document::NodeId; use graphene_core::uuid::generate_uuid; use glam::{DVec2, IVec2, UVec2}; @@ -26,7 +27,7 @@ impl MessageHandler for NewDocumentDialogMessageHa let create_artboard = !self.infinite && self.dimensions.x > 0 && self.dimensions.y > 0; if create_artboard { - let id = generate_uuid(); + let id = NodeId(generate_uuid()); responses.add(GraphOperationMessage::NewArtboard { id, artboard: graphene_core::Artboard::new(IVec2::ZERO, self.dimensions.as_ivec2()), diff --git a/editor/src/messages/layout/layout_message.rs b/editor/src/messages/layout/layout_message.rs index 25797f82ed..02ab03ce05 100644 --- a/editor/src/messages/layout/layout_message.rs +++ b/editor/src/messages/layout/layout_message.rs @@ -7,7 +7,17 @@ use serde::{Deserialize, Serialize}; #[impl_message(Message, Layout)] #[derive(PartialEq, Clone, Debug, Serialize, Deserialize)] pub enum LayoutMessage { - ResendActiveWidget { layout_target: LayoutTarget, dirty_id: u64 }, - SendLayout { layout: Layout, layout_target: LayoutTarget }, - UpdateLayout { layout_target: LayoutTarget, widget_id: u64, value: serde_json::Value }, + ResendActiveWidget { + layout_target: LayoutTarget, + dirty_id: WidgetId, + }, + SendLayout { + layout: Layout, + layout_target: LayoutTarget, + }, + UpdateLayout { + layout_target: LayoutTarget, + widget_id: WidgetId, + value: serde_json::Value, + }, } diff --git a/editor/src/messages/layout/layout_message_handler.rs b/editor/src/messages/layout/layout_message_handler.rs index 1e471ef939..8c75d4688c 100644 --- a/editor/src/messages/layout/layout_message_handler.rs +++ b/editor/src/messages/layout/layout_message_handler.rs @@ -14,7 +14,7 @@ pub struct LayoutMessageHandler { impl LayoutMessageHandler { /// Get the widget path for the widget with the specified id - fn get_widget_path(widget_layout: &WidgetLayout, id: u64) -> Option<(&WidgetHolder, Vec)> { + fn get_widget_path(widget_layout: &WidgetLayout, id: WidgetId) -> Option<(&WidgetHolder, Vec)> { let mut stack = widget_layout.layout.iter().enumerate().map(|(index, val)| (vec![index], val)).collect::>(); while let Some((mut widget_path, group)) = stack.pop() { match group { diff --git a/editor/src/messages/layout/utility_types/layout_widget.rs b/editor/src/messages/layout/utility_types/layout_widget.rs index 9d8fd7d598..f1262130ae 100644 --- a/editor/src/messages/layout/utility_types/layout_widget.rs +++ b/editor/src/messages/layout/utility_types/layout_widget.rs @@ -10,6 +10,16 @@ use crate::messages::prelude::*; use serde::{Deserialize, Serialize}; use std::sync::Arc; +#[repr(transparent)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, serde::Serialize, serde::Deserialize, specta::Type)] +pub struct WidgetId(pub u64); + +impl core::fmt::Display for WidgetId { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.0) + } +} + #[remain::sorted] #[derive(PartialEq, Clone, Debug, Hash, Eq, Copy, Serialize, Deserialize, specta::Type)] #[repr(u8)] @@ -419,14 +429,17 @@ impl LayoutGroup { #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, specta::Type)] pub struct WidgetHolder { #[serde(rename = "widgetId")] - pub widget_id: u64, + pub widget_id: WidgetId, pub widget: Widget, } impl WidgetHolder { #[deprecated(since = "0.0.0", note = "Please use the builder pattern, e.g. TextLabel::new(\"hello\").widget_holder()")] pub fn new(widget: Widget) -> Self { - Self { widget_id: generate_uuid(), widget } + Self { + widget_id: WidgetId(generate_uuid()), + widget, + } } /// Diffing updates self (where self is old) based on new, updating the list of modifications as it does so. diff --git a/editor/src/messages/portfolio/document/document_message_handler.rs b/editor/src/messages/portfolio/document/document_message_handler.rs index 796a0ce2d7..1853114d00 100644 --- a/editor/src/messages/portfolio/document/document_message_handler.rs +++ b/editor/src/messages/portfolio/document/document_message_handler.rs @@ -174,8 +174,8 @@ fn root_network() -> NodeNetwork { name: "Output".into(), inputs: vec![NodeInput::value(TaggedValue::GraphicGroup(Default::default()), true), NodeInput::Network(concrete!(WasmEditorApi))], implementation: graph_craft::document::DocumentNodeImplementation::Network(NodeNetwork { - inputs: vec![3, 0], - outputs: vec![NodeOutput::new(3, 0)], + inputs: vec![NodeId(3), NodeId(0)], + outputs: vec![NodeOutput::new(NodeId(3), 0)], nodes: [ DocumentNode { name: "EditorApi".to_string(), @@ -185,7 +185,7 @@ fn root_network() -> NodeNetwork { }, DocumentNode { name: "Create Canvas".to_string(), - inputs: vec![NodeInput::node(0, 0)], + inputs: vec![NodeInput::node(NodeId(0), 0)], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_std::wasm_application_io::CreateSurfaceNode")), skip_deduplication: true, ..Default::default() @@ -193,16 +193,16 @@ fn root_network() -> NodeNetwork { DocumentNode { name: "Cache".to_string(), manual_composition: Some(concrete!(())), - inputs: vec![NodeInput::node(1, 0)], + inputs: vec![NodeInput::node(NodeId(1), 0)], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::memo::MemoNode<_, _>")), ..Default::default() }, DocumentNode { name: "RenderNode".to_string(), inputs: vec![ - NodeInput::node(0, 0), + NodeInput::node(NodeId(0), 0), NodeInput::Network(graphene_core::Type::Fn(Box::new(concrete!(Footprint)), Box::new(generic!(T)))), - NodeInput::node(2, 0), + NodeInput::node(NodeId(2), 0), ], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_std::wasm_application_io::RenderNode<_, _, _>")), ..Default::default() @@ -210,7 +210,7 @@ fn root_network() -> NodeNetwork { ] .into_iter() .enumerate() - .map(|(id, node)| (id as NodeId, node)) + .map(|(id, node)| (NodeId(id as u64), node)) .collect(), ..Default::default() }), @@ -345,7 +345,7 @@ impl MessageHandler> for DocumentMessageHand } CommitTransaction => (), CreateEmptyFolder { parent } => { - let id = generate_uuid(); + let id = NodeId(generate_uuid()); responses.add(GraphOperationMessage::NewCustomLayer { id, @@ -416,7 +416,7 @@ impl MessageHandler> for DocumentMessageHand // TODO: Add code that changes the insert index of the new folder based on the selected layer let parent = self.metadata().deepest_common_ancestor(self.metadata().selected_layers(), true).unwrap_or(LayerNodeIdentifier::ROOT); - let folder_id = generate_uuid(); + let folder_id = NodeId(generate_uuid()); responses.add(PortfolioMessage::Copy { clipboard: Clipboard::Internal }); responses.add(DocumentMessage::DeleteSelectedLayers); @@ -547,7 +547,7 @@ impl MessageHandler> for DocumentMessageHand let image_frame = ImageFrame { image, ..Default::default() }; use crate::messages::tool::common_functionality::graph_modification_utils; - let layer = graph_modification_utils::new_image_layer(image_frame, generate_uuid(), self.new_layer_parent(), responses); + let layer = graph_modification_utils::new_image_layer(image_frame, NodeId(generate_uuid()), self.new_layer_parent(), responses); responses.add(NodeGraphMessage::SelectedNodesSet { nodes: vec![layer.to_node()] }); @@ -907,14 +907,14 @@ impl DocumentMessageHandler { path.push(layer_node); // TODO: Skip if folder is not expanded. - structure.push(LayerNodeIdentifier::new_unchecked(space)); + structure.push(LayerNodeIdentifier::new_unchecked(NodeId(space))); self.serialize_structure(layer_node, structure, data, path); space = 0; path.pop(); } } - structure.push(LayerNodeIdentifier::new_unchecked(space | 1 << 63)); + structure.push(LayerNodeIdentifier::new_unchecked(NodeId(space | 1 << 63))); } /// Serializes the layer structure into a condensed 1D structure. @@ -954,10 +954,10 @@ impl DocumentMessageHandler { let mut data = Vec::new(); self.serialize_structure(self.metadata().root(), &mut structure, &mut data, &mut vec![]); - structure[0] = LayerNodeIdentifier::new_unchecked(structure.len() as NodeId - 1); + structure[0] = LayerNodeIdentifier::new_unchecked(NodeId(structure.len() as u64 - 1)); structure.extend(data); - structure.iter().map(|id| id.to_node()).collect::>().as_slice().into() + structure.iter().map(|id| id.to_node().0).collect::>().as_slice().into() } /// Places a document into the history system diff --git a/editor/src/messages/portfolio/document/node_graph/graph_operation_message_handler.rs b/editor/src/messages/portfolio/document/node_graph/graph_operation_message_handler.rs index 7b739bcf56..86e7bb4bd5 100644 --- a/editor/src/messages/portfolio/document/node_graph/graph_operation_message_handler.rs +++ b/editor/src/messages/portfolio/document/node_graph/graph_operation_message_handler.rs @@ -118,7 +118,7 @@ impl<'a> ModifyInputsContext<'a> { } else { // The user has connected another node to the output. Insert a layer node between the output and the node. let node = resolve_document_node_type("Layer").expect("Layer node").default_document_node(); - let node_id = self.insert_between(generate_uuid(), NodeOutput::new(node_id, output_index), output, node, 0, 0, IVec2::new(-8, 0))?; + let node_id = self.insert_between(NodeId(generate_uuid()), NodeOutput::new(node_id, output_index), output, node, 0, 0, IVec2::new(-8, 0))?; sibling_layer = Some(NodeOutput::new(node_id, 0)); } @@ -182,7 +182,7 @@ impl<'a> ModifyInputsContext<'a> { Default::default(), ); self.responses.add(NodeGraphMessage::SendGraph { should_rerender: true }); - self.insert_node_before(generate_uuid(), layer, 0, artboard_node, IVec2::new(-8, 0)) + self.insert_node_before(NodeId(generate_uuid()), layer, 0, artboard_node, IVec2::new(-8, 0)) } fn insert_vector_data(&mut self, subpaths: Vec>, layer: NodeId) { @@ -195,15 +195,15 @@ impl<'a> ModifyInputsContext<'a> { let fill = resolve_document_node_type("Fill").expect("Fill node does not exist").default_document_node(); let stroke = resolve_document_node_type("Stroke").expect("Stroke node does not exist").default_document_node(); - let stroke_id = generate_uuid(); + let stroke_id = NodeId(generate_uuid()); self.insert_node_before(stroke_id, layer, 0, stroke, IVec2::new(-8, 0)); - let fill_id = generate_uuid(); + let fill_id = NodeId(generate_uuid()); self.insert_node_before(fill_id, stroke_id, 0, fill, IVec2::new(-8, 0)); - let transform_id = generate_uuid(); + let transform_id = NodeId(generate_uuid()); self.insert_node_before(transform_id, fill_id, 0, transform, IVec2::new(-8, 0)); - let cull_id = generate_uuid(); + let cull_id = NodeId(generate_uuid()); self.insert_node_before(cull_id, transform_id, 0, cull, IVec2::new(-8, 0)); - let shape_id = generate_uuid(); + let shape_id = NodeId(generate_uuid()); self.insert_node_before(shape_id, cull_id, 0, shape, IVec2::new(-8, 0)); self.responses.add(NodeGraphMessage::SendGraph { should_rerender: true }); } @@ -223,15 +223,15 @@ impl<'a> ModifyInputsContext<'a> { let fill = resolve_document_node_type("Fill").expect("Fill node does not exist").default_document_node(); let stroke = resolve_document_node_type("Stroke").expect("Stroke node does not exist").default_document_node(); - let stroke_id = generate_uuid(); + let stroke_id = NodeId(generate_uuid()); self.insert_node_before(stroke_id, layer, 0, stroke, IVec2::new(-8, 0)); - let fill_id = generate_uuid(); + let fill_id = NodeId(generate_uuid()); self.insert_node_before(fill_id, stroke_id, 0, fill, IVec2::new(-8, 0)); - let transform_id = generate_uuid(); + let transform_id = NodeId(generate_uuid()); self.insert_node_before(transform_id, fill_id, 0, transform, IVec2::new(-8, 0)); - let cull_id = generate_uuid(); + let cull_id = NodeId(generate_uuid()); self.insert_node_before(cull_id, transform_id, 0, cull, IVec2::new(-8, 0)); - let text_id = generate_uuid(); + let text_id = NodeId(generate_uuid()); self.insert_node_before(text_id, cull_id, 0, text, IVec2::new(-8, 0)); self.responses.add(NodeGraphMessage::SendGraph { should_rerender: true }); } @@ -244,11 +244,11 @@ impl<'a> ModifyInputsContext<'a> { let sample = resolve_document_node_type("Sample").expect("Sample node does not exist").default_document_node(); let transform = resolve_document_node_type("Transform").expect("Transform node does not exist").default_document_node(); - let transform_id = generate_uuid(); + let transform_id = NodeId(generate_uuid()); self.insert_node_before(transform_id, layer, 0, transform, IVec2::new(-8, 0)); - let sample_id = generate_uuid(); + let sample_id = NodeId(generate_uuid()); self.insert_node_before(sample_id, transform_id, 0, sample, IVec2::new(-8, 0)); - let image_id = generate_uuid(); + let image_id = NodeId(generate_uuid()); self.insert_node_before(image_id, sample_id, 0, image, IVec2::new(-8, 0)); self.responses.add(NodeGraphMessage::SendGraph { should_rerender: true }); } @@ -283,7 +283,7 @@ impl<'a> ModifyInputsContext<'a> { let metadata = output_node.metadata.clone(); let new_input = output_node.inputs.first().cloned().filter(|input| input.as_node().is_some()); - let node_id = generate_uuid(); + let node_id = NodeId(generate_uuid()); output_node.inputs[0] = NodeInput::node(node_id, 0); @@ -678,10 +678,10 @@ impl MessageHandler = nodes.iter().map(|(&id, _)| (id, crate::application::generate_uuid())).collect(); + let new_ids: HashMap<_, _> = nodes.iter().map(|(&id, _)| (id, NodeId(generate_uuid()))).collect(); let shift = nodes - .get(&0) + .get(&NodeId(0)) .and_then(|node| { modify_inputs .document_network @@ -704,7 +704,7 @@ impl MessageHandler MessageHandler> for NodeGrap }; // Collect the selected nodes - let new_ids = &metadata.selected_nodes().copied().enumerate().map(|(new, old)| (old, new as NodeId)).collect(); + let new_ids = &metadata.selected_nodes().copied().enumerate().map(|(new, old)| (old, NodeId(new as u64))).collect(); let copied_nodes: Vec<_> = Self::copy_nodes(network, new_ids).collect(); // Prefix to show that this is nodes @@ -522,7 +523,7 @@ impl<'a> MessageHandler> for NodeGrap responses.add(FrontendMessage::TriggerTextCopy { copy_text }); } NodeGraphMessage::CreateNode { node_id, node_type, x, y } => { - let node_id = node_id.unwrap_or_else(crate::application::generate_uuid); + let node_id = node_id.unwrap_or_else(|| NodeId(generate_uuid())); let Some(document_node_type) = document_node_types::resolve_document_node_type(&node_type) else { responses.add(DialogMessage::DisplayDialogError { @@ -608,7 +609,7 @@ impl<'a> MessageHandler> for NodeGrap if let Some(network) = document_network.nested_network(&self.network) { responses.add(DocumentMessage::StartTransaction); - let new_ids = &metadata.selected_nodes().map(|&id| (id, crate::application::generate_uuid())).collect(); + let new_ids = &metadata.selected_nodes().map(|&id| (id, NodeId(generate_uuid()))).collect(); metadata.clear_selected_nodes(); responses.add(BroadcastEvent::SelectionChanged); @@ -722,7 +723,7 @@ impl<'a> MessageHandler> for NodeGrap responses.add(DocumentMessage::StartTransaction); - let new_ids: HashMap<_, _> = data.iter().map(|&(id, _)| (id, crate::application::generate_uuid())).collect(); + let new_ids: HashMap<_, _> = data.iter().map(|&(id, _)| (id, NodeId(generate_uuid()))).collect(); for (old_id, mut document_node) in data { // Shift copied node document_node.metadata.position += shift; diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs index 181dfb9011..62f2cbb6d6 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs @@ -203,11 +203,11 @@ fn static_nodes() -> Vec { name: "Layer", category: "General", implementation: NodeImplementation::DocumentNode(NodeNetwork { - inputs: vec![0, 2], - outputs: vec![NodeOutput::new(2, 0)], + inputs: vec![NodeId(0), NodeId(2)], + outputs: vec![NodeOutput::new(NodeId(2), 0)], nodes: [ ( - 0, + NodeId(0), DocumentNode { name: "To Graphic Element".to_string(), inputs: vec![NodeInput::Network(generic!(T))], @@ -217,19 +217,19 @@ fn static_nodes() -> Vec { ), // The monitor node is used to display a thumbnail in the UI. ( - 1, + NodeId(1), DocumentNode { - inputs: vec![NodeInput::node(0, 0)], + inputs: vec![NodeInput::node(NodeId(0), 0)], ..monitor_node() }, ), ( - 2, + NodeId(2), DocumentNode { name: "ConstructLayer".to_string(), manual_composition: Some(concrete!(Footprint)), inputs: vec![ - NodeInput::node(1, 0), + NodeInput::node(NodeId(1), 0), NodeInput::Network(graphene_core::Type::Fn(Box::new(concrete!(Footprint)), Box::new(concrete!(graphene_core::GraphicGroup)))), ], implementation: DocumentNodeImplementation::proto("graphene_core::ConstructLayerNode<_, _>"), @@ -284,8 +284,8 @@ fn static_nodes() -> Vec { name: "Load Image", category: "Structural", implementation: NodeImplementation::DocumentNode(NodeNetwork { - inputs: vec![0, 0], - outputs: vec![NodeOutput::new(1, 0)], + inputs: vec![NodeId(0), NodeId(0)], + outputs: vec![NodeOutput::new(NodeId(1), 0)], nodes: [ DocumentNode { name: "Load Resource".to_string(), @@ -295,14 +295,14 @@ fn static_nodes() -> Vec { }, DocumentNode { name: "Decode Image".to_string(), - inputs: vec![NodeInput::node(0, 0)], + inputs: vec![NodeInput::node(NodeId(0), 0)], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_std::wasm_application_io::DecodeImageNode")), ..Default::default() }, ] .into_iter() .enumerate() - .map(|(id, node)| (id as NodeId, node)) + .map(|(id, node)| (NodeId(id as u64), node)) .collect(), ..Default::default() }), @@ -329,8 +329,8 @@ fn static_nodes() -> Vec { name: "Create Canvas", category: "Structural", implementation: NodeImplementation::DocumentNode(NodeNetwork { - inputs: vec![0], - outputs: vec![NodeOutput::new(1, 0)], + inputs: vec![NodeId(0)], + outputs: vec![NodeOutput::new(NodeId(1), 0)], nodes: [ DocumentNode { name: "Create Canvas".to_string(), @@ -342,14 +342,14 @@ fn static_nodes() -> Vec { DocumentNode { name: "Cache".to_string(), manual_composition: Some(concrete!(())), - inputs: vec![NodeInput::node(0, 0)], + inputs: vec![NodeInput::node(NodeId(0), 0)], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::memo::MemoNode<_, _>")), ..Default::default() }, ] .into_iter() .enumerate() - .map(|(id, node)| (id as NodeId, node)) + .map(|(id, node)| (NodeId(id as u64), node)) .collect(), ..Default::default() }), @@ -368,8 +368,8 @@ fn static_nodes() -> Vec { name: "Draw Canvas", category: "Structural", implementation: NodeImplementation::DocumentNode(NodeNetwork { - inputs: vec![0, 2], - outputs: vec![NodeOutput::new(3, 0)], + inputs: vec![NodeId(0), NodeId(2)], + outputs: vec![NodeOutput::new(NodeId(3), 0)], nodes: [ DocumentNode { name: "Convert Image Frame".to_string(), @@ -387,20 +387,20 @@ fn static_nodes() -> Vec { DocumentNode { name: "Cache".to_string(), manual_composition: Some(concrete!(())), - inputs: vec![NodeInput::node(1, 0)], + inputs: vec![NodeInput::node(NodeId(1), 0)], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::memo::MemoNode<_, _>")), ..Default::default() }, DocumentNode { name: "Draw Canvas".to_string(), - inputs: vec![NodeInput::node(0, 0), NodeInput::node(2, 0)], + inputs: vec![NodeInput::node(NodeId(0), 0), NodeInput::node(NodeId(2), 0)], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_std::wasm_application_io::DrawImageFrameNode<_>")), ..Default::default() }, ] .into_iter() .enumerate() - .map(|(id, node)| (id as NodeId, node)) + .map(|(id, node)| (NodeId(id as u64), node)) .collect(), ..Default::default() }), @@ -426,8 +426,8 @@ fn static_nodes() -> Vec { name: "Begin Scope", category: "Ignore", implementation: NodeImplementation::DocumentNode(NodeNetwork { - inputs: vec![0], - outputs: vec![NodeOutput::new(1, 0), NodeOutput::new(2, 0)], + inputs: vec![NodeId(0)], + outputs: vec![NodeOutput::new(NodeId(1), 0), NodeOutput::new(NodeId(2), 0)], nodes: [ DocumentNode { name: "SetNode".to_string(), @@ -437,21 +437,21 @@ fn static_nodes() -> Vec { }, DocumentNode { name: "LetNode".to_string(), - inputs: vec![NodeInput::node(0, 0)], + inputs: vec![NodeInput::node(NodeId(0), 0)], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::memo::LetNode<_>")), ..Default::default() }, DocumentNode { name: "RefNode".to_string(), manual_composition: Some(concrete!(())), - inputs: vec![NodeInput::lambda(1, 0)], + inputs: vec![NodeInput::lambda(NodeId(1), 0)], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::memo::RefNode<_, _>")), ..Default::default() }, ] .into_iter() .enumerate() - .map(|(id, node)| (id as NodeId, node)) + .map(|(id, node)| (NodeId(id as u64), node)) .collect(), ..Default::default() @@ -501,8 +501,8 @@ fn static_nodes() -> Vec { name: "Output", category: "Ignore", implementation: NodeImplementation::DocumentNode(NodeNetwork { - inputs: vec![3, 0], - outputs: vec![NodeOutput::new(4, 0)], + inputs: vec![NodeId(3), NodeId(0)], + outputs: vec![NodeOutput::new(NodeId(4), 0)], nodes: [ DocumentNode { name: "EditorApi".to_string(), @@ -512,7 +512,7 @@ fn static_nodes() -> Vec { }, DocumentNode { name: "Create Canvas".to_string(), - inputs: vec![NodeInput::node(0, 0)], + inputs: vec![NodeInput::node(NodeId(0), 0)], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_std::wasm_application_io::CreateSurfaceNode")), skip_deduplication: true, ..Default::default() @@ -520,7 +520,7 @@ fn static_nodes() -> Vec { DocumentNode { name: "Cache".to_string(), manual_composition: Some(concrete!(())), - inputs: vec![NodeInput::node(1, 0)], + inputs: vec![NodeInput::node(NodeId(1), 0)], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::memo::MemoNode<_, _>")), ..Default::default() }, @@ -532,14 +532,14 @@ fn static_nodes() -> Vec { }, DocumentNode { name: "RenderNode".to_string(), - inputs: vec![NodeInput::node(0, 0), NodeInput::node(3, 0), NodeInput::node(2, 0)], + inputs: vec![NodeInput::node(NodeId(0), 0), NodeInput::node(NodeId(3), 0), NodeInput::node(NodeId(2), 0)], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_std::wasm_application_io::RenderNode<_, _>")), ..Default::default() }, ] .into_iter() .enumerate() - .map(|(id, node)| (id as NodeId, node)) + .map(|(id, node)| (NodeId(id as u64), node)) .collect(), ..Default::default() }), @@ -809,8 +809,13 @@ fn static_nodes() -> Vec { name: "Split Channels", category: "Image Adjustments", implementation: NodeImplementation::DocumentNode(NodeNetwork { - inputs: vec![0], - outputs: vec![NodeOutput::new(1, 0), NodeOutput::new(2, 0), NodeOutput::new(3, 0), NodeOutput::new(4, 0)], + inputs: vec![NodeId(0)], + outputs: vec![ + NodeOutput::new(NodeId(1), 0), + NodeOutput::new(NodeId(2), 0), + NodeOutput::new(NodeId(3), 0), + NodeOutput::new(NodeId(4), 0), + ], nodes: [ // The input image feeds into the identity, then we take its passed-through value when the other channels are reading from it instead of the original input. // We do this for technical restrictions imposed by Graphene which doesn't allow an input to feed into multiple interior nodes in the subgraph. @@ -823,32 +828,32 @@ fn static_nodes() -> Vec { }, DocumentNode { name: "RedNode".to_string(), - inputs: vec![NodeInput::node(0, 0), NodeInput::value(TaggedValue::RedGreenBlue(RedGreenBlue::Red), false)], + inputs: vec![NodeInput::node(NodeId(0), 0), NodeInput::value(TaggedValue::RedGreenBlue(RedGreenBlue::Red), false)], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::raster::ExtractChannelNode<_>")), ..Default::default() }, DocumentNode { name: "GreenNode".to_string(), - inputs: vec![NodeInput::node(0, 0), NodeInput::value(TaggedValue::RedGreenBlue(RedGreenBlue::Green), false)], + inputs: vec![NodeInput::node(NodeId(0), 0), NodeInput::value(TaggedValue::RedGreenBlue(RedGreenBlue::Green), false)], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::raster::ExtractChannelNode<_>")), ..Default::default() }, DocumentNode { name: "BlueNode".to_string(), - inputs: vec![NodeInput::node(0, 0), NodeInput::value(TaggedValue::RedGreenBlue(RedGreenBlue::Blue), false)], + inputs: vec![NodeInput::node(NodeId(0), 0), NodeInput::value(TaggedValue::RedGreenBlue(RedGreenBlue::Blue), false)], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::raster::ExtractChannelNode<_>")), ..Default::default() }, DocumentNode { name: "AlphaNode".to_string(), - inputs: vec![NodeInput::node(0, 0)], + inputs: vec![NodeInput::node(NodeId(0), 0)], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::raster::ExtractAlphaNode<>")), ..Default::default() }, ] .into_iter() .enumerate() - .map(|(id, node)| (id as NodeId, node)) + .map(|(id, node)| (NodeId(id as u64), node)) .collect(), ..Default::default() @@ -913,8 +918,8 @@ fn static_nodes() -> Vec { name: "Uniform", category: "Gpu", implementation: NodeImplementation::DocumentNode(NodeNetwork { - inputs: vec![1, 0], - outputs: vec![NodeOutput::new(2, 0)], + inputs: vec![NodeId(1), NodeId(0)], + outputs: vec![NodeOutput::new(NodeId(2), 0)], nodes: [ DocumentNode { name: "Extract Executor".to_string(), @@ -924,21 +929,21 @@ fn static_nodes() -> Vec { }, DocumentNode { name: "Create Uniform".to_string(), - inputs: vec![NodeInput::Network(generic!(T)), NodeInput::node(0, 0)], + inputs: vec![NodeInput::Network(generic!(T)), NodeInput::node(NodeId(0), 0)], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("gpu_executor::UniformNode<_>")), ..Default::default() }, DocumentNode { name: "Cache".to_string(), manual_composition: Some(concrete!(())), - inputs: vec![NodeInput::node(1, 0)], + inputs: vec![NodeInput::node(NodeId(1), 0)], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::memo::MemoNode<_, _>")), ..Default::default() }, ] .into_iter() .enumerate() - .map(|(id, node)| (id as NodeId, node)) + .map(|(id, node)| (NodeId(id as u64), node)) .collect(), ..Default::default() }), @@ -965,8 +970,8 @@ fn static_nodes() -> Vec { name: "Storage", category: "Gpu", implementation: NodeImplementation::DocumentNode(NodeNetwork { - inputs: vec![1, 0], - outputs: vec![NodeOutput::new(2, 0)], + inputs: vec![NodeId(1), NodeId(0)], + outputs: vec![NodeOutput::new(NodeId(2), 0)], nodes: [ DocumentNode { name: "Extract Executor".to_string(), @@ -976,21 +981,21 @@ fn static_nodes() -> Vec { }, DocumentNode { name: "Create Storage".to_string(), - inputs: vec![NodeInput::Network(concrete!(Vec)), NodeInput::node(0, 0)], + inputs: vec![NodeInput::Network(concrete!(Vec)), NodeInput::node(NodeId(0), 0)], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("gpu_executor::StorageNode<_>")), ..Default::default() }, DocumentNode { name: "Cache".to_string(), manual_composition: Some(concrete!(())), - inputs: vec![NodeInput::node(1, 0)], + inputs: vec![NodeInput::node(NodeId(1), 0)], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::memo::MemoNode<_, _>")), ..Default::default() }, ] .into_iter() .enumerate() - .map(|(id, node)| (id as NodeId, node)) + .map(|(id, node)| (NodeId(id as u64), node)) .collect(), ..Default::default() }), @@ -1017,8 +1022,8 @@ fn static_nodes() -> Vec { name: "CreateOutputBuffer", category: "Gpu", implementation: NodeImplementation::DocumentNode(NodeNetwork { - inputs: vec![1, 1, 0], - outputs: vec![NodeOutput::new(2, 0)], + inputs: vec![NodeId(1), NodeId(1), NodeId(0)], + outputs: vec![NodeOutput::new(NodeId(2), 0)], nodes: [ DocumentNode { name: "Extract Executor".to_string(), @@ -1028,21 +1033,21 @@ fn static_nodes() -> Vec { }, DocumentNode { name: "Create Output Buffer".to_string(), - inputs: vec![NodeInput::Network(concrete!(usize)), NodeInput::node(0, 0), NodeInput::Network(concrete!(Type))], + inputs: vec![NodeInput::Network(concrete!(usize)), NodeInput::node(NodeId(0), 0), NodeInput::Network(concrete!(Type))], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("gpu_executor::CreateOutputBufferNode<_, _>")), ..Default::default() }, DocumentNode { name: "Cache".to_string(), manual_composition: Some(concrete!(())), - inputs: vec![NodeInput::node(1, 0)], + inputs: vec![NodeInput::node(NodeId(1), 0)], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::memo::MemoNode<_, _>")), ..Default::default() }, ] .into_iter() .enumerate() - .map(|(id, node)| (id as NodeId, node)) + .map(|(id, node)| (NodeId(id as u64), node)) .collect(), ..Default::default() }), @@ -1075,8 +1080,8 @@ fn static_nodes() -> Vec { name: "CreateComputePass", category: "Gpu", implementation: NodeImplementation::DocumentNode(NodeNetwork { - inputs: vec![1, 0, 1, 1], - outputs: vec![NodeOutput::new(2, 0)], + inputs: vec![NodeId(1), NodeId(0), NodeId(1), NodeId(1)], + outputs: vec![NodeOutput::new(NodeId(2), 0)], nodes: [ DocumentNode { name: "Extract Executor".to_string(), @@ -1088,7 +1093,7 @@ fn static_nodes() -> Vec { name: "Create Compute Pass".to_string(), inputs: vec![ NodeInput::Network(concrete!(gpu_executor::PipelineLayout)), - NodeInput::node(0, 0), + NodeInput::node(NodeId(0), 0), NodeInput::Network(concrete!(ShaderInput)), NodeInput::Network(concrete!(gpu_executor::ComputePassDimensions)), ], @@ -1098,14 +1103,14 @@ fn static_nodes() -> Vec { DocumentNode { name: "Cache".to_string(), manual_composition: Some(concrete!(())), - inputs: vec![NodeInput::node(1, 0)], + inputs: vec![NodeInput::node(NodeId(1), 0)], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::memo::MemoNode<_, _>")), ..Default::default() }, ] .into_iter() .enumerate() - .map(|(id, node)| (id as NodeId, node)) + .map(|(id, node)| (NodeId(id as u64), node)) .collect(), ..Default::default() }), @@ -1177,8 +1182,8 @@ fn static_nodes() -> Vec { name: "ExecuteComputePipeline", category: "Gpu", implementation: NodeImplementation::DocumentNode(NodeNetwork { - inputs: vec![1, 0], - outputs: vec![NodeOutput::new(2, 0)], + inputs: vec![NodeId(1), NodeId(0)], + outputs: vec![NodeOutput::new(NodeId(2), 0)], nodes: [ DocumentNode { name: "Extract Executor".to_string(), @@ -1188,21 +1193,21 @@ fn static_nodes() -> Vec { }, DocumentNode { name: "Execute Compute Pipeline".to_string(), - inputs: vec![NodeInput::Network(concrete!(::CommandBuffer)), NodeInput::node(0, 0)], + inputs: vec![NodeInput::Network(concrete!(::CommandBuffer)), NodeInput::node(NodeId(0), 0)], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("gpu_executor::ExecuteComputePipelineNode<_>")), ..Default::default() }, DocumentNode { name: "Cache".to_string(), manual_composition: Some(concrete!(())), - inputs: vec![NodeInput::node(1, 0)], + inputs: vec![NodeInput::node(NodeId(1), 0)], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::memo::MemoNode<_, _>")), ..Default::default() }, ] .into_iter() .enumerate() - .map(|(id, node)| (id as NodeId, node)) + .map(|(id, node)| (NodeId(id as u64), node)) .collect(), ..Default::default() }), @@ -1229,8 +1234,8 @@ fn static_nodes() -> Vec { name: "ReadOutputBuffer", category: "Gpu", implementation: NodeImplementation::DocumentNode(NodeNetwork { - inputs: vec![1, 0], - outputs: vec![NodeOutput::new(2, 0)], + inputs: vec![NodeId(1), NodeId(0)], + outputs: vec![NodeOutput::new(NodeId(2), 0)], nodes: [ DocumentNode { name: "Extract Executor".to_string(), @@ -1240,21 +1245,21 @@ fn static_nodes() -> Vec { }, DocumentNode { name: "Read Output Buffer".to_string(), - inputs: vec![NodeInput::Network(concrete!(Arc>)), NodeInput::node(0, 0)], + inputs: vec![NodeInput::Network(concrete!(Arc>)), NodeInput::node(NodeId(0), 0)], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("gpu_executor::ReadOutputBufferNode<_, _>")), ..Default::default() }, DocumentNode { name: "Cache".to_string(), manual_composition: Some(concrete!(())), - inputs: vec![NodeInput::node(1, 0)], + inputs: vec![NodeInput::node(NodeId(1), 0)], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::memo::MemoNode<_, _>")), ..Default::default() }, ] .into_iter() .enumerate() - .map(|(id, node)| (id as NodeId, node)) + .map(|(id, node)| (NodeId(id as u64), node)) .collect(), ..Default::default() }), @@ -1281,8 +1286,8 @@ fn static_nodes() -> Vec { name: "CreateGpuSurface", category: "Gpu", implementation: NodeImplementation::DocumentNode(NodeNetwork { - inputs: vec![0], - outputs: vec![NodeOutput::new(1, 0)], + inputs: vec![NodeId(0)], + outputs: vec![NodeOutput::new(NodeId(1), 0)], nodes: [ DocumentNode { name: "Create Gpu Surface".to_string(), @@ -1293,14 +1298,14 @@ fn static_nodes() -> Vec { DocumentNode { name: "Cache".to_string(), manual_composition: Some(concrete!(())), - inputs: vec![NodeInput::node(0, 0)], + inputs: vec![NodeInput::node(NodeId(0), 0)], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::memo::MemoNode<_, _>")), ..Default::default() }, ] .into_iter() .enumerate() - .map(|(id, node)| (id as NodeId, node)) + .map(|(id, node)| (NodeId(id as u64), node)) .collect(), ..Default::default() }), @@ -1320,8 +1325,8 @@ fn static_nodes() -> Vec { name: "RenderTexture", category: "Gpu", implementation: NodeImplementation::DocumentNode(NodeNetwork { - inputs: vec![1, 1, 0], - outputs: vec![NodeOutput::new(1, 0)], + inputs: vec![NodeId(1), NodeId(1), NodeId(0)], + outputs: vec![NodeOutput::new(NodeId(1), 0)], nodes: [ DocumentNode { name: "Extract Executor".to_string(), @@ -1334,7 +1339,7 @@ fn static_nodes() -> Vec { inputs: vec![ NodeInput::Network(concrete!(ShaderInputFrame)), NodeInput::Network(concrete!(Arc::Surface>>)), - NodeInput::node(0, 0), + NodeInput::node(NodeId(0), 0), ], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("gpu_executor::RenderTextureNode<_, _>")), ..Default::default() @@ -1342,7 +1347,7 @@ fn static_nodes() -> Vec { ] .into_iter() .enumerate() - .map(|(id, node)| (id as NodeId, node)) + .map(|(id, node)| (NodeId(id as u64), node)) .collect(), ..Default::default() }), @@ -1374,8 +1379,8 @@ fn static_nodes() -> Vec { name: "UploadTexture", category: "Gpu", implementation: NodeImplementation::DocumentNode(NodeNetwork { - inputs: vec![1, 0], - outputs: vec![NodeOutput::new(2, 0)], + inputs: vec![NodeId(1), NodeId(0)], + outputs: vec![NodeOutput::new(NodeId(2), 0)], nodes: [ DocumentNode { name: "Extract Executor".to_string(), @@ -1385,21 +1390,21 @@ fn static_nodes() -> Vec { }, DocumentNode { name: "Upload Texture".to_string(), - inputs: vec![NodeInput::Network(concrete!(ImageFrame)), NodeInput::node(0, 0)], + inputs: vec![NodeInput::Network(concrete!(ImageFrame)), NodeInput::node(NodeId(0), 0)], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("gpu_executor::UploadTextureNode<_>")), ..Default::default() }, DocumentNode { name: "Cache".to_string(), manual_composition: Some(concrete!(())), - inputs: vec![NodeInput::node(1, 0)], + inputs: vec![NodeInput::node(NodeId(1), 0)], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::memo::MemoNode<_, _>")), ..Default::default() }, ] .into_iter() .enumerate() - .map(|(id, node)| (id as NodeId, node)) + .map(|(id, node)| (NodeId(id as u64), node)) .collect(), ..Default::default() }), @@ -2149,8 +2154,8 @@ fn static_nodes() -> Vec { name: "Transform", category: "Transform", implementation: NodeImplementation::DocumentNode(NodeNetwork { - inputs: vec![0, 1, 1, 1, 1, 1], - outputs: vec![NodeOutput::new(1, 0)], + inputs: vec![NodeId(0), NodeId(1), NodeId(1), NodeId(1), NodeId(1), NodeId(1)], + outputs: vec![NodeOutput::new(NodeId(1), 0)], nodes: [ DocumentNode { inputs: vec![NodeInput::Network(concrete!(VectorData))], @@ -2159,7 +2164,7 @@ fn static_nodes() -> Vec { DocumentNode { name: "Transform".to_string(), inputs: vec![ - NodeInput::node(0, 0), + NodeInput::node(NodeId(0), 0), NodeInput::Network(concrete!(DVec2)), NodeInput::Network(concrete!(f32)), NodeInput::Network(concrete!(DVec2)), @@ -2173,7 +2178,7 @@ fn static_nodes() -> Vec { ] .into_iter() .enumerate() - .map(|(id, node)| (id as NodeId, node)) + .map(|(id, node)| (NodeId(id as u64), node)) .collect(), ..Default::default() }), @@ -2375,22 +2380,40 @@ pub static IMAGINATE_NODE: Lazy = Lazy::new(|| DocumentN name: "Imaginate", category: "Image Synthesis", implementation: NodeImplementation::DocumentNode(NodeNetwork { - inputs: vec![0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - outputs: vec![NodeOutput::new(1, 0)], + inputs: vec![ + NodeId(0), + NodeId(1), + NodeId(1), + NodeId(1), + NodeId(1), + NodeId(1), + NodeId(1), + NodeId(1), + NodeId(1), + NodeId(1), + NodeId(1), + NodeId(1), + NodeId(1), + NodeId(1), + NodeId(1), + NodeId(1), + NodeId(1), + ], + outputs: vec![NodeOutput::new(NodeId(1), 0)], nodes: [ ( - 0, + NodeId(0), DocumentNode { inputs: vec![NodeInput::Network(concrete!(ImageFrame))], ..monitor_node() }, ), ( - 1, + NodeId(1), DocumentNode { name: "Imaginate".into(), inputs: vec![ - NodeInput::node(0, 0), + NodeInput::node(NodeId(0), 0), NodeInput::Network(concrete!(WasmEditorApi)), NodeInput::Network(concrete!(ImaginateController)), NodeInput::Network(concrete!(f64)), @@ -2468,9 +2491,9 @@ impl DocumentNodeDefinition { /* NodeNetwork { inputs: (0..num_inputs).map(|_| 0).collect(), - outputs: vec![NodeOutput::new(0, 0)], + outputs: vec![NodeOutput::new(NodeId(0), 0)], nodes: [( - 0, + NodeId(0), DocumentNode { name: format!("{}_impl", self.name), // TODO: Allow inserting nodes that contain other nodes. @@ -2483,8 +2506,6 @@ impl DocumentNodeDefinition { .collect(), ..Default::default() } - - } */ NodeImplementation::Extract => return DocumentNodeImplementation::Extract, }; @@ -2555,7 +2576,7 @@ pub fn wrap_network_in_scope(mut network: NodeNetwork, hash: u64) -> NodeNetwork let inner_network = DocumentNode { name: "Scope".to_string(), implementation: DocumentNodeImplementation::Network(network), - inputs: core::iter::repeat(NodeInput::node(0, 1)).take(len).collect(), + inputs: core::iter::repeat(NodeInput::node(NodeId(0), 1)).take(len).collect(), ..Default::default() }; @@ -2563,7 +2584,7 @@ pub fn wrap_network_in_scope(mut network: NodeNetwork, hash: u64) -> NodeNetwork .expect("Begin Scope node type not found") .to_document_node(vec![input_type.unwrap()], DocumentNodeMetadata::default()); if let DocumentNodeImplementation::Network(g) = &mut begin_scope.implementation { - if let Some(node) = g.nodes.get_mut(&0) { + if let Some(node) = g.nodes.get_mut(&NodeId(0)) { node.world_state_hash = hash; } } @@ -2574,20 +2595,20 @@ pub fn wrap_network_in_scope(mut network: NodeNetwork, hash: u64) -> NodeNetwork inner_network, resolve_document_node_type("End Scope") .expect("End Scope node type not found") - .to_document_node(vec![NodeInput::node(0, 0), NodeInput::node(1, 0)], DocumentNodeMetadata::default()), + .to_document_node(vec![NodeInput::node(NodeId(0), 0), NodeInput::node(NodeId(1), 0)], DocumentNodeMetadata::default()), ]; NodeNetwork { - inputs: vec![0], - outputs: vec![NodeOutput::new(2, 0)], - nodes: nodes.into_iter().enumerate().map(|(id, node)| (id as NodeId, node)).collect(), + inputs: vec![NodeId(0)], + outputs: vec![NodeOutput::new(NodeId(2), 0)], + nodes: nodes.into_iter().enumerate().map(|(id, node)| (NodeId(id as u64), node)).collect(), ..Default::default() } } pub fn new_image_network(output_offset: i32, output_node_id: NodeId) -> NodeNetwork { let mut network = NodeNetwork { - inputs: vec![0], + inputs: vec![NodeId(0)], ..Default::default() }; network.push_node( @@ -2611,7 +2632,7 @@ pub fn new_text_network(text: String, font: Font, size: f64) -> NodeNetwork { let output = resolve_document_node_type("Output").expect("Output node does not exist"); let mut network = NodeNetwork { - inputs: vec![0], + inputs: vec![NodeId(0)], ..Default::default() }; network.push_node(text_generator.to_document_node( 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 c31415b677..a679caf63e 100644 --- a/editor/src/messages/portfolio/document/utility_types/document_metadata.rs +++ b/editor/src/messages/portfolio/document/utility_types/document_metadata.rs @@ -363,12 +363,12 @@ impl core::fmt::Debug for LayerNodeIdentifier { } impl LayerNodeIdentifier { - pub const ROOT: Self = LayerNodeIdentifier::new_unchecked(0); + pub const ROOT: Self = LayerNodeIdentifier::new_unchecked(NodeId(0)); /// Construct a [`LayerNodeIdentifier`] without checking if it is a layer node pub const fn new_unchecked(node_id: NodeId) -> Self { // Safety: will always be >=1 - Self(unsafe { NonZeroU64::new_unchecked(node_id + 1) }) + Self(unsafe { NonZeroU64::new_unchecked(node_id.0 + 1) }) } /// Construct a [`LayerNodeIdentifier`], debug asserting that it is a layer node @@ -384,7 +384,7 @@ impl LayerNodeIdentifier { /// Access the node id of this layer pub fn to_node(self) -> NodeId { - u64::from(self.0) - 1 + NodeId(u64::from(self.0) - 1) } /// Access the parent layer if possible @@ -662,32 +662,44 @@ fn test_tree() { let mut document_metadata = DocumentMetadata::default(); let root = document_metadata.root(); let document_metadata = &mut document_metadata; - root.push_child(document_metadata, LayerNodeIdentifier::new_unchecked(3)); - assert_eq!(root.children(document_metadata).collect::>(), vec![LayerNodeIdentifier::new_unchecked(3)]); - root.push_child(document_metadata, LayerNodeIdentifier::new_unchecked(6)); - assert_eq!(root.children(document_metadata).map(LayerNodeIdentifier::to_node).collect::>(), vec![3, 6]); - assert_eq!(root.decendants(document_metadata).map(LayerNodeIdentifier::to_node).collect::>(), vec![3, 6]); - LayerNodeIdentifier::new_unchecked(3).add_after(document_metadata, LayerNodeIdentifier::new_unchecked(4)); - LayerNodeIdentifier::new_unchecked(3).add_before(document_metadata, LayerNodeIdentifier::new_unchecked(2)); - LayerNodeIdentifier::new_unchecked(6).add_before(document_metadata, LayerNodeIdentifier::new_unchecked(5)); - LayerNodeIdentifier::new_unchecked(6).add_after(document_metadata, LayerNodeIdentifier::new_unchecked(9)); - LayerNodeIdentifier::new_unchecked(6).push_child(document_metadata, LayerNodeIdentifier::new_unchecked(8)); - LayerNodeIdentifier::new_unchecked(6).push_front_child(document_metadata, LayerNodeIdentifier::new_unchecked(7)); - root.push_front_child(document_metadata, LayerNodeIdentifier::new_unchecked(1)); - assert_eq!(root.children(document_metadata).map(LayerNodeIdentifier::to_node).collect::>(), vec![1, 2, 3, 4, 5, 6, 9]); + root.push_child(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(3))); + assert_eq!(root.children(document_metadata).collect::>(), vec![LayerNodeIdentifier::new_unchecked(NodeId(3))]); + root.push_child(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(6))); + assert_eq!(root.children(document_metadata).map(LayerNodeIdentifier::to_node).collect::>(), vec![NodeId(3), NodeId(6)]); + assert_eq!(root.decendants(document_metadata).map(LayerNodeIdentifier::to_node).collect::>(), vec![NodeId(3), NodeId(6)]); + LayerNodeIdentifier::new_unchecked(NodeId(3)).add_after(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(4))); + LayerNodeIdentifier::new_unchecked(NodeId(3)).add_before(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(2))); + LayerNodeIdentifier::new_unchecked(NodeId(6)).add_before(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(5))); + LayerNodeIdentifier::new_unchecked(NodeId(6)).add_after(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(9))); + LayerNodeIdentifier::new_unchecked(NodeId(6)).push_child(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(8))); + LayerNodeIdentifier::new_unchecked(NodeId(6)).push_front_child(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(7))); + root.push_front_child(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(1))); + assert_eq!( + root.children(document_metadata).map(LayerNodeIdentifier::to_node).collect::>(), + vec![NodeId(1), NodeId(2), NodeId(3), NodeId(4), NodeId(5), NodeId(6), NodeId(9)] + ); assert_eq!( root.decendants(document_metadata).map(LayerNodeIdentifier::to_node).collect::>(), - vec![1, 2, 3, 4, 5, 6, 7, 8, 9] + vec![NodeId(1), NodeId(2), NodeId(3), NodeId(4), NodeId(5), NodeId(6), NodeId(7), NodeId(8), NodeId(9)] ); assert_eq!( root.decendants(document_metadata).map(LayerNodeIdentifier::to_node).rev().collect::>(), - vec![9, 8, 7, 6, 5, 4, 3, 2, 1] + vec![NodeId(9), NodeId(8), NodeId(7), NodeId(6), NodeId(5), NodeId(4), NodeId(3), NodeId(2), NodeId(1)] ); assert!(root.children(document_metadata).all(|child| child.parent(document_metadata) == Some(root))); - LayerNodeIdentifier::new_unchecked(6).delete(document_metadata); - LayerNodeIdentifier::new_unchecked(1).delete(document_metadata); - LayerNodeIdentifier::new_unchecked(9).push_child(document_metadata, LayerNodeIdentifier::new_unchecked(10)); - assert_eq!(root.children(document_metadata).map(LayerNodeIdentifier::to_node).collect::>(), vec![2, 3, 4, 5, 9]); - assert_eq!(root.decendants(document_metadata).map(LayerNodeIdentifier::to_node).collect::>(), vec![2, 3, 4, 5, 9, 10]); - assert_eq!(root.decendants(document_metadata).map(LayerNodeIdentifier::to_node).rev().collect::>(), vec![10, 9, 5, 4, 3, 2]); + LayerNodeIdentifier::new_unchecked(NodeId(6)).delete(document_metadata); + LayerNodeIdentifier::new_unchecked(NodeId(1)).delete(document_metadata); + LayerNodeIdentifier::new_unchecked(NodeId(9)).push_child(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(10))); + assert_eq!( + root.children(document_metadata).map(LayerNodeIdentifier::to_node).collect::>(), + vec![NodeId(2), NodeId(3), NodeId(4), NodeId(5), NodeId(9)] + ); + assert_eq!( + root.decendants(document_metadata).map(LayerNodeIdentifier::to_node).collect::>(), + vec![NodeId(2), NodeId(3), NodeId(4), NodeId(5), NodeId(9), NodeId(10)] + ); + assert_eq!( + root.decendants(document_metadata).map(LayerNodeIdentifier::to_node).rev().collect::>(), + vec![NodeId(10), NodeId(9), NodeId(5), NodeId(4), NodeId(3), NodeId(2)] + ); } diff --git a/editor/src/messages/portfolio/document/utility_types/misc.rs b/editor/src/messages/portfolio/document/utility_types/misc.rs index f347ad3d83..6700544ac4 100644 --- a/editor/src/messages/portfolio/document/utility_types/misc.rs +++ b/editor/src/messages/portfolio/document/utility_types/misc.rs @@ -4,6 +4,10 @@ use glam::DVec2; use serde::{Deserialize, Serialize}; use std::fmt; +#[repr(transparent)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, serde::Serialize, serde::Deserialize, specta::Type)] +pub struct DocumentId(pub u64); + #[derive(PartialEq, Eq, Clone, Copy, Debug, Serialize, Deserialize, Hash)] pub enum FlipAxis { X, diff --git a/editor/src/messages/portfolio/portfolio_message_handler.rs b/editor/src/messages/portfolio/portfolio_message_handler.rs index da77df04d7..0b8dc5c24a 100644 --- a/editor/src/messages/portfolio/portfolio_message_handler.rs +++ b/editor/src/messages/portfolio/portfolio_message_handler.rs @@ -187,7 +187,7 @@ impl MessageHandler { let new_document = DocumentMessageHandler::with_name(name, ipp, responses); - let document_id = generate_uuid(); + let document_id = DocumentId(generate_uuid()); if self.active_document().is_some() { responses.add(BroadcastEvent::ToolAbort); responses.add(NavigationMessage::TranslateCanvas { delta: (0., 0.).into() }); @@ -353,7 +353,7 @@ impl MessageHandler { responses.add(PortfolioMessage::OpenDocumentFileWithId { - document_id: generate_uuid(), + document_id: DocumentId(generate_uuid()), document_name, document_is_auto_saved: false, document_is_saved: true, @@ -389,7 +389,7 @@ impl MessageHandler| { if self.active_document().is_some() { trace!("Pasting into folder {parent:?} as index: {insert_index}"); - let id = generate_uuid(); + let id = NodeId(generate_uuid()); responses.add(GraphOperationMessage::NewCustomLayer { id, nodes: entry.nodes.clone(), @@ -422,7 +422,7 @@ impl MessageHandler); diff --git a/editor/src/messages/tool/tool_messages/artboard_tool.rs b/editor/src/messages/tool/tool_messages/artboard_tool.rs index 0cbb7bee75..612aa7fc44 100644 --- a/editor/src/messages/tool/tool_messages/artboard_tool.rs +++ b/editor/src/messages/tool/tool_messages/artboard_tool.rs @@ -7,6 +7,7 @@ use crate::messages::tool::common_functionality::snapping::SnapManager; use crate::messages::tool::common_functionality::transformation_cage::*; use glam::{IVec2, Vec2Swizzles}; +use graph_craft::document::NodeId; #[derive(Default)] pub struct ArtboardTool { @@ -273,7 +274,7 @@ impl Fsm for ArtboardToolFsmState { dimensions: size.round().as_ivec2(), }); } else { - let id = generate_uuid(); + let id = NodeId(generate_uuid()); tool_data.selected_artboard = Some(LayerNodeIdentifier::new_unchecked(id)); tool_data.snap_manager.start_snap(document, input, document.bounding_boxes(), true, true); diff --git a/editor/src/messages/tool/tool_messages/brush_tool.rs b/editor/src/messages/tool/tool_messages/brush_tool.rs index 0dad7bb11d..76331f187c 100644 --- a/editor/src/messages/tool/tool_messages/brush_tool.rs +++ b/editor/src/messages/tool/tool_messages/brush_tool.rs @@ -5,7 +5,7 @@ use crate::messages::portfolio::document::utility_types::document_metadata::Laye use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType}; use graph_craft::document::value::TaggedValue; -use graph_craft::document::{DocumentNodeMetadata, NodeInput}; +use graph_craft::document::{DocumentNodeMetadata, NodeId, NodeInput}; use graphene_core::raster::BlendMode; use graphene_core::uuid::generate_uuid; use graphene_core::vector::brush_stroke::{BrushInputSample, BrushStroke, BrushStyle}; @@ -422,12 +422,12 @@ fn new_brush_layer(document: &DocumentMessageHandler, responses: &mut VecDeque { shape_data.start(responses, document, input); responses.add(DocumentMessage::StartTransaction); - shape_data.layer = Some(LayerNodeIdentifier::new(generate_uuid(), document.network())); + shape_data.layer = Some(LayerNodeIdentifier::new(NodeId(generate_uuid()), document.network())); responses.add(DocumentMessage::DeselectAllLayers); use graph_craft::document::*; @@ -140,15 +140,17 @@ impl Fsm for ImaginateToolFsmState { let imaginate_node_type = &*IMAGINATE_NODE; // Give them a unique ID - let [transform_node_id, imaginate_node_id] = [100, 101]; + let transform_node_id = NodeId(100); + let imaginate_node_id = NodeId(101); // Create the network based on the Input -> Output passthrough default network let mut network = node_graph::new_image_network(16, imaginate_node_id); // Insert the nodes into the default network - network - .nodes - .insert(transform_node_id, transform_node_type.to_document_node_default_inputs([Some(NodeInput::node(0, 0))], next_pos())); + network.nodes.insert( + transform_node_id, + transform_node_type.to_document_node_default_inputs([Some(NodeInput::node(NodeId(0), 0))], next_pos()), + ); network.nodes.insert( imaginate_node_id, imaginate_node_type.to_document_node_default_inputs([Some(graph_craft::document::NodeInput::node(transform_node_id, 0))], next_pos()), diff --git a/editor/src/messages/tool/tool_messages/line_tool.rs b/editor/src/messages/tool/tool_messages/line_tool.rs index 47edbb75ab..95b5eaec5d 100644 --- a/editor/src/messages/tool/tool_messages/line_tool.rs +++ b/editor/src/messages/tool/tool_messages/line_tool.rs @@ -5,6 +5,7 @@ use crate::messages::tool::common_functionality::color_selector::{ToolColorOptio use crate::messages::tool::common_functionality::graph_modification_utils; use crate::messages::tool::common_functionality::snapping::SnapManager; +use graph_craft::document::NodeId; use graphene_core::uuid::generate_uuid; use graphene_core::vector::style::Stroke; use graphene_core::Color; @@ -183,7 +184,7 @@ impl Fsm for LineToolFsmState { responses.add(DocumentMessage::StartTransaction); - let layer = graph_modification_utils::new_vector_layer(vec![subpath], generate_uuid(), document.new_layer_parent(), responses); + let layer = graph_modification_utils::new_vector_layer(vec![subpath], NodeId(generate_uuid()), document.new_layer_parent(), responses); responses.add(GraphOperationMessage::StrokeSet { layer, stroke: Stroke::new(tool_options.stroke.active_color(), tool_options.line_weight), diff --git a/editor/src/messages/tool/tool_messages/pen_tool.rs b/editor/src/messages/tool/tool_messages/pen_tool.rs index 1165e0de1a..a385d5a5ea 100644 --- a/editor/src/messages/tool/tool_messages/pen_tool.rs +++ b/editor/src/messages/tool/tool_messages/pen_tool.rs @@ -9,6 +9,7 @@ use crate::messages::tool::common_functionality::graph_modification_utils; use crate::messages::tool::common_functionality::graph_modification_utils::get_subpaths; use crate::messages::tool::common_functionality::snapping::SnapManager; +use graph_craft::document::NodeId; use graphene_core::uuid::{generate_uuid, ManipulatorGroupId}; use graphene_core::vector::style::{Fill, Stroke}; use graphene_core::vector::{ManipulatorPointId, SelectedType}; @@ -255,7 +256,7 @@ impl PenToolData { // Create the initial shape with a `bez_path` (only contains a moveto initially) let subpath = bezier_rs::Subpath::new(vec![bezier_rs::ManipulatorGroup::new(start_position, Some(start_position), Some(start_position))], false); - let layer = graph_modification_utils::new_vector_layer(vec![subpath], generate_uuid(), parent, responses); + let layer = graph_modification_utils::new_vector_layer(vec![subpath], NodeId(generate_uuid()), parent, responses); self.layer = Some(layer); responses.add(GraphOperationMessage::FillSet { diff --git a/editor/src/messages/tool/tool_messages/polygon_tool.rs b/editor/src/messages/tool/tool_messages/polygon_tool.rs index 9031089778..64010ed177 100644 --- a/editor/src/messages/tool/tool_messages/polygon_tool.rs +++ b/editor/src/messages/tool/tool_messages/polygon_tool.rs @@ -3,6 +3,7 @@ use crate::messages::tool::common_functionality::color_selector::{ToolColorOptio use crate::messages::tool::common_functionality::graph_modification_utils; use crate::messages::tool::common_functionality::resize::Resize; +use graph_craft::document::NodeId; use graphene_core::uuid::generate_uuid; use graphene_core::vector::style::{Fill, Stroke}; use graphene_core::Color; @@ -246,7 +247,7 @@ impl Fsm for PolygonToolFsmState { PrimitiveShapeType::Polygon => bezier_rs::Subpath::new_regular_polygon(DVec2::ZERO, tool_options.vertices as u64, 1.), PrimitiveShapeType::Star => bezier_rs::Subpath::new_star_polygon(DVec2::ZERO, tool_options.vertices as u64, 1., 0.5), }; - let layer = graph_modification_utils::new_vector_layer(vec![subpath], generate_uuid(), document.new_layer_parent(), responses); + let layer = graph_modification_utils::new_vector_layer(vec![subpath], NodeId(generate_uuid()), document.new_layer_parent(), responses); polygon_data.layer = Some(layer); let fill_color = tool_options.fill.active_color(); diff --git a/editor/src/messages/tool/tool_messages/rectangle_tool.rs b/editor/src/messages/tool/tool_messages/rectangle_tool.rs index e6890410d8..6bbeca1a8e 100644 --- a/editor/src/messages/tool/tool_messages/rectangle_tool.rs +++ b/editor/src/messages/tool/tool_messages/rectangle_tool.rs @@ -3,6 +3,7 @@ use crate::messages::tool::common_functionality::color_selector::{ToolColorOptio use crate::messages::tool::common_functionality::graph_modification_utils; use crate::messages::tool::common_functionality::resize::Resize; +use graph_craft::document::NodeId; use graphene_core::uuid::generate_uuid; use graphene_core::vector::style::{Fill, Stroke}; use graphene_core::Color; @@ -215,7 +216,7 @@ impl Fsm for RectangleToolFsmState { responses.add(DocumentMessage::StartTransaction); - let layer = graph_modification_utils::new_vector_layer(vec![subpath], generate_uuid(), document.new_layer_parent(), responses); + let layer = graph_modification_utils::new_vector_layer(vec![subpath], NodeId(generate_uuid()), document.new_layer_parent(), responses); shape_data.layer = Some(layer); let fill_color = tool_options.fill.active_color(); diff --git a/editor/src/messages/tool/tool_messages/spline_tool.rs b/editor/src/messages/tool/tool_messages/spline_tool.rs index dc104367c5..96cdef4731 100644 --- a/editor/src/messages/tool/tool_messages/spline_tool.rs +++ b/editor/src/messages/tool/tool_messages/spline_tool.rs @@ -6,6 +6,7 @@ use crate::messages::tool::common_functionality::color_selector::{ToolColorOptio use crate::messages::tool::common_functionality::graph_modification_utils; use crate::messages::tool::common_functionality::snapping::SnapManager; +use graph_craft::document::NodeId; use graphene_core::uuid::generate_uuid; use graphene_core::vector::style::{Fill, Stroke}; use graphene_core::Color; @@ -224,7 +225,7 @@ impl Fsm for SplineToolFsmState { tool_data.weight = tool_options.line_weight; - let layer = graph_modification_utils::new_vector_layer(vec![], generate_uuid(), parent, responses); + let layer = graph_modification_utils::new_vector_layer(vec![], NodeId(generate_uuid()), parent, responses); responses.add(GraphOperationMessage::FillSet { layer, diff --git a/editor/src/messages/tool/tool_messages/text_tool.rs b/editor/src/messages/tool/tool_messages/text_tool.rs index 27e9b4b47f..3ac63fb7d8 100644 --- a/editor/src/messages/tool/tool_messages/text_tool.rs +++ b/editor/src/messages/tool/tool_messages/text_tool.rs @@ -8,6 +8,7 @@ use crate::messages::tool::common_functionality::color_selector::{ToolColorOptio use crate::messages::tool::common_functionality::graph_modification_utils::{self, is_layer_fed_by_node_of_name}; use graph_craft::document::value::TaggedValue; +use graph_craft::document::NodeId; use graphene_core::renderer::Quad; use graphene_core::text::{load_face, Font, FontCache}; use graphene_core::vector::style::Fill; @@ -287,7 +288,7 @@ impl TextToolData { else if let Some(editing_text) = self.editing_text.as_ref().filter(|_| state == TextToolFsmState::Ready) { responses.add(DocumentMessage::StartTransaction); - self.layer = LayerNodeIdentifier::new_unchecked(generate_uuid()); + self.layer = LayerNodeIdentifier::new_unchecked(NodeId(generate_uuid())); responses.add(GraphOperationMessage::NewTextLayer { id: self.layer.to_node(), diff --git a/editor/src/node_graph_executor.rs b/editor/src/node_graph_executor.rs index 038b471571..fe629bea04 100644 --- a/editor/src/node_graph_executor.rs +++ b/editor/src/node_graph_executor.rs @@ -278,7 +278,10 @@ impl NodeRuntime { image_data.extend(render.image_data.into_iter().filter_map(|(_, image)| NodeGraphExecutor::to_frontend_image_data(image, resize).ok())) } if !image_data.is_empty() { - responses.add(FrontendMessage::UpdateImageData { document_id: 0, image_data }); + responses.add(FrontendMessage::UpdateImageData { + document_id: DocumentId(0), + image_data, + }); } } diff --git a/frontend/wasm/src/editor_api.rs b/frontend/wasm/src/editor_api.rs index 5d44ae12df..a5805a6760 100644 --- a/frontend/wasm/src/editor_api.rs +++ b/frontend/wasm/src/editor_api.rs @@ -1,8 +1,10 @@ #[allow(clippy::too_many_arguments)] #[allow(clippy::non_snake_case)] +// // This file is where functions are defined to be called directly from JS. // It serves as a thin wrapper over the editor backend API that relies // on the dispatcher messaging system and more complex Rust data types. +// use crate::helpers::translate_key; use crate::{Error, EDITOR_HAS_CRASHED, EDITOR_INSTANCES, JS_EDITOR_HANDLES}; @@ -14,6 +16,7 @@ use editor::messages::input_mapper::utility_types::input_mouse::{EditorMouseStat use editor::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; use editor::messages::portfolio::utility_types::Platform; use editor::messages::prelude::*; +use editor::messages::tool::tool_messages::tool_prelude::WidgetId; use graph_craft::document::NodeId; use graphene_core::raster::color::Color; @@ -276,6 +279,7 @@ impl JsEditorHandle { /// Update layout of a given UI #[wasm_bindgen(js_name = updateLayout)] pub fn update_layout(&self, layout_target: JsValue, widget_id: u64, value: JsValue) -> Result<(), JsValue> { + let widget_id = WidgetId(widget_id); match (from_value(layout_target), from_value(value)) { (Ok(layout_target), Ok(value)) => { let message = LayoutMessage::UpdateLayout { layout_target, widget_id, value }; @@ -294,7 +298,8 @@ impl JsEditorHandle { } #[wasm_bindgen(js_name = selectDocument)] - pub fn select_document(&self, document_id: DocumentId) { + pub fn select_document(&self, document_id: u64) { + let document_id = DocumentId(document_id); let message = PortfolioMessage::SelectDocument { document_id }; self.dispatch(message); } @@ -327,7 +332,8 @@ impl JsEditorHandle { } #[wasm_bindgen(js_name = openAutoSavedDocument)] - pub fn open_auto_saved_document(&self, document_id: DocumentId, document_name: String, document_is_saved: bool, document_serialized_content: String) { + pub fn open_auto_saved_document(&self, document_id: u64, document_name: String, document_is_saved: bool, document_serialized_content: String) { + let document_id = DocumentId(document_id); let message = PortfolioMessage::OpenDocumentFileWithId { document_id, document_name, @@ -339,13 +345,15 @@ impl JsEditorHandle { } #[wasm_bindgen(js_name = triggerAutoSave)] - pub fn trigger_auto_save(&self, document_id: DocumentId) { + pub fn trigger_auto_save(&self, document_id: u64) { + let document_id = DocumentId(document_id); let message = PortfolioMessage::AutoSaveDocument { document_id }; self.dispatch(message); } #[wasm_bindgen(js_name = closeDocumentWithConfirmation)] - pub fn close_document_with_confirmation(&self, document_id: DocumentId) { + pub fn close_document_with_confirmation(&self, document_id: u64) { + let document_id = DocumentId(document_id); let message = PortfolioMessage::CloseDocumentWithConfirmation { document_id }; self.dispatch(message); } @@ -528,7 +536,8 @@ impl JsEditorHandle { /// Modify the layer selection based on the layer which is clicked while holding down the Ctrl and/or Shift modifier keys used for range selection behavior #[wasm_bindgen(js_name = selectLayer)] - pub fn select_layer(&self, id: NodeId, ctrl: bool, shift: bool) { + pub fn select_layer(&self, id: u64, ctrl: bool, shift: bool) { + let id = NodeId(id); let message = DocumentMessage::SelectLayer { id, ctrl, shift }; self.dispatch(message); } @@ -544,7 +553,9 @@ impl JsEditorHandle { /// If the folder is `None`, it is inserted into the document root. /// If the insert index is `None`, it is inserted at the end of the folder (equivalent to index infinity). #[wasm_bindgen(js_name = moveLayerInTree)] - pub fn move_layer_in_tree(&self, insert_parent_id: Option, insert_index: Option) { + pub fn move_layer_in_tree(&self, insert_parent_id: Option, insert_index: Option) { + let insert_parent_id = insert_parent_id.map(|id| NodeId(id)); + let parent = insert_parent_id.map(|id| LayerNodeIdentifier::new_unchecked(id)).unwrap_or(LayerNodeIdentifier::default()); let message = DocumentMessage::MoveSelectedLayersTo { parent, @@ -555,7 +566,8 @@ impl JsEditorHandle { /// Set the name for the layer #[wasm_bindgen(js_name = setLayerName)] - pub fn set_layer_name(&self, id: NodeId, name: String) { + pub fn set_layer_name(&self, id: u64, name: String) { + let id = NodeId(id); let message = NodeGraphMessage::SetName { node_id: id, name }; self.dispatch(message); } @@ -576,7 +588,9 @@ impl JsEditorHandle { /// Notifies the backend that the user connected a node's primary output to one of another node's inputs #[wasm_bindgen(js_name = connectNodesByLink)] - pub fn connect_nodes_by_link(&self, output_node: NodeId, output_node_connector_index: usize, input_node: NodeId, input_node_connector_index: usize) { + pub fn connect_nodes_by_link(&self, output_node: u64, output_node_connector_index: usize, input_node: u64, input_node_connector_index: usize) { + let output_node = NodeId(output_node); + let input_node = NodeId(input_node); let message = NodeGraphMessage::ConnectNodesByLink { output_node, output_node_connector_index, @@ -588,14 +602,16 @@ impl JsEditorHandle { /// Shifts the node and its children to stop nodes going on top of each other #[wasm_bindgen(js_name = shiftNode)] - pub fn shift_node(&self, node_id: NodeId) { + pub fn shift_node(&self, node_id: u64) { + let node_id = NodeId(node_id); let message = NodeGraphMessage::ShiftNode { node_id }; self.dispatch(message); } /// Notifies the backend that the user disconnected a node #[wasm_bindgen(js_name = disconnectNodes)] - pub fn disconnect_nodes(&self, node_id: NodeId, input_index: usize) { + pub fn disconnect_nodes(&self, node_id: u64, input_index: usize) { + let node_id = NodeId(node_id); let message = NodeGraphMessage::DisconnectNodes { node_id, input_index }; self.dispatch(message); } @@ -614,16 +630,17 @@ impl JsEditorHandle { /// Creates a new document node in the node graph #[wasm_bindgen(js_name = createNode)] - pub fn create_node(&self, node_type: String, x: i32, y: i32) -> NodeId { - let id = generate_uuid(); + pub fn create_node(&self, node_type: String, x: i32, y: i32) -> u64 { + let id = NodeId(generate_uuid()); let message = NodeGraphMessage::CreateNode { node_id: Some(id), node_type, x, y }; self.dispatch(message); - id + id.0 } /// Notifies the backend that the user selected a node in the node graph #[wasm_bindgen(js_name = selectNodes)] - pub fn select_nodes(&self, nodes: Option>) { + pub fn select_nodes(&self, nodes: Option>) { + let nodes = nodes.map(|nodes| nodes.into_iter().map(|id| NodeId(id)).collect::>()); let nodes = nodes.unwrap_or_default(); let message = NodeGraphMessage::SelectedNodesSet { nodes }; self.dispatch(message); @@ -638,7 +655,8 @@ impl JsEditorHandle { /// Notifies the backend that the user double clicked a node #[wasm_bindgen(js_name = doubleClickNode)] - pub fn double_click_node(&self, node: NodeId) { + pub fn double_click_node(&self, node: u64) { + let node = NodeId(node); let message = NodeGraphMessage::DoubleClickNode { node }; self.dispatch(message); } @@ -655,7 +673,8 @@ impl JsEditorHandle { /// Toggle preview on node #[wasm_bindgen(js_name = togglePreview)] - pub fn toggle_preview(&self, node_id: NodeId) { + pub fn toggle_preview(&self, node_id: u64) { + let node_id = NodeId(node_id); let message = NodeGraphMessage::TogglePreview { node_id }; self.dispatch(message); } @@ -671,21 +690,24 @@ impl JsEditorHandle { /// Toggle visibility of a layer from the layer list #[wasm_bindgen(js_name = toggleLayerVisibility)] - pub fn toggle_layer_visibility(&self, id: NodeId) { + pub fn toggle_layer_visibility(&self, id: u64) { + let id = NodeId(id); let message = NodeGraphMessage::ToggleHidden { node_id: id }; self.dispatch(message); } /// Toggle expansions state of a layer from the layer list #[wasm_bindgen(js_name = toggleLayerExpansion)] - pub fn toggle_layer_expansion(&self, id: NodeId) { + pub fn toggle_layer_expansion(&self, id: u64) { + let id = NodeId(id); let message = DocumentMessage::ToggleLayerExpansion { id }; self.dispatch(message); } /// Returns the string representation of the nodes contents #[wasm_bindgen(js_name = introspectNode)] - pub fn introspect_node(&self, node_path: Vec) -> JsValue { + pub fn introspect_node(&self, node_path: Vec) -> JsValue { + let node_path = node_path.into_iter().map(|id| NodeId(id)).collect::>(); let frontend_messages = EDITOR_INSTANCES.with(|instances| { // Mutably borrow the editors, and if successful, we can access them in the closure instances.try_borrow_mut().map(|mut editors| { diff --git a/node-graph/compilation-client/src/main.rs b/node-graph/compilation-client/src/main.rs index 010965ca7d..8bf4893e23 100644 --- a/node-graph/compilation-client/src/main.rs +++ b/node-graph/compilation-client/src/main.rs @@ -38,7 +38,7 @@ fn main() { fn add_network() -> NodeNetwork { NodeNetwork { inputs: vec![], - outputs: vec![NodeOutput::new(0, 0)], + outputs: vec![NodeOutput::new(NodeId(0), 0)], disabled: vec![], previous_outputs: None, nodes: [DocumentNode { @@ -66,7 +66,7 @@ fn add_network() -> NodeNetwork { }] .into_iter() .enumerate() - .map(|(id, node)| (id as NodeId, node)) + .map(|(id, node)| (NodeId(id as u64), node)) .collect(), } } diff --git a/node-graph/gcore/src/vector/id_vec.rs b/node-graph/gcore/src/vector/id_vec.rs index cbcc34e088..f34e361b2d 100644 --- a/node-graph/gcore/src/vector/id_vec.rs +++ b/node-graph/gcore/src/vector/id_vec.rs @@ -1,11 +1,12 @@ -use core::ops::{Deref, DerefMut}; -use serde::{Deserialize, Serialize}; - use alloc::vec; use alloc::vec::Vec; +use core::iter::Zip; +use core::ops::{Deref, DerefMut}; +use core::slice::Iter; +use serde::{Deserialize, Serialize}; -/// Brief description: A vec that allows indexing elements by both index and an assigned unique ID -/// Goals of this Data Structure: +/// Brief description: A vec that allows indexing elements by both index and an assigned unique ID. +/// Goals of this data structure: /// - Drop-in replacement for a Vec. /// - Provide an auto-assigned Unique ID per element upon insertion. /// - Add elements to the start or end. @@ -16,8 +17,10 @@ use alloc::vec::Vec; /// This data structure is somewhat similar to a linked list in terms of invariants. /// The downside is that currently it requires a lot of iteration. -// TODO: Convert from a type alias to a newtype -pub type ElementId = u64; +#[repr(transparent)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, serde::Serialize, serde::Deserialize, specta::Type)] +pub struct ElementId(pub u64); + #[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, specta::Type, Hash)] pub struct IdBackedVec { /// Contained elements @@ -34,13 +37,13 @@ impl IdBackedVec { IdBackedVec { elements: vec![], element_ids: vec![], - next_id: 0, + next_id: ElementId(0), } } /// Push a new element to the start of the vector pub fn push_front(&mut self, element: T) -> Option { - self.next_id += 1; + self.next_id = ElementId(self.next_id.0 + 1); self.elements.insert(0, element); self.element_ids.insert(0, self.next_id); Some(self.next_id) @@ -48,7 +51,7 @@ impl IdBackedVec { /// Push an element to the end of the vector pub fn push_end(&mut self, element: T) -> Option { - self.next_id += 1; + self.next_id = ElementId(self.next_id.0 + 1); self.elements.push(element); self.element_ids.push(self.next_id); Some(self.next_id) @@ -57,7 +60,7 @@ impl IdBackedVec { /// Insert an element adjacent to the given ID pub fn insert(&mut self, element: T, id: ElementId) -> Option { if let Some(index) = self.index_from_id(id) { - self.next_id += 1; + self.next_id = ElementId(self.next_id.0 + 1); self.elements.insert(index, element); self.element_ids.insert(index, self.next_id); return Some(self.next_id); @@ -125,7 +128,7 @@ impl IdBackedVec { } /// Enumerate the ids and elements in this container `(&ElementId, &T)` - pub fn enumerate(&self) -> core::iter::Zip, core::slice::Iter> { + pub fn enumerate(&self) -> Zip, Iter> { self.element_ids.iter().zip(self.elements.iter()) } diff --git a/node-graph/gcore/src/vector/subpath.rs b/node-graph/gcore/src/vector/subpath.rs index 9efd15d269..f7783d3582 100644 --- a/node-graph/gcore/src/vector/subpath.rs +++ b/node-graph/gcore/src/vector/subpath.rs @@ -1,12 +1,14 @@ -use super::id_vec::IdBackedVec; +use super::consts::ManipulatorType; +use super::id_vec::{ElementId, IdBackedVec}; use super::manipulator_group::ManipulatorGroup; use super::manipulator_point::ManipulatorPoint; -use super::{consts::ManipulatorType, id_vec::ElementId}; use crate::uuid::ManipulatorGroupId; use alloc::string::String; use alloc::vec; use alloc::vec::Vec; +use core::iter::Zip; +use core::slice::Iter; use dyn_any::{DynAny, StaticType}; use glam::{DAffine2, DVec2}; use kurbo::{BezPath, PathEl, Shape}; @@ -460,7 +462,7 @@ impl BezierId { /// An iterator over [`bezier_rs::Bezier`] segments constructable via [`Subpath::bezier_iter`]. pub struct PathIter<'a> { - path: core::iter::Zip, core::slice::Iter<'a, ManipulatorGroup>>, + path: Zip, Iter<'a, ManipulatorGroup>>, last_anchor: Option, last_out_handle: Option, @@ -482,7 +484,8 @@ impl<'a> Iterator for PathIter<'a> { let mut result = None; while result.is_none() { - let (&id, manipulator_group) = self.path.next()?; + let (id, manipulator_group) = self.path.next()?; + let id = id.0; let in_handle = manipulator_group.points[ManipulatorType::InHandle].as_ref().map(|point| point.position); let anchor = manipulator_group.points[ManipulatorType::Anchor].as_ref().map(|point| point.position); diff --git a/node-graph/graph-craft/src/document.rs b/node-graph/graph-craft/src/document.rs index a8b7e0f235..ea658c66ac 100644 --- a/node-graph/graph-craft/src/document.rs +++ b/node-graph/graph-craft/src/document.rs @@ -12,8 +12,15 @@ use std::hash::{Hash, Hasher}; pub mod value; -// TODO: Convert from a type alias to a newtype -pub type NodeId = u64; +#[repr(transparent)] +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, PartialOrd, Ord, serde::Serialize, serde::Deserialize, specta::Type)] +pub struct NodeId(pub u64); + +impl core::fmt::Display for NodeId { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.0) + } +} /// Hash two IDs together, returning a new ID that is always consistant for two input IDs in a specific order. /// This is used during [`NodeNetwork::flatten`] in order to ensure consistant yet non-conflicting IDs for inner networks. @@ -21,7 +28,7 @@ fn merge_ids(a: NodeId, b: NodeId) -> NodeId { let mut hasher = DefaultHasher::new(); a.hash(&mut hasher); b.hash(&mut hasher); - hasher.finish() + NodeId(hasher.finish()) } #[derive(Clone, Debug, PartialEq, Default, specta::Type, Hash, DynAny)] @@ -468,9 +475,9 @@ impl NodeNetwork { pub fn value_network(node: DocumentNode) -> Self { Self { - inputs: node.inputs.iter().filter(|input| matches!(input, NodeInput::Network(_))).map(|_| 0).collect(), - outputs: vec![NodeOutput::new(0, 0)], - nodes: [(0, node)].into_iter().collect(), + inputs: node.inputs.iter().filter(|input| matches!(input, NodeInput::Network(_))).map(|_| NodeId(0)).collect(), + outputs: vec![NodeOutput::new(NodeId(0), 0)], + nodes: [(NodeId(0), node)].into_iter().collect(), disabled: vec![], previous_outputs: None, } @@ -479,10 +486,10 @@ impl NodeNetwork { /// A graph with just an input node pub fn new_network() -> Self { Self { - inputs: vec![0], - outputs: vec![NodeOutput::new(0, 0)], + inputs: vec![NodeId(0)], + outputs: vec![NodeOutput::new(NodeId(0), 0)], nodes: [( - 0, + NodeId(0), DocumentNode { name: "Input Frame".into(), manual_composition: Some(concrete!(u32)), @@ -499,7 +506,7 @@ impl NodeNetwork { /// Appends a new node to the network after the output node and sets it as the new output pub fn push_node(&mut self, mut node: DocumentNode) -> NodeId { - let id = self.nodes.len().try_into().expect("Too many nodes in network"); + let id = NodeId(self.nodes.len().try_into().expect("Too many nodes in network")); // Set the correct position for the new node if node.metadata.position == IVec2::default() { if let Some(pos) = self.original_outputs().first().and_then(|first| self.nodes.get(&first.node_id)).map(|n| n.metadata.position) { @@ -536,11 +543,11 @@ impl NodeNetwork { name: "Cache".into(), inputs: vec![], implementation: DocumentNodeImplementation::Network(NodeNetwork { - inputs: vec![0], - outputs: vec![NodeOutput::new(1, 0)], + inputs: vec![NodeId(0)], + outputs: vec![NodeOutput::new(NodeId(1), 0)], nodes: vec![ ( - 0, + NodeId(0), DocumentNode { name: "MemoNode".to_string(), manual_composition: Some(concrete!(())), @@ -550,10 +557,10 @@ impl NodeNetwork { }, ), ( - 1, + NodeId(1), DocumentNode { name: "CloneNode".to_string(), - inputs: vec![NodeInput::node(0, 0)], + inputs: vec![NodeInput::node(NodeId(0), 0)], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::ops::CloneNode<_>")), ..Default::default() }, @@ -819,7 +826,7 @@ impl NodeNetwork { /// Remove all nodes that contain [`DocumentNodeImplementation::Network`] by moving the nested nodes into the parent network. pub fn flatten(&mut self, node: NodeId) { - self.flatten_with_fns(node, merge_ids, generate_uuid) + self.flatten_with_fns(node, merge_ids, || NodeId(generate_uuid())) } /// Remove all nodes that contain [`DocumentNodeImplementation::Network`] by moving the nested nodes into the parent network. @@ -1062,7 +1069,7 @@ impl NodeNetwork { } = input { if *graphic_group == GraphicGroup::EMPTY { - *input = NodeInput::node(new_id, 0); + *input = NodeInput::node(NodeId(new_id), 0); used = true; } } @@ -1078,7 +1085,7 @@ impl NodeNetwork { inputs: vec![NodeInput::value(TaggedValue::GraphicGroup(graphene_core::GraphicGroup::EMPTY), false)], ..Default::default() }; - self.nodes.insert(new_id, new_node); + self.nodes.insert(NodeId(new_id), new_node); } } @@ -1128,16 +1135,16 @@ mod test { fn gen_node_id() -> NodeId { static NODE_ID: AtomicU64 = AtomicU64::new(4); - NODE_ID.fetch_add(1, std::sync::atomic::Ordering::SeqCst) + NodeId(NODE_ID.fetch_add(1, std::sync::atomic::Ordering::SeqCst)) } fn add_network() -> NodeNetwork { NodeNetwork { - inputs: vec![0, 0], - outputs: vec![NodeOutput::new(1, 0)], + inputs: vec![NodeId(0), NodeId(0)], + outputs: vec![NodeOutput::new(NodeId(1), 0)], nodes: [ ( - 0, + NodeId(0), DocumentNode { name: "Cons".into(), inputs: vec![NodeInput::Network(concrete!(u32)), NodeInput::Network(concrete!(u32))], @@ -1146,10 +1153,10 @@ mod test { }, ), ( - 1, + NodeId(1), DocumentNode { name: "Add".into(), - inputs: vec![NodeInput::node(0, 0)], + inputs: vec![NodeInput::node(NodeId(0), 0)], implementation: DocumentNodeImplementation::Unresolved("graphene_core::ops::AddPairNode".into()), ..Default::default() }, @@ -1164,13 +1171,13 @@ mod test { #[test] fn map_ids() { let mut network = add_network(); - network.map_ids(|id| id + 1); + network.map_ids(|id| NodeId(id.0 + 1)); let mapped_add = NodeNetwork { - inputs: vec![1, 1], - outputs: vec![NodeOutput::new(2, 0)], + inputs: vec![NodeId(1), NodeId(1)], + outputs: vec![NodeOutput::new(NodeId(2), 0)], nodes: [ ( - 1, + NodeId(1), DocumentNode { name: "Cons".into(), inputs: vec![NodeInput::Network(concrete!(u32)), NodeInput::Network(concrete!(u32))], @@ -1179,10 +1186,10 @@ mod test { }, ), ( - 2, + NodeId(2), DocumentNode { name: "Add".into(), - inputs: vec![NodeInput::node(1, 0)], + inputs: vec![NodeInput::node(NodeId(1), 0)], implementation: DocumentNodeImplementation::Unresolved("graphene_core::ops::AddPairNode".into()), ..Default::default() }, @@ -1206,25 +1213,25 @@ mod test { // TODO: Extend test cases to test nested network let mut extraction_network = NodeNetwork { inputs: vec![], - outputs: vec![NodeOutput::new(1, 0)], + outputs: vec![NodeOutput::new(NodeId(1), 0)], nodes: [ id_node.clone(), DocumentNode { name: "Extract".into(), - inputs: vec![NodeInput::lambda(0, 0)], + inputs: vec![NodeInput::lambda(NodeId(0), 0)], implementation: DocumentNodeImplementation::Extract, ..Default::default() }, ] .into_iter() .enumerate() - .map(|(id, node)| (id as NodeId, node)) + .map(|(id, node)| (NodeId(id as u64), node)) .collect(), ..Default::default() }; extraction_network.resolve_extract_nodes(); assert_eq!(extraction_network.nodes.len(), 1); - let inputs = extraction_network.nodes.get(&1).unwrap().inputs.clone(); + let inputs = extraction_network.nodes.get(&NodeId(1)).unwrap().inputs.clone(); assert_eq!(inputs.len(), 1); assert!(matches!(&inputs[0], &NodeInput::Value{ tagged_value: TaggedValue::DocumentNode(ref network), ..} if network == &id_node)); } @@ -1232,10 +1239,10 @@ mod test { #[test] fn flatten_add() { let mut network = NodeNetwork { - inputs: vec![1], - outputs: vec![NodeOutput::new(1, 0)], + inputs: vec![NodeId(1)], + outputs: vec![NodeOutput::new(NodeId(1), 0)], nodes: [( - 1, + NodeId(1), DocumentNode { name: "Inc".into(), inputs: vec![ @@ -1254,7 +1261,7 @@ mod test { ..Default::default() }; network.generate_node_paths(&[]); - network.flatten_with_fns(1, |self_id, inner_id| self_id * 10 + inner_id, gen_node_id); + network.flatten_with_fns(NodeId(1), |self_id, inner_id| NodeId(self_id.0 * 10 + inner_id.0), gen_node_id); let flat_network = flat_network(); println!("{flat_network:#?}"); println!("{network:#?}"); @@ -1266,7 +1273,7 @@ mod test { fn resolve_proto_node_add() { let document_node = DocumentNode { name: "Cons".into(), - inputs: vec![NodeInput::Network(concrete!(u32)), NodeInput::node(0, 0)], + inputs: vec![NodeInput::Network(concrete!(u32)), NodeInput::node(NodeId(0), 0)], implementation: DocumentNodeImplementation::Unresolved("graphene_core::structural::ConsNode".into()), ..Default::default() }; @@ -1275,7 +1282,7 @@ mod test { let reference = ProtoNode { identifier: "graphene_core::structural::ConsNode".into(), input: ProtoNodeInput::ManualComposition(concrete!(u32)), - construction_args: ConstructionArgs::Nodes(vec![(0, false)]), + construction_args: ConstructionArgs::Nodes(vec![(NodeId(0), false)]), ..Default::default() }; assert_eq!(proto_node, reference); @@ -1284,30 +1291,30 @@ mod test { #[test] fn resolve_flatten_add_as_proto_network() { let construction_network = ProtoNetwork { - inputs: vec![10], - output: 11, + inputs: vec![NodeId(10)], + output: NodeId(11), nodes: [ ( - 10, + NodeId(10), ProtoNode { identifier: "graphene_core::structural::ConsNode".into(), input: ProtoNodeInput::ManualComposition(concrete!(u32)), - construction_args: ConstructionArgs::Nodes(vec![(14, false)]), - document_node_path: vec![1, 0], + construction_args: ConstructionArgs::Nodes(vec![(NodeId(14), false)]), + document_node_path: vec![NodeId(1), NodeId(0)], ..Default::default() }, ), ( - 11, + NodeId(11), ProtoNode { identifier: "graphene_core::ops::AddPairNode".into(), - input: ProtoNodeInput::Node(10, false), + input: ProtoNodeInput::Node(NodeId(10), false), construction_args: ConstructionArgs::Nodes(vec![]), - document_node_path: vec![1, 1], + document_node_path: vec![NodeId(1), NodeId(1)], ..Default::default() }, ), - (14, ProtoNode::value(ConstructionArgs::Value(TaggedValue::U32(2)), vec![1, 4])), + (NodeId(14), ProtoNode::value(ConstructionArgs::Value(TaggedValue::U32(2)), vec![NodeId(1), NodeId(4)])), ] .into_iter() .collect(), @@ -1322,21 +1329,21 @@ mod test { fn flat_network() -> NodeNetwork { NodeNetwork { - inputs: vec![10], - outputs: vec![NodeOutput::new(11, 0)], + inputs: vec![NodeId(10)], + outputs: vec![NodeOutput::new(NodeId(11), 0)], nodes: [ ( - 10, + NodeId(10), DocumentNode { name: "Cons".into(), - inputs: vec![NodeInput::Network(concrete!(u32)), NodeInput::node(14, 0)], + inputs: vec![NodeInput::Network(concrete!(u32)), NodeInput::node(NodeId(14), 0)], implementation: DocumentNodeImplementation::Unresolved("graphene_core::structural::ConsNode".into()), - path: Some(vec![1, 0]), + path: Some(vec![NodeId(1), NodeId(0)]), ..Default::default() }, ), ( - 14, + NodeId(14), DocumentNode { name: "Value".into(), inputs: vec![NodeInput::Value { @@ -1344,17 +1351,17 @@ mod test { exposed: false, }], implementation: DocumentNodeImplementation::Unresolved("graphene_core::value::ClonedNode".into()), - path: Some(vec![1, 4]), + path: Some(vec![NodeId(1), NodeId(4)]), ..Default::default() }, ), ( - 11, + NodeId(11), DocumentNode { name: "Add".into(), - inputs: vec![NodeInput::node(10, 0)], + inputs: vec![NodeInput::node(NodeId(10), 0)], implementation: DocumentNodeImplementation::Unresolved("graphene_core::ops::AddPairNode".into()), - path: Some(vec![1, 1]), + path: Some(vec![NodeId(1), NodeId(1)]), ..Default::default() }, ), @@ -1367,11 +1374,11 @@ mod test { fn two_node_identity() -> NodeNetwork { NodeNetwork { - inputs: vec![1, 2], - outputs: vec![NodeOutput::new(1, 0), NodeOutput::new(2, 0)], + inputs: vec![NodeId(1), NodeId(2)], + outputs: vec![NodeOutput::new(NodeId(1), 0), NodeOutput::new(NodeId(2), 0)], nodes: [ ( - 1, + NodeId(1), DocumentNode { name: "Identity 1".into(), inputs: vec![NodeInput::Network(concrete!(u32))], @@ -1380,7 +1387,7 @@ mod test { }, ), ( - 2, + NodeId(2), DocumentNode { name: "Identity 2".into(), inputs: vec![NodeInput::Network(concrete!(u32))], @@ -1401,7 +1408,7 @@ mod test { outputs: network_outputs, nodes: [ ( - 1, + NodeId(1), DocumentNode { name: "Nested network".into(), inputs: vec![NodeInput::value(TaggedValue::F32(1.), false), NodeInput::value(TaggedValue::F32(2.), false)], @@ -1410,7 +1417,7 @@ mod test { }, ), ( - 2, + NodeId(2), DocumentNode { name: "Result".into(), inputs: vec![result_node_input], @@ -1424,61 +1431,67 @@ mod test { ..Default::default() }; let _new_ids = 101..; - network.flatten_with_fns(1, |self_id, inner_id| self_id * 10 + inner_id, || 10000); - network.flatten_with_fns(2, |self_id, inner_id| self_id * 10 + inner_id, || 10001); + network.flatten_with_fns(NodeId(1), |self_id, inner_id| NodeId(self_id.0 * 10 + inner_id.0), || NodeId(10000)); + network.flatten_with_fns(NodeId(2), |self_id, inner_id| NodeId(self_id.0 * 10 + inner_id.0), || NodeId(10001)); network.remove_dead_nodes(); network } #[test] fn simple_duplicate() { - let result = output_duplicate(vec![NodeOutput::new(1, 0)], NodeInput::node(1, 0)); + let result = output_duplicate(vec![NodeOutput::new(NodeId(1), 0)], NodeInput::node(NodeId(1), 0)); println!("{result:#?}"); assert_eq!(result.outputs.len(), 1, "The number of outputs should remain as 1"); - assert_eq!(result.outputs[0], NodeOutput::new(11, 0), "The outer network output should be from a duplicated inner network"); + assert_eq!(result.outputs[0], NodeOutput::new(NodeId(11), 0), "The outer network output should be from a duplicated inner network"); let mut ids = result.nodes.keys().copied().collect::>(); ids.sort(); - assert_eq!(ids, vec![11, 10010], "Should only contain identity and values"); + assert_eq!(ids, vec![NodeId(11), NodeId(10010)], "Should only contain identity and values"); } // TODO: Write more tests - /* - #[test] - fn out_of_order_duplicate() { - let result = output_duplicate(vec![NodeOutput::new(10, 1), NodeOutput::new(10, 0)], NodeInput::node(10, 0)); - assert_eq!(result.outputs[0], NodeOutput::new(101, 0), "The first network output should be from a duplicated nested network"); - assert_eq!(result.outputs[1], NodeOutput::new(10, 0), "The second network output should be from the original nested network"); - assert!( - result.nodes.contains_key(&10) && result.nodes.contains_key(&101) && result.nodes.len() == 2, - "Network should contain two duplicated nodes" - ); - for (node_id, input_value, inner_id) in [(10, 1., 1), (101, 2., 2)] { - let nested_network_node = result.nodes.get(&node_id).unwrap(); - assert_eq!(nested_network_node.name, "Nested network".to_string(), "Name should not change"); - assert_eq!(nested_network_node.inputs, vec![NodeInput::value(TaggedValue::F32(input_value), false)], "Input should be stable"); - let inner_network = nested_network_node.implementation.get_network().expect("Implementation should be network"); - assert_eq!(inner_network.inputs, vec![inner_id], "The input should be sent to the second node"); - assert_eq!(inner_network.outputs, vec![NodeOutput::new(inner_id, 0)], "The output should be node id"); - assert_eq!(inner_network.nodes.get(&inner_id).unwrap().name, format!("Identity {inner_id}"), "The node should be identity"); - } - } - #[test] - fn using_other_node_duplicate() { - let result = output_duplicate(vec![NodeOutput::new(11, 0)], NodeInput::node(10, 1)); - assert_eq!(result.outputs, vec![NodeOutput::new(11, 0)], "The network output should be the result node"); - assert!( - result.nodes.contains_key(&11) && result.nodes.contains_key(&101) && result.nodes.len() == 2, - "Network should contain a duplicated node and a result node" - ); - let result_node = result.nodes.get(&11).unwrap(); - assert_eq!(result_node.inputs, vec![NodeInput::node(101, 0)], "Result node should refer to duplicate node as input"); - let nested_network_node = result.nodes.get(&101).unwrap(); - assert_eq!(nested_network_node.name, "Nested network".to_string(), "Name should not change"); - assert_eq!(nested_network_node.inputs, vec![NodeInput::value(TaggedValue::F32(2.), false)], "Input should be 2"); - let inner_network = nested_network_node.implementation.get_network().expect("Implementation should be network"); - assert_eq!(inner_network.inputs, vec![2], "The input should be sent to the second node"); - assert_eq!(inner_network.outputs, vec![NodeOutput::new(2, 0)], "The output should be node id 2"); - assert_eq!(inner_network.nodes.get(&2).unwrap().name, "Identity 2", "The node should be identity 2"); - } - */ + // #[test] + // fn out_of_order_duplicate() { + // let result = output_duplicate(vec![NodeOutput::new(NodeId(10), 1), NodeOutput::new(NodeId(10), 0)], NodeInput::node(NodeId(10), 0); + // assert_eq!( + // result.outputs[0], + // NodeOutput::new(NodeId(101), 0), + // "The first network output should be from a duplicated nested network" + // ); + // assert_eq!( + // result.outputs[1], + // NodeOutput::new(NodeId(10), 0), + // "The second network output should be from the original nested network" + // ); + // assert!( + // result.nodes.contains_key(&NodeId(10)) && result.nodes.contains_key(&NodeId(101)) && result.nodes.len() == 2, + // "Network should contain two duplicated nodes" + // ); + // for (node_id, input_value, inner_id) in [(10, 1., 1), (101, 2., 2)] { + // let nested_network_node = result.nodes.get(&NodeId(node_id)).unwrap(); + // assert_eq!(nested_network_node.name, "Nested network".to_string(), "Name should not change"); + // assert_eq!(nested_network_node.inputs, vec![NodeInput::value(TaggedValue::F32(input_value), false)], "Input should be stable"); + // let inner_network = nested_network_node.implementation.get_network().expect("Implementation should be network"); + // assert_eq!(inner_network.inputs, vec![inner_id], "The input should be sent to the second node"); + // assert_eq!(inner_network.outputs, vec![NodeOutput::new(NodeId(inner_id), 0)], "The output should be node id"); + // assert_eq!(inner_network.nodes.get(&NodeId(inner_id)).unwrap().name, format!("Identity {inner_id}"), "The node should be identity"); + // } + // } + // #[test] + // fn using_other_node_duplicate() { + // let result = output_duplicate(vec![NodeOutput::new(NodeId(11), 0)], NodeInput::node(NodeId(10), 1); + // assert_eq!(result.outputs, vec![NodeOutput::new(NodeId(11), 0)], "The network output should be the result node"); + // assert!( + // result.nodes.contains_key(&NodeId(11)) && result.nodes.contains_key(&NodeId(101)) && result.nodes.len() == 2, + // "Network should contain a duplicated node and a result node" + // ); + // let result_node = result.nodes.get(&NodeId(11)).unwrap(); + // assert_eq!(result_node.inputs, vec![NodeInput::node(NodeId(101), 0)], "Result node should refer to duplicate node as input"); + // let nested_network_node = result.nodes.get(&NodeId(101)).unwrap(); + // assert_eq!(nested_network_node.name, "Nested network".to_string(), "Name should not change"); + // assert_eq!(nested_network_node.inputs, vec![NodeInput::value(TaggedValue::F32(2.), false)], "Input should be 2"); + // let inner_network = nested_network_node.implementation.get_network().expect("Implementation should be network"); + // assert_eq!(inner_network.inputs, vec![2], "The input should be sent to the second node"); + // assert_eq!(inner_network.outputs, vec![NodeOutput::new(NodeId(2), 0)], "The output should be node id 2"); + // assert_eq!(inner_network.nodes.get(&NodeId(2)).unwrap().name, "Identity 2", "The node should be identity 2"); + // } } diff --git a/node-graph/graph-craft/src/proto.rs b/node-graph/graph-craft/src/proto.rs index 35ce4f6ca9..8a91fcac2a 100644 --- a/node-graph/graph-craft/src/proto.rs +++ b/node-graph/graph-craft/src/proto.rs @@ -191,7 +191,7 @@ impl ConstructionArgs { // TODO: what? Used in the gpu_compiler crate for something. pub fn new_function_args(&self) -> Vec { match self { - ConstructionArgs::Nodes(nodes) => nodes.iter().map(|n| format!("n{:0x}", n.0)).collect(), + ConstructionArgs::Nodes(nodes) => nodes.iter().map(|(n, _)| format!("n{:0x}", n.0)).collect(), ConstructionArgs::Value(value) => vec![value.to_primitive_string()], ConstructionArgs::Inline(inline) => vec![inline.expr.clone()], } @@ -277,7 +277,7 @@ impl ProtoNode { } ProtoNodeInput::Node(id, lambda) => (id, lambda).hash(&mut hasher), }; - Some(hasher.finish() as NodeId) + Some(NodeId(hasher.finish())) } /// Construct a new [`ProtoNode`] with the specified construction args and a `ClonedNode` implementation. @@ -349,8 +349,8 @@ impl ProtoNetwork { let Some(sni) = self.nodes[index].1.stable_node_id() else { panic!("failed to generate stable node id for node {:#?}", self.nodes[index].1); }; - self.replace_node_id(&outwards_edges, index as NodeId, sni, false); - self.nodes[index].0 = sni as NodeId; + self.replace_node_id(&outwards_edges, NodeId(index as u64), sni, false); + self.nodes[index].0 = sni; } } @@ -377,20 +377,26 @@ impl ProtoNetwork { // Perform topological sort once self.reorder_ids()?; - let max_id = self.nodes.len() as NodeId - 1; + let max_id = self.nodes.len() as u64 - 1; // Collect outward edges once let outwards_edges = self.collect_outwards_edges(); // Iterate over nodes in topological order for node_id in 0..=max_id { - let node = &mut self.nodes[node_id as usize].1; + let node_id = NodeId(node_id); + + let (_, node) = &mut self.nodes[node_id.0 as usize]; if let ProtoNodeInput::Node(input_node_id, false) = node.input { // Create a new node that composes the current node and its input node - let compose_node_id = self.nodes.len() as NodeId; - let input = self.nodes[input_node_id as usize].1.input.clone(); - let mut path = self.nodes[input_node_id as usize].1.document_node_path.clone(); + let compose_node_id = NodeId(self.nodes.len() as u64); + + let (_, input_node_id_proto) = &self.nodes[input_node_id.0 as usize]; + + let input = input_node_id_proto.input.clone(); + + let mut path = input_node_id_proto.document_node_path.clone(); path.push(node_id); self.nodes.push(( @@ -417,7 +423,7 @@ impl ProtoNetwork { // Update references in other nodes to use the new compose node if let Some(referring_nodes) = outwards_edges.get(&node_id) { for &referring_node_id in referring_nodes { - let referring_node = &mut self.nodes[referring_node_id as usize].1; + let (_, referring_node) = &mut self.nodes[referring_node_id.0 as usize]; referring_node.map_ids(|id| if id == node_id { compose_node_id } else { id }, skip_lambdas) } } @@ -515,13 +521,13 @@ impl ProtoNetwork { let current_positions: HashMap<_, _> = self.nodes.iter().enumerate().map(|(pos, (id, _))| (*id, pos)).collect(); // Map of node ids to their new index based on topological order - let new_positions: HashMap<_, _> = order.iter().enumerate().map(|(pos, id)| (*id, pos as NodeId)).collect(); + let new_positions: HashMap<_, _> = order.iter().enumerate().map(|(pos, id)| (*id, NodeId(pos as u64))).collect(); // Create a new nodes vector based on the topological order let mut new_nodes = Vec::with_capacity(order.len()); for (index, &id) in order.iter().enumerate() { let current_pos = *current_positions.get(&id).unwrap(); - new_nodes.push((index as NodeId, self.nodes[current_pos].1.clone())); + new_nodes.push((NodeId(index as u64), self.nodes[current_pos].1.clone())); } // Update node references to reflect the new order @@ -733,7 +739,7 @@ mod test { let construction_network = test_network(); let sorted = construction_network.topological_sort().expect("Error when calling 'topological_sort' on 'construction_network."); println!("{sorted:#?}"); - assert_eq!(sorted, vec![14, 10, 11, 1]); + assert_eq!(sorted, vec![NodeId(14), NodeId(10), NodeId(11), NodeId(1)]); } #[test] @@ -750,12 +756,12 @@ mod test { construction_network.reorder_ids().expect("Error when calling 'reorder_ids' on 'construction_network."); let sorted = construction_network.topological_sort().expect("Error when calling 'topological_sort' on 'construction_network."); println!("nodes: {:#?}", construction_network.nodes); - assert_eq!(sorted, vec![0, 1, 2, 3]); + assert_eq!(sorted, vec![NodeId(0), NodeId(1), NodeId(2), NodeId(3)]); let ids: Vec<_> = construction_network.nodes.iter().map(|(id, _)| *id).collect(); println!("{ids:#?}"); println!("nodes: {:#?}", construction_network.nodes); assert_eq!(construction_network.nodes[0].1.identifier.name.as_ref(), "value"); - assert_eq!(ids, vec![0, 1, 2, 3]); + assert_eq!(ids, vec![NodeId(0), NodeId(1), NodeId(2), NodeId(3)]); } #[test] @@ -764,11 +770,11 @@ mod test { construction_network.reorder_ids().expect("Error when calling 'reorder_ids' on 'construction_network."); construction_network.reorder_ids().expect("Error when calling 'reorder_ids' on 'construction_network."); let sorted = construction_network.topological_sort().expect("Error when calling 'topological_sort' on 'construction_network."); - assert_eq!(sorted, vec![0, 1, 2, 3]); + assert_eq!(sorted, vec![NodeId(0), NodeId(1), NodeId(2), NodeId(3)]); let ids: Vec<_> = construction_network.nodes.iter().map(|(id, _)| *id).collect(); println!("{ids:#?}"); assert_eq!(construction_network.nodes[0].1.identifier.name.as_ref(), "value"); - assert_eq!(ids, vec![0, 1, 2, 3]); + assert_eq!(ids, vec![NodeId(0), NodeId(1), NodeId(2), NodeId(3)]); } #[test] @@ -778,7 +784,7 @@ mod test { println!("{construction_network:#?}"); assert_eq!(construction_network.nodes[0].1.identifier.name.as_ref(), "value"); assert_eq!(construction_network.nodes.len(), 6); - assert_eq!(construction_network.nodes[5].1.construction_args, ConstructionArgs::Nodes(vec![(3, false), (4, true)])); + assert_eq!(construction_network.nodes[5].1.construction_args, ConstructionArgs::Nodes(vec![(NodeId(3), false), (NodeId(4), true)])); } #[test] @@ -791,59 +797,59 @@ mod test { assert_eq!( ids, vec![ - 17957338642374791135, - 1303972037140595827, - 15485192931817078264, - 9739645351331265115, - 4165308598738454684, - 5557529806312473178 + NodeId(17957338642374791135), + NodeId(1303972037140595827), + NodeId(15485192931817078264), + NodeId(9739645351331265115), + NodeId(4165308598738454684), + NodeId(5557529806312473178) ] ); } fn test_network() -> ProtoNetwork { ProtoNetwork { - inputs: vec![10], - output: 1, + inputs: vec![NodeId(10)], + output: NodeId(1), nodes: [ ( - 7, + NodeId(7), ProtoNode { identifier: "id".into(), - input: ProtoNodeInput::Node(11, false), + input: ProtoNodeInput::Node(NodeId(11), false), construction_args: ConstructionArgs::Nodes(vec![]), ..Default::default() }, ), ( - 1, + NodeId(1), ProtoNode { identifier: "id".into(), - input: ProtoNodeInput::Node(11, false), + input: ProtoNodeInput::Node(NodeId(11), false), construction_args: ConstructionArgs::Nodes(vec![]), ..Default::default() }, ), ( - 10, + NodeId(10), ProtoNode { identifier: "cons".into(), input: ProtoNodeInput::ManualComposition(concrete!(u32)), - construction_args: ConstructionArgs::Nodes(vec![(14, false)]), + construction_args: ConstructionArgs::Nodes(vec![(NodeId(14), false)]), ..Default::default() }, ), ( - 11, + NodeId(11), ProtoNode { identifier: "add".into(), - input: ProtoNodeInput::Node(10, false), + input: ProtoNodeInput::Node(NodeId(10), false), construction_args: ConstructionArgs::Nodes(vec![]), ..Default::default() }, ), ( - 14, + NodeId(14), ProtoNode { identifier: "value".into(), input: ProtoNodeInput::None, @@ -859,23 +865,23 @@ mod test { fn test_network_with_cycles() -> ProtoNetwork { ProtoNetwork { - inputs: vec![1], - output: 1, + inputs: vec![NodeId(1)], + output: NodeId(1), nodes: [ ( - 1, + NodeId(1), ProtoNode { identifier: "id".into(), - input: ProtoNodeInput::Node(2, false), + input: ProtoNodeInput::Node(NodeId(2), false), construction_args: ConstructionArgs::Nodes(vec![]), ..Default::default() }, ), ( - 2, + NodeId(2), ProtoNode { identifier: "id".into(), - input: ProtoNodeInput::Node(1, false), + input: ProtoNodeInput::Node(NodeId(1), false), construction_args: ConstructionArgs::Nodes(vec![]), ..Default::default() }, diff --git a/node-graph/graphene-cli/src/main.rs b/node-graph/graphene-cli/src/main.rs index 8b4d4feaeb..bd883b928e 100644 --- a/node-graph/graphene-cli/src/main.rs +++ b/node-graph/graphene-cli/src/main.rs @@ -124,7 +124,7 @@ pub fn wrap_network_in_scope(mut network: NodeNetwork) -> NodeNetwork { let inner_network = DocumentNode { name: "Scope".to_string(), implementation: DocumentNodeImplementation::Network(network), - inputs: core::iter::repeat(NodeInput::node(0, 1)).take(len).collect(), + inputs: core::iter::repeat(NodeInput::node(NodeId(0), 1)).take(len).collect(), ..Default::default() }; @@ -135,14 +135,14 @@ pub fn wrap_network_in_scope(mut network: NodeNetwork) -> NodeNetwork { DocumentNode { name: "End Scope".to_string(), implementation: DocumentNodeImplementation::proto("graphene_core::memo::EndLetNode<_, _>"), - inputs: vec![NodeInput::node(0, 0), NodeInput::node(1, 0)], + inputs: vec![NodeInput::node(NodeId(0), 0), NodeInput::node(NodeId(1), 0)], ..Default::default() }, ]; NodeNetwork { - inputs: vec![0], - outputs: vec![NodeOutput::new(2, 0)], - nodes: nodes.into_iter().enumerate().map(|(id, node)| (id as NodeId, node)).collect(), + inputs: vec![NodeId(0)], + outputs: vec![NodeOutput::new(NodeId(2), 0)], + nodes: nodes.into_iter().enumerate().map(|(id, node)| (NodeId(id as u64), node)).collect(), ..Default::default() } } @@ -151,8 +151,8 @@ fn begin_scope() -> DocumentNode { DocumentNode { name: "Begin Scope".to_string(), implementation: DocumentNodeImplementation::Network(NodeNetwork { - inputs: vec![0], - outputs: vec![NodeOutput::new(1, 0), NodeOutput::new(2, 0)], + inputs: vec![NodeId(0)], + outputs: vec![NodeOutput::new(NodeId(1), 0), NodeOutput::new(NodeId(2), 0)], nodes: [ DocumentNode { name: "SetNode".to_string(), @@ -162,21 +162,21 @@ fn begin_scope() -> DocumentNode { }, DocumentNode { name: "LetNode".to_string(), - inputs: vec![NodeInput::node(0, 0)], + inputs: vec![NodeInput::node(NodeId(0), 0)], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::memo::LetNode<_>")), ..Default::default() }, DocumentNode { name: "RefNode".to_string(), manual_composition: Some(concrete!(WasmEditorApi)), - inputs: vec![NodeInput::lambda(1, 0)], + inputs: vec![NodeInput::lambda(NodeId(1), 0)], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::memo::RefNode<_, _>")), ..Default::default() }, ] .into_iter() .enumerate() - .map(|(id, node)| (id as NodeId, node)) + .map(|(id, node)| (NodeId(id as u64), node)) .collect(), ..Default::default() diff --git a/node-graph/gstd/src/gpu_nodes.rs b/node-graph/gstd/src/gpu_nodes.rs index 8279d5a135..ef3e546644 100644 --- a/node-graph/gstd/src/gpu_nodes.rs +++ b/node-graph/gstd/src/gpu_nodes.rs @@ -167,11 +167,11 @@ async fn create_compute_pass_descriptor( log::debug!("inner_network: {inner_network:?}"); let network = NodeNetwork { - inputs: vec![2, 1], //vec![0, 1], + inputs: vec![NodeId(2), NodeId(1)], //vec![0, 1], #[cfg(feature = "quantization")] - outputs: vec![NodeOutput::new(5, 0)], + outputs: vec![NodeOutput::new(NodeId(5), 0)], #[cfg(not(feature = "quantization"))] - outputs: vec![NodeOutput::new(3, 0)], + outputs: vec![NodeOutput::new(NodeId(3), 0)], nodes: [ DocumentNode { name: "Slice".into(), @@ -201,30 +201,30 @@ async fn create_compute_pass_descriptor( /* DocumentNode { name: "GetNode".into(), - inputs: vec![NodeInput::node(1, 0), NodeInput::node(0, 0)], + inputs: vec![NodeInput::node(NodeId(1), 0), NodeInput::node(NodeId(0), 0)], implementation: DocumentNodeImplementation::Unresolved("graphene_core::storage::GetNode".into()), ..Default::default() },*/ #[cfg(feature = "quantization")] DocumentNode { name: "Dequantize".into(), - inputs: vec![NodeInput::node(0, 0), NodeInput::node(1, 0)], + inputs: vec![NodeInput::node(NodeId(0), 0), NodeInput::node(NodeId(1), 0)], implementation: DocumentNodeImplementation::proto("graphene_core::quantization::DeQuantizeNode"), ..Default::default() }, DocumentNode { name: "MapNode".into(), #[cfg(feature = "quantization")] - inputs: vec![NodeInput::node(3, 0)], + inputs: vec![NodeInput::node(NodeId(3), 0)], #[cfg(not(feature = "quantization"))] - inputs: vec![NodeInput::node(0, 0)], + inputs: vec![NodeInput::node(NodeId(0), 0)], implementation: DocumentNodeImplementation::Network(inner_network), ..Default::default() }, #[cfg(feature = "quantization")] DocumentNode { name: "Quantize".into(), - inputs: vec![NodeInput::node(4, 0), NodeInput::node(1, 0)], + inputs: vec![NodeInput::node(NodeId(4), 0), NodeInput::node(NodeId(1), 0)], implementation: DocumentNodeImplementation::proto("graphene_core::quantization::QuantizeNode"), ..Default::default() }, @@ -232,7 +232,7 @@ async fn create_compute_pass_descriptor( DocumentNode { name: "SaveNode".into(), inputs: vec![ - NodeInput::node(5, 0), + NodeInput::node(NodeId(5), 0), NodeInput::Inline(InlineRust::new( "|x| o0[(_global_index.y * i1 + _global_index.x) as usize] = x".into(), //"|x|()".into(), @@ -246,7 +246,7 @@ async fn create_compute_pass_descriptor( ] .into_iter() .enumerate() - .map(|(id, node)| (id as NodeId, node)) + .map(|(id, node)| (NodeId(id as u64), node)) .collect(), ..Default::default() }; @@ -386,12 +386,12 @@ fn map_gpu_single_image(input: Image, node: String) -> Image { let identifier = ProtoNodeIdentifier { name: std::borrow::Cow::Owned(node) }; let network = NodeNetwork { - inputs: vec![0], + inputs: vec![NodeId(0)], disabled: vec![], previous_outputs: None, - outputs: vec![NodeOutput::new(0, 0)], + outputs: vec![NodeOutput::new(NodeId(0), 0)], nodes: [( - 0, + NodeId(0), DocumentNode { name: "Image Filter".into(), inputs: vec![NodeInput::Network(concrete!(Color))], @@ -433,7 +433,7 @@ async fn blend_gpu_image(foreground: ImageFrame, background: ImageFrame, background: ImageFrame NodeNetwork { NodeNetwork { - inputs: vec![0, 0], - outputs: vec![NodeOutput::new(1, 0)], + inputs: vec![NodeId(0), NodeId(0)], + outputs: vec![NodeOutput::new(NodeId(1), 0)], nodes: [ ( - 0, + NodeId(0), DocumentNode { name: "Cons".into(), inputs: vec![NodeInput::Network(concrete!(u32)), NodeInput::Network(concrete!(&u32))], @@ -29,10 +29,10 @@ mod tests { }, ), ( - 1, + NodeId(1), DocumentNode { name: "Add".into(), - inputs: vec![NodeInput::node(0, 0)], + inputs: vec![NodeInput::node(NodeId(0), 0)], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::ops::AddPairNode")), ..Default::default() }, @@ -45,10 +45,10 @@ mod tests { } let network = NodeNetwork { - inputs: vec![0], - outputs: vec![NodeOutput::new(0, 0)], + inputs: vec![NodeId(0)], + outputs: vec![NodeOutput::new(NodeId(0), 0)], nodes: [( - 0, + NodeId(0), DocumentNode { name: "Inc".into(), inputs: vec![ @@ -86,12 +86,12 @@ mod tests { use graph_craft::*; let network = NodeNetwork { - inputs: vec![0], - outputs: vec![NodeOutput::new(1, 0)], + inputs: vec![NodeId(0)], + outputs: vec![NodeOutput::new(NodeId(1), 0)], nodes: [ // Simple identity node taking a number as input from outside the graph ( - 0, + NodeId(0), DocumentNode { name: "id".into(), inputs: vec![NodeInput::Network(concrete!(u32))], @@ -101,10 +101,10 @@ mod tests { ), // An add node adding the result of the id node to its self ( - 1, + NodeId(1), DocumentNode { name: "Add".into(), - inputs: vec![NodeInput::node(0, 0), NodeInput::node(0, 0)], + inputs: vec![NodeInput::node(NodeId(0), 0), NodeInput::node(NodeId(0), 0)], implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::ops::AddNode<_>")), ..Default::default() }, diff --git a/node-graph/vulkan-executor/src/executor.rs b/node-graph/vulkan-executor/src/executor.rs index 10af32e6e7..a04e39fff6 100644 --- a/node-graph/vulkan-executor/src/executor.rs +++ b/node-graph/vulkan-executor/src/executor.rs @@ -121,11 +121,11 @@ fn create_buffer(data: Vec, alloc: &StandardMemoryAlloc // fn inc_network() -> ProtoNetwork { // let mut construction_network = ProtoNetwork { -// inputs: vec![10], -// output: 1, +// inputs: vec![NodeId(10)], +// output: NodeId(1), // nodes: [ // ( -// 1, +// NodeId(1), // ProtoNode { // identifier: ProtoNodeIdentifier::new("graphene_core::ops::IdentityNode", &[generic!("u32")]), // input: ProtoNodeInput::Node(11), @@ -133,7 +133,7 @@ fn create_buffer(data: Vec, alloc: &StandardMemoryAlloc // }, // ), // ( -// 10, +// NodeId(10), // ProtoNode { // identifier: ProtoNodeIdentifier::new("graphene_core::structural::ConsNode", &[generic!("&ValueNode"), generic!("()")]), // input: ProtoNodeInput::Network, @@ -141,7 +141,7 @@ fn create_buffer(data: Vec, alloc: &StandardMemoryAlloc // }, // ), // ( -// 11, +// NodeId(11), // ProtoNode { // identifier: ProtoNodeIdentifier::new("graphene_core::ops::AddPairNode", &[generic!("u32"), generic!("u32")]), // input: ProtoNodeInput::Node(10), @@ -149,7 +149,7 @@ fn create_buffer(data: Vec, alloc: &StandardMemoryAlloc // }, // ), // ( -// 14, +// NodeId(14), // ProtoNode { // identifier: ProtoNodeIdentifier::new("graphene_core::value::ValueNode", &[concrete!("u32")]), // input: ProtoNodeInput::None, diff --git a/node-graph/wgpu-executor/src/executor.rs b/node-graph/wgpu-executor/src/executor.rs index 6502691f33..f144d18eef 100644 --- a/node-graph/wgpu-executor/src/executor.rs +++ b/node-graph/wgpu-executor/src/executor.rs @@ -203,11 +203,11 @@ async fn execute_shader(device: Arc< // fn inc_network() -> ProtoNetwork { // let mut construction_network = ProtoNetwork { -// inputs: vec![10], -// output: 1, +// inputs: vec![NodeId(10)], +// output: NodeId(1), // nodes: [ // ( -// 1, +// NodeId(1), // ProtoNode { // identifier: ProtoNodeIdentifier::new("graphene_core::ops::IdentityNode", &[generic!("u32")]), // input: ProtoNodeInput::Node(11), @@ -215,7 +215,7 @@ async fn execute_shader(device: Arc< // }, // ), // ( -// 10, +// NodeId(10), // ProtoNode { // identifier: ProtoNodeIdentifier::new("graphene_core::structural::ConsNode", &[generic!("&ValueNode"), generic!("()")]), // input: ProtoNodeInput::Network, @@ -223,7 +223,7 @@ async fn execute_shader(device: Arc< // }, // ), // ( -// 11, +// NodeId(11), // ProtoNode { // identifier: ProtoNodeIdentifier::new("graphene_core::ops::AddPairNode", &[generic!("u32"), generic!("u32")]), // input: ProtoNodeInput::Node(10), @@ -231,7 +231,7 @@ async fn execute_shader(device: Arc< // }, // ), // ( -// 14, +// NodeId(14), // ProtoNode { // identifier: ProtoNodeIdentifier::new("graphene_core::value::ValueNode", &[concrete!("u32")]), // input: ProtoNodeInput::None,