ezu_graph/node.rs
1//! The `Node` trait — what every operation in the graph implements.
2
3use xxhash_rust::xxh3::Xxh3;
4
5use crate::eval::{EvalCtx, EvalError};
6use crate::port::{CoordSpace, PortKind, PortSpec};
7use crate::value::PortValue;
8
9/// One operation in the DAG. Stored as `Box<dyn Node>` inside
10/// [`crate::Graph`]; the graph never mutates a node after construction.
11pub trait Node: Send + Sync {
12 /// Stable identifier for the operation (e.g. `"blur"`,
13 /// `"scatter-dabs"`). Matches the `op` field in the style JSON.
14 fn op_name(&self) -> &'static str;
15
16 /// Declared input ports in positional order. The style JSON
17 /// connects each port by name; `eval` receives values in this same
18 /// positional order.
19 fn inputs(&self) -> &[PortSpec];
20
21 /// The kind of value this node produces.
22 ///
23 /// `input_kinds` carries the resolved [`PortKind`] of each input
24 /// port, in the same positional order as [`Node::inputs`]. Entries
25 /// are `Some` for connected ports (including optional ones) and
26 /// `None` for unconnected optional ports.
27 ///
28 /// Most nodes return a constant; polymorphic nodes (e.g. `blur`
29 /// accepting both `Raster` and `Sprite`) inspect `input_kinds` and
30 /// mirror the upstream kind. The graph builder resolves nodes in
31 /// topological order, so upstream kinds are always known when this
32 /// is called.
33 fn output(&self, input_kinds: &[Option<PortKind>]) -> PortKind;
34
35 /// Coordinate space the node operates in. Defaults to inheriting
36 /// from inputs.
37 fn coord_space(&self) -> CoordSpace {
38 CoordSpace::Inherit
39 }
40
41 /// How much canvas padding this node requires *upstream* given the
42 /// padding requested by downstream consumers. Blur-like ops grow
43 /// the value; most pass it through unchanged.
44 fn required_pad(&self, downstream: u32) -> u32 {
45 downstream
46 }
47
48 /// Produce this node's output given resolved inputs. `inputs` has
49 /// one entry per declared port, in the order returned by
50 /// [`Node::inputs`]; unconnected optional ports are `None`.
51 fn eval(&self, ctx: &EvalCtx<'_>, inputs: &[Option<PortValue>])
52 -> Result<PortValue, EvalError>;
53
54 /// Stable content hash of this node's *own* parameters (not inputs).
55 /// Used as part of the cache key. Implementations should feed every
56 /// configuration value that influences output into the hasher.
57 fn param_hash(&self, hasher: &mut Xxh3);
58
59 /// Named asset bindings this node samples via the
60 /// [`AssetLoader`](crate::eval::AssetLoader). The evaluator folds
61 /// each binding's `AssetLoader::hash` into this node's cache key,
62 /// so changes in bound data invalidate caches automatically. Like
63 /// declaring uniforms in a shader.
64 ///
65 /// Default: no bindings.
66 fn asset_inputs(&self) -> Vec<String> {
67 Vec::new()
68 }
69}