mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-10-01 16:38:13 +08:00
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:
@@ -618,6 +618,7 @@ impl NodeNetworkInterface {
|
|||||||
}
|
}
|
||||||
NodeInput::Scope(_) => todo!(),
|
NodeInput::Scope(_) => todo!(),
|
||||||
NodeInput::Inline(_) => 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)) {
|
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 {
|
match post_node_input {
|
||||||
// Create a new stack
|
// 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);
|
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);
|
let final_layer_position = after_move_post_layer_position + IVec2::new(-8, 3);
|
||||||
@@ -4444,7 +4445,7 @@ impl NodeNetworkInterface {
|
|||||||
} else {
|
} else {
|
||||||
match post_node_input {
|
match post_node_input {
|
||||||
// Move to the bottom of the stack
|
// 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
|
// 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);
|
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);
|
self.shift_absolute_node_position(&layer.to_node(), offset, network_path);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ pub use graphene_core::uuid::generate_uuid;
|
|||||||
use graphene_core::{Cow, MemoHash, ProtoNodeIdentifier, Type};
|
use graphene_core::{Cow, MemoHash, ProtoNodeIdentifier, Type};
|
||||||
|
|
||||||
use glam::IVec2;
|
use glam::IVec2;
|
||||||
|
use log::Metadata;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use std::collections::hash_map::DefaultHasher;
|
use std::collections::hash_map::DefaultHasher;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@@ -15,7 +16,7 @@ use std::hash::{Hash, Hasher};
|
|||||||
pub mod value;
|
pub mod value;
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[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);
|
pub struct NodeId(pub u64);
|
||||||
|
|
||||||
// TODO: Find and replace all `NodeId(generate_uuid())` with `NodeId::new()`.
|
// 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::Network { import_type, .. } => (ProtoNodeInput::ManualComposition(import_type), ConstructionArgs::Nodes(vec![])),
|
||||||
NodeInput::Inline(inline) => (ProtoNodeInput::None, ConstructionArgs::Inline(inline)),
|
NodeInput::Inline(inline) => (ProtoNodeInput::None, ConstructionArgs::Inline(inline)),
|
||||||
NodeInput::Scope(_) => unreachable!("Scope input was not resolved"),
|
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");
|
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.
|
/// Input that is extracted from the parent scopes the node resides in. The string argument is the key.
|
||||||
Scope(Cow<'static, str>),
|
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.
|
/// 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.
|
/// 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),
|
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 {
|
impl NodeInput {
|
||||||
pub const fn node(node_id: NodeId, output_index: usize) -> Self {
|
pub const fn node(node_id: NodeId, output_index: usize) -> Self {
|
||||||
Self::Node { node_id, output_index, lambda: false }
|
Self::Node { node_id, output_index, lambda: false }
|
||||||
@@ -412,6 +423,7 @@ impl NodeInput {
|
|||||||
NodeInput::Network { .. } => true,
|
NodeInput::Network { .. } => true,
|
||||||
NodeInput::Inline(_) => false,
|
NodeInput::Inline(_) => false,
|
||||||
NodeInput::Scope(_) => false,
|
NodeInput::Scope(_) => false,
|
||||||
|
NodeInput::Reflection(_) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Network node inputs in the document network are not displayed, but still exist in the compiled network
|
/// 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::Network { .. } => !is_document_network,
|
||||||
NodeInput::Inline(_) => false,
|
NodeInput::Inline(_) => false,
|
||||||
NodeInput::Scope(_) => false,
|
NodeInput::Scope(_) => false,
|
||||||
|
NodeInput::Reflection(_) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -432,6 +445,7 @@ impl NodeInput {
|
|||||||
NodeInput::Network { import_type, .. } => import_type.clone(),
|
NodeInput::Network { import_type, .. } => import_type.clone(),
|
||||||
NodeInput::Inline(_) => panic!("ty() called on NodeInput::Inline"),
|
NodeInput::Inline(_) => panic!("ty() called on NodeInput::Inline"),
|
||||||
NodeInput::Scope(_) => unreachable!("ty() called on NodeInput::Scope"),
|
NodeInput::Scope(_) => unreachable!("ty() called on NodeInput::Scope"),
|
||||||
|
NodeInput::Reflection(_) => concrete!(Metadata),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1022,7 +1036,7 @@ impl NodeNetwork {
|
|||||||
return;
|
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(
|
Self::replace_value_inputs_with_nodes(
|
||||||
&mut inner_network.exports,
|
&mut inner_network.exports,
|
||||||
&mut inner_network.nodes,
|
&mut inner_network.nodes,
|
||||||
@@ -1076,6 +1090,7 @@ impl NodeNetwork {
|
|||||||
// TODO use correct output index
|
// TODO use correct output index
|
||||||
nested_node.inputs[nested_input_index] = NodeInput::node(*import_id, 0);
|
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 {
|
for export in inputs {
|
||||||
let export: &mut NodeInput = export;
|
let export: &mut NodeInput = export;
|
||||||
let previous_export = std::mem::replace(export, NodeInput::network(concrete!(()), 0));
|
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 {
|
println!("export {:?}", previous_export);
|
||||||
path.push(value_node_id);
|
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,
|
let value_node_id = gen_id();
|
||||||
DocumentNode {
|
let merged_node_id = map_ids(id, value_node_id);
|
||||||
inputs: vec![NodeInput::Value { tagged_value, exposed }],
|
let mut original_location = OriginalLocation {
|
||||||
implementation: DocumentNodeImplementation::ProtoNode("graphene_core::value::ClonedNode".into()),
|
path: Some(path.to_vec()),
|
||||||
original_location,
|
dependants: vec![vec![id]],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
};
|
||||||
);
|
|
||||||
*export = NodeInput::Node {
|
if let Some(path) = &mut original_location.path {
|
||||||
node_id: merged_node_id,
|
path.push(value_node_id);
|
||||||
output_index: 0,
|
|
||||||
lambda: false,
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
*export = previous_export;
|
|
||||||
}
|
}
|
||||||
|
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,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use super::DocumentNode;
|
use super::DocumentNode;
|
||||||
|
use crate::document::NodeId;
|
||||||
pub use crate::imaginate_input::{ImaginateCache, ImaginateController, ImaginateMaskStartingFill, ImaginateSamplingMethod};
|
pub use crate::imaginate_input::{ImaginateCache, ImaginateController, ImaginateMaskStartingFill, ImaginateSamplingMethod};
|
||||||
use crate::proto::{Any as DAny, FutureAny};
|
use crate::proto::{Any as DAny, FutureAny};
|
||||||
use crate::wasm_application_io::WasmEditorApi;
|
use crate::wasm_application_io::WasmEditorApi;
|
||||||
@@ -138,6 +139,8 @@ tagged_value! {
|
|||||||
F64Array4([f64; 4]),
|
F64Array4([f64; 4]),
|
||||||
#[serde(alias = "VecF32")] // TODO: Eventually remove this alias (probably starting late 2024)
|
#[serde(alias = "VecF32")] // TODO: Eventually remove this alias (probably starting late 2024)
|
||||||
VecF64(Vec<f64>),
|
VecF64(Vec<f64>),
|
||||||
|
VecU64(Vec<u64>),
|
||||||
|
NodePath(Vec<NodeId>),
|
||||||
VecDVec2(Vec<DVec2>),
|
VecDVec2(Vec<DVec2>),
|
||||||
RedGreenBlue(graphene_core::raster::RedGreenBlue),
|
RedGreenBlue(graphene_core::raster::RedGreenBlue),
|
||||||
RedGreenBlueAlpha(graphene_core::raster::RedGreenBlueAlpha),
|
RedGreenBlueAlpha(graphene_core::raster::RedGreenBlueAlpha),
|
||||||
|
|||||||
Reference in New Issue
Block a user