Restructure node crates (#3384)

* Restructure node-graph folder

* Fix wasm compilation

* Move node definitions out of *-types crates

* Cleanup

* Fix warnings

* Fix warnings

* Start adding migrations

* Add migrations and move memo nodes to gcore

* Move nodes/gsvg-render -> rendering

* Replace some hard coded identifiers and fix automatic conversion

* Fix Vec2Value node migration

* Fix formatting

* Add more migrations

* Cleanup features

* Fix core_types::raster import

* Update demo artwork (to make profile ci work)

* Move *-types to node-graph/libraries folder

* Add missing node migrations

* Migrate more nodes

* Remove impure memo node

* More fixes and remove warning

* Migrate context and add a few missing migrations

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Dennis Kobert
2025-11-18 11:21:54 +01:00
committed by GitHub
parent 12453d2e61
commit 57b0b9c7ed
193 changed files with 3871 additions and 2720 deletions

View File

@@ -2,12 +2,12 @@ pub mod value;
use crate::document::value::TaggedValue;
use crate::proto::{ConstructionArgs, ProtoNetwork, ProtoNode};
use core_types::memo::MemoHashGuard;
pub use core_types::uuid::NodeId;
pub use core_types::uuid::generate_uuid;
use core_types::{Context, ContextDependencies, Cow, MemoHash, ProtoNodeIdentifier, Type};
use dyn_any::DynAny;
use glam::IVec2;
use graphene_core::memo::MemoHashGuard;
pub use graphene_core::uuid::NodeId;
pub use graphene_core::uuid::generate_uuid;
use graphene_core::{Context, ContextDependencies, Cow, MemoHash, ProtoNodeIdentifier, Type};
use log::Metadata;
use rustc_hash::{FxBuildHasher, FxHashMap};
use std::collections::HashMap;
@@ -318,7 +318,7 @@ pub enum DocumentNodeImplementation {
impl Default for DocumentNodeImplementation {
fn default() -> Self {
Self::ProtoNode(ProtoNodeIdentifier::new("graphene_core::ops::IdentityNode"))
Self::ProtoNode(graphene_core::ops::identity::IDENTIFIER)
}
}
@@ -475,7 +475,7 @@ pub struct OldNodeNetwork {
#[serde(alias = "outputs", deserialize_with = "deserialize_exports")] // TODO: Eventually remove this alias document upgrade code
pub exports: Vec<NodeInput>,
/// The list of all nodes in this network.
//cfg_attr(feature = "serde", #[serde(serialize_with = "graphene_core::vector::serialize_hashmap", deserialize_with = "graphene_core::vector::deserialize_hashmap"))]
//cfg_attr(feature = "serde", #[serde(serialize_with = "core_types::vector::serialize_hashmap", deserialize_with = "core_types::vector::deserialize_hashmap"))]
pub nodes: HashMap<NodeId, OldDocumentNode>,
/// Indicates whether the network is currently rendered with a particular node that is previewed, and if so, which connection should be restored when the preview ends.
#[serde(default)]
@@ -488,7 +488,7 @@ pub struct OldNodeNetwork {
/// A network may expose nodes as constants which can by used by other nodes using a `NodeInput::Scope(key)`.
#[serde(default)]
//cfg_attr(feature = "serde", #[serde(serialize_with = "graphene_core::vector::serialize_hashmap", deserialize_with = "graphene_core::vector::deserialize_hashmap"))]
//cfg_attr(feature = "serde", #[serde(serialize_with = "core_types::vector::serialize_hashmap", deserialize_with = "core_types::vector::deserialize_hashmap"))]
pub scope_injections: HashMap<String, (NodeId, Type)>,
}
@@ -520,11 +520,17 @@ pub struct NodeNetwork {
// TODO: Instead of storing import types in each NodeInput::Import connection, the types are stored here. This is similar to how types need to be defined for parameters when creating a function in Rust.
// pub import_types: Vec<Type>,
/// The list of all nodes in this network.
#[serde(serialize_with = "graphene_core::vector::serialize_hashmap", deserialize_with = "graphene_core::vector::deserialize_hashmap")]
#[serde(
serialize_with = "graphic_types::vector_types::vector::serialize_hashmap",
deserialize_with = "graphic_types::vector_types::vector::deserialize_hashmap"
)]
pub nodes: FxHashMap<NodeId, DocumentNode>,
/// A network may expose nodes as constants which can by used by other nodes using a `NodeInput::Scope(key)`.
#[serde(default)]
#[serde(serialize_with = "graphene_core::vector::serialize_hashmap", deserialize_with = "graphene_core::vector::deserialize_hashmap")]
#[serde(
serialize_with = "graphic_types::vector_types::vector::serialize_hashmap",
deserialize_with = "graphic_types::vector_types::vector::deserialize_hashmap"
)]
pub scope_injections: FxHashMap<String, (NodeId, Type)>,
#[serde(skip)]
pub generated: bool,
@@ -773,7 +779,7 @@ impl NodeNetwork {
};
// If the node is hidden, replace it with an identity node
let identity_node = DocumentNodeImplementation::ProtoNode("graphene_core::ops::IdentityNode".into());
let identity_node = DocumentNodeImplementation::ProtoNode(graphene_core::ops::identity::IDENTIFIER);
if !node.visible && node.implementation != identity_node {
node.implementation = identity_node;
@@ -787,7 +793,7 @@ impl NodeNetwork {
let path = node.original_location.path.clone().unwrap_or_default();
// Replace value inputs with dedicated value nodes
if node.implementation != DocumentNodeImplementation::ProtoNode("graphene_core::value::ClonedNode".into()) {
if node.implementation != DocumentNodeImplementation::ProtoNode("core_types::value::ClonedNode".into()) {
Self::replace_value_inputs_with_nodes(&mut node.inputs, &mut self.nodes, &path, gen_id, map_ids, id);
}
@@ -923,7 +929,7 @@ impl NodeNetwork {
merged_node_id,
DocumentNode {
inputs: vec![NodeInput::Value { tagged_value, exposed }],
implementation: DocumentNodeImplementation::ProtoNode("graphene_core::value::ClonedNode".into()),
implementation: DocumentNodeImplementation::ProtoNode("core_types::value::ClonedNode".into()),
original_location,
..Default::default()
},
@@ -989,7 +995,7 @@ impl NodeNetwork {
.nodes
.iter()
.filter(|(_, node)| {
matches!(&node.implementation, DocumentNodeImplementation::ProtoNode(ident) if ident == &ProtoNodeIdentifier::new("graphene_core::ops::IdentityNode"))
matches!(&node.implementation, DocumentNodeImplementation::ProtoNode(ident) if ident == &graphene_core::ops::identity::IDENTIFIER)
&& node.inputs.len() == 1
&& matches!(node.inputs[0], NodeInput::Node { .. })
})
@@ -1022,7 +1028,7 @@ impl NodeNetwork {
assert_eq!(output_index, 0);
// TODO: check if we can read lambda checking?
let mut input_node = self.nodes.remove(&node_id).unwrap();
node.implementation = DocumentNodeImplementation::ProtoNode("graphene_core::value::ClonedNode".into());
node.implementation = DocumentNodeImplementation::ProtoNode("core_types::value::ClonedNode".into());
if let Some(input) = input_node.inputs.get_mut(0) {
*input = match &input {
NodeInput::Node { .. } => NodeInput::import(generic!(T), 0),
@@ -1139,7 +1145,7 @@ mod test {
NodeId(0),
DocumentNode {
inputs: vec![NodeInput::import(concrete!(u32), 0), NodeInput::import(concrete!(u32), 1)],
implementation: DocumentNodeImplementation::ProtoNode("graphene_core::structural::ConsNode".into()),
implementation: DocumentNodeImplementation::ProtoNode("core_types::structural::ConsNode".into()),
..Default::default()
},
),
@@ -1147,7 +1153,7 @@ mod test {
NodeId(1),
DocumentNode {
inputs: vec![NodeInput::node(NodeId(0), 0)],
implementation: DocumentNodeImplementation::ProtoNode("graphene_core::ops::AddPairNode".into()),
implementation: DocumentNodeImplementation::ProtoNode("core_types::ops::AddPairNode".into()),
..Default::default()
},
),
@@ -1169,7 +1175,7 @@ mod test {
NodeId(1),
DocumentNode {
inputs: vec![NodeInput::import(concrete!(u32), 0), NodeInput::import(concrete!(u32), 1)],
implementation: DocumentNodeImplementation::ProtoNode("graphene_core::structural::ConsNode".into()),
implementation: DocumentNodeImplementation::ProtoNode("core_types::structural::ConsNode".into()),
..Default::default()
},
),
@@ -1177,7 +1183,7 @@ mod test {
NodeId(2),
DocumentNode {
inputs: vec![NodeInput::node(NodeId(1), 0)],
implementation: DocumentNodeImplementation::ProtoNode("graphene_core::ops::AddPairNode".into()),
implementation: DocumentNodeImplementation::ProtoNode("core_types::ops::AddPairNode".into()),
..Default::default()
},
),
@@ -1193,7 +1199,7 @@ mod test {
fn extract_node() {
let id_node = DocumentNode {
inputs: vec![],
implementation: DocumentNodeImplementation::ProtoNode("graphene_core::ops::IdentityNode".into()),
implementation: DocumentNodeImplementation::ProtoNode(graphene_core::ops::identity::IDENTIFIER),
..Default::default()
};
// TODO: Extend test cases to test nested network
@@ -1250,13 +1256,13 @@ mod test {
let document_node = DocumentNode {
inputs: vec![NodeInput::node(NodeId(0), 0)],
call_argument: concrete!(u32),
implementation: DocumentNodeImplementation::ProtoNode("graphene_core::structural::ConsNode".into()),
implementation: DocumentNodeImplementation::ProtoNode("core_types::structural::ConsNode".into()),
..Default::default()
};
let proto_node = document_node.resolve_proto_node();
let reference = ProtoNode {
identifier: "graphene_core::structural::ConsNode".into(),
identifier: "core_types::structural::ConsNode".into(),
call_argument: concrete!(u32),
construction_args: ConstructionArgs::Nodes(vec![NodeId(0)]),
..Default::default()
@@ -1273,7 +1279,7 @@ mod test {
(
NodeId(10),
ProtoNode {
identifier: "graphene_core::structural::ConsNode".into(),
identifier: "core_types::structural::ConsNode".into(),
call_argument: concrete!(u32),
construction_args: ConstructionArgs::Nodes(vec![NodeId(14)]),
original_location: OriginalLocation {
@@ -1289,7 +1295,7 @@ mod test {
(
NodeId(11),
ProtoNode {
identifier: "graphene_core::ops::AddPairNode".into(),
identifier: "core_types::ops::AddPairNode".into(),
call_argument: concrete!(Context),
construction_args: ConstructionArgs::Nodes(vec![NodeId(10)]),
original_location: OriginalLocation {
@@ -1304,8 +1310,8 @@ mod test {
(
NodeId(14),
ProtoNode {
identifier: "graphene_core::value::ClonedNode".into(),
call_argument: concrete!(graphene_core::Context),
identifier: "core_types::value::ClonedNode".into(),
call_argument: concrete!(core_types::Context),
construction_args: ConstructionArgs::Value(TaggedValue::U32(2).into()),
original_location: OriginalLocation {
path: Some(vec![NodeId(1), NodeId(4)]),
@@ -1338,7 +1344,7 @@ mod test {
DocumentNode {
inputs: vec![NodeInput::node(NodeId(14), 0)],
call_argument: concrete!(u32),
implementation: DocumentNodeImplementation::ProtoNode("graphene_core::structural::ConsNode".into()),
implementation: DocumentNodeImplementation::ProtoNode("core_types::structural::ConsNode".into()),
original_location: OriginalLocation {
path: Some(vec![NodeId(1), NodeId(0)]),
inputs_source: [(Source { node: vec![NodeId(1)], index: 1 }, 1)].into(),
@@ -1352,7 +1358,7 @@ mod test {
NodeId(14),
DocumentNode {
inputs: vec![NodeInput::value(TaggedValue::U32(2), false)],
implementation: DocumentNodeImplementation::ProtoNode("graphene_core::value::ClonedNode".into()),
implementation: DocumentNodeImplementation::ProtoNode("core_types::value::ClonedNode".into()),
original_location: OriginalLocation {
path: Some(vec![NodeId(1), NodeId(4)]),
inputs_source: HashMap::new(),
@@ -1366,7 +1372,7 @@ mod test {
NodeId(11),
DocumentNode {
inputs: vec![NodeInput::node(NodeId(10), 0)],
implementation: DocumentNodeImplementation::ProtoNode("graphene_core::ops::AddPairNode".into()),
implementation: DocumentNodeImplementation::ProtoNode("core_types::ops::AddPairNode".into()),
original_location: OriginalLocation {
path: Some(vec![NodeId(1), NodeId(1)]),
inputs_source: HashMap::new(),