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
//! The `Node` trait — what every operation in the graph implements.
use xxhash_rust::xxh3::Xxh3;
use crate::eval::{EvalCtx, EvalError};
use crate::port::{CoordSpace, PortKind, PortSpec};
use crate::value::PortValue;
/// One operation in the DAG. Stored as `Box<dyn Node>` inside
/// [`crate::Graph`]; the graph never mutates a node after construction.
pub trait Node: Send + Sync {
/// Stable identifier for the operation (e.g. `"blur"`,
/// `"scatter-dabs"`). Matches the `op` field in the style JSON.
fn op_name(&self) -> &'static str;
/// Declared input ports in positional order. The style JSON
/// connects each port by name; `eval` receives values in this same
/// positional order.
fn inputs(&self) -> &[PortSpec];
/// The kind of value this node produces.
///
/// `input_kinds` carries the resolved [`PortKind`] of each input
/// port, in the same positional order as [`Node::inputs`]. Entries
/// are `Some` for connected ports (including optional ones) and
/// `None` for unconnected optional ports.
///
/// Most nodes return a constant; polymorphic nodes (e.g. `blur`
/// accepting both `Raster` and `Sprite`) inspect `input_kinds` and
/// mirror the upstream kind. The graph builder resolves nodes in
/// topological order, so upstream kinds are always known when this
/// is called.
fn output(&self, input_kinds: &[Option<PortKind>]) -> PortKind;
/// Coordinate space the node operates in. Defaults to inheriting
/// from inputs.
fn coord_space(&self) -> CoordSpace {
CoordSpace::Inherit
}
/// How much canvas padding this node requires *upstream* given the
/// padding requested by downstream consumers. Blur-like ops grow
/// the value; most pass it through unchanged.
fn required_pad(&self, downstream: u32) -> u32 {
downstream
}
/// Produce this node's output given resolved inputs. `inputs` has
/// one entry per declared port, in the order returned by
/// [`Node::inputs`]; unconnected optional ports are `None`.
fn eval(&self, ctx: &EvalCtx<'_>, inputs: &[Option<PortValue>])
-> Result<PortValue, EvalError>;
/// Stable content hash of this node's *own* parameters (not inputs).
/// Used as part of the cache key. Implementations should feed every
/// configuration value that influences output into the hasher.
fn param_hash(&self, hasher: &mut Xxh3);
/// Named asset bindings this node samples via the
/// [`AssetLoader`](crate::eval::AssetLoader). The evaluator folds
/// each binding's `AssetLoader::hash` into this node's cache key,
/// so changes in bound data invalidate caches automatically. Like
/// declaring uniforms in a shader.
///
/// Default: no bindings.
fn asset_inputs(&self) -> Vec<String> {
Vec::new()
}
}