Implement Node Path Insertion at Compile Time (#1947)

* Implement node path insertion at compile time

* Fix ci failure

* Continue instead of returning from the function
This commit is contained in:
Dennis Kobert 2024-08-31 12:11:38 +02:00 committed by GitHub
parent f2493d5308
commit 432385343e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 57 additions and 30 deletions

View file

@ -618,6 +618,7 @@ impl NodeNetworkInterface {
}
NodeInput::Scope(_) => todo!(),
NodeInput::Inline(_) => todo!(),
NodeInput::Reflection(_) => todo!(),
}
}
}
@ -4418,7 +4419,7 @@ impl NodeNetworkInterface {
if post_node.input_index() == 1 || matches!(post_node, InputConnector::Export(_)) || !post_node.node_id().is_some_and(|post_node_id| self.is_layer(&post_node_id, network_path)) {
match post_node_input {
// Create a new stack
NodeInput::Value { .. } | NodeInput::Scope(_) | NodeInput::Inline(_) => {
NodeInput::Value { .. } | NodeInput::Scope(_) | NodeInput::Inline(_) | NodeInput::Reflection(_) => {
self.create_wire(&OutputConnector::node(layer.to_node(), 0), &post_node, network_path);
let final_layer_position = after_move_post_layer_position + IVec2::new(-8, 3);
@ -4444,7 +4445,7 @@ impl NodeNetworkInterface {
} else {
match post_node_input {
// Move to the bottom of the stack
NodeInput::Value { .. } | NodeInput::Scope(_) | NodeInput::Inline(_) => {
NodeInput::Value { .. } | NodeInput::Scope(_) | NodeInput::Inline(_) | NodeInput::Reflection(_) => {
// TODO: Calculate height of bottom layer by getting height of upstream nodes instead of setting to 3
let offset = after_move_post_layer_position - previous_layer_position + IVec2::new(0, 3);
self.shift_absolute_node_position(&layer.to_node(), offset, network_path);

View file

@ -7,6 +7,7 @@ pub use graphene_core::uuid::generate_uuid;
use graphene_core::{Cow, MemoHash, ProtoNodeIdentifier, Type};
use glam::IVec2;
use log::Metadata;
use rustc_hash::FxHashMap;
use std::collections::hash_map::DefaultHasher;
use std::collections::HashMap;
@ -15,7 +16,7 @@ use std::hash::{Hash, Hasher};
pub mod value;
#[repr(transparent)]
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, PartialOrd, Ord, serde::Serialize, serde::Deserialize, specta::Type)]
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, PartialOrd, Ord, serde::Serialize, serde::Deserialize, specta::Type, DynAny)]
pub struct NodeId(pub u64);
// TODO: Find and replace all `NodeId(generate_uuid())` with `NodeId::new()`.
@ -308,6 +309,7 @@ impl DocumentNode {
NodeInput::Network { import_type, .. } => (ProtoNodeInput::ManualComposition(import_type), ConstructionArgs::Nodes(vec![])),
NodeInput::Inline(inline) => (ProtoNodeInput::None, ConstructionArgs::Inline(inline)),
NodeInput::Scope(_) => unreachable!("Scope input was not resolved"),
NodeInput::Reflection(_) => unreachable!("Reflection input was not resolved"),
}
};
assert!(!self.inputs.iter().any(|input| matches!(input, NodeInput::Network { .. })), "received non resolved parameter");
@ -355,6 +357,9 @@ pub enum NodeInput {
/// Input that is extracted from the parent scopes the node resides in. The string argument is the key.
Scope(Cow<'static, str>),
/// Input that is extracted from the parent scopes the node resides in. The string argument is the key.
Reflection(DocumentNodeMetadata),
/// A Rust source code string. Allows us to insert literal Rust code. Only used for GPU compilation.
/// We can use this whenever we spin up Rustc. Sort of like inline assembly, but because our language is Rust, it acts as inline Rust.
Inline(InlineRust),
@ -373,6 +378,12 @@ impl InlineRust {
}
}
#[derive(Debug, Clone, PartialEq, Hash, DynAny)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum DocumentNodeMetadata {
DocumentNodePath,
}
impl NodeInput {
pub const fn node(node_id: NodeId, output_index: usize) -> Self {
Self::Node { node_id, output_index, lambda: false }
@ -412,6 +423,7 @@ impl NodeInput {
NodeInput::Network { .. } => true,
NodeInput::Inline(_) => false,
NodeInput::Scope(_) => false,
NodeInput::Reflection(_) => false,
}
}
/// Network node inputs in the document network are not displayed, but still exist in the compiled network
@ -422,6 +434,7 @@ impl NodeInput {
NodeInput::Network { .. } => !is_document_network,
NodeInput::Inline(_) => false,
NodeInput::Scope(_) => false,
NodeInput::Reflection(_) => false,
}
}
@ -432,6 +445,7 @@ impl NodeInput {
NodeInput::Network { import_type, .. } => import_type.clone(),
NodeInput::Inline(_) => panic!("ty() called on NodeInput::Inline"),
NodeInput::Scope(_) => unreachable!("ty() called on NodeInput::Scope"),
NodeInput::Reflection(_) => concrete!(Metadata),
}
}
@ -1022,7 +1036,7 @@ impl NodeNetwork {
return;
};
// Replace value exports with value nodes, added inside nested network
// Replace value and reflection imports with value nodes, added inside nested network
Self::replace_value_inputs_with_nodes(
&mut inner_network.exports,
&mut inner_network.nodes,
@ -1076,6 +1090,7 @@ impl NodeNetwork {
// TODO use correct output index
nested_node.inputs[nested_input_index] = NodeInput::node(*import_id, 0);
}
NodeInput::Reflection(_) => unreachable!("Reflection inputs should have been replaced with value nodes"),
}
}
}
@ -1120,35 +1135,43 @@ impl NodeNetwork {
for export in inputs {
let export: &mut NodeInput = export;
let previous_export = std::mem::replace(export, NodeInput::network(concrete!(()), 0));
if let NodeInput::Value { tagged_value, exposed } = previous_export {
let value_node_id = gen_id();
let merged_node_id = map_ids(id, value_node_id);
let mut original_location = OriginalLocation {
path: Some(path.to_vec()),
dependants: vec![vec![id]],
..Default::default()
};
if let Some(path) = &mut original_location.path {
path.push(value_node_id);
println!("export {:?}", previous_export);
let (tagged_value, exposed) = match previous_export {
NodeInput::Value { tagged_value, exposed } => (tagged_value, exposed),
NodeInput::Reflection(reflect) => match reflect {
DocumentNodeMetadata::DocumentNodePath => (TaggedValue::NodePath(path.to_vec()).into(), false),
},
previous_export => {
*export = previous_export;
continue;
}
collection.insert(
merged_node_id,
DocumentNode {
inputs: vec![NodeInput::Value { tagged_value, exposed }],
implementation: DocumentNodeImplementation::ProtoNode("graphene_core::value::ClonedNode".into()),
original_location,
..Default::default()
},
);
*export = NodeInput::Node {
node_id: merged_node_id,
output_index: 0,
lambda: false,
};
} else {
*export = previous_export;
};
let value_node_id = gen_id();
let merged_node_id = map_ids(id, value_node_id);
let mut original_location = OriginalLocation {
path: Some(path.to_vec()),
dependants: vec![vec![id]],
..Default::default()
};
if let Some(path) = &mut original_location.path {
path.push(value_node_id);
}
collection.insert(
merged_node_id,
DocumentNode {
inputs: vec![NodeInput::Value { tagged_value, exposed }],
implementation: DocumentNodeImplementation::ProtoNode("graphene_core::value::ClonedNode".into()),
original_location,
..Default::default()
},
);
*export = NodeInput::Node {
node_id: merged_node_id,
output_index: 0,
lambda: false,
};
}
}

View file

@ -1,4 +1,5 @@
use super::DocumentNode;
use crate::document::NodeId;
pub use crate::imaginate_input::{ImaginateCache, ImaginateController, ImaginateMaskStartingFill, ImaginateSamplingMethod};
use crate::proto::{Any as DAny, FutureAny};
use crate::wasm_application_io::WasmEditorApi;
@ -138,6 +139,8 @@ tagged_value! {
F64Array4([f64; 4]),
#[serde(alias = "VecF32")] // TODO: Eventually remove this alias (probably starting late 2024)
VecF64(Vec<f64>),
VecU64(Vec<u64>),
NodePath(Vec<NodeId>),
VecDVec2(Vec<DVec2>),
RedGreenBlue(graphene_core::raster::RedGreenBlue),
RedGreenBlueAlpha(graphene_core::raster::RedGreenBlueAlpha),