Convert u64 IDs to newtypes (#1532)

This commit is contained in:
Keavon Chambers 2023-12-22 03:24:13 -08:00 committed by GitHub
parent 7bfe0ce55b
commit 34f952bad1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
38 changed files with 565 additions and 446 deletions

View file

@ -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(), preferences: r#"{"imaginate_server_hostname":"https://exchange-encoding-watched-insured.trycloudflare.com/","imaginate_refresh_frequency":1,"zoom_with_scroll":false}"#.to_string(),
}), }),
PortfolioMessage::OpenDocumentFileWithId { PortfolioMessage::OpenDocumentFileWithId {
document_id: 0, document_id: DocumentId(0),
document_name: "".into(), document_name: "".into(),
document_is_auto_saved: true, document_is_auto_saved: true,
document_is_saved: true, document_is_saved: true,

View file

@ -256,7 +256,7 @@ impl Dispatcher {
mod test { mod test {
use crate::application::Editor; use crate::application::Editor;
use crate::messages::portfolio::document::utility_types::clipboards::Clipboard; 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::prelude::*;
use crate::messages::tool::tool_messages::tool_prelude::ToolType; use crate::messages::tool::tool_messages::tool_prelude::ToolType;
use crate::test_utils::EditorTestUtils; use crate::test_utils::EditorTestUtils;
@ -359,7 +359,7 @@ mod test {
fn copy_paste_folder() { fn copy_paste_folder() {
let mut editor = create_editor_with_three_layers(); let mut editor = create_editor_with_three_layers();
const FOLDER_ID: NodeId = 3; const FOLDER_ID: NodeId = NodeId(3);
editor.handle_message(GraphOperationMessage::NewCustomLayer { editor.handle_message(GraphOperationMessage::NewCustomLayer {
id: FOLDER_ID, id: FOLDER_ID,
@ -369,9 +369,6 @@ mod test {
}); });
editor.handle_message(NodeGraphMessage::SelectedNodesSet { nodes: vec![FOLDER_ID] }); 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::Line, 0., 0., 10., 10.);
editor.drag_tool(ToolType::Freehand, 10., 20., 30., 40.); 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 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::<Vec<_>>();
let layers_before_copy = document_before_copy.metadata.all_layers().collect::<Vec<_>>(); let layers_before_copy = document_before_copy.metadata.all_layers().collect::<Vec<_>>();
let layers_after_copy = document_after_copy.metadata.all_layers().collect::<Vec<_>>(); let layers_after_copy = document_after_copy.metadata.all_layers().collect::<Vec<_>>();
let [original_folder, original_freehand, original_line, original_ellipse, original_polygon, original_rect] = layers_before_copy[..] else { let [original_folder, original_freehand, original_line, original_ellipse, original_polygon, original_rect] = layers_before_copy[..] else {
panic!("Layers before incorrect"); 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"); panic!("Layers after incorrect");
}; };
assert_eq!(original_folder, folder); assert_eq!(original_folder, folder);
assert_eq!(original_freehand, freehand);
assert_eq!(original_line, line);
assert_eq!(original_ellipse, ellipse); assert_eq!(original_ellipse, ellipse);
assert_eq!(original_rect, rect);
assert_eq!(original_polygon, polygon); assert_eq!(original_polygon, polygon);
assert_eq!(original_rect, rect);
} }
#[test] #[test]

View file

@ -1,6 +1,7 @@
use crate::messages::layout::utility_types::widget_prelude::*; use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::prelude::*; use crate::messages::prelude::*;
use graph_craft::document::NodeId;
use graphene_core::uuid::generate_uuid; use graphene_core::uuid::generate_uuid;
use glam::{DVec2, IVec2, UVec2}; use glam::{DVec2, IVec2, UVec2};
@ -26,7 +27,7 @@ impl MessageHandler<NewDocumentDialogMessage, ()> for NewDocumentDialogMessageHa
let create_artboard = !self.infinite && self.dimensions.x > 0 && self.dimensions.y > 0; let create_artboard = !self.infinite && self.dimensions.x > 0 && self.dimensions.y > 0;
if create_artboard { if create_artboard {
let id = generate_uuid(); let id = NodeId(generate_uuid());
responses.add(GraphOperationMessage::NewArtboard { responses.add(GraphOperationMessage::NewArtboard {
id, id,
artboard: graphene_core::Artboard::new(IVec2::ZERO, self.dimensions.as_ivec2()), artboard: graphene_core::Artboard::new(IVec2::ZERO, self.dimensions.as_ivec2()),

View file

@ -7,7 +7,17 @@ use serde::{Deserialize, Serialize};
#[impl_message(Message, Layout)] #[impl_message(Message, Layout)]
#[derive(PartialEq, Clone, Debug, Serialize, Deserialize)] #[derive(PartialEq, Clone, Debug, Serialize, Deserialize)]
pub enum LayoutMessage { pub enum LayoutMessage {
ResendActiveWidget { layout_target: LayoutTarget, dirty_id: u64 }, ResendActiveWidget {
SendLayout { layout: Layout, layout_target: LayoutTarget }, layout_target: LayoutTarget,
UpdateLayout { layout_target: LayoutTarget, widget_id: u64, value: serde_json::Value }, dirty_id: WidgetId,
},
SendLayout {
layout: Layout,
layout_target: LayoutTarget,
},
UpdateLayout {
layout_target: LayoutTarget,
widget_id: WidgetId,
value: serde_json::Value,
},
} }

View file

@ -14,7 +14,7 @@ pub struct LayoutMessageHandler {
impl LayoutMessageHandler { impl LayoutMessageHandler {
/// Get the widget path for the widget with the specified id /// Get the widget path for the widget with the specified id
fn get_widget_path(widget_layout: &WidgetLayout, id: u64) -> Option<(&WidgetHolder, Vec<usize>)> { fn get_widget_path(widget_layout: &WidgetLayout, id: WidgetId) -> Option<(&WidgetHolder, Vec<usize>)> {
let mut stack = widget_layout.layout.iter().enumerate().map(|(index, val)| (vec![index], val)).collect::<Vec<_>>(); let mut stack = widget_layout.layout.iter().enumerate().map(|(index, val)| (vec![index], val)).collect::<Vec<_>>();
while let Some((mut widget_path, group)) = stack.pop() { while let Some((mut widget_path, group)) = stack.pop() {
match group { match group {

View file

@ -10,6 +10,16 @@ use crate::messages::prelude::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::sync::Arc; 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] #[remain::sorted]
#[derive(PartialEq, Clone, Debug, Hash, Eq, Copy, Serialize, Deserialize, specta::Type)] #[derive(PartialEq, Clone, Debug, Hash, Eq, Copy, Serialize, Deserialize, specta::Type)]
#[repr(u8)] #[repr(u8)]
@ -419,14 +429,17 @@ impl LayoutGroup {
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, specta::Type)] #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, specta::Type)]
pub struct WidgetHolder { pub struct WidgetHolder {
#[serde(rename = "widgetId")] #[serde(rename = "widgetId")]
pub widget_id: u64, pub widget_id: WidgetId,
pub widget: Widget, pub widget: Widget,
} }
impl WidgetHolder { impl WidgetHolder {
#[deprecated(since = "0.0.0", note = "Please use the builder pattern, e.g. TextLabel::new(\"hello\").widget_holder()")] #[deprecated(since = "0.0.0", note = "Please use the builder pattern, e.g. TextLabel::new(\"hello\").widget_holder()")]
pub fn new(widget: Widget) -> Self { 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. /// Diffing updates self (where self is old) based on new, updating the list of modifications as it does so.

View file

@ -174,8 +174,8 @@ fn root_network() -> NodeNetwork {
name: "Output".into(), name: "Output".into(),
inputs: vec![NodeInput::value(TaggedValue::GraphicGroup(Default::default()), true), NodeInput::Network(concrete!(WasmEditorApi))], inputs: vec![NodeInput::value(TaggedValue::GraphicGroup(Default::default()), true), NodeInput::Network(concrete!(WasmEditorApi))],
implementation: graph_craft::document::DocumentNodeImplementation::Network(NodeNetwork { implementation: graph_craft::document::DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![3, 0], inputs: vec![NodeId(3), NodeId(0)],
outputs: vec![NodeOutput::new(3, 0)], outputs: vec![NodeOutput::new(NodeId(3), 0)],
nodes: [ nodes: [
DocumentNode { DocumentNode {
name: "EditorApi".to_string(), name: "EditorApi".to_string(),
@ -185,7 +185,7 @@ fn root_network() -> NodeNetwork {
}, },
DocumentNode { DocumentNode {
name: "Create Canvas".to_string(), 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")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_std::wasm_application_io::CreateSurfaceNode")),
skip_deduplication: true, skip_deduplication: true,
..Default::default() ..Default::default()
@ -193,16 +193,16 @@ fn root_network() -> NodeNetwork {
DocumentNode { DocumentNode {
name: "Cache".to_string(), name: "Cache".to_string(),
manual_composition: Some(concrete!(())), 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<_, _>")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::memo::MemoNode<_, _>")),
..Default::default() ..Default::default()
}, },
DocumentNode { DocumentNode {
name: "RenderNode".to_string(), name: "RenderNode".to_string(),
inputs: vec![ 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::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<_, _, _>")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_std::wasm_application_io::RenderNode<_, _, _>")),
..Default::default() ..Default::default()
@ -210,7 +210,7 @@ fn root_network() -> NodeNetwork {
] ]
.into_iter() .into_iter()
.enumerate() .enumerate()
.map(|(id, node)| (id as NodeId, node)) .map(|(id, node)| (NodeId(id as u64), node))
.collect(), .collect(),
..Default::default() ..Default::default()
}), }),
@ -345,7 +345,7 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
} }
CommitTransaction => (), CommitTransaction => (),
CreateEmptyFolder { parent } => { CreateEmptyFolder { parent } => {
let id = generate_uuid(); let id = NodeId(generate_uuid());
responses.add(GraphOperationMessage::NewCustomLayer { responses.add(GraphOperationMessage::NewCustomLayer {
id, id,
@ -416,7 +416,7 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
// TODO: Add code that changes the insert index of the new folder based on the selected layer // 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 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(PortfolioMessage::Copy { clipboard: Clipboard::Internal });
responses.add(DocumentMessage::DeleteSelectedLayers); responses.add(DocumentMessage::DeleteSelectedLayers);
@ -547,7 +547,7 @@ impl MessageHandler<DocumentMessage, DocumentInputs<'_>> for DocumentMessageHand
let image_frame = ImageFrame { image, ..Default::default() }; let image_frame = ImageFrame { image, ..Default::default() };
use crate::messages::tool::common_functionality::graph_modification_utils; 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()] }); responses.add(NodeGraphMessage::SelectedNodesSet { nodes: vec![layer.to_node()] });
@ -907,14 +907,14 @@ impl DocumentMessageHandler {
path.push(layer_node); path.push(layer_node);
// TODO: Skip if folder is not expanded. // 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); self.serialize_structure(layer_node, structure, data, path);
space = 0; space = 0;
path.pop(); 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. /// Serializes the layer structure into a condensed 1D structure.
@ -954,10 +954,10 @@ impl DocumentMessageHandler {
let mut data = Vec::new(); let mut data = Vec::new();
self.serialize_structure(self.metadata().root(), &mut structure, &mut data, &mut vec![]); 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.extend(data);
structure.iter().map(|id| id.to_node()).collect::<Vec<_>>().as_slice().into() structure.iter().map(|id| id.to_node().0).collect::<Vec<_>>().as_slice().into()
} }
/// Places a document into the history system /// Places a document into the history system

View file

@ -118,7 +118,7 @@ impl<'a> ModifyInputsContext<'a> {
} else { } else {
// The user has connected another node to the output. Insert a layer node between the output and the node. // 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 = 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)); sibling_layer = Some(NodeOutput::new(node_id, 0));
} }
@ -182,7 +182,7 @@ impl<'a> ModifyInputsContext<'a> {
Default::default(), Default::default(),
); );
self.responses.add(NodeGraphMessage::SendGraph { should_rerender: true }); 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<Subpath<ManipulatorGroupId>>, layer: NodeId) { fn insert_vector_data(&mut self, subpaths: Vec<Subpath<ManipulatorGroupId>>, 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 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 = 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)); 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)); 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)); 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)); 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.insert_node_before(shape_id, cull_id, 0, shape, IVec2::new(-8, 0));
self.responses.add(NodeGraphMessage::SendGraph { should_rerender: true }); 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 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 = 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)); 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)); 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)); 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)); 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.insert_node_before(text_id, cull_id, 0, text, IVec2::new(-8, 0));
self.responses.add(NodeGraphMessage::SendGraph { should_rerender: true }); 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 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 = 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)); 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)); 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.insert_node_before(image_id, sample_id, 0, image, IVec2::new(-8, 0));
self.responses.add(NodeGraphMessage::SendGraph { should_rerender: true }); self.responses.add(NodeGraphMessage::SendGraph { should_rerender: true });
} }
@ -283,7 +283,7 @@ impl<'a> ModifyInputsContext<'a> {
let metadata = output_node.metadata.clone(); let metadata = output_node.metadata.clone();
let new_input = output_node.inputs.first().cloned().filter(|input| input.as_node().is_some()); 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); output_node.inputs[0] = NodeInput::node(node_id, 0);
@ -678,10 +678,10 @@ impl MessageHandler<GraphOperationMessage, (&mut NodeNetwork, &mut DocumentMetad
let mut modify_inputs = ModifyInputsContext::new(document_network, document_metadata, node_graph, responses); let mut modify_inputs = ModifyInputsContext::new(document_network, document_metadata, node_graph, responses);
if let Some(layer) = modify_inputs.create_layer_with_insert_index(id, insert_index, parent) { if let Some(layer) = modify_inputs.create_layer_with_insert_index(id, insert_index, parent) {
let new_ids: HashMap<_, _> = 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 let shift = nodes
.get(&0) .get(&NodeId(0))
.and_then(|node| { .and_then(|node| {
modify_inputs modify_inputs
.document_network .document_network
@ -704,7 +704,7 @@ impl MessageHandler<GraphOperationMessage, (&mut NodeNetwork, &mut DocumentMetad
} }
if let Some(layer_node) = modify_inputs.document_network.nodes.get_mut(&layer) { if let Some(layer_node) = modify_inputs.document_network.nodes.get_mut(&layer) {
if let Some(&input) = new_ids.get(&0) { if let Some(&input) = new_ids.get(&NodeId(0)) {
layer_node.inputs[0] = NodeInput::node(input, 0) layer_node.inputs[0] = NodeInput::node(input, 0)
} }
} }

View file

@ -1,5 +1,6 @@
pub use self::document_node_types::*; pub use self::document_node_types::*;
use super::load_network_structure; use super::load_network_structure;
use crate::application::generate_uuid;
use crate::messages::input_mapper::utility_types::macros::action_keys; use crate::messages::input_mapper::utility_types::macros::action_keys;
use crate::messages::layout::utility_types::widget_prelude::*; use crate::messages::layout::utility_types::widget_prelude::*;
use crate::messages::portfolio::document::utility_types::document_metadata::{DocumentMetadata, LayerNodeIdentifier}; use crate::messages::portfolio::document::utility_types::document_metadata::{DocumentMetadata, LayerNodeIdentifier};
@ -512,7 +513,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
}; };
// Collect the selected nodes // 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(); let copied_nodes: Vec<_> = Self::copy_nodes(network, new_ids).collect();
// Prefix to show that this is nodes // Prefix to show that this is nodes
@ -522,7 +523,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
responses.add(FrontendMessage::TriggerTextCopy { copy_text }); responses.add(FrontendMessage::TriggerTextCopy { copy_text });
} }
NodeGraphMessage::CreateNode { node_id, node_type, x, y } => { 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 { let Some(document_node_type) = document_node_types::resolve_document_node_type(&node_type) else {
responses.add(DialogMessage::DisplayDialogError { responses.add(DialogMessage::DisplayDialogError {
@ -608,7 +609,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
if let Some(network) = document_network.nested_network(&self.network) { if let Some(network) = document_network.nested_network(&self.network) {
responses.add(DocumentMessage::StartTransaction); 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(); metadata.clear_selected_nodes();
responses.add(BroadcastEvent::SelectionChanged); responses.add(BroadcastEvent::SelectionChanged);
@ -722,7 +723,7 @@ impl<'a> MessageHandler<NodeGraphMessage, NodeGraphHandlerData<'a>> for NodeGrap
responses.add(DocumentMessage::StartTransaction); 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 { for (old_id, mut document_node) in data {
// Shift copied node // Shift copied node
document_node.metadata.position += shift; document_node.metadata.position += shift;

View file

@ -203,11 +203,11 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Layer", name: "Layer",
category: "General", category: "General",
implementation: NodeImplementation::DocumentNode(NodeNetwork { implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![0, 2], inputs: vec![NodeId(0), NodeId(2)],
outputs: vec![NodeOutput::new(2, 0)], outputs: vec![NodeOutput::new(NodeId(2), 0)],
nodes: [ nodes: [
( (
0, NodeId(0),
DocumentNode { DocumentNode {
name: "To Graphic Element".to_string(), name: "To Graphic Element".to_string(),
inputs: vec![NodeInput::Network(generic!(T))], inputs: vec![NodeInput::Network(generic!(T))],
@ -217,19 +217,19 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
), ),
// The monitor node is used to display a thumbnail in the UI. // The monitor node is used to display a thumbnail in the UI.
( (
1, NodeId(1),
DocumentNode { DocumentNode {
inputs: vec![NodeInput::node(0, 0)], inputs: vec![NodeInput::node(NodeId(0), 0)],
..monitor_node() ..monitor_node()
}, },
), ),
( (
2, NodeId(2),
DocumentNode { DocumentNode {
name: "ConstructLayer".to_string(), name: "ConstructLayer".to_string(),
manual_composition: Some(concrete!(Footprint)), manual_composition: Some(concrete!(Footprint)),
inputs: vec![ 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)))), NodeInput::Network(graphene_core::Type::Fn(Box::new(concrete!(Footprint)), Box::new(concrete!(graphene_core::GraphicGroup)))),
], ],
implementation: DocumentNodeImplementation::proto("graphene_core::ConstructLayerNode<_, _>"), implementation: DocumentNodeImplementation::proto("graphene_core::ConstructLayerNode<_, _>"),
@ -284,8 +284,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Load Image", name: "Load Image",
category: "Structural", category: "Structural",
implementation: NodeImplementation::DocumentNode(NodeNetwork { implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![0, 0], inputs: vec![NodeId(0), NodeId(0)],
outputs: vec![NodeOutput::new(1, 0)], outputs: vec![NodeOutput::new(NodeId(1), 0)],
nodes: [ nodes: [
DocumentNode { DocumentNode {
name: "Load Resource".to_string(), name: "Load Resource".to_string(),
@ -295,14 +295,14 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
}, },
DocumentNode { DocumentNode {
name: "Decode Image".to_string(), 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")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_std::wasm_application_io::DecodeImageNode")),
..Default::default() ..Default::default()
}, },
] ]
.into_iter() .into_iter()
.enumerate() .enumerate()
.map(|(id, node)| (id as NodeId, node)) .map(|(id, node)| (NodeId(id as u64), node))
.collect(), .collect(),
..Default::default() ..Default::default()
}), }),
@ -329,8 +329,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Create Canvas", name: "Create Canvas",
category: "Structural", category: "Structural",
implementation: NodeImplementation::DocumentNode(NodeNetwork { implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![0], inputs: vec![NodeId(0)],
outputs: vec![NodeOutput::new(1, 0)], outputs: vec![NodeOutput::new(NodeId(1), 0)],
nodes: [ nodes: [
DocumentNode { DocumentNode {
name: "Create Canvas".to_string(), name: "Create Canvas".to_string(),
@ -342,14 +342,14 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
DocumentNode { DocumentNode {
name: "Cache".to_string(), name: "Cache".to_string(),
manual_composition: Some(concrete!(())), 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<_, _>")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::memo::MemoNode<_, _>")),
..Default::default() ..Default::default()
}, },
] ]
.into_iter() .into_iter()
.enumerate() .enumerate()
.map(|(id, node)| (id as NodeId, node)) .map(|(id, node)| (NodeId(id as u64), node))
.collect(), .collect(),
..Default::default() ..Default::default()
}), }),
@ -368,8 +368,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Draw Canvas", name: "Draw Canvas",
category: "Structural", category: "Structural",
implementation: NodeImplementation::DocumentNode(NodeNetwork { implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![0, 2], inputs: vec![NodeId(0), NodeId(2)],
outputs: vec![NodeOutput::new(3, 0)], outputs: vec![NodeOutput::new(NodeId(3), 0)],
nodes: [ nodes: [
DocumentNode { DocumentNode {
name: "Convert Image Frame".to_string(), name: "Convert Image Frame".to_string(),
@ -387,20 +387,20 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
DocumentNode { DocumentNode {
name: "Cache".to_string(), name: "Cache".to_string(),
manual_composition: Some(concrete!(())), 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<_, _>")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::memo::MemoNode<_, _>")),
..Default::default() ..Default::default()
}, },
DocumentNode { DocumentNode {
name: "Draw Canvas".to_string(), 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<_>")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_std::wasm_application_io::DrawImageFrameNode<_>")),
..Default::default() ..Default::default()
}, },
] ]
.into_iter() .into_iter()
.enumerate() .enumerate()
.map(|(id, node)| (id as NodeId, node)) .map(|(id, node)| (NodeId(id as u64), node))
.collect(), .collect(),
..Default::default() ..Default::default()
}), }),
@ -426,8 +426,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Begin Scope", name: "Begin Scope",
category: "Ignore", category: "Ignore",
implementation: NodeImplementation::DocumentNode(NodeNetwork { implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![0], inputs: vec![NodeId(0)],
outputs: vec![NodeOutput::new(1, 0), NodeOutput::new(2, 0)], outputs: vec![NodeOutput::new(NodeId(1), 0), NodeOutput::new(NodeId(2), 0)],
nodes: [ nodes: [
DocumentNode { DocumentNode {
name: "SetNode".to_string(), name: "SetNode".to_string(),
@ -437,21 +437,21 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
}, },
DocumentNode { DocumentNode {
name: "LetNode".to_string(), 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<_>")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::memo::LetNode<_>")),
..Default::default() ..Default::default()
}, },
DocumentNode { DocumentNode {
name: "RefNode".to_string(), name: "RefNode".to_string(),
manual_composition: Some(concrete!(())), 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<_, _>")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::memo::RefNode<_, _>")),
..Default::default() ..Default::default()
}, },
] ]
.into_iter() .into_iter()
.enumerate() .enumerate()
.map(|(id, node)| (id as NodeId, node)) .map(|(id, node)| (NodeId(id as u64), node))
.collect(), .collect(),
..Default::default() ..Default::default()
@ -501,8 +501,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Output", name: "Output",
category: "Ignore", category: "Ignore",
implementation: NodeImplementation::DocumentNode(NodeNetwork { implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![3, 0], inputs: vec![NodeId(3), NodeId(0)],
outputs: vec![NodeOutput::new(4, 0)], outputs: vec![NodeOutput::new(NodeId(4), 0)],
nodes: [ nodes: [
DocumentNode { DocumentNode {
name: "EditorApi".to_string(), name: "EditorApi".to_string(),
@ -512,7 +512,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
}, },
DocumentNode { DocumentNode {
name: "Create Canvas".to_string(), 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")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_std::wasm_application_io::CreateSurfaceNode")),
skip_deduplication: true, skip_deduplication: true,
..Default::default() ..Default::default()
@ -520,7 +520,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
DocumentNode { DocumentNode {
name: "Cache".to_string(), name: "Cache".to_string(),
manual_composition: Some(concrete!(())), 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<_, _>")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::memo::MemoNode<_, _>")),
..Default::default() ..Default::default()
}, },
@ -532,14 +532,14 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
}, },
DocumentNode { DocumentNode {
name: "RenderNode".to_string(), 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<_, _>")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_std::wasm_application_io::RenderNode<_, _>")),
..Default::default() ..Default::default()
}, },
] ]
.into_iter() .into_iter()
.enumerate() .enumerate()
.map(|(id, node)| (id as NodeId, node)) .map(|(id, node)| (NodeId(id as u64), node))
.collect(), .collect(),
..Default::default() ..Default::default()
}), }),
@ -809,8 +809,13 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Split Channels", name: "Split Channels",
category: "Image Adjustments", category: "Image Adjustments",
implementation: NodeImplementation::DocumentNode(NodeNetwork { implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![0], inputs: vec![NodeId(0)],
outputs: vec![NodeOutput::new(1, 0), NodeOutput::new(2, 0), NodeOutput::new(3, 0), NodeOutput::new(4, 0)], outputs: vec![
NodeOutput::new(NodeId(1), 0),
NodeOutput::new(NodeId(2), 0),
NodeOutput::new(NodeId(3), 0),
NodeOutput::new(NodeId(4), 0),
],
nodes: [ 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. // 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. // 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<DocumentNodeDefinition> {
}, },
DocumentNode { DocumentNode {
name: "RedNode".to_string(), 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<_>")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::raster::ExtractChannelNode<_>")),
..Default::default() ..Default::default()
}, },
DocumentNode { DocumentNode {
name: "GreenNode".to_string(), 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<_>")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::raster::ExtractChannelNode<_>")),
..Default::default() ..Default::default()
}, },
DocumentNode { DocumentNode {
name: "BlueNode".to_string(), 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<_>")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::raster::ExtractChannelNode<_>")),
..Default::default() ..Default::default()
}, },
DocumentNode { DocumentNode {
name: "AlphaNode".to_string(), 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<>")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::raster::ExtractAlphaNode<>")),
..Default::default() ..Default::default()
}, },
] ]
.into_iter() .into_iter()
.enumerate() .enumerate()
.map(|(id, node)| (id as NodeId, node)) .map(|(id, node)| (NodeId(id as u64), node))
.collect(), .collect(),
..Default::default() ..Default::default()
@ -913,8 +918,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Uniform", name: "Uniform",
category: "Gpu", category: "Gpu",
implementation: NodeImplementation::DocumentNode(NodeNetwork { implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![1, 0], inputs: vec![NodeId(1), NodeId(0)],
outputs: vec![NodeOutput::new(2, 0)], outputs: vec![NodeOutput::new(NodeId(2), 0)],
nodes: [ nodes: [
DocumentNode { DocumentNode {
name: "Extract Executor".to_string(), name: "Extract Executor".to_string(),
@ -924,21 +929,21 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
}, },
DocumentNode { DocumentNode {
name: "Create Uniform".to_string(), 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<_>")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("gpu_executor::UniformNode<_>")),
..Default::default() ..Default::default()
}, },
DocumentNode { DocumentNode {
name: "Cache".to_string(), name: "Cache".to_string(),
manual_composition: Some(concrete!(())), 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<_, _>")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::memo::MemoNode<_, _>")),
..Default::default() ..Default::default()
}, },
] ]
.into_iter() .into_iter()
.enumerate() .enumerate()
.map(|(id, node)| (id as NodeId, node)) .map(|(id, node)| (NodeId(id as u64), node))
.collect(), .collect(),
..Default::default() ..Default::default()
}), }),
@ -965,8 +970,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Storage", name: "Storage",
category: "Gpu", category: "Gpu",
implementation: NodeImplementation::DocumentNode(NodeNetwork { implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![1, 0], inputs: vec![NodeId(1), NodeId(0)],
outputs: vec![NodeOutput::new(2, 0)], outputs: vec![NodeOutput::new(NodeId(2), 0)],
nodes: [ nodes: [
DocumentNode { DocumentNode {
name: "Extract Executor".to_string(), name: "Extract Executor".to_string(),
@ -976,21 +981,21 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
}, },
DocumentNode { DocumentNode {
name: "Create Storage".to_string(), name: "Create Storage".to_string(),
inputs: vec![NodeInput::Network(concrete!(Vec<u8>)), NodeInput::node(0, 0)], inputs: vec![NodeInput::Network(concrete!(Vec<u8>)), NodeInput::node(NodeId(0), 0)],
implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("gpu_executor::StorageNode<_>")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("gpu_executor::StorageNode<_>")),
..Default::default() ..Default::default()
}, },
DocumentNode { DocumentNode {
name: "Cache".to_string(), name: "Cache".to_string(),
manual_composition: Some(concrete!(())), 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<_, _>")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::memo::MemoNode<_, _>")),
..Default::default() ..Default::default()
}, },
] ]
.into_iter() .into_iter()
.enumerate() .enumerate()
.map(|(id, node)| (id as NodeId, node)) .map(|(id, node)| (NodeId(id as u64), node))
.collect(), .collect(),
..Default::default() ..Default::default()
}), }),
@ -1017,8 +1022,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "CreateOutputBuffer", name: "CreateOutputBuffer",
category: "Gpu", category: "Gpu",
implementation: NodeImplementation::DocumentNode(NodeNetwork { implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![1, 1, 0], inputs: vec![NodeId(1), NodeId(1), NodeId(0)],
outputs: vec![NodeOutput::new(2, 0)], outputs: vec![NodeOutput::new(NodeId(2), 0)],
nodes: [ nodes: [
DocumentNode { DocumentNode {
name: "Extract Executor".to_string(), name: "Extract Executor".to_string(),
@ -1028,21 +1033,21 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
}, },
DocumentNode { DocumentNode {
name: "Create Output Buffer".to_string(), 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<_, _>")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("gpu_executor::CreateOutputBufferNode<_, _>")),
..Default::default() ..Default::default()
}, },
DocumentNode { DocumentNode {
name: "Cache".to_string(), name: "Cache".to_string(),
manual_composition: Some(concrete!(())), 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<_, _>")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::memo::MemoNode<_, _>")),
..Default::default() ..Default::default()
}, },
] ]
.into_iter() .into_iter()
.enumerate() .enumerate()
.map(|(id, node)| (id as NodeId, node)) .map(|(id, node)| (NodeId(id as u64), node))
.collect(), .collect(),
..Default::default() ..Default::default()
}), }),
@ -1075,8 +1080,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "CreateComputePass", name: "CreateComputePass",
category: "Gpu", category: "Gpu",
implementation: NodeImplementation::DocumentNode(NodeNetwork { implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![1, 0, 1, 1], inputs: vec![NodeId(1), NodeId(0), NodeId(1), NodeId(1)],
outputs: vec![NodeOutput::new(2, 0)], outputs: vec![NodeOutput::new(NodeId(2), 0)],
nodes: [ nodes: [
DocumentNode { DocumentNode {
name: "Extract Executor".to_string(), name: "Extract Executor".to_string(),
@ -1088,7 +1093,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Create Compute Pass".to_string(), name: "Create Compute Pass".to_string(),
inputs: vec![ inputs: vec![
NodeInput::Network(concrete!(gpu_executor::PipelineLayout<WgpuExecutor>)), NodeInput::Network(concrete!(gpu_executor::PipelineLayout<WgpuExecutor>)),
NodeInput::node(0, 0), NodeInput::node(NodeId(0), 0),
NodeInput::Network(concrete!(ShaderInput<WgpuExecutor>)), NodeInput::Network(concrete!(ShaderInput<WgpuExecutor>)),
NodeInput::Network(concrete!(gpu_executor::ComputePassDimensions)), NodeInput::Network(concrete!(gpu_executor::ComputePassDimensions)),
], ],
@ -1098,14 +1103,14 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
DocumentNode { DocumentNode {
name: "Cache".to_string(), name: "Cache".to_string(),
manual_composition: Some(concrete!(())), 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<_, _>")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::memo::MemoNode<_, _>")),
..Default::default() ..Default::default()
}, },
] ]
.into_iter() .into_iter()
.enumerate() .enumerate()
.map(|(id, node)| (id as NodeId, node)) .map(|(id, node)| (NodeId(id as u64), node))
.collect(), .collect(),
..Default::default() ..Default::default()
}), }),
@ -1177,8 +1182,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "ExecuteComputePipeline", name: "ExecuteComputePipeline",
category: "Gpu", category: "Gpu",
implementation: NodeImplementation::DocumentNode(NodeNetwork { implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![1, 0], inputs: vec![NodeId(1), NodeId(0)],
outputs: vec![NodeOutput::new(2, 0)], outputs: vec![NodeOutput::new(NodeId(2), 0)],
nodes: [ nodes: [
DocumentNode { DocumentNode {
name: "Extract Executor".to_string(), name: "Extract Executor".to_string(),
@ -1188,21 +1193,21 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
}, },
DocumentNode { DocumentNode {
name: "Execute Compute Pipeline".to_string(), name: "Execute Compute Pipeline".to_string(),
inputs: vec![NodeInput::Network(concrete!(<WgpuExecutor as GpuExecutor>::CommandBuffer)), NodeInput::node(0, 0)], inputs: vec![NodeInput::Network(concrete!(<WgpuExecutor as GpuExecutor>::CommandBuffer)), NodeInput::node(NodeId(0), 0)],
implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("gpu_executor::ExecuteComputePipelineNode<_>")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("gpu_executor::ExecuteComputePipelineNode<_>")),
..Default::default() ..Default::default()
}, },
DocumentNode { DocumentNode {
name: "Cache".to_string(), name: "Cache".to_string(),
manual_composition: Some(concrete!(())), 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<_, _>")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::memo::MemoNode<_, _>")),
..Default::default() ..Default::default()
}, },
] ]
.into_iter() .into_iter()
.enumerate() .enumerate()
.map(|(id, node)| (id as NodeId, node)) .map(|(id, node)| (NodeId(id as u64), node))
.collect(), .collect(),
..Default::default() ..Default::default()
}), }),
@ -1229,8 +1234,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "ReadOutputBuffer", name: "ReadOutputBuffer",
category: "Gpu", category: "Gpu",
implementation: NodeImplementation::DocumentNode(NodeNetwork { implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![1, 0], inputs: vec![NodeId(1), NodeId(0)],
outputs: vec![NodeOutput::new(2, 0)], outputs: vec![NodeOutput::new(NodeId(2), 0)],
nodes: [ nodes: [
DocumentNode { DocumentNode {
name: "Extract Executor".to_string(), name: "Extract Executor".to_string(),
@ -1240,21 +1245,21 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
}, },
DocumentNode { DocumentNode {
name: "Read Output Buffer".to_string(), name: "Read Output Buffer".to_string(),
inputs: vec![NodeInput::Network(concrete!(Arc<ShaderInput<WgpuExecutor>>)), NodeInput::node(0, 0)], inputs: vec![NodeInput::Network(concrete!(Arc<ShaderInput<WgpuExecutor>>)), NodeInput::node(NodeId(0), 0)],
implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("gpu_executor::ReadOutputBufferNode<_, _>")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("gpu_executor::ReadOutputBufferNode<_, _>")),
..Default::default() ..Default::default()
}, },
DocumentNode { DocumentNode {
name: "Cache".to_string(), name: "Cache".to_string(),
manual_composition: Some(concrete!(())), 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<_, _>")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::memo::MemoNode<_, _>")),
..Default::default() ..Default::default()
}, },
] ]
.into_iter() .into_iter()
.enumerate() .enumerate()
.map(|(id, node)| (id as NodeId, node)) .map(|(id, node)| (NodeId(id as u64), node))
.collect(), .collect(),
..Default::default() ..Default::default()
}), }),
@ -1281,8 +1286,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "CreateGpuSurface", name: "CreateGpuSurface",
category: "Gpu", category: "Gpu",
implementation: NodeImplementation::DocumentNode(NodeNetwork { implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![0], inputs: vec![NodeId(0)],
outputs: vec![NodeOutput::new(1, 0)], outputs: vec![NodeOutput::new(NodeId(1), 0)],
nodes: [ nodes: [
DocumentNode { DocumentNode {
name: "Create Gpu Surface".to_string(), name: "Create Gpu Surface".to_string(),
@ -1293,14 +1298,14 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
DocumentNode { DocumentNode {
name: "Cache".to_string(), name: "Cache".to_string(),
manual_composition: Some(concrete!(())), 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<_, _>")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::memo::MemoNode<_, _>")),
..Default::default() ..Default::default()
}, },
] ]
.into_iter() .into_iter()
.enumerate() .enumerate()
.map(|(id, node)| (id as NodeId, node)) .map(|(id, node)| (NodeId(id as u64), node))
.collect(), .collect(),
..Default::default() ..Default::default()
}), }),
@ -1320,8 +1325,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "RenderTexture", name: "RenderTexture",
category: "Gpu", category: "Gpu",
implementation: NodeImplementation::DocumentNode(NodeNetwork { implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![1, 1, 0], inputs: vec![NodeId(1), NodeId(1), NodeId(0)],
outputs: vec![NodeOutput::new(1, 0)], outputs: vec![NodeOutput::new(NodeId(1), 0)],
nodes: [ nodes: [
DocumentNode { DocumentNode {
name: "Extract Executor".to_string(), name: "Extract Executor".to_string(),
@ -1334,7 +1339,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
inputs: vec![ inputs: vec![
NodeInput::Network(concrete!(ShaderInputFrame<WgpuExecutor>)), NodeInput::Network(concrete!(ShaderInputFrame<WgpuExecutor>)),
NodeInput::Network(concrete!(Arc<SurfaceHandle<<WgpuExecutor as GpuExecutor>::Surface>>)), NodeInput::Network(concrete!(Arc<SurfaceHandle<<WgpuExecutor as GpuExecutor>::Surface>>)),
NodeInput::node(0, 0), NodeInput::node(NodeId(0), 0),
], ],
implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("gpu_executor::RenderTextureNode<_, _>")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("gpu_executor::RenderTextureNode<_, _>")),
..Default::default() ..Default::default()
@ -1342,7 +1347,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
] ]
.into_iter() .into_iter()
.enumerate() .enumerate()
.map(|(id, node)| (id as NodeId, node)) .map(|(id, node)| (NodeId(id as u64), node))
.collect(), .collect(),
..Default::default() ..Default::default()
}), }),
@ -1374,8 +1379,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "UploadTexture", name: "UploadTexture",
category: "Gpu", category: "Gpu",
implementation: NodeImplementation::DocumentNode(NodeNetwork { implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![1, 0], inputs: vec![NodeId(1), NodeId(0)],
outputs: vec![NodeOutput::new(2, 0)], outputs: vec![NodeOutput::new(NodeId(2), 0)],
nodes: [ nodes: [
DocumentNode { DocumentNode {
name: "Extract Executor".to_string(), name: "Extract Executor".to_string(),
@ -1385,21 +1390,21 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
}, },
DocumentNode { DocumentNode {
name: "Upload Texture".to_string(), name: "Upload Texture".to_string(),
inputs: vec![NodeInput::Network(concrete!(ImageFrame<Color>)), NodeInput::node(0, 0)], inputs: vec![NodeInput::Network(concrete!(ImageFrame<Color>)), NodeInput::node(NodeId(0), 0)],
implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("gpu_executor::UploadTextureNode<_>")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("gpu_executor::UploadTextureNode<_>")),
..Default::default() ..Default::default()
}, },
DocumentNode { DocumentNode {
name: "Cache".to_string(), name: "Cache".to_string(),
manual_composition: Some(concrete!(())), 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<_, _>")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::memo::MemoNode<_, _>")),
..Default::default() ..Default::default()
}, },
] ]
.into_iter() .into_iter()
.enumerate() .enumerate()
.map(|(id, node)| (id as NodeId, node)) .map(|(id, node)| (NodeId(id as u64), node))
.collect(), .collect(),
..Default::default() ..Default::default()
}), }),
@ -2149,8 +2154,8 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
name: "Transform", name: "Transform",
category: "Transform", category: "Transform",
implementation: NodeImplementation::DocumentNode(NodeNetwork { implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![0, 1, 1, 1, 1, 1], inputs: vec![NodeId(0), NodeId(1), NodeId(1), NodeId(1), NodeId(1), NodeId(1)],
outputs: vec![NodeOutput::new(1, 0)], outputs: vec![NodeOutput::new(NodeId(1), 0)],
nodes: [ nodes: [
DocumentNode { DocumentNode {
inputs: vec![NodeInput::Network(concrete!(VectorData))], inputs: vec![NodeInput::Network(concrete!(VectorData))],
@ -2159,7 +2164,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
DocumentNode { DocumentNode {
name: "Transform".to_string(), name: "Transform".to_string(),
inputs: vec![ inputs: vec![
NodeInput::node(0, 0), NodeInput::node(NodeId(0), 0),
NodeInput::Network(concrete!(DVec2)), NodeInput::Network(concrete!(DVec2)),
NodeInput::Network(concrete!(f32)), NodeInput::Network(concrete!(f32)),
NodeInput::Network(concrete!(DVec2)), NodeInput::Network(concrete!(DVec2)),
@ -2173,7 +2178,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
] ]
.into_iter() .into_iter()
.enumerate() .enumerate()
.map(|(id, node)| (id as NodeId, node)) .map(|(id, node)| (NodeId(id as u64), node))
.collect(), .collect(),
..Default::default() ..Default::default()
}), }),
@ -2375,22 +2380,40 @@ pub static IMAGINATE_NODE: Lazy<DocumentNodeDefinition> = Lazy::new(|| DocumentN
name: "Imaginate", name: "Imaginate",
category: "Image Synthesis", category: "Image Synthesis",
implementation: NodeImplementation::DocumentNode(NodeNetwork { implementation: NodeImplementation::DocumentNode(NodeNetwork {
inputs: vec![0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], inputs: vec![
outputs: vec![NodeOutput::new(1, 0)], 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: [ nodes: [
( (
0, NodeId(0),
DocumentNode { DocumentNode {
inputs: vec![NodeInput::Network(concrete!(ImageFrame<Color>))], inputs: vec![NodeInput::Network(concrete!(ImageFrame<Color>))],
..monitor_node() ..monitor_node()
}, },
), ),
( (
1, NodeId(1),
DocumentNode { DocumentNode {
name: "Imaginate".into(), name: "Imaginate".into(),
inputs: vec![ inputs: vec![
NodeInput::node(0, 0), NodeInput::node(NodeId(0), 0),
NodeInput::Network(concrete!(WasmEditorApi)), NodeInput::Network(concrete!(WasmEditorApi)),
NodeInput::Network(concrete!(ImaginateController)), NodeInput::Network(concrete!(ImaginateController)),
NodeInput::Network(concrete!(f64)), NodeInput::Network(concrete!(f64)),
@ -2468,9 +2491,9 @@ impl DocumentNodeDefinition {
/* /*
NodeNetwork { NodeNetwork {
inputs: (0..num_inputs).map(|_| 0).collect(), inputs: (0..num_inputs).map(|_| 0).collect(),
outputs: vec![NodeOutput::new(0, 0)], outputs: vec![NodeOutput::new(NodeId(0), 0)],
nodes: [( nodes: [(
0, NodeId(0),
DocumentNode { DocumentNode {
name: format!("{}_impl", self.name), name: format!("{}_impl", self.name),
// TODO: Allow inserting nodes that contain other nodes. // TODO: Allow inserting nodes that contain other nodes.
@ -2483,8 +2506,6 @@ impl DocumentNodeDefinition {
.collect(), .collect(),
..Default::default() ..Default::default()
} }
}
*/ */
NodeImplementation::Extract => return DocumentNodeImplementation::Extract, 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 { let inner_network = DocumentNode {
name: "Scope".to_string(), name: "Scope".to_string(),
implementation: DocumentNodeImplementation::Network(network), 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() ..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") .expect("Begin Scope node type not found")
.to_document_node(vec![input_type.unwrap()], DocumentNodeMetadata::default()); .to_document_node(vec![input_type.unwrap()], DocumentNodeMetadata::default());
if let DocumentNodeImplementation::Network(g) = &mut begin_scope.implementation { 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; node.world_state_hash = hash;
} }
} }
@ -2574,20 +2595,20 @@ pub fn wrap_network_in_scope(mut network: NodeNetwork, hash: u64) -> NodeNetwork
inner_network, inner_network,
resolve_document_node_type("End Scope") resolve_document_node_type("End Scope")
.expect("End Scope node type not found") .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 { NodeNetwork {
inputs: vec![0], inputs: vec![NodeId(0)],
outputs: vec![NodeOutput::new(2, 0)], outputs: vec![NodeOutput::new(NodeId(2), 0)],
nodes: nodes.into_iter().enumerate().map(|(id, node)| (id as NodeId, node)).collect(), nodes: nodes.into_iter().enumerate().map(|(id, node)| (NodeId(id as u64), node)).collect(),
..Default::default() ..Default::default()
} }
} }
pub fn new_image_network(output_offset: i32, output_node_id: NodeId) -> NodeNetwork { pub fn new_image_network(output_offset: i32, output_node_id: NodeId) -> NodeNetwork {
let mut network = NodeNetwork { let mut network = NodeNetwork {
inputs: vec![0], inputs: vec![NodeId(0)],
..Default::default() ..Default::default()
}; };
network.push_node( 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 output = resolve_document_node_type("Output").expect("Output node does not exist");
let mut network = NodeNetwork { let mut network = NodeNetwork {
inputs: vec![0], inputs: vec![NodeId(0)],
..Default::default() ..Default::default()
}; };
network.push_node(text_generator.to_document_node( network.push_node(text_generator.to_document_node(

View file

@ -363,12 +363,12 @@ impl core::fmt::Debug for LayerNodeIdentifier {
} }
impl 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 /// Construct a [`LayerNodeIdentifier`] without checking if it is a layer node
pub const fn new_unchecked(node_id: NodeId) -> Self { pub const fn new_unchecked(node_id: NodeId) -> Self {
// Safety: will always be >=1 // 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 /// Construct a [`LayerNodeIdentifier`], debug asserting that it is a layer node
@ -384,7 +384,7 @@ impl LayerNodeIdentifier {
/// Access the node id of this layer /// Access the node id of this layer
pub fn to_node(self) -> NodeId { pub fn to_node(self) -> NodeId {
u64::from(self.0) - 1 NodeId(u64::from(self.0) - 1)
} }
/// Access the parent layer if possible /// Access the parent layer if possible
@ -662,32 +662,44 @@ fn test_tree() {
let mut document_metadata = DocumentMetadata::default(); let mut document_metadata = DocumentMetadata::default();
let root = document_metadata.root(); let root = document_metadata.root();
let document_metadata = &mut document_metadata; let document_metadata = &mut document_metadata;
root.push_child(document_metadata, LayerNodeIdentifier::new_unchecked(3)); root.push_child(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(3)));
assert_eq!(root.children(document_metadata).collect::<Vec<_>>(), vec![LayerNodeIdentifier::new_unchecked(3)]); assert_eq!(root.children(document_metadata).collect::<Vec<_>>(), vec![LayerNodeIdentifier::new_unchecked(NodeId(3))]);
root.push_child(document_metadata, LayerNodeIdentifier::new_unchecked(6)); root.push_child(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(6)));
assert_eq!(root.children(document_metadata).map(LayerNodeIdentifier::to_node).collect::<Vec<_>>(), vec![3, 6]); assert_eq!(root.children(document_metadata).map(LayerNodeIdentifier::to_node).collect::<Vec<_>>(), vec![NodeId(3), NodeId(6)]);
assert_eq!(root.decendants(document_metadata).map(LayerNodeIdentifier::to_node).collect::<Vec<_>>(), vec![3, 6]); assert_eq!(root.decendants(document_metadata).map(LayerNodeIdentifier::to_node).collect::<Vec<_>>(), vec![NodeId(3), NodeId(6)]);
LayerNodeIdentifier::new_unchecked(3).add_after(document_metadata, LayerNodeIdentifier::new_unchecked(4)); LayerNodeIdentifier::new_unchecked(NodeId(3)).add_after(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(4)));
LayerNodeIdentifier::new_unchecked(3).add_before(document_metadata, LayerNodeIdentifier::new_unchecked(2)); LayerNodeIdentifier::new_unchecked(NodeId(3)).add_before(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(2)));
LayerNodeIdentifier::new_unchecked(6).add_before(document_metadata, LayerNodeIdentifier::new_unchecked(5)); LayerNodeIdentifier::new_unchecked(NodeId(6)).add_before(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(5)));
LayerNodeIdentifier::new_unchecked(6).add_after(document_metadata, LayerNodeIdentifier::new_unchecked(9)); LayerNodeIdentifier::new_unchecked(NodeId(6)).add_after(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(9)));
LayerNodeIdentifier::new_unchecked(6).push_child(document_metadata, LayerNodeIdentifier::new_unchecked(8)); LayerNodeIdentifier::new_unchecked(NodeId(6)).push_child(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(8)));
LayerNodeIdentifier::new_unchecked(6).push_front_child(document_metadata, LayerNodeIdentifier::new_unchecked(7)); LayerNodeIdentifier::new_unchecked(NodeId(6)).push_front_child(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(7)));
root.push_front_child(document_metadata, LayerNodeIdentifier::new_unchecked(1)); root.push_front_child(document_metadata, LayerNodeIdentifier::new_unchecked(NodeId(1)));
assert_eq!(root.children(document_metadata).map(LayerNodeIdentifier::to_node).collect::<Vec<_>>(), vec![1, 2, 3, 4, 5, 6, 9]); assert_eq!(
root.children(document_metadata).map(LayerNodeIdentifier::to_node).collect::<Vec<_>>(),
vec![NodeId(1), NodeId(2), NodeId(3), NodeId(4), NodeId(5), NodeId(6), NodeId(9)]
);
assert_eq!( assert_eq!(
root.decendants(document_metadata).map(LayerNodeIdentifier::to_node).collect::<Vec<_>>(), root.decendants(document_metadata).map(LayerNodeIdentifier::to_node).collect::<Vec<_>>(),
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!( assert_eq!(
root.decendants(document_metadata).map(LayerNodeIdentifier::to_node).rev().collect::<Vec<_>>(), root.decendants(document_metadata).map(LayerNodeIdentifier::to_node).rev().collect::<Vec<_>>(),
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))); assert!(root.children(document_metadata).all(|child| child.parent(document_metadata) == Some(root)));
LayerNodeIdentifier::new_unchecked(6).delete(document_metadata); LayerNodeIdentifier::new_unchecked(NodeId(6)).delete(document_metadata);
LayerNodeIdentifier::new_unchecked(1).delete(document_metadata); LayerNodeIdentifier::new_unchecked(NodeId(1)).delete(document_metadata);
LayerNodeIdentifier::new_unchecked(9).push_child(document_metadata, LayerNodeIdentifier::new_unchecked(10)); 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<_>>(), vec![2, 3, 4, 5, 9]); assert_eq!(
assert_eq!(root.decendants(document_metadata).map(LayerNodeIdentifier::to_node).collect::<Vec<_>>(), vec![2, 3, 4, 5, 9, 10]); root.children(document_metadata).map(LayerNodeIdentifier::to_node).collect::<Vec<_>>(),
assert_eq!(root.decendants(document_metadata).map(LayerNodeIdentifier::to_node).rev().collect::<Vec<_>>(), vec![10, 9, 5, 4, 3, 2]); vec![NodeId(2), NodeId(3), NodeId(4), NodeId(5), NodeId(9)]
);
assert_eq!(
root.decendants(document_metadata).map(LayerNodeIdentifier::to_node).collect::<Vec<_>>(),
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<_>>(),
vec![NodeId(10), NodeId(9), NodeId(5), NodeId(4), NodeId(3), NodeId(2)]
);
} }

View file

@ -4,6 +4,10 @@ use glam::DVec2;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt; 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)] #[derive(PartialEq, Eq, Clone, Copy, Debug, Serialize, Deserialize, Hash)]
pub enum FlipAxis { pub enum FlipAxis {
X, X,

View file

@ -187,7 +187,7 @@ impl MessageHandler<PortfolioMessage, (&InputPreprocessorMessageHandler, &Prefer
.network() .network()
.upstream_flow_back_from_nodes(vec![node], false) .upstream_flow_back_from_nodes(vec![node], false)
.enumerate() .enumerate()
.map(|(index, (_, node_id))| (node_id, index as NodeId)) .map(|(index, (_, node_id))| (node_id, NodeId(index as u64)))
.collect(), .collect(),
) )
.collect(), .collect(),
@ -327,7 +327,7 @@ impl MessageHandler<PortfolioMessage, (&InputPreprocessorMessageHandler, &Prefer
} }
PortfolioMessage::NewDocumentWithName { name } => { PortfolioMessage::NewDocumentWithName { name } => {
let new_document = DocumentMessageHandler::with_name(name, ipp, responses); 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() { if self.active_document().is_some() {
responses.add(BroadcastEvent::ToolAbort); responses.add(BroadcastEvent::ToolAbort);
responses.add(NavigationMessage::TranslateCanvas { delta: (0., 0.).into() }); responses.add(NavigationMessage::TranslateCanvas { delta: (0., 0.).into() });
@ -353,7 +353,7 @@ impl MessageHandler<PortfolioMessage, (&InputPreprocessorMessageHandler, &Prefer
document_serialized_content, document_serialized_content,
} => { } => {
responses.add(PortfolioMessage::OpenDocumentFileWithId { responses.add(PortfolioMessage::OpenDocumentFileWithId {
document_id: generate_uuid(), document_id: DocumentId(generate_uuid()),
document_name, document_name,
document_is_auto_saved: false, document_is_auto_saved: false,
document_is_saved: true, document_is_saved: true,
@ -389,7 +389,7 @@ impl MessageHandler<PortfolioMessage, (&InputPreprocessorMessageHandler, &Prefer
let paste = |entry: &CopyBufferEntry, responses: &mut VecDeque<_>| { let paste = |entry: &CopyBufferEntry, responses: &mut VecDeque<_>| {
if self.active_document().is_some() { if self.active_document().is_some() {
trace!("Pasting into folder {parent:?} as index: {insert_index}"); trace!("Pasting into folder {parent:?} as index: {insert_index}");
let id = generate_uuid(); let id = NodeId(generate_uuid());
responses.add(GraphOperationMessage::NewCustomLayer { responses.add(GraphOperationMessage::NewCustomLayer {
id, id,
nodes: entry.nodes.clone(), nodes: entry.nodes.clone(),
@ -422,7 +422,7 @@ impl MessageHandler<PortfolioMessage, (&InputPreprocessorMessageHandler, &Prefer
for entry in data.into_iter().rev() { for entry in data.into_iter().rev() {
document.load_layer_resources(responses); document.load_layer_resources(responses);
let id = generate_uuid(); let id = NodeId(generate_uuid());
responses.add(GraphOperationMessage::NewCustomLayer { responses.add(GraphOperationMessage::NewCustomLayer {
id, id,
nodes: entry.nodes, nodes: entry.nodes,

View file

@ -51,14 +51,12 @@ pub use crate::messages::tool::tool_messages::text_tool::{TextToolMessage, TextT
// Helper // Helper
pub use crate::messages::globals::global_variables::*; pub use crate::messages::globals::global_variables::*;
pub use crate::messages::portfolio::document::node_graph::TransformIn; pub use crate::messages::portfolio::document::node_graph::TransformIn;
pub use crate::messages::portfolio::document::utility_types::misc::DocumentId;
pub use graphite_proc_macros::*; pub use graphite_proc_macros::*;
pub use std::collections::{HashMap, HashSet, VecDeque}; pub use std::collections::{HashMap, HashSet, VecDeque};
// TODO: Convert from a type alias to a newtype
pub type DocumentId = u64;
pub trait Responses { pub trait Responses {
fn add(&mut self, message: impl Into<Message>); fn add(&mut self, message: impl Into<Message>);

View file

@ -7,6 +7,7 @@ use crate::messages::tool::common_functionality::snapping::SnapManager;
use crate::messages::tool::common_functionality::transformation_cage::*; use crate::messages::tool::common_functionality::transformation_cage::*;
use glam::{IVec2, Vec2Swizzles}; use glam::{IVec2, Vec2Swizzles};
use graph_craft::document::NodeId;
#[derive(Default)] #[derive(Default)]
pub struct ArtboardTool { pub struct ArtboardTool {
@ -273,7 +274,7 @@ impl Fsm for ArtboardToolFsmState {
dimensions: size.round().as_ivec2(), dimensions: size.round().as_ivec2(),
}); });
} else { } else {
let id = generate_uuid(); let id = NodeId(generate_uuid());
tool_data.selected_artboard = Some(LayerNodeIdentifier::new_unchecked(id)); tool_data.selected_artboard = Some(LayerNodeIdentifier::new_unchecked(id));
tool_data.snap_manager.start_snap(document, input, document.bounding_boxes(), true, true); tool_data.snap_manager.start_snap(document, input, document.bounding_boxes(), true, true);

View file

@ -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 crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType};
use graph_craft::document::value::TaggedValue; 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::raster::BlendMode;
use graphene_core::uuid::generate_uuid; use graphene_core::uuid::generate_uuid;
use graphene_core::vector::brush_stroke::{BrushInputSample, BrushStroke, BrushStyle}; use graphene_core::vector::brush_stroke::{BrushInputSample, BrushStroke, BrushStyle};
@ -422,12 +422,12 @@ fn new_brush_layer(document: &DocumentMessageHandler, responses: &mut VecDeque<M
.to_document_node_default_inputs([], DocumentNodeMetadata::position((-8, 0))); .to_document_node_default_inputs([], DocumentNodeMetadata::position((-8, 0)));
let cull_node = resolve_document_node_type("Cull") let cull_node = resolve_document_node_type("Cull")
.expect("Cull node does not exist") .expect("Cull node does not exist")
.to_document_node_default_inputs([Some(NodeInput::node(1, 0))], DocumentNodeMetadata::default()); .to_document_node_default_inputs([Some(NodeInput::node(NodeId(1), 0))], DocumentNodeMetadata::default());
let id = generate_uuid(); let id = NodeId(generate_uuid());
responses.add(GraphOperationMessage::NewCustomLayer { responses.add(GraphOperationMessage::NewCustomLayer {
id, id,
nodes: HashMap::from([(1, brush_node), (0, cull_node)]), nodes: HashMap::from([(NodeId(1), brush_node), (NodeId(0), cull_node)]),
parent: document.new_layer_parent(), parent: document.new_layer_parent(),
insert_index: -1, insert_index: -1,
}); });

View file

@ -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::graph_modification_utils;
use crate::messages::tool::common_functionality::resize::Resize; use crate::messages::tool::common_functionality::resize::Resize;
use graph_craft::document::NodeId;
use graphene_core::uuid::generate_uuid; use graphene_core::uuid::generate_uuid;
use graphene_core::vector::style::{Fill, Stroke}; use graphene_core::vector::style::{Fill, Stroke};
use graphene_core::Color; use graphene_core::Color;
@ -205,7 +206,7 @@ impl Fsm for EllipseToolFsmState {
// Create a new ellipse vector shape // Create a new ellipse vector shape
let subpath = bezier_rs::Subpath::new_ellipse(DVec2::ZERO, DVec2::ONE); let subpath = bezier_rs::Subpath::new_ellipse(DVec2::ZERO, DVec2::ONE);
let manipulator_groups = subpath.manipulator_groups().to_vec(); let manipulator_groups = subpath.manipulator_groups().to_vec();
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);
graph_modification_utils::set_manipulator_mirror_angle(&manipulator_groups, layer, true, responses); graph_modification_utils::set_manipulator_mirror_angle(&manipulator_groups, layer, true, responses);
shape_data.layer = Some(layer); shape_data.layer = Some(layer);

View file

@ -4,6 +4,7 @@ use crate::messages::portfolio::document::utility_types::document_metadata::Laye
use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType}; use crate::messages::tool::common_functionality::color_selector::{ToolColorOptions, ToolColorType};
use crate::messages::tool::common_functionality::graph_modification_utils; use crate::messages::tool::common_functionality::graph_modification_utils;
use graph_craft::document::NodeId;
use graphene_core::uuid::generate_uuid; use graphene_core::uuid::generate_uuid;
use graphene_core::vector::style::{Fill, Stroke}; use graphene_core::vector::style::{Fill, Stroke};
use graphene_core::Color; use graphene_core::Color;
@ -211,7 +212,7 @@ impl Fsm for FreehandToolFsmState {
let subpath = bezier_rs::Subpath::from_anchors([pos], false); let subpath = bezier_rs::Subpath::from_anchors([pos], 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);
tool_data.layer = Some(layer); tool_data.layer = Some(layer);
responses.add(GraphOperationMessage::FillSet { responses.add(GraphOperationMessage::FillSet {

View file

@ -120,7 +120,7 @@ impl Fsm for ImaginateToolFsmState {
(ImaginateToolFsmState::Ready, ImaginateToolMessage::DragStart) => { (ImaginateToolFsmState::Ready, ImaginateToolMessage::DragStart) => {
shape_data.start(responses, document, input); shape_data.start(responses, document, input);
responses.add(DocumentMessage::StartTransaction); 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); responses.add(DocumentMessage::DeselectAllLayers);
use graph_craft::document::*; use graph_craft::document::*;
@ -140,15 +140,17 @@ impl Fsm for ImaginateToolFsmState {
let imaginate_node_type = &*IMAGINATE_NODE; let imaginate_node_type = &*IMAGINATE_NODE;
// Give them a unique ID // 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 // Create the network based on the Input -> Output passthrough default network
let mut network = node_graph::new_image_network(16, imaginate_node_id); let mut network = node_graph::new_image_network(16, imaginate_node_id);
// Insert the nodes into the default network // Insert the nodes into the default network
network network.nodes.insert(
.nodes transform_node_id,
.insert(transform_node_id, transform_node_type.to_document_node_default_inputs([Some(NodeInput::node(0, 0))], next_pos())); transform_node_type.to_document_node_default_inputs([Some(NodeInput::node(NodeId(0), 0))], next_pos()),
);
network.nodes.insert( network.nodes.insert(
imaginate_node_id, imaginate_node_id,
imaginate_node_type.to_document_node_default_inputs([Some(graph_craft::document::NodeInput::node(transform_node_id, 0))], next_pos()), imaginate_node_type.to_document_node_default_inputs([Some(graph_craft::document::NodeInput::node(transform_node_id, 0))], next_pos()),

View file

@ -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::graph_modification_utils;
use crate::messages::tool::common_functionality::snapping::SnapManager; use crate::messages::tool::common_functionality::snapping::SnapManager;
use graph_craft::document::NodeId;
use graphene_core::uuid::generate_uuid; use graphene_core::uuid::generate_uuid;
use graphene_core::vector::style::Stroke; use graphene_core::vector::style::Stroke;
use graphene_core::Color; use graphene_core::Color;
@ -183,7 +184,7 @@ impl Fsm for LineToolFsmState {
responses.add(DocumentMessage::StartTransaction); 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 { responses.add(GraphOperationMessage::StrokeSet {
layer, layer,
stroke: Stroke::new(tool_options.stroke.active_color(), tool_options.line_weight), stroke: Stroke::new(tool_options.stroke.active_color(), tool_options.line_weight),

View file

@ -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::graph_modification_utils::get_subpaths;
use crate::messages::tool::common_functionality::snapping::SnapManager; use crate::messages::tool::common_functionality::snapping::SnapManager;
use graph_craft::document::NodeId;
use graphene_core::uuid::{generate_uuid, ManipulatorGroupId}; use graphene_core::uuid::{generate_uuid, ManipulatorGroupId};
use graphene_core::vector::style::{Fill, Stroke}; use graphene_core::vector::style::{Fill, Stroke};
use graphene_core::vector::{ManipulatorPointId, SelectedType}; 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) // 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 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); self.layer = Some(layer);
responses.add(GraphOperationMessage::FillSet { responses.add(GraphOperationMessage::FillSet {

View file

@ -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::graph_modification_utils;
use crate::messages::tool::common_functionality::resize::Resize; use crate::messages::tool::common_functionality::resize::Resize;
use graph_craft::document::NodeId;
use graphene_core::uuid::generate_uuid; use graphene_core::uuid::generate_uuid;
use graphene_core::vector::style::{Fill, Stroke}; use graphene_core::vector::style::{Fill, Stroke};
use graphene_core::Color; 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::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), 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); polygon_data.layer = Some(layer);
let fill_color = tool_options.fill.active_color(); let fill_color = tool_options.fill.active_color();

View file

@ -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::graph_modification_utils;
use crate::messages::tool::common_functionality::resize::Resize; use crate::messages::tool::common_functionality::resize::Resize;
use graph_craft::document::NodeId;
use graphene_core::uuid::generate_uuid; use graphene_core::uuid::generate_uuid;
use graphene_core::vector::style::{Fill, Stroke}; use graphene_core::vector::style::{Fill, Stroke};
use graphene_core::Color; use graphene_core::Color;
@ -215,7 +216,7 @@ impl Fsm for RectangleToolFsmState {
responses.add(DocumentMessage::StartTransaction); 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); shape_data.layer = Some(layer);
let fill_color = tool_options.fill.active_color(); let fill_color = tool_options.fill.active_color();

View file

@ -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::graph_modification_utils;
use crate::messages::tool::common_functionality::snapping::SnapManager; use crate::messages::tool::common_functionality::snapping::SnapManager;
use graph_craft::document::NodeId;
use graphene_core::uuid::generate_uuid; use graphene_core::uuid::generate_uuid;
use graphene_core::vector::style::{Fill, Stroke}; use graphene_core::vector::style::{Fill, Stroke};
use graphene_core::Color; use graphene_core::Color;
@ -224,7 +225,7 @@ impl Fsm for SplineToolFsmState {
tool_data.weight = tool_options.line_weight; 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 { responses.add(GraphOperationMessage::FillSet {
layer, layer,

View file

@ -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 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::value::TaggedValue;
use graph_craft::document::NodeId;
use graphene_core::renderer::Quad; use graphene_core::renderer::Quad;
use graphene_core::text::{load_face, Font, FontCache}; use graphene_core::text::{load_face, Font, FontCache};
use graphene_core::vector::style::Fill; 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) { else if let Some(editing_text) = self.editing_text.as_ref().filter(|_| state == TextToolFsmState::Ready) {
responses.add(DocumentMessage::StartTransaction); responses.add(DocumentMessage::StartTransaction);
self.layer = LayerNodeIdentifier::new_unchecked(generate_uuid()); self.layer = LayerNodeIdentifier::new_unchecked(NodeId(generate_uuid()));
responses.add(GraphOperationMessage::NewTextLayer { responses.add(GraphOperationMessage::NewTextLayer {
id: self.layer.to_node(), id: self.layer.to_node(),

View file

@ -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())) image_data.extend(render.image_data.into_iter().filter_map(|(_, image)| NodeGraphExecutor::to_frontend_image_data(image, resize).ok()))
} }
if !image_data.is_empty() { if !image_data.is_empty() {
responses.add(FrontendMessage::UpdateImageData { document_id: 0, image_data }); responses.add(FrontendMessage::UpdateImageData {
document_id: DocumentId(0),
image_data,
});
} }
} }

View file

@ -1,8 +1,10 @@
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
#[allow(clippy::non_snake_case)] #[allow(clippy::non_snake_case)]
//
// This file is where functions are defined to be called directly from JS. // 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 // It serves as a thin wrapper over the editor backend API that relies
// on the dispatcher messaging system and more complex Rust data types. // on the dispatcher messaging system and more complex Rust data types.
//
use crate::helpers::translate_key; use crate::helpers::translate_key;
use crate::{Error, EDITOR_HAS_CRASHED, EDITOR_INSTANCES, JS_EDITOR_HANDLES}; 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::document::utility_types::document_metadata::LayerNodeIdentifier;
use editor::messages::portfolio::utility_types::Platform; use editor::messages::portfolio::utility_types::Platform;
use editor::messages::prelude::*; use editor::messages::prelude::*;
use editor::messages::tool::tool_messages::tool_prelude::WidgetId;
use graph_craft::document::NodeId; use graph_craft::document::NodeId;
use graphene_core::raster::color::Color; use graphene_core::raster::color::Color;
@ -276,6 +279,7 @@ impl JsEditorHandle {
/// Update layout of a given UI /// Update layout of a given UI
#[wasm_bindgen(js_name = updateLayout)] #[wasm_bindgen(js_name = updateLayout)]
pub fn update_layout(&self, layout_target: JsValue, widget_id: u64, value: JsValue) -> Result<(), JsValue> { 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)) { match (from_value(layout_target), from_value(value)) {
(Ok(layout_target), Ok(value)) => { (Ok(layout_target), Ok(value)) => {
let message = LayoutMessage::UpdateLayout { layout_target, widget_id, value }; let message = LayoutMessage::UpdateLayout { layout_target, widget_id, value };
@ -294,7 +298,8 @@ impl JsEditorHandle {
} }
#[wasm_bindgen(js_name = selectDocument)] #[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 }; let message = PortfolioMessage::SelectDocument { document_id };
self.dispatch(message); self.dispatch(message);
} }
@ -327,7 +332,8 @@ impl JsEditorHandle {
} }
#[wasm_bindgen(js_name = openAutoSavedDocument)] #[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 { let message = PortfolioMessage::OpenDocumentFileWithId {
document_id, document_id,
document_name, document_name,
@ -339,13 +345,15 @@ impl JsEditorHandle {
} }
#[wasm_bindgen(js_name = triggerAutoSave)] #[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 }; let message = PortfolioMessage::AutoSaveDocument { document_id };
self.dispatch(message); self.dispatch(message);
} }
#[wasm_bindgen(js_name = closeDocumentWithConfirmation)] #[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 }; let message = PortfolioMessage::CloseDocumentWithConfirmation { document_id };
self.dispatch(message); self.dispatch(message);
} }
@ -528,7 +536,8 @@ impl JsEditorHandle {
/// Modify the layer selection based on the layer which is clicked while holding down the <kbd>Ctrl</kbd> and/or <kbd>Shift</kbd> modifier keys used for range selection behavior /// Modify the layer selection based on the layer which is clicked while holding down the <kbd>Ctrl</kbd> and/or <kbd>Shift</kbd> modifier keys used for range selection behavior
#[wasm_bindgen(js_name = selectLayer)] #[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 }; let message = DocumentMessage::SelectLayer { id, ctrl, shift };
self.dispatch(message); self.dispatch(message);
} }
@ -544,7 +553,9 @@ impl JsEditorHandle {
/// If the folder is `None`, it is inserted into the document root. /// 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). /// If the insert index is `None`, it is inserted at the end of the folder (equivalent to index infinity).
#[wasm_bindgen(js_name = moveLayerInTree)] #[wasm_bindgen(js_name = moveLayerInTree)]
pub fn move_layer_in_tree(&self, insert_parent_id: Option<NodeId>, insert_index: Option<usize>) { pub fn move_layer_in_tree(&self, insert_parent_id: Option<u64>, insert_index: Option<usize>) {
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 parent = insert_parent_id.map(|id| LayerNodeIdentifier::new_unchecked(id)).unwrap_or(LayerNodeIdentifier::default());
let message = DocumentMessage::MoveSelectedLayersTo { let message = DocumentMessage::MoveSelectedLayersTo {
parent, parent,
@ -555,7 +566,8 @@ impl JsEditorHandle {
/// Set the name for the layer /// Set the name for the layer
#[wasm_bindgen(js_name = setLayerName)] #[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 }; let message = NodeGraphMessage::SetName { node_id: id, name };
self.dispatch(message); 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 /// Notifies the backend that the user connected a node's primary output to one of another node's inputs
#[wasm_bindgen(js_name = connectNodesByLink)] #[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 { let message = NodeGraphMessage::ConnectNodesByLink {
output_node, output_node,
output_node_connector_index, 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 /// Shifts the node and its children to stop nodes going on top of each other
#[wasm_bindgen(js_name = shiftNode)] #[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 }; let message = NodeGraphMessage::ShiftNode { node_id };
self.dispatch(message); self.dispatch(message);
} }
/// Notifies the backend that the user disconnected a node /// Notifies the backend that the user disconnected a node
#[wasm_bindgen(js_name = disconnectNodes)] #[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 }; let message = NodeGraphMessage::DisconnectNodes { node_id, input_index };
self.dispatch(message); self.dispatch(message);
} }
@ -614,16 +630,17 @@ impl JsEditorHandle {
/// Creates a new document node in the node graph /// Creates a new document node in the node graph
#[wasm_bindgen(js_name = createNode)] #[wasm_bindgen(js_name = createNode)]
pub fn create_node(&self, node_type: String, x: i32, y: i32) -> NodeId { pub fn create_node(&self, node_type: String, x: i32, y: i32) -> u64 {
let id = generate_uuid(); let id = NodeId(generate_uuid());
let message = NodeGraphMessage::CreateNode { node_id: Some(id), node_type, x, y }; let message = NodeGraphMessage::CreateNode { node_id: Some(id), node_type, x, y };
self.dispatch(message); self.dispatch(message);
id id.0
} }
/// Notifies the backend that the user selected a node in the node graph /// Notifies the backend that the user selected a node in the node graph
#[wasm_bindgen(js_name = selectNodes)] #[wasm_bindgen(js_name = selectNodes)]
pub fn select_nodes(&self, nodes: Option<Vec<NodeId>>) { pub fn select_nodes(&self, nodes: Option<Vec<u64>>) {
let nodes = nodes.map(|nodes| nodes.into_iter().map(|id| NodeId(id)).collect::<Vec<_>>());
let nodes = nodes.unwrap_or_default(); let nodes = nodes.unwrap_or_default();
let message = NodeGraphMessage::SelectedNodesSet { nodes }; let message = NodeGraphMessage::SelectedNodesSet { nodes };
self.dispatch(message); self.dispatch(message);
@ -638,7 +655,8 @@ impl JsEditorHandle {
/// Notifies the backend that the user double clicked a node /// Notifies the backend that the user double clicked a node
#[wasm_bindgen(js_name = doubleClickNode)] #[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 }; let message = NodeGraphMessage::DoubleClickNode { node };
self.dispatch(message); self.dispatch(message);
} }
@ -655,7 +673,8 @@ impl JsEditorHandle {
/// Toggle preview on node /// Toggle preview on node
#[wasm_bindgen(js_name = togglePreview)] #[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 }; let message = NodeGraphMessage::TogglePreview { node_id };
self.dispatch(message); self.dispatch(message);
} }
@ -671,21 +690,24 @@ impl JsEditorHandle {
/// Toggle visibility of a layer from the layer list /// Toggle visibility of a layer from the layer list
#[wasm_bindgen(js_name = toggleLayerVisibility)] #[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 }; let message = NodeGraphMessage::ToggleHidden { node_id: id };
self.dispatch(message); self.dispatch(message);
} }
/// Toggle expansions state of a layer from the layer list /// Toggle expansions state of a layer from the layer list
#[wasm_bindgen(js_name = toggleLayerExpansion)] #[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 }; let message = DocumentMessage::ToggleLayerExpansion { id };
self.dispatch(message); self.dispatch(message);
} }
/// Returns the string representation of the nodes contents /// Returns the string representation of the nodes contents
#[wasm_bindgen(js_name = introspectNode)] #[wasm_bindgen(js_name = introspectNode)]
pub fn introspect_node(&self, node_path: Vec<NodeId>) -> JsValue { pub fn introspect_node(&self, node_path: Vec<u64>) -> JsValue {
let node_path = node_path.into_iter().map(|id| NodeId(id)).collect::<Vec<_>>();
let frontend_messages = EDITOR_INSTANCES.with(|instances| { let frontend_messages = EDITOR_INSTANCES.with(|instances| {
// Mutably borrow the editors, and if successful, we can access them in the closure // Mutably borrow the editors, and if successful, we can access them in the closure
instances.try_borrow_mut().map(|mut editors| { instances.try_borrow_mut().map(|mut editors| {

View file

@ -38,7 +38,7 @@ fn main() {
fn add_network() -> NodeNetwork { fn add_network() -> NodeNetwork {
NodeNetwork { NodeNetwork {
inputs: vec![], inputs: vec![],
outputs: vec![NodeOutput::new(0, 0)], outputs: vec![NodeOutput::new(NodeId(0), 0)],
disabled: vec![], disabled: vec![],
previous_outputs: None, previous_outputs: None,
nodes: [DocumentNode { nodes: [DocumentNode {
@ -66,7 +66,7 @@ fn add_network() -> NodeNetwork {
}] }]
.into_iter() .into_iter()
.enumerate() .enumerate()
.map(|(id, node)| (id as NodeId, node)) .map(|(id, node)| (NodeId(id as u64), node))
.collect(), .collect(),
} }
} }

View file

@ -1,11 +1,12 @@
use core::ops::{Deref, DerefMut};
use serde::{Deserialize, Serialize};
use alloc::vec; use alloc::vec;
use alloc::vec::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 /// Brief description: A vec that allows indexing elements by both index and an assigned unique ID.
/// Goals of this Data Structure: /// Goals of this data structure:
/// - Drop-in replacement for a Vec. /// - Drop-in replacement for a Vec.
/// - Provide an auto-assigned Unique ID per element upon insertion. /// - Provide an auto-assigned Unique ID per element upon insertion.
/// - Add elements to the start or end. /// - 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. /// 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. /// The downside is that currently it requires a lot of iteration.
// TODO: Convert from a type alias to a newtype #[repr(transparent)]
pub type ElementId = u64; #[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)] #[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, specta::Type, Hash)]
pub struct IdBackedVec<T> { pub struct IdBackedVec<T> {
/// Contained elements /// Contained elements
@ -34,13 +37,13 @@ impl<T> IdBackedVec<T> {
IdBackedVec { IdBackedVec {
elements: vec![], elements: vec![],
element_ids: vec![], element_ids: vec![],
next_id: 0, next_id: ElementId(0),
} }
} }
/// Push a new element to the start of the vector /// Push a new element to the start of the vector
pub fn push_front(&mut self, element: T) -> Option<ElementId> { pub fn push_front(&mut self, element: T) -> Option<ElementId> {
self.next_id += 1; self.next_id = ElementId(self.next_id.0 + 1);
self.elements.insert(0, element); self.elements.insert(0, element);
self.element_ids.insert(0, self.next_id); self.element_ids.insert(0, self.next_id);
Some(self.next_id) Some(self.next_id)
@ -48,7 +51,7 @@ impl<T> IdBackedVec<T> {
/// Push an element to the end of the vector /// Push an element to the end of the vector
pub fn push_end(&mut self, element: T) -> Option<ElementId> { pub fn push_end(&mut self, element: T) -> Option<ElementId> {
self.next_id += 1; self.next_id = ElementId(self.next_id.0 + 1);
self.elements.push(element); self.elements.push(element);
self.element_ids.push(self.next_id); self.element_ids.push(self.next_id);
Some(self.next_id) Some(self.next_id)
@ -57,7 +60,7 @@ impl<T> IdBackedVec<T> {
/// Insert an element adjacent to the given ID /// Insert an element adjacent to the given ID
pub fn insert(&mut self, element: T, id: ElementId) -> Option<ElementId> { pub fn insert(&mut self, element: T, id: ElementId) -> Option<ElementId> {
if let Some(index) = self.index_from_id(id) { 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.elements.insert(index, element);
self.element_ids.insert(index, self.next_id); self.element_ids.insert(index, self.next_id);
return Some(self.next_id); return Some(self.next_id);
@ -125,7 +128,7 @@ impl<T> IdBackedVec<T> {
} }
/// Enumerate the ids and elements in this container `(&ElementId, &T)` /// Enumerate the ids and elements in this container `(&ElementId, &T)`
pub fn enumerate(&self) -> core::iter::Zip<core::slice::Iter<ElementId>, core::slice::Iter<T>> { pub fn enumerate(&self) -> Zip<Iter<ElementId>, Iter<T>> {
self.element_ids.iter().zip(self.elements.iter()) self.element_ids.iter().zip(self.elements.iter())
} }

View file

@ -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_group::ManipulatorGroup;
use super::manipulator_point::ManipulatorPoint; use super::manipulator_point::ManipulatorPoint;
use super::{consts::ManipulatorType, id_vec::ElementId};
use crate::uuid::ManipulatorGroupId; use crate::uuid::ManipulatorGroupId;
use alloc::string::String; use alloc::string::String;
use alloc::vec; use alloc::vec;
use alloc::vec::Vec; use alloc::vec::Vec;
use core::iter::Zip;
use core::slice::Iter;
use dyn_any::{DynAny, StaticType}; use dyn_any::{DynAny, StaticType};
use glam::{DAffine2, DVec2}; use glam::{DAffine2, DVec2};
use kurbo::{BezPath, PathEl, Shape}; use kurbo::{BezPath, PathEl, Shape};
@ -460,7 +462,7 @@ impl BezierId {
/// An iterator over [`bezier_rs::Bezier`] segments constructable via [`Subpath::bezier_iter`]. /// An iterator over [`bezier_rs::Bezier`] segments constructable via [`Subpath::bezier_iter`].
pub struct PathIter<'a> { pub struct PathIter<'a> {
path: core::iter::Zip<core::slice::Iter<'a, u64>, core::slice::Iter<'a, ManipulatorGroup>>, path: Zip<Iter<'a, ElementId>, Iter<'a, ManipulatorGroup>>,
last_anchor: Option<DVec2>, last_anchor: Option<DVec2>,
last_out_handle: Option<DVec2>, last_out_handle: Option<DVec2>,
@ -482,7 +484,8 @@ impl<'a> Iterator for PathIter<'a> {
let mut result = None; let mut result = None;
while result.is_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 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); let anchor = manipulator_group.points[ManipulatorType::Anchor].as_ref().map(|point| point.position);

View file

@ -12,8 +12,15 @@ use std::hash::{Hash, Hasher};
pub mod value; pub mod value;
// TODO: Convert from a type alias to a newtype #[repr(transparent)]
pub type NodeId = u64; #[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. /// 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. /// 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(); let mut hasher = DefaultHasher::new();
a.hash(&mut hasher); a.hash(&mut hasher);
b.hash(&mut hasher); b.hash(&mut hasher);
hasher.finish() NodeId(hasher.finish())
} }
#[derive(Clone, Debug, PartialEq, Default, specta::Type, Hash, DynAny)] #[derive(Clone, Debug, PartialEq, Default, specta::Type, Hash, DynAny)]
@ -468,9 +475,9 @@ impl NodeNetwork {
pub fn value_network(node: DocumentNode) -> Self { pub fn value_network(node: DocumentNode) -> Self {
Self { Self {
inputs: node.inputs.iter().filter(|input| matches!(input, NodeInput::Network(_))).map(|_| 0).collect(), inputs: node.inputs.iter().filter(|input| matches!(input, NodeInput::Network(_))).map(|_| NodeId(0)).collect(),
outputs: vec![NodeOutput::new(0, 0)], outputs: vec![NodeOutput::new(NodeId(0), 0)],
nodes: [(0, node)].into_iter().collect(), nodes: [(NodeId(0), node)].into_iter().collect(),
disabled: vec![], disabled: vec![],
previous_outputs: None, previous_outputs: None,
} }
@ -479,10 +486,10 @@ impl NodeNetwork {
/// A graph with just an input node /// A graph with just an input node
pub fn new_network() -> Self { pub fn new_network() -> Self {
Self { Self {
inputs: vec![0], inputs: vec![NodeId(0)],
outputs: vec![NodeOutput::new(0, 0)], outputs: vec![NodeOutput::new(NodeId(0), 0)],
nodes: [( nodes: [(
0, NodeId(0),
DocumentNode { DocumentNode {
name: "Input Frame".into(), name: "Input Frame".into(),
manual_composition: Some(concrete!(u32)), 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 /// 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 { 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 // Set the correct position for the new node
if node.metadata.position == IVec2::default() { 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) { 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(), name: "Cache".into(),
inputs: vec![], inputs: vec![],
implementation: DocumentNodeImplementation::Network(NodeNetwork { implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![0], inputs: vec![NodeId(0)],
outputs: vec![NodeOutput::new(1, 0)], outputs: vec![NodeOutput::new(NodeId(1), 0)],
nodes: vec![ nodes: vec![
( (
0, NodeId(0),
DocumentNode { DocumentNode {
name: "MemoNode".to_string(), name: "MemoNode".to_string(),
manual_composition: Some(concrete!(())), manual_composition: Some(concrete!(())),
@ -550,10 +557,10 @@ impl NodeNetwork {
}, },
), ),
( (
1, NodeId(1),
DocumentNode { DocumentNode {
name: "CloneNode".to_string(), 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<_>")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::ops::CloneNode<_>")),
..Default::default() ..Default::default()
}, },
@ -819,7 +826,7 @@ impl NodeNetwork {
/// Remove all nodes that contain [`DocumentNodeImplementation::Network`] by moving the nested nodes into the parent network. /// Remove all nodes that contain [`DocumentNodeImplementation::Network`] by moving the nested nodes into the parent network.
pub fn flatten(&mut self, node: NodeId) { 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. /// Remove all nodes that contain [`DocumentNodeImplementation::Network`] by moving the nested nodes into the parent network.
@ -1062,7 +1069,7 @@ impl NodeNetwork {
} = input } = input
{ {
if *graphic_group == GraphicGroup::EMPTY { if *graphic_group == GraphicGroup::EMPTY {
*input = NodeInput::node(new_id, 0); *input = NodeInput::node(NodeId(new_id), 0);
used = true; used = true;
} }
} }
@ -1078,7 +1085,7 @@ impl NodeNetwork {
inputs: vec![NodeInput::value(TaggedValue::GraphicGroup(graphene_core::GraphicGroup::EMPTY), false)], inputs: vec![NodeInput::value(TaggedValue::GraphicGroup(graphene_core::GraphicGroup::EMPTY), false)],
..Default::default() ..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 { fn gen_node_id() -> NodeId {
static NODE_ID: AtomicU64 = AtomicU64::new(4); 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 { fn add_network() -> NodeNetwork {
NodeNetwork { NodeNetwork {
inputs: vec![0, 0], inputs: vec![NodeId(0), NodeId(0)],
outputs: vec![NodeOutput::new(1, 0)], outputs: vec![NodeOutput::new(NodeId(1), 0)],
nodes: [ nodes: [
( (
0, NodeId(0),
DocumentNode { DocumentNode {
name: "Cons".into(), name: "Cons".into(),
inputs: vec![NodeInput::Network(concrete!(u32)), NodeInput::Network(concrete!(u32))], inputs: vec![NodeInput::Network(concrete!(u32)), NodeInput::Network(concrete!(u32))],
@ -1146,10 +1153,10 @@ mod test {
}, },
), ),
( (
1, NodeId(1),
DocumentNode { DocumentNode {
name: "Add".into(), name: "Add".into(),
inputs: vec![NodeInput::node(0, 0)], inputs: vec![NodeInput::node(NodeId(0), 0)],
implementation: DocumentNodeImplementation::Unresolved("graphene_core::ops::AddPairNode".into()), implementation: DocumentNodeImplementation::Unresolved("graphene_core::ops::AddPairNode".into()),
..Default::default() ..Default::default()
}, },
@ -1164,13 +1171,13 @@ mod test {
#[test] #[test]
fn map_ids() { fn map_ids() {
let mut network = add_network(); let mut network = add_network();
network.map_ids(|id| id + 1); network.map_ids(|id| NodeId(id.0 + 1));
let mapped_add = NodeNetwork { let mapped_add = NodeNetwork {
inputs: vec![1, 1], inputs: vec![NodeId(1), NodeId(1)],
outputs: vec![NodeOutput::new(2, 0)], outputs: vec![NodeOutput::new(NodeId(2), 0)],
nodes: [ nodes: [
( (
1, NodeId(1),
DocumentNode { DocumentNode {
name: "Cons".into(), name: "Cons".into(),
inputs: vec![NodeInput::Network(concrete!(u32)), NodeInput::Network(concrete!(u32))], inputs: vec![NodeInput::Network(concrete!(u32)), NodeInput::Network(concrete!(u32))],
@ -1179,10 +1186,10 @@ mod test {
}, },
), ),
( (
2, NodeId(2),
DocumentNode { DocumentNode {
name: "Add".into(), name: "Add".into(),
inputs: vec![NodeInput::node(1, 0)], inputs: vec![NodeInput::node(NodeId(1), 0)],
implementation: DocumentNodeImplementation::Unresolved("graphene_core::ops::AddPairNode".into()), implementation: DocumentNodeImplementation::Unresolved("graphene_core::ops::AddPairNode".into()),
..Default::default() ..Default::default()
}, },
@ -1206,25 +1213,25 @@ mod test {
// TODO: Extend test cases to test nested network // TODO: Extend test cases to test nested network
let mut extraction_network = NodeNetwork { let mut extraction_network = NodeNetwork {
inputs: vec![], inputs: vec![],
outputs: vec![NodeOutput::new(1, 0)], outputs: vec![NodeOutput::new(NodeId(1), 0)],
nodes: [ nodes: [
id_node.clone(), id_node.clone(),
DocumentNode { DocumentNode {
name: "Extract".into(), name: "Extract".into(),
inputs: vec![NodeInput::lambda(0, 0)], inputs: vec![NodeInput::lambda(NodeId(0), 0)],
implementation: DocumentNodeImplementation::Extract, implementation: DocumentNodeImplementation::Extract,
..Default::default() ..Default::default()
}, },
] ]
.into_iter() .into_iter()
.enumerate() .enumerate()
.map(|(id, node)| (id as NodeId, node)) .map(|(id, node)| (NodeId(id as u64), node))
.collect(), .collect(),
..Default::default() ..Default::default()
}; };
extraction_network.resolve_extract_nodes(); extraction_network.resolve_extract_nodes();
assert_eq!(extraction_network.nodes.len(), 1); 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_eq!(inputs.len(), 1);
assert!(matches!(&inputs[0], &NodeInput::Value{ tagged_value: TaggedValue::DocumentNode(ref network), ..} if network == &id_node)); assert!(matches!(&inputs[0], &NodeInput::Value{ tagged_value: TaggedValue::DocumentNode(ref network), ..} if network == &id_node));
} }
@ -1232,10 +1239,10 @@ mod test {
#[test] #[test]
fn flatten_add() { fn flatten_add() {
let mut network = NodeNetwork { let mut network = NodeNetwork {
inputs: vec![1], inputs: vec![NodeId(1)],
outputs: vec![NodeOutput::new(1, 0)], outputs: vec![NodeOutput::new(NodeId(1), 0)],
nodes: [( nodes: [(
1, NodeId(1),
DocumentNode { DocumentNode {
name: "Inc".into(), name: "Inc".into(),
inputs: vec![ inputs: vec![
@ -1254,7 +1261,7 @@ mod test {
..Default::default() ..Default::default()
}; };
network.generate_node_paths(&[]); 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(); let flat_network = flat_network();
println!("{flat_network:#?}"); println!("{flat_network:#?}");
println!("{network:#?}"); println!("{network:#?}");
@ -1266,7 +1273,7 @@ mod test {
fn resolve_proto_node_add() { fn resolve_proto_node_add() {
let document_node = DocumentNode { let document_node = DocumentNode {
name: "Cons".into(), 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()), implementation: DocumentNodeImplementation::Unresolved("graphene_core::structural::ConsNode".into()),
..Default::default() ..Default::default()
}; };
@ -1275,7 +1282,7 @@ mod test {
let reference = ProtoNode { let reference = ProtoNode {
identifier: "graphene_core::structural::ConsNode".into(), identifier: "graphene_core::structural::ConsNode".into(),
input: ProtoNodeInput::ManualComposition(concrete!(u32)), input: ProtoNodeInput::ManualComposition(concrete!(u32)),
construction_args: ConstructionArgs::Nodes(vec![(0, false)]), construction_args: ConstructionArgs::Nodes(vec![(NodeId(0), false)]),
..Default::default() ..Default::default()
}; };
assert_eq!(proto_node, reference); assert_eq!(proto_node, reference);
@ -1284,30 +1291,30 @@ mod test {
#[test] #[test]
fn resolve_flatten_add_as_proto_network() { fn resolve_flatten_add_as_proto_network() {
let construction_network = ProtoNetwork { let construction_network = ProtoNetwork {
inputs: vec![10], inputs: vec![NodeId(10)],
output: 11, output: NodeId(11),
nodes: [ nodes: [
( (
10, NodeId(10),
ProtoNode { ProtoNode {
identifier: "graphene_core::structural::ConsNode".into(), identifier: "graphene_core::structural::ConsNode".into(),
input: ProtoNodeInput::ManualComposition(concrete!(u32)), input: ProtoNodeInput::ManualComposition(concrete!(u32)),
construction_args: ConstructionArgs::Nodes(vec![(14, false)]), construction_args: ConstructionArgs::Nodes(vec![(NodeId(14), false)]),
document_node_path: vec![1, 0], document_node_path: vec![NodeId(1), NodeId(0)],
..Default::default() ..Default::default()
}, },
), ),
( (
11, NodeId(11),
ProtoNode { ProtoNode {
identifier: "graphene_core::ops::AddPairNode".into(), identifier: "graphene_core::ops::AddPairNode".into(),
input: ProtoNodeInput::Node(10, false), input: ProtoNodeInput::Node(NodeId(10), false),
construction_args: ConstructionArgs::Nodes(vec![]), construction_args: ConstructionArgs::Nodes(vec![]),
document_node_path: vec![1, 1], document_node_path: vec![NodeId(1), NodeId(1)],
..Default::default() ..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() .into_iter()
.collect(), .collect(),
@ -1322,21 +1329,21 @@ mod test {
fn flat_network() -> NodeNetwork { fn flat_network() -> NodeNetwork {
NodeNetwork { NodeNetwork {
inputs: vec![10], inputs: vec![NodeId(10)],
outputs: vec![NodeOutput::new(11, 0)], outputs: vec![NodeOutput::new(NodeId(11), 0)],
nodes: [ nodes: [
( (
10, NodeId(10),
DocumentNode { DocumentNode {
name: "Cons".into(), 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()), implementation: DocumentNodeImplementation::Unresolved("graphene_core::structural::ConsNode".into()),
path: Some(vec![1, 0]), path: Some(vec![NodeId(1), NodeId(0)]),
..Default::default() ..Default::default()
}, },
), ),
( (
14, NodeId(14),
DocumentNode { DocumentNode {
name: "Value".into(), name: "Value".into(),
inputs: vec![NodeInput::Value { inputs: vec![NodeInput::Value {
@ -1344,17 +1351,17 @@ mod test {
exposed: false, exposed: false,
}], }],
implementation: DocumentNodeImplementation::Unresolved("graphene_core::value::ClonedNode".into()), implementation: DocumentNodeImplementation::Unresolved("graphene_core::value::ClonedNode".into()),
path: Some(vec![1, 4]), path: Some(vec![NodeId(1), NodeId(4)]),
..Default::default() ..Default::default()
}, },
), ),
( (
11, NodeId(11),
DocumentNode { DocumentNode {
name: "Add".into(), name: "Add".into(),
inputs: vec![NodeInput::node(10, 0)], inputs: vec![NodeInput::node(NodeId(10), 0)],
implementation: DocumentNodeImplementation::Unresolved("graphene_core::ops::AddPairNode".into()), implementation: DocumentNodeImplementation::Unresolved("graphene_core::ops::AddPairNode".into()),
path: Some(vec![1, 1]), path: Some(vec![NodeId(1), NodeId(1)]),
..Default::default() ..Default::default()
}, },
), ),
@ -1367,11 +1374,11 @@ mod test {
fn two_node_identity() -> NodeNetwork { fn two_node_identity() -> NodeNetwork {
NodeNetwork { NodeNetwork {
inputs: vec![1, 2], inputs: vec![NodeId(1), NodeId(2)],
outputs: vec![NodeOutput::new(1, 0), NodeOutput::new(2, 0)], outputs: vec![NodeOutput::new(NodeId(1), 0), NodeOutput::new(NodeId(2), 0)],
nodes: [ nodes: [
( (
1, NodeId(1),
DocumentNode { DocumentNode {
name: "Identity 1".into(), name: "Identity 1".into(),
inputs: vec![NodeInput::Network(concrete!(u32))], inputs: vec![NodeInput::Network(concrete!(u32))],
@ -1380,7 +1387,7 @@ mod test {
}, },
), ),
( (
2, NodeId(2),
DocumentNode { DocumentNode {
name: "Identity 2".into(), name: "Identity 2".into(),
inputs: vec![NodeInput::Network(concrete!(u32))], inputs: vec![NodeInput::Network(concrete!(u32))],
@ -1401,7 +1408,7 @@ mod test {
outputs: network_outputs, outputs: network_outputs,
nodes: [ nodes: [
( (
1, NodeId(1),
DocumentNode { DocumentNode {
name: "Nested network".into(), name: "Nested network".into(),
inputs: vec![NodeInput::value(TaggedValue::F32(1.), false), NodeInput::value(TaggedValue::F32(2.), false)], inputs: vec![NodeInput::value(TaggedValue::F32(1.), false), NodeInput::value(TaggedValue::F32(2.), false)],
@ -1410,7 +1417,7 @@ mod test {
}, },
), ),
( (
2, NodeId(2),
DocumentNode { DocumentNode {
name: "Result".into(), name: "Result".into(),
inputs: vec![result_node_input], inputs: vec![result_node_input],
@ -1424,61 +1431,67 @@ mod test {
..Default::default() ..Default::default()
}; };
let _new_ids = 101..; let _new_ids = 101..;
network.flatten_with_fns(1, |self_id, inner_id| self_id * 10 + inner_id, || 10000); network.flatten_with_fns(NodeId(1), |self_id, inner_id| NodeId(self_id.0 * 10 + inner_id.0), || NodeId(10000));
network.flatten_with_fns(2, |self_id, inner_id| self_id * 10 + inner_id, || 10001); 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.remove_dead_nodes();
network network
} }
#[test] #[test]
fn simple_duplicate() { 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:#?}"); println!("{result:#?}");
assert_eq!(result.outputs.len(), 1, "The number of outputs should remain as 1"); 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::<Vec<_>>(); let mut ids = result.nodes.keys().copied().collect::<Vec<_>>();
ids.sort(); 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 // TODO: Write more tests
/* // #[test]
#[test] // fn out_of_order_duplicate() {
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);
let result = output_duplicate(vec![NodeOutput::new(10, 1), NodeOutput::new(10, 0)], NodeInput::node(10, 0)); // assert_eq!(
assert_eq!(result.outputs[0], NodeOutput::new(101, 0), "The first network output should be from a duplicated nested network"); // result.outputs[0],
assert_eq!(result.outputs[1], NodeOutput::new(10, 0), "The second network output should be from the original nested network"); // NodeOutput::new(NodeId(101), 0),
assert!( // "The first network output should be from a duplicated nested network"
result.nodes.contains_key(&10) && result.nodes.contains_key(&101) && result.nodes.len() == 2, // );
"Network should contain two duplicated nodes" // assert_eq!(
); // result.outputs[1],
for (node_id, input_value, inner_id) in [(10, 1., 1), (101, 2., 2)] { // NodeOutput::new(NodeId(10), 0),
let nested_network_node = result.nodes.get(&node_id).unwrap(); // "The second network output should be from the original nested network"
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"); // assert!(
let inner_network = nested_network_node.implementation.get_network().expect("Implementation should be network"); // result.nodes.contains_key(&NodeId(10)) && result.nodes.contains_key(&NodeId(101)) && result.nodes.len() == 2,
assert_eq!(inner_network.inputs, vec![inner_id], "The input should be sent to the second node"); // "Network should contain two duplicated nodes"
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"); // 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");
#[test] // assert_eq!(nested_network_node.inputs, vec![NodeInput::value(TaggedValue::F32(input_value), false)], "Input should be stable");
fn using_other_node_duplicate() { // let inner_network = nested_network_node.implementation.get_network().expect("Implementation should be network");
let result = output_duplicate(vec![NodeOutput::new(11, 0)], NodeInput::node(10, 1)); // assert_eq!(inner_network.inputs, vec![inner_id], "The input should be sent to the second node");
assert_eq!(result.outputs, vec![NodeOutput::new(11, 0)], "The network output should be the result node"); // assert_eq!(inner_network.outputs, vec![NodeOutput::new(NodeId(inner_id), 0)], "The output should be node id");
assert!( // assert_eq!(inner_network.nodes.get(&NodeId(inner_id)).unwrap().name, format!("Identity {inner_id}"), "The node should be identity");
result.nodes.contains_key(&11) && result.nodes.contains_key(&101) && result.nodes.len() == 2, // }
"Network should contain a duplicated node and a result node" // }
); // #[test]
let result_node = result.nodes.get(&11).unwrap(); // fn using_other_node_duplicate() {
assert_eq!(result_node.inputs, vec![NodeInput::node(101, 0)], "Result node should refer to duplicate node as input"); // let result = output_duplicate(vec![NodeOutput::new(NodeId(11), 0)], NodeInput::node(NodeId(10), 1);
let nested_network_node = result.nodes.get(&101).unwrap(); // assert_eq!(result.outputs, vec![NodeOutput::new(NodeId(11), 0)], "The network output should be the result node");
assert_eq!(nested_network_node.name, "Nested network".to_string(), "Name should not change"); // assert!(
assert_eq!(nested_network_node.inputs, vec![NodeInput::value(TaggedValue::F32(2.), false)], "Input should be 2"); // result.nodes.contains_key(&NodeId(11)) && result.nodes.contains_key(&NodeId(101)) && result.nodes.len() == 2,
let inner_network = nested_network_node.implementation.get_network().expect("Implementation should be network"); // "Network should contain a duplicated node and a result node"
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"); // let result_node = result.nodes.get(&NodeId(11)).unwrap();
assert_eq!(inner_network.nodes.get(&2).unwrap().name, "Identity 2", "The node should be identity 2"); // 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");
// }
} }

View file

@ -191,7 +191,7 @@ impl ConstructionArgs {
// TODO: what? Used in the gpu_compiler crate for something. // TODO: what? Used in the gpu_compiler crate for something.
pub fn new_function_args(&self) -> Vec<String> { pub fn new_function_args(&self) -> Vec<String> {
match self { 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::Value(value) => vec![value.to_primitive_string()],
ConstructionArgs::Inline(inline) => vec![inline.expr.clone()], ConstructionArgs::Inline(inline) => vec![inline.expr.clone()],
} }
@ -277,7 +277,7 @@ impl ProtoNode {
} }
ProtoNodeInput::Node(id, lambda) => (id, lambda).hash(&mut hasher), 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. /// 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 { let Some(sni) = self.nodes[index].1.stable_node_id() else {
panic!("failed to generate stable node id for node {:#?}", self.nodes[index].1); 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.replace_node_id(&outwards_edges, NodeId(index as u64), sni, false);
self.nodes[index].0 = sni as NodeId; self.nodes[index].0 = sni;
} }
} }
@ -377,20 +377,26 @@ impl ProtoNetwork {
// Perform topological sort once // Perform topological sort once
self.reorder_ids()?; 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 // Collect outward edges once
let outwards_edges = self.collect_outwards_edges(); let outwards_edges = self.collect_outwards_edges();
// Iterate over nodes in topological order // Iterate over nodes in topological order
for node_id in 0..=max_id { 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 { if let ProtoNodeInput::Node(input_node_id, false) = node.input {
// Create a new node that composes the current node and its input node // Create a new node that composes the current node and its input node
let compose_node_id = self.nodes.len() as NodeId; let compose_node_id = NodeId(self.nodes.len() as u64);
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 (_, 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); path.push(node_id);
self.nodes.push(( self.nodes.push((
@ -417,7 +423,7 @@ impl ProtoNetwork {
// Update references in other nodes to use the new compose node // Update references in other nodes to use the new compose node
if let Some(referring_nodes) = outwards_edges.get(&node_id) { if let Some(referring_nodes) = outwards_edges.get(&node_id) {
for &referring_node_id in referring_nodes { 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) 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(); 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 // 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 // Create a new nodes vector based on the topological order
let mut new_nodes = Vec::with_capacity(order.len()); let mut new_nodes = Vec::with_capacity(order.len());
for (index, &id) in order.iter().enumerate() { for (index, &id) in order.iter().enumerate() {
let current_pos = *current_positions.get(&id).unwrap(); 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 // Update node references to reflect the new order
@ -733,7 +739,7 @@ mod test {
let construction_network = test_network(); let construction_network = test_network();
let sorted = construction_network.topological_sort().expect("Error when calling 'topological_sort' on 'construction_network."); let sorted = construction_network.topological_sort().expect("Error when calling 'topological_sort' on 'construction_network.");
println!("{sorted:#?}"); println!("{sorted:#?}");
assert_eq!(sorted, vec![14, 10, 11, 1]); assert_eq!(sorted, vec![NodeId(14), NodeId(10), NodeId(11), NodeId(1)]);
} }
#[test] #[test]
@ -750,12 +756,12 @@ 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."); let sorted = construction_network.topological_sort().expect("Error when calling 'topological_sort' on 'construction_network.");
println!("nodes: {:#?}", construction_network.nodes); 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(); let ids: Vec<_> = construction_network.nodes.iter().map(|(id, _)| *id).collect();
println!("{ids:#?}"); println!("{ids:#?}");
println!("nodes: {:#?}", construction_network.nodes); println!("nodes: {:#?}", construction_network.nodes);
assert_eq!(construction_network.nodes[0].1.identifier.name.as_ref(), "value"); 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] #[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.");
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."); 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(); let ids: Vec<_> = construction_network.nodes.iter().map(|(id, _)| *id).collect();
println!("{ids:#?}"); println!("{ids:#?}");
assert_eq!(construction_network.nodes[0].1.identifier.name.as_ref(), "value"); 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] #[test]
@ -778,7 +784,7 @@ mod test {
println!("{construction_network:#?}"); println!("{construction_network:#?}");
assert_eq!(construction_network.nodes[0].1.identifier.name.as_ref(), "value"); assert_eq!(construction_network.nodes[0].1.identifier.name.as_ref(), "value");
assert_eq!(construction_network.nodes.len(), 6); 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] #[test]
@ -791,59 +797,59 @@ mod test {
assert_eq!( assert_eq!(
ids, ids,
vec![ vec![
17957338642374791135, NodeId(17957338642374791135),
1303972037140595827, NodeId(1303972037140595827),
15485192931817078264, NodeId(15485192931817078264),
9739645351331265115, NodeId(9739645351331265115),
4165308598738454684, NodeId(4165308598738454684),
5557529806312473178 NodeId(5557529806312473178)
] ]
); );
} }
fn test_network() -> ProtoNetwork { fn test_network() -> ProtoNetwork {
ProtoNetwork { ProtoNetwork {
inputs: vec![10], inputs: vec![NodeId(10)],
output: 1, output: NodeId(1),
nodes: [ nodes: [
( (
7, NodeId(7),
ProtoNode { ProtoNode {
identifier: "id".into(), identifier: "id".into(),
input: ProtoNodeInput::Node(11, false), input: ProtoNodeInput::Node(NodeId(11), false),
construction_args: ConstructionArgs::Nodes(vec![]), construction_args: ConstructionArgs::Nodes(vec![]),
..Default::default() ..Default::default()
}, },
), ),
( (
1, NodeId(1),
ProtoNode { ProtoNode {
identifier: "id".into(), identifier: "id".into(),
input: ProtoNodeInput::Node(11, false), input: ProtoNodeInput::Node(NodeId(11), false),
construction_args: ConstructionArgs::Nodes(vec![]), construction_args: ConstructionArgs::Nodes(vec![]),
..Default::default() ..Default::default()
}, },
), ),
( (
10, NodeId(10),
ProtoNode { ProtoNode {
identifier: "cons".into(), identifier: "cons".into(),
input: ProtoNodeInput::ManualComposition(concrete!(u32)), input: ProtoNodeInput::ManualComposition(concrete!(u32)),
construction_args: ConstructionArgs::Nodes(vec![(14, false)]), construction_args: ConstructionArgs::Nodes(vec![(NodeId(14), false)]),
..Default::default() ..Default::default()
}, },
), ),
( (
11, NodeId(11),
ProtoNode { ProtoNode {
identifier: "add".into(), identifier: "add".into(),
input: ProtoNodeInput::Node(10, false), input: ProtoNodeInput::Node(NodeId(10), false),
construction_args: ConstructionArgs::Nodes(vec![]), construction_args: ConstructionArgs::Nodes(vec![]),
..Default::default() ..Default::default()
}, },
), ),
( (
14, NodeId(14),
ProtoNode { ProtoNode {
identifier: "value".into(), identifier: "value".into(),
input: ProtoNodeInput::None, input: ProtoNodeInput::None,
@ -859,23 +865,23 @@ mod test {
fn test_network_with_cycles() -> ProtoNetwork { fn test_network_with_cycles() -> ProtoNetwork {
ProtoNetwork { ProtoNetwork {
inputs: vec![1], inputs: vec![NodeId(1)],
output: 1, output: NodeId(1),
nodes: [ nodes: [
( (
1, NodeId(1),
ProtoNode { ProtoNode {
identifier: "id".into(), identifier: "id".into(),
input: ProtoNodeInput::Node(2, false), input: ProtoNodeInput::Node(NodeId(2), false),
construction_args: ConstructionArgs::Nodes(vec![]), construction_args: ConstructionArgs::Nodes(vec![]),
..Default::default() ..Default::default()
}, },
), ),
( (
2, NodeId(2),
ProtoNode { ProtoNode {
identifier: "id".into(), identifier: "id".into(),
input: ProtoNodeInput::Node(1, false), input: ProtoNodeInput::Node(NodeId(1), false),
construction_args: ConstructionArgs::Nodes(vec![]), construction_args: ConstructionArgs::Nodes(vec![]),
..Default::default() ..Default::default()
}, },

View file

@ -124,7 +124,7 @@ pub fn wrap_network_in_scope(mut network: NodeNetwork) -> NodeNetwork {
let inner_network = DocumentNode { let inner_network = DocumentNode {
name: "Scope".to_string(), name: "Scope".to_string(),
implementation: DocumentNodeImplementation::Network(network), 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() ..Default::default()
}; };
@ -135,14 +135,14 @@ pub fn wrap_network_in_scope(mut network: NodeNetwork) -> NodeNetwork {
DocumentNode { DocumentNode {
name: "End Scope".to_string(), name: "End Scope".to_string(),
implementation: DocumentNodeImplementation::proto("graphene_core::memo::EndLetNode<_, _>"), 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() ..Default::default()
}, },
]; ];
NodeNetwork { NodeNetwork {
inputs: vec![0], inputs: vec![NodeId(0)],
outputs: vec![NodeOutput::new(2, 0)], outputs: vec![NodeOutput::new(NodeId(2), 0)],
nodes: nodes.into_iter().enumerate().map(|(id, node)| (id as NodeId, node)).collect(), nodes: nodes.into_iter().enumerate().map(|(id, node)| (NodeId(id as u64), node)).collect(),
..Default::default() ..Default::default()
} }
} }
@ -151,8 +151,8 @@ fn begin_scope() -> DocumentNode {
DocumentNode { DocumentNode {
name: "Begin Scope".to_string(), name: "Begin Scope".to_string(),
implementation: DocumentNodeImplementation::Network(NodeNetwork { implementation: DocumentNodeImplementation::Network(NodeNetwork {
inputs: vec![0], inputs: vec![NodeId(0)],
outputs: vec![NodeOutput::new(1, 0), NodeOutput::new(2, 0)], outputs: vec![NodeOutput::new(NodeId(1), 0), NodeOutput::new(NodeId(2), 0)],
nodes: [ nodes: [
DocumentNode { DocumentNode {
name: "SetNode".to_string(), name: "SetNode".to_string(),
@ -162,21 +162,21 @@ fn begin_scope() -> DocumentNode {
}, },
DocumentNode { DocumentNode {
name: "LetNode".to_string(), 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<_>")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::memo::LetNode<_>")),
..Default::default() ..Default::default()
}, },
DocumentNode { DocumentNode {
name: "RefNode".to_string(), name: "RefNode".to_string(),
manual_composition: Some(concrete!(WasmEditorApi)), 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<_, _>")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::memo::RefNode<_, _>")),
..Default::default() ..Default::default()
}, },
] ]
.into_iter() .into_iter()
.enumerate() .enumerate()
.map(|(id, node)| (id as NodeId, node)) .map(|(id, node)| (NodeId(id as u64), node))
.collect(), .collect(),
..Default::default() ..Default::default()

View file

@ -167,11 +167,11 @@ async fn create_compute_pass_descriptor<T: Clone + Pixel + StaticTypeSized>(
log::debug!("inner_network: {inner_network:?}"); log::debug!("inner_network: {inner_network:?}");
let network = NodeNetwork { let network = NodeNetwork {
inputs: vec![2, 1], //vec![0, 1], inputs: vec![NodeId(2), NodeId(1)], //vec![0, 1],
#[cfg(feature = "quantization")] #[cfg(feature = "quantization")]
outputs: vec![NodeOutput::new(5, 0)], outputs: vec![NodeOutput::new(NodeId(5), 0)],
#[cfg(not(feature = "quantization"))] #[cfg(not(feature = "quantization"))]
outputs: vec![NodeOutput::new(3, 0)], outputs: vec![NodeOutput::new(NodeId(3), 0)],
nodes: [ nodes: [
DocumentNode { DocumentNode {
name: "Slice".into(), name: "Slice".into(),
@ -201,30 +201,30 @@ async fn create_compute_pass_descriptor<T: Clone + Pixel + StaticTypeSized>(
/* /*
DocumentNode { DocumentNode {
name: "GetNode".into(), 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()), implementation: DocumentNodeImplementation::Unresolved("graphene_core::storage::GetNode".into()),
..Default::default() ..Default::default()
},*/ },*/
#[cfg(feature = "quantization")] #[cfg(feature = "quantization")]
DocumentNode { DocumentNode {
name: "Dequantize".into(), 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"), implementation: DocumentNodeImplementation::proto("graphene_core::quantization::DeQuantizeNode"),
..Default::default() ..Default::default()
}, },
DocumentNode { DocumentNode {
name: "MapNode".into(), name: "MapNode".into(),
#[cfg(feature = "quantization")] #[cfg(feature = "quantization")]
inputs: vec![NodeInput::node(3, 0)], inputs: vec![NodeInput::node(NodeId(3), 0)],
#[cfg(not(feature = "quantization"))] #[cfg(not(feature = "quantization"))]
inputs: vec![NodeInput::node(0, 0)], inputs: vec![NodeInput::node(NodeId(0), 0)],
implementation: DocumentNodeImplementation::Network(inner_network), implementation: DocumentNodeImplementation::Network(inner_network),
..Default::default() ..Default::default()
}, },
#[cfg(feature = "quantization")] #[cfg(feature = "quantization")]
DocumentNode { DocumentNode {
name: "Quantize".into(), 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"), implementation: DocumentNodeImplementation::proto("graphene_core::quantization::QuantizeNode"),
..Default::default() ..Default::default()
}, },
@ -232,7 +232,7 @@ async fn create_compute_pass_descriptor<T: Clone + Pixel + StaticTypeSized>(
DocumentNode { DocumentNode {
name: "SaveNode".into(), name: "SaveNode".into(),
inputs: vec![ inputs: vec![
NodeInput::node(5, 0), NodeInput::node(NodeId(5), 0),
NodeInput::Inline(InlineRust::new( NodeInput::Inline(InlineRust::new(
"|x| o0[(_global_index.y * i1 + _global_index.x) as usize] = x".into(), "|x| o0[(_global_index.y * i1 + _global_index.x) as usize] = x".into(),
//"|x|()".into(), //"|x|()".into(),
@ -246,7 +246,7 @@ async fn create_compute_pass_descriptor<T: Clone + Pixel + StaticTypeSized>(
] ]
.into_iter() .into_iter()
.enumerate() .enumerate()
.map(|(id, node)| (id as NodeId, node)) .map(|(id, node)| (NodeId(id as u64), node))
.collect(), .collect(),
..Default::default() ..Default::default()
}; };
@ -386,12 +386,12 @@ fn map_gpu_single_image(input: Image<Color>, node: String) -> Image<Color> {
let identifier = ProtoNodeIdentifier { name: std::borrow::Cow::Owned(node) }; let identifier = ProtoNodeIdentifier { name: std::borrow::Cow::Owned(node) };
let network = NodeNetwork { let network = NodeNetwork {
inputs: vec![0], inputs: vec![NodeId(0)],
disabled: vec![], disabled: vec![],
previous_outputs: None, previous_outputs: None,
outputs: vec![NodeOutput::new(0, 0)], outputs: vec![NodeOutput::new(NodeId(0), 0)],
nodes: [( nodes: [(
0, NodeId(0),
DocumentNode { DocumentNode {
name: "Image Filter".into(), name: "Image Filter".into(),
inputs: vec![NodeInput::Network(concrete!(Color))], inputs: vec![NodeInput::Network(concrete!(Color))],
@ -433,7 +433,7 @@ async fn blend_gpu_image(foreground: ImageFrame<Color>, background: ImageFrame<C
let network = NodeNetwork { let network = NodeNetwork {
inputs: vec![], inputs: vec![],
outputs: vec![NodeOutput::new(0, 0)], outputs: vec![NodeOutput::new(NodeId(0), 0)],
nodes: [DocumentNode { nodes: [DocumentNode {
name: "BlendOp".into(), name: "BlendOp".into(),
inputs: vec![NodeInput::Inline(InlineRust::new( inputs: vec![NodeInput::Inline(InlineRust::new(
@ -464,7 +464,7 @@ async fn blend_gpu_image(foreground: ImageFrame<Color>, background: ImageFrame<C
}] }]
.into_iter() .into_iter()
.enumerate() .enumerate()
.map(|(id, node)| (id as NodeId, node)) .map(|(id, node)| (NodeId(id as u64), node))
.collect(), .collect(),
..Default::default() ..Default::default()
}; };

View file

@ -193,10 +193,10 @@ mod test {
let mut tree = BorrowTree::default(); let mut tree = BorrowTree::default();
let val_1_protonode = ProtoNode::value(ConstructionArgs::Value(TaggedValue::U32(2u32)), vec![]); let val_1_protonode = ProtoNode::value(ConstructionArgs::Value(TaggedValue::U32(2u32)), vec![]);
let context = TypingContext::default(); let context = TypingContext::default();
let future = tree.push_node(0, val_1_protonode, &context); //.await.unwrap(); let future = tree.push_node(NodeId(0), val_1_protonode, &context); //.await.unwrap();
futures::executor::block_on(future).unwrap(); futures::executor::block_on(future).unwrap();
let _node = tree.get(0).unwrap(); let _node = tree.get(NodeId(0)).unwrap();
let result = futures::executor::block_on(tree.eval(0, ())); let result = futures::executor::block_on(tree.eval(NodeId(0), ()));
assert_eq!(result, Some(2u32)); assert_eq!(result, Some(2u32));
} }
} }

View file

@ -16,11 +16,11 @@ mod tests {
fn add_network() -> NodeNetwork { fn add_network() -> NodeNetwork {
NodeNetwork { NodeNetwork {
inputs: vec![0, 0], inputs: vec![NodeId(0), NodeId(0)],
outputs: vec![NodeOutput::new(1, 0)], outputs: vec![NodeOutput::new(NodeId(1), 0)],
nodes: [ nodes: [
( (
0, NodeId(0),
DocumentNode { DocumentNode {
name: "Cons".into(), name: "Cons".into(),
inputs: vec![NodeInput::Network(concrete!(u32)), NodeInput::Network(concrete!(&u32))], inputs: vec![NodeInput::Network(concrete!(u32)), NodeInput::Network(concrete!(&u32))],
@ -29,10 +29,10 @@ mod tests {
}, },
), ),
( (
1, NodeId(1),
DocumentNode { DocumentNode {
name: "Add".into(), 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")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::ops::AddPairNode")),
..Default::default() ..Default::default()
}, },
@ -45,10 +45,10 @@ mod tests {
} }
let network = NodeNetwork { let network = NodeNetwork {
inputs: vec![0], inputs: vec![NodeId(0)],
outputs: vec![NodeOutput::new(0, 0)], outputs: vec![NodeOutput::new(NodeId(0), 0)],
nodes: [( nodes: [(
0, NodeId(0),
DocumentNode { DocumentNode {
name: "Inc".into(), name: "Inc".into(),
inputs: vec![ inputs: vec![
@ -86,12 +86,12 @@ mod tests {
use graph_craft::*; use graph_craft::*;
let network = NodeNetwork { let network = NodeNetwork {
inputs: vec![0], inputs: vec![NodeId(0)],
outputs: vec![NodeOutput::new(1, 0)], outputs: vec![NodeOutput::new(NodeId(1), 0)],
nodes: [ nodes: [
// Simple identity node taking a number as input from outside the graph // Simple identity node taking a number as input from outside the graph
( (
0, NodeId(0),
DocumentNode { DocumentNode {
name: "id".into(), name: "id".into(),
inputs: vec![NodeInput::Network(concrete!(u32))], 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 // An add node adding the result of the id node to its self
( (
1, NodeId(1),
DocumentNode { DocumentNode {
name: "Add".into(), 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<_>")), implementation: DocumentNodeImplementation::Unresolved(ProtoNodeIdentifier::new("graphene_core::ops::AddNode<_>")),
..Default::default() ..Default::default()
}, },

View file

@ -121,11 +121,11 @@ fn create_buffer<T: Pod + Send + Sync>(data: Vec<T>, alloc: &StandardMemoryAlloc
// fn inc_network() -> ProtoNetwork { // fn inc_network() -> ProtoNetwork {
// let mut construction_network = ProtoNetwork { // let mut construction_network = ProtoNetwork {
// inputs: vec![10], // inputs: vec![NodeId(10)],
// output: 1, // output: NodeId(1),
// nodes: [ // nodes: [
// ( // (
// 1, // NodeId(1),
// ProtoNode { // ProtoNode {
// identifier: ProtoNodeIdentifier::new("graphene_core::ops::IdentityNode", &[generic!("u32")]), // identifier: ProtoNodeIdentifier::new("graphene_core::ops::IdentityNode", &[generic!("u32")]),
// input: ProtoNodeInput::Node(11), // input: ProtoNodeInput::Node(11),
@ -133,7 +133,7 @@ fn create_buffer<T: Pod + Send + Sync>(data: Vec<T>, alloc: &StandardMemoryAlloc
// }, // },
// ), // ),
// ( // (
// 10, // NodeId(10),
// ProtoNode { // ProtoNode {
// identifier: ProtoNodeIdentifier::new("graphene_core::structural::ConsNode", &[generic!("&ValueNode<u32>"), generic!("()")]), // identifier: ProtoNodeIdentifier::new("graphene_core::structural::ConsNode", &[generic!("&ValueNode<u32>"), generic!("()")]),
// input: ProtoNodeInput::Network, // input: ProtoNodeInput::Network,
@ -141,7 +141,7 @@ fn create_buffer<T: Pod + Send + Sync>(data: Vec<T>, alloc: &StandardMemoryAlloc
// }, // },
// ), // ),
// ( // (
// 11, // NodeId(11),
// ProtoNode { // ProtoNode {
// identifier: ProtoNodeIdentifier::new("graphene_core::ops::AddPairNode", &[generic!("u32"), generic!("u32")]), // identifier: ProtoNodeIdentifier::new("graphene_core::ops::AddPairNode", &[generic!("u32"), generic!("u32")]),
// input: ProtoNodeInput::Node(10), // input: ProtoNodeInput::Node(10),
@ -149,7 +149,7 @@ fn create_buffer<T: Pod + Send + Sync>(data: Vec<T>, alloc: &StandardMemoryAlloc
// }, // },
// ), // ),
// ( // (
// 14, // NodeId(14),
// ProtoNode { // ProtoNode {
// identifier: ProtoNodeIdentifier::new("graphene_core::value::ValueNode", &[concrete!("u32")]), // identifier: ProtoNodeIdentifier::new("graphene_core::value::ValueNode", &[concrete!("u32")]),
// input: ProtoNodeInput::None, // input: ProtoNodeInput::None,

View file

@ -203,11 +203,11 @@ async fn execute_shader<I: Pod + Send + Sync, O: Pod + Send + Sync>(device: Arc<
// fn inc_network() -> ProtoNetwork { // fn inc_network() -> ProtoNetwork {
// let mut construction_network = ProtoNetwork { // let mut construction_network = ProtoNetwork {
// inputs: vec![10], // inputs: vec![NodeId(10)],
// output: 1, // output: NodeId(1),
// nodes: [ // nodes: [
// ( // (
// 1, // NodeId(1),
// ProtoNode { // ProtoNode {
// identifier: ProtoNodeIdentifier::new("graphene_core::ops::IdentityNode", &[generic!("u32")]), // identifier: ProtoNodeIdentifier::new("graphene_core::ops::IdentityNode", &[generic!("u32")]),
// input: ProtoNodeInput::Node(11), // input: ProtoNodeInput::Node(11),
@ -215,7 +215,7 @@ async fn execute_shader<I: Pod + Send + Sync, O: Pod + Send + Sync>(device: Arc<
// }, // },
// ), // ),
// ( // (
// 10, // NodeId(10),
// ProtoNode { // ProtoNode {
// identifier: ProtoNodeIdentifier::new("graphene_core::structural::ConsNode", &[generic!("&ValueNode<u32>"), generic!("()")]), // identifier: ProtoNodeIdentifier::new("graphene_core::structural::ConsNode", &[generic!("&ValueNode<u32>"), generic!("()")]),
// input: ProtoNodeInput::Network, // input: ProtoNodeInput::Network,
@ -223,7 +223,7 @@ async fn execute_shader<I: Pod + Send + Sync, O: Pod + Send + Sync>(device: Arc<
// }, // },
// ), // ),
// ( // (
// 11, // NodeId(11),
// ProtoNode { // ProtoNode {
// identifier: ProtoNodeIdentifier::new("graphene_core::ops::AddPairNode", &[generic!("u32"), generic!("u32")]), // identifier: ProtoNodeIdentifier::new("graphene_core::ops::AddPairNode", &[generic!("u32"), generic!("u32")]),
// input: ProtoNodeInput::Node(10), // input: ProtoNodeInput::Node(10),
@ -231,7 +231,7 @@ async fn execute_shader<I: Pod + Send + Sync, O: Pod + Send + Sync>(device: Arc<
// }, // },
// ), // ),
// ( // (
// 14, // NodeId(14),
// ProtoNode { // ProtoNode {
// identifier: ProtoNodeIdentifier::new("graphene_core::value::ValueNode", &[concrete!("u32")]), // identifier: ProtoNodeIdentifier::new("graphene_core::value::ValueNode", &[concrete!("u32")]),
// input: ProtoNodeInput::None, // input: ProtoNodeInput::None,