1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
use egui_snarl::{InPinId, NodeId, OutPinId, Snarl};
use std::array::from_fn;
use std::fmt;
use topological_sort::TopologicalSort;
use crate::node::{AnyNode, CompileError, ConcreteNode, MAX_INPUTS};
use crate::types::{Type, TypeSignature};
pub trait WithSignatures {
// internal
fn get_input_types(&self, node: NodeId) -> [Option<Type>; MAX_INPUTS];
// for rendering
fn get_visible_inputs(&self, node: NodeId) -> Vec<Option<Type>>;
// for compiling
fn get_node_signature(&self, node: NodeId) -> Result<TypeSignature, CompileError>;
fn get_node_signature_with_overrides(
&self,
node: NodeId,
overrides: &[Option<Type>; MAX_INPUTS],
) -> Result<TypeSignature, CompileError>;
}
impl WithSignatures for Snarl<AnyNode> {
fn get_input_types(&self, node: NodeId) -> [Option<Type>; MAX_INPUTS] {
from_fn(
move |input| match &*self.in_pin(InPinId { node, input }).remotes {
[] => None,
[out_pin] => self
.get_node_signature(out_pin.node)
.map(|s| s.outputs[out_pin.output])
.ok(),
_ => unreachable!("cannot connect to multiple inputs"),
},
)
}
fn get_visible_inputs(&self, node: NodeId) -> Vec<Option<Type>> {
self[node].visible_inputs(&self.get_input_types(node))
}
fn get_node_signature(&self, node: NodeId) -> Result<TypeSignature, CompileError> {
self[node].signature(&self.get_input_types(node))
}
fn get_node_signature_with_overrides(
&self,
node: NodeId,
overrides: &[Option<Type>; MAX_INPUTS],
) -> Result<TypeSignature, CompileError> {
let mut inputs = self.get_input_types(node);
for (i, over) in overrides.iter().enumerate() {
inputs[i] = over.or(inputs[i]);
}
self[node].signature(&inputs)
}
}
#[derive(fmt::Debug, Copy, Clone)]
pub struct GraphError(pub CompileError, pub Option<NodeId>);
impl From<fmt::Error> for GraphError {
fn from(v: fmt::Error) -> Self {
Self(v.into(), None)
}
}
pub trait Compilable {
fn compile_node(&self, f: &mut dyn fmt::Write, node: NodeId) -> Result<(), CompileError>;
fn compile(&self, f: &mut dyn fmt::Write) -> Result<(), GraphError>;
}
fn compile_output(pin: OutPinId) -> String {
let node_id = pin.node.0;
let out_id = pin.output;
format!("n{node_id}_o{out_id}")
}
impl Compilable for Snarl<AnyNode> {
fn compile(&self, f: &mut dyn fmt::Write) -> Result<(), GraphError> {
let mut order = TopologicalSort::<NodeId>::new();
for (out, inp) in self.wires() {
order.add_dependency(out.node, inp.node);
}
write!(
f,
"
#version 450
in vec2 in_uv;
out vec4 out_color;
layout(std140, binding = 0) uniform Uniforms {{
vec2 in_resolution;
float in_time;
float _pad3;
}} uniforms;
void main() {{
"
)?;
while let Some(id) = order.pop() {
self.compile_node(f, id)
.map_err(|inner| GraphError(inner, Some(id)))?;
}
writeln!(f, "}}")?;
Ok(())
}
fn compile_node(&self, f: &mut dyn fmt::Write, node: NodeId) -> Result<(), CompileError> {
let signature = self.get_node_signature(node)?;
// log::info!("{node} {self[node]}: {signature:?}");
let inputs: Vec<Option<String>> = (0..signature.inputs.len())
.map(
|input| match &*self.in_pin(InPinId { node, input }).remotes {
[] => None,
[pin] => Some(compile_output(*pin)),
_ => unreachable!("cannot connect to multiple inputs"),
},
)
.collect();
let outputs: Vec<String> = (0..signature.outputs.len())
.map(|output| compile_output(OutPinId { node, output }))
.collect();
self[node].compile(f, signature, inputs, outputs)
}
}
|