Skip to content

Commit de38de1

Browse files
committed
Prototype document network level into node insertion
1 parent 76ecdc8 commit de38de1

File tree

3 files changed

+233
-104
lines changed

3 files changed

+233
-104
lines changed

editor/src/messages/portfolio/document/node_graph/document_node_definitions.rs

Lines changed: 4 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ use std::collections::{HashMap, HashSet, VecDeque};
2626
#[cfg(feature = "gpu")]
2727
use wgpu_executor::{Bindgroup, CommandBuffer, PipelineLayout, ShaderHandle, ShaderInputFrame, WgpuShaderInput};
2828

29+
mod document_node_derive;
30+
2931
pub struct NodePropertiesContext<'a> {
3032
pub persistent_data: &'a PersistentData,
3133
pub responses: &'a mut VecDeque<Message>,
@@ -93,7 +95,7 @@ static DOCUMENT_NODE_TYPES: once_cell::sync::Lazy<Vec<DocumentNodeDefinition>> =
9395
/// Defines the "signature" or "header file"-like metadata for the document nodes, but not the implementation (which is defined in the node registry).
9496
/// The [`DocumentNode`] is the instance while these [`DocumentNodeDefinition`]s are the "classes" or "blueprints" from which the instances are built.
9597
fn static_nodes() -> Vec<DocumentNodeDefinition> {
96-
let mut custom = vec![
98+
let custom = vec![
9799
// TODO: Auto-generate this from its proto node macro
98100
DocumentNodeDefinition {
99101
identifier: "Identity",
@@ -2533,109 +2535,7 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
25332535
},
25342536
];
25352537

2536-
// Remove struct generics
2537-
for DocumentNodeDefinition { node_template, .. } in custom.iter_mut() {
2538-
let NodeTemplate {
2539-
document_node: DocumentNode { implementation, .. },
2540-
..
2541-
} = node_template;
2542-
if let DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier { name }) = implementation {
2543-
if let Some((new_name, _suffix)) = name.rsplit_once("<") {
2544-
*name = Cow::Owned(new_name.to_string())
2545-
}
2546-
};
2547-
}
2548-
let node_registry = graphene_core::registry::NODE_REGISTRY.lock().unwrap();
2549-
'outer: for (id, metadata) in graphene_core::registry::NODE_METADATA.lock().unwrap().iter() {
2550-
use graphene_core::registry::*;
2551-
let id = id.clone();
2552-
2553-
for node in custom.iter() {
2554-
let DocumentNodeDefinition {
2555-
node_template: NodeTemplate {
2556-
document_node: DocumentNode { implementation, .. },
2557-
..
2558-
},
2559-
..
2560-
} = node;
2561-
match implementation {
2562-
DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier { name }) if name == &id => continue 'outer,
2563-
_ => (),
2564-
}
2565-
}
2566-
2567-
let NodeMetadata {
2568-
display_name,
2569-
category,
2570-
fields,
2571-
description,
2572-
properties,
2573-
} = metadata;
2574-
let Some(implementations) = &node_registry.get(&id) else { continue };
2575-
let valid_inputs: HashSet<_> = implementations.iter().map(|(_, node_io)| node_io.call_argument.clone()).collect();
2576-
let first_node_io = implementations.first().map(|(_, node_io)| node_io).unwrap_or(const { &NodeIOTypes::empty() });
2577-
let mut input_type = &first_node_io.call_argument;
2578-
if valid_inputs.len() > 1 {
2579-
input_type = &const { generic!(D) };
2580-
}
2581-
let output_type = &first_node_io.return_value;
2582-
2583-
let inputs = fields
2584-
.iter()
2585-
.zip(first_node_io.inputs.iter())
2586-
.enumerate()
2587-
.map(|(index, (field, node_io_ty))| {
2588-
let ty = field.default_type.as_ref().unwrap_or(node_io_ty);
2589-
let exposed = if index == 0 { *ty != fn_type_fut!(Context, ()) } else { field.exposed };
2590-
2591-
match field.value_source {
2592-
RegistryValueSource::None => {}
2593-
RegistryValueSource::Default(data) => return NodeInput::value(TaggedValue::from_primitive_string(data, ty).unwrap_or(TaggedValue::None), exposed),
2594-
RegistryValueSource::Scope(data) => return NodeInput::scope(Cow::Borrowed(data)),
2595-
};
2596-
2597-
if let Some(type_default) = TaggedValue::from_type(ty) {
2598-
return NodeInput::value(type_default, exposed);
2599-
}
2600-
NodeInput::value(TaggedValue::None, true)
2601-
})
2602-
.collect();
2603-
2604-
let node = DocumentNodeDefinition {
2605-
identifier: display_name,
2606-
node_template: NodeTemplate {
2607-
document_node: DocumentNode {
2608-
inputs,
2609-
manual_composition: Some(input_type.clone()),
2610-
implementation: DocumentNodeImplementation::ProtoNode(id.clone().into()),
2611-
visible: true,
2612-
skip_deduplication: false,
2613-
..Default::default()
2614-
},
2615-
persistent_node_metadata: DocumentNodePersistentMetadata {
2616-
// TODO: Store information for input overrides in the node macro
2617-
input_properties: fields
2618-
.iter()
2619-
.map(|f| match f.widget_override {
2620-
RegistryWidgetOverride::None => (f.name, f.description).into(),
2621-
RegistryWidgetOverride::Hidden => PropertiesRow::with_override(f.name, f.description, WidgetOverride::Hidden),
2622-
RegistryWidgetOverride::String(str) => PropertiesRow::with_override(f.name, f.description, WidgetOverride::String(str.to_string())),
2623-
RegistryWidgetOverride::Custom(str) => PropertiesRow::with_override(f.name, f.description, WidgetOverride::Custom(str.to_string())),
2624-
})
2625-
.collect(),
2626-
output_names: vec![output_type.to_string()],
2627-
has_primary_output: true,
2628-
locked: false,
2629-
..Default::default()
2630-
},
2631-
},
2632-
category: category.unwrap_or("UNCATEGORIZED"),
2633-
description: Cow::Borrowed(description),
2634-
properties: *properties,
2635-
};
2636-
custom.push(node);
2637-
}
2638-
custom
2538+
document_node_derive::post_process_nodes(custom)
26392539
}
26402540

26412541
// pub static IMAGINATE_NODE: Lazy<DocumentNodeDefinition> = Lazy::new(|| DocumentNodeDefinition {
Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
use super::DocumentNodeDefinition;
2+
use crate::messages::portfolio::document::utility_types::network_interface::{
3+
DocumentNodeMetadata, DocumentNodePersistentMetadata, NodeNetworkMetadata, NodeNetworkPersistentMetadata, NodePersistentMetadata, NodePosition, NodeTemplate, NodeTypePersistentMetadata,
4+
PropertiesRow, WidgetOverride,
5+
};
6+
use graph_craft::ProtoNodeIdentifier;
7+
use graph_craft::concrete;
8+
use graph_craft::document::value::*;
9+
use graph_craft::document::*;
10+
use graphene_core::*;
11+
use std::collections::{HashMap, HashSet};
12+
13+
pub(super) fn post_process_nodes(mut custom: Vec<DocumentNodeDefinition>) -> Vec<DocumentNodeDefinition> {
14+
// Remove struct generics
15+
for DocumentNodeDefinition { node_template, .. } in custom.iter_mut() {
16+
let NodeTemplate {
17+
document_node: DocumentNode { implementation, .. },
18+
..
19+
} = node_template;
20+
if let DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier { name }) = implementation {
21+
if let Some((new_name, _suffix)) = name.rsplit_once("<") {
22+
*name = Cow::Owned(new_name.to_string())
23+
}
24+
};
25+
}
26+
let node_registry = graphene_core::registry::NODE_REGISTRY.lock().unwrap();
27+
'outer: for (id, metadata) in graphene_core::registry::NODE_METADATA.lock().unwrap().iter() {
28+
use graphene_core::registry::*;
29+
let id = id.clone();
30+
31+
for node in custom.iter() {
32+
let DocumentNodeDefinition {
33+
node_template: NodeTemplate {
34+
document_node: DocumentNode { implementation, .. },
35+
..
36+
},
37+
..
38+
} = node;
39+
match implementation {
40+
DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier { name }) if name == &id => continue 'outer,
41+
_ => (),
42+
}
43+
}
44+
45+
let NodeMetadata {
46+
display_name,
47+
category,
48+
fields,
49+
description,
50+
properties,
51+
} = metadata;
52+
let Some(implementations) = &node_registry.get(&id) else { continue };
53+
let valid_inputs: HashSet<_> = implementations.iter().map(|(_, node_io)| node_io.call_argument.clone()).collect();
54+
let first_node_io = implementations.first().map(|(_, node_io)| node_io).unwrap_or(const { &NodeIOTypes::empty() });
55+
let mut node_io_types = vec![HashSet::new(); fields.len()];
56+
for (_, node_io) in implementations.iter() {
57+
for (i, ty) in node_io.inputs.iter().enumerate() {
58+
node_io_types[i].insert(ty.clone());
59+
}
60+
}
61+
let mut input_type = &first_node_io.call_argument;
62+
if valid_inputs.len() > 1 {
63+
input_type = &const { generic!(D) };
64+
}
65+
let output_type = &first_node_io.return_value;
66+
67+
let inputs: Vec<_> = fields
68+
.iter()
69+
.zip(first_node_io.inputs.iter())
70+
.enumerate()
71+
.map(|(index, (field, node_io_ty))| {
72+
let ty = field.default_type.as_ref().unwrap_or(node_io_ty);
73+
let exposed = if index == 0 { *ty != fn_type_fut!(Context, ()) } else { field.exposed };
74+
75+
match field.value_source {
76+
RegistryValueSource::None => {}
77+
RegistryValueSource::Default(data) => return NodeInput::value(TaggedValue::from_primitive_string(data, ty).unwrap_or(TaggedValue::None), exposed),
78+
RegistryValueSource::Scope(data) => return NodeInput::scope(Cow::Borrowed(data)),
79+
};
80+
81+
if let Some(type_default) = TaggedValue::from_type(ty) {
82+
return NodeInput::value(type_default, exposed);
83+
}
84+
NodeInput::value(TaggedValue::None, true)
85+
})
86+
.collect();
87+
let input_count = inputs.len();
88+
let network_inputs = (0..input_count).map(|i| NodeInput::node(NodeId(i as u64), 0)).collect();
89+
let identity_node = ProtoNodeIdentifier::new("graphene_core::ops::IdentityNode");
90+
let into_node_registry = &interpreted_executor::node_registry::NODE_REGISTRY;
91+
let mut nodes: HashMap<_, _, _> = node_io_types
92+
.iter()
93+
.enumerate()
94+
.map(|(i, inputs)| {
95+
(
96+
NodeId(i as u64),
97+
match inputs.len() {
98+
1 => {
99+
let input = inputs.iter().next().unwrap();
100+
let input_ty = input.nested_type();
101+
let into_node_identifier = ProtoNodeIdentifier {
102+
name: format!("graphene_core::ops::IntoNode<{}>", input_ty.clone()).into(),
103+
};
104+
let proto_node = if into_node_registry.iter().any(|(ident, _)| {
105+
let ident = ident.name.as_ref();
106+
// log::debug!("checking: {} against {}", ident, into_node_identifier.name.as_ref());
107+
ident == into_node_identifier.name.as_ref()
108+
}) {
109+
// log::debug!("placing {}", into_node_identifier.name.as_ref());
110+
into_node_identifier
111+
} else {
112+
identity_node.clone()
113+
};
114+
DocumentNode {
115+
inputs: vec![NodeInput::network(input.clone(), i)],
116+
// manual_composition: Some(fn_input.clone()),
117+
implementation: DocumentNodeImplementation::ProtoNode(proto_node),
118+
visible: true,
119+
..Default::default()
120+
}
121+
}
122+
_ => DocumentNode {
123+
inputs: vec![NodeInput::network(generic!(X), i)],
124+
implementation: DocumentNodeImplementation::ProtoNode(identity_node.clone()),
125+
visible: true,
126+
..Default::default()
127+
},
128+
},
129+
)
130+
})
131+
.collect();
132+
133+
let document_node = DocumentNode {
134+
inputs: network_inputs,
135+
manual_composition: Some(input_type.clone()),
136+
implementation: DocumentNodeImplementation::ProtoNode(id.clone().into()),
137+
visible: true,
138+
skip_deduplication: false,
139+
..Default::default()
140+
};
141+
let mut node_names: HashMap<NodeId, String> = nodes
142+
.iter()
143+
.map(|(id, node)| (*id, node.implementation.get_proto_node().unwrap().name.rsplit_once("::").unwrap().1.to_string()))
144+
.collect();
145+
nodes.insert(NodeId(input_count as u64), document_node);
146+
node_names.insert(NodeId(input_count as u64), display_name.to_string());
147+
let node_type_metadata = |id: NodeId| {
148+
NodeTypePersistentMetadata::Node(NodePersistentMetadata::new(NodePosition::Absolute(if id.0 == input_count as u64 {
149+
IVec2::default()
150+
} else {
151+
IVec2 { x: -10, y: id.0 as i32 }
152+
})))
153+
};
154+
155+
let node = DocumentNodeDefinition {
156+
identifier: display_name,
157+
node_template: NodeTemplate {
158+
document_node: DocumentNode {
159+
inputs,
160+
manual_composition: Some(input_type.clone()),
161+
implementation: DocumentNodeImplementation::Network(NodeNetwork {
162+
exports: vec![NodeInput::Node {
163+
node_id: NodeId(input_count as u64),
164+
output_index: 0,
165+
lambda: false,
166+
}],
167+
nodes,
168+
scope_injections: Default::default(),
169+
}),
170+
visible: true,
171+
skip_deduplication: false,
172+
..Default::default()
173+
},
174+
persistent_node_metadata: DocumentNodePersistentMetadata {
175+
// TODO: Store information for input overrides in the node macro
176+
input_properties: fields
177+
.iter()
178+
.map(|f| match f.widget_override {
179+
RegistryWidgetOverride::None => (f.name, f.description).into(),
180+
RegistryWidgetOverride::Hidden => PropertiesRow::with_override(f.name, f.description, WidgetOverride::Hidden),
181+
RegistryWidgetOverride::String(str) => PropertiesRow::with_override(f.name, f.description, WidgetOverride::String(str.to_string())),
182+
RegistryWidgetOverride::Custom(str) => PropertiesRow::with_override(f.name, f.description, WidgetOverride::Custom(str.to_string())),
183+
})
184+
.collect(),
185+
output_names: vec![output_type.to_string()],
186+
has_primary_output: true,
187+
locked: false,
188+
189+
network_metadata: Some(NodeNetworkMetadata {
190+
persistent_metadata: NodeNetworkPersistentMetadata {
191+
node_metadata: node_names
192+
.into_iter()
193+
.map(|(id, display_name)| {
194+
let node_type_metadata = node_type_metadata(id);
195+
(
196+
id,
197+
DocumentNodeMetadata {
198+
persistent_metadata: DocumentNodePersistentMetadata {
199+
display_name,
200+
node_type_metadata,
201+
..Default::default()
202+
},
203+
..Default::default()
204+
},
205+
)
206+
})
207+
.collect(),
208+
..Default::default()
209+
},
210+
..Default::default()
211+
}),
212+
213+
..Default::default()
214+
},
215+
},
216+
category: category.unwrap_or("UNCATEGORIZED"),
217+
description: Cow::Borrowed(description),
218+
properties: *properties,
219+
};
220+
custom.push(node);
221+
}
222+
custom
223+
}

editor/src/messages/portfolio/document/utility_types/network_interface.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6488,6 +6488,12 @@ pub struct NodePersistentMetadata {
64886488
position: NodePosition,
64896489
}
64906490

6491+
impl NodePersistentMetadata {
6492+
pub fn new(position: NodePosition) -> Self {
6493+
Self { position }
6494+
}
6495+
}
6496+
64916497
/// A layer can either be position as Absolute or in a Stack
64926498
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
64936499
pub enum LayerPosition {

0 commit comments

Comments
 (0)