bevy_react/filters/mod.rs
1//! Filter wire types, built-in filters, and the filter registry: the
2//! layer-based `filter` style chain.
3//!
4//! This module owns the filter wire format and registry the way
5//! [`crate::canvas`]/[`crate::animations`] own theirs: `protocol`/
6//! `reconcile`/`ui_map` reference these types by module path, never the
7//! reverse. On the wire a filter is one `{"name", "params"}` object or an
8//! ordered array of them; `params` stays an untyped JSON map at this layer —
9//! typed validation happens later against the registry, not during decode.
10//!
11//! Decoding follows the protocol's warn-don't-abort convention (see
12//! [`Length`](crate::protocol::units::Length)'s custom `Deserialize`): a malformed
13//! value emits a `decode_warn` and the whole chain degrades to empty, never
14//! failing the containing `Style`'s deserialization.
15//!
16//! The typed layer below the wire — [`ReactFilter`], the built-in param
17//! structs, and [`FilterRegistry`] — turns a [`FilterUse`] into
18//! [`ResolvedFilterPass`]es: deserialize the raw params (strict:
19//! deny-unknown-fields), pack them into a `Vec4` uniform array with a
20//! [`ParamSlot`] layout (no-straddle rule: a slot never crosses a `Vec4`
21//! boundary), and pick the pass shader. The ten built-ins register via
22//! [`register_builtin_filters`]; custom filters are `#[react_filter]` structs
23//! registered with `add_react_filter`.
24//!
25//! The module also owns the runtime write path of a chain.
26//! [`resolve_chains`] turns a promoted root's [`FilterInput`] into a
27//! [`ResolvedFilterChain`] component — resolving each entry against the
28//! registry (invalid entries skip with a `filterParams` warning), rewriting
29//! `Length` slots to physical px, stamping [`ResolvedFilterPass::wire_index`],
30//! and summing the chain outset. The interpolation primitives
31//! ([`lerp_packed_params`], [`lerp_angle`]) blend packed param arrays
32//! layout-aware for the easing paths. Exactly three systems write
33//! [`ResolvedFilterChain`] and bump its `version` counter: the resolver's
34//! snap, the transition filter channel's whole-value ease (`transition.rs`,
35//! planned by [`plan_filter_ease`] with identity-padding for chain
36//! extensions), and the animation per-param `filter[<i>].<param>` bindings
37//! (`animations`) — see [`ResolvedFilterChain::version`] for the writer
38//! registry and precedence.
39//!
40//! File map: `wire` (the wire format + warn-don't-abort decode), `params`
41//! (packing layout, caps, param value types, interpolation), `registry` (the
42//! [`ReactFilter`] trait, resolved passes, the registry), `builtin` (the
43//! ten built-ins), `transition` (whole-value `filter` transition planning),
44//! `resolve` (the chain resolve system). Submodules are private; everything
45//! is re-exported here, so `crate::filters::X` is the one path.
46
47mod backdrop;
48mod builtin;
49mod params;
50mod registry;
51mod resolve;
52mod transition;
53mod wire;
54
55#[cfg(test)]
56mod macro_tests;
57#[cfg(test)]
58pub(crate) mod test_util;
59
60pub use backdrop::{BackdropInput, ResolvedBackdropChain};
61pub use builtin::{
62 BloomParams, BlurParams, BrightnessParams, ChromaticAberrationParams, ContrastParams,
63 GrayscaleParams, HueRotateParams, InvertParams, SaturateParams, SepiaParams,
64 register_builtin_filters,
65};
66pub use params::{
67 FilterColor, MAX_FILTER_OUTSET_PX, MAX_FILTER_PARAM_VECS, ParamSlot, length_logical_px,
68 lerp_angle, lerp_packed_params,
69};
70pub use registry::{
71 FilterRegistration, FilterRegistry, ReactFilter, ResolvedFilterPass, resolve_single_pass,
72};
73pub use resolve::{
74 ChainInput, FilterInput, ResolvedChain, ResolvedFilterChain, quantize_outset, resolve_chains,
75};
76pub(crate) use transition::{FilterEase, plan_filter_ease};
77pub use wire::{FilterChain, FilterUse, MAX_CHAIN_LEN};