Skip to main content

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}