{
pub data: Vec,
}
+impl Debug for Image {
+ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+ let length = self.data.len();
+ f.debug_struct("Image")
+ .field("width", &self.width)
+ .field("height", &self.height)
+ .field("data", if length < 100 { &self.data } else { &length })
+ .finish()
+ }
+}
+
unsafe impl StaticType for Image
where
P::Static: Pixel,
diff --git a/node-graph/graph-craft/src/document.rs b/node-graph/graph-craft/src/document.rs
index edd4aa947b..00bb0d0e72 100644
--- a/node-graph/graph-craft/src/document.rs
+++ b/node-graph/graph-craft/src/document.rs
@@ -243,6 +243,10 @@ impl DocumentNodeImplementation {
_ => None,
}
}
+
+ pub const fn proto(name: &'static str) -> Self {
+ Self::Unresolved(NodeIdentifier::new(name))
+ }
}
#[derive(Clone, Copy, Debug, Default, PartialEq, DynAny, specta::Type, Hash)]
@@ -812,6 +816,28 @@ impl NodeNetwork {
nodes: nodes.clone(),
})
}
+
+ /// Create a [`RecursiveNodeIter`] that iterates over all [`DocumentNode`]s, including ones that are deeply nested.
+ pub fn recursive_nodes(&self) -> RecursiveNodeIter {
+ let nodes = self.nodes.iter().map(|(id, node)| (node, self, vec![*id])).collect();
+ RecursiveNodeIter { nodes }
+ }
+}
+
+/// An iterator over all [`DocumentNode`]s, including ones that are deeply nested.
+pub struct RecursiveNodeIter<'a> {
+ nodes: Vec<(&'a DocumentNode, &'a NodeNetwork, Vec)>,
+}
+
+impl<'a> Iterator for RecursiveNodeIter<'a> {
+ type Item = (&'a DocumentNode, &'a NodeNetwork, Vec);
+ fn next(&mut self) -> Option {
+ let (node, network, path) = self.nodes.pop()?;
+ if let DocumentNodeImplementation::Network(network) = &node.implementation {
+ self.nodes.extend(network.nodes.iter().map(|(id, node)| (node, network, [path.as_slice(), &[*id]].concat())));
+ }
+ Some((node, network, path))
+ }
}
#[cfg(test)]
diff --git a/node-graph/graph-craft/src/executor.rs b/node-graph/graph-craft/src/executor.rs
index 314cc64a9e..dbc1dd2e0e 100644
--- a/node-graph/graph-craft/src/executor.rs
+++ b/node-graph/graph-craft/src/executor.rs
@@ -10,7 +10,6 @@ pub struct Compiler {}
impl Compiler {
pub fn compile(&self, mut network: NodeNetwork, resolve_inputs: bool) -> impl Iterator- {
let node_ids = network.nodes.keys().copied().collect::>();
- network.generate_node_paths(&[]);
network.resolve_extract_nodes();
println!("flattening");
for id in node_ids {
diff --git a/node-graph/graph-craft/src/proto.rs b/node-graph/graph-craft/src/proto.rs
index 7d63f09484..dbc29fd983 100644
--- a/node-graph/graph-craft/src/proto.rs
+++ b/node-graph/graph-craft/src/proto.rs
@@ -156,6 +156,7 @@ impl ProtoNode {
self.identifier.name.hash(&mut hasher);
self.construction_args.hash(&mut hasher);
+ self.document_node_path.hash(&mut hasher);
match self.input {
ProtoNodeInput::None => "none".hash(&mut hasher),
ProtoNodeInput::ShortCircut(ref ty) => {
@@ -629,12 +630,12 @@ mod test {
assert_eq!(
ids,
vec![
- 10739226043134366700,
- 17332796976541881019,
- 7897288931440576543,
- 7388412494950743023,
- 359700384277940942,
- 12822947441562012352
+ 4471348669260178714,
+ 12892313567093808068,
+ 6883586777044498729,
+ 13841339389284532934,
+ 4412916056300566478,
+ 15358108940336208665
]
);
}
diff --git a/node-graph/interpreted-executor/src/executor.rs b/node-graph/interpreted-executor/src/executor.rs
index fa1cdf13a2..96b4c2d0cb 100644
--- a/node-graph/interpreted-executor/src/executor.rs
+++ b/node-graph/interpreted-executor/src/executor.rs
@@ -139,8 +139,8 @@ impl BorrowTree {
node.reset();
}
old_nodes.remove(&id);
- self.source_map.retain(|_, nid| !old_nodes.contains(nid));
}
+ self.source_map.retain(|_, nid| !old_nodes.contains(nid));
Ok(old_nodes.into_iter().collect())
}
diff --git a/node-graph/interpreted-executor/src/node_registry.rs b/node-graph/interpreted-executor/src/node_registry.rs
index 5a9e0164ff..d63150ec31 100644
--- a/node-graph/interpreted-executor/src/node_registry.rs
+++ b/node-graph/interpreted-executor/src/node_registry.rs
@@ -155,6 +155,7 @@ fn node_registry() -> HashMap, input: ImageFrame, params: [ImageFrame]),
register_node!(graphene_std::raster::EmptyImageNode<_, _>, input: DAffine2, params: [Color]),
register_node!(graphene_std::memo::MonitorNode<_>, input: ImageFrame, params: []),
+ register_node!(graphene_std::memo::MonitorNode<_>, input: graphene_core::GraphicGroup, params: []),
#[cfg(feature = "gpu")]
register_node!(graphene_std::executor::MapGpuSingleImageNode<_>, input: Image, params: [String]),
vec![(
@@ -366,6 +367,26 @@ fn node_registry() -> HashMap"),
+ |args| {
+ let input: DowncastBothNode<(), graphene_core::GraphicGroup> = DowncastBothNode::new(args[0]);
+ let node = graphene_std::memo::EndLetNode::new(input);
+ let any: DynAnyInRefNode = graphene_std::any::DynAnyInRefNode::new(node);
+ any.into_type_erased()
+ },
+ NodeIOTypes::new(generic!(T), concrete!(graphene_core::EditorApi), vec![value_fn!(graphene_core::GraphicGroup)]),
+ ),
+ (
+ NodeIdentifier::new("graphene_std::memo::EndLetNode<_>"),
+ |args| {
+ let input: DowncastBothNode<(), graphene_core::Artboard> = DowncastBothNode::new(args[0]);
+ let node = graphene_std::memo::EndLetNode::new(input);
+ let any: DynAnyInRefNode = graphene_std::any::DynAnyInRefNode::new(node);
+ any.into_type_erased()
+ },
+ NodeIOTypes::new(generic!(T), concrete!(graphene_core::EditorApi), vec![value_fn!(graphene_core::Artboard)]),
+ ),
(
NodeIdentifier::new("graphene_std::memo::RefNode<_, _>"),
|args| {