Commit Graph

1426 Commits

Author SHA1 Message Date
Keavon Chambers
244a7e0f78 Add a "Cyclic" gradient option that closes the ramp into a seamless loop (#4416)
* Add a Cyclic gradient attribute that wraps the stop list through the 1|0 boundary back to the first stop

* Show the wrap segment's midpoint diamond in the color picker spectrum strip when cyclic

* Keep the wrap midpoint diamond tracking the pointer by a wrapped strip width when dragged past the ends

* Give the Gradient tool's viewport overlay the same cyclic wrap midpoint diamond and drag behavior

* Correct the docs claiming the final stop's midpoint is always ignored now that cyclic uses it

* Move the gradient cyclic toggle onto the Ends row as a Link icon checkbox

* Update labels

* Register GradientHueDirection with the Data panel so its attribute column renders

* Reword wrap segment to wrapped interval and stray segment usages to interval

* Clean up comments

* Fix the color picker write-back losing default position elision and the blend path guessing the cyclic flag
2026-09-14 12:58:41 +02:00
Keavon Chambers
a35143586a Add the "Perceptual" and "Classic" families of gradient spaces with OkLab as the new default (#4415)
* Add an OkLab gradient interpolation space and make it the new default

* Fix the Properties panel fill row resetting the gradient interpolation space to the default

* Add OkLch, Lab, LCh, and HSL gradient interpolation spaces

* Add a hue direction attribute and picker choice for polar gradient interpolation spaces

* Add an HSV gradient interpolation space

* Rename the sRGB Linear and sRGB Gamma gradient spaces to RGB Linear and RGB Gamma

* Divide the gradient interpolation dropdown between absolute and relative color spaces

* Rename the OkLch gradient interpolation space to OkLCh for channel-notation capitalization

* Shorten the color picker popover's hue direction row label to Arc

* Call the Gradient Interpolation node's parameter Space and extend the picker tooltip title to match

* Rename the gradient interpolation attribute and type family to gradient space

* Rename the gradient tool's gradient space transform to gradient to viewport transform

* Add serde aliases and a node replacement covering the gradient space renames

* Give the gradient space choices artist-facing labels and reorder the dropdown sections

* Add a Gradient Hue Direction node and its attribute read node

* Say interpolate instead of blend for gradient stop color traversal in docs and tooltips

* Label the polar perceptual gradient spaces as Perceptual Hue and group the dropdown sections by geometry

* Add a migration alias covering the gradient space attribute reader rename

* Carry the gradient hue direction attribute through boolean operations

* Register GradientHueDirection wire types in the node registry
2026-09-14 12:58:40 +02:00
Keavon Chambers
11dfc27645 Make gradient evaluation follow the ramp's interpolation space attribute (#4414) 2026-09-14 12:58:39 +02:00
Keavon Chambers
3678826a48 Give whole-expanse gradient layers a transform cage based on the gradient line (#4413) 2026-09-14 12:58:37 +02:00
Keavon Chambers
f8975b7d94 Add a gradient interpolation space attribute with sRGB Gamma (existing) and sRGB Linear (new) (#4412)
* Build dropdown menu entries from choice type metadata

* Add a gradient interpolation color space attribute, blending stops in linear light by default

* Add a Space interpolation dropdown to the color picker popover

* Stamp legacy gradient ramps with their implicit gamma interpolation during deserialization

* Resolve color-interpolation from SVG style blocks and fix cascade order among repeated declarations
2026-09-14 12:58:36 +02:00
Keavon Chambers
c71f78edb5 Add a Clear gradient spread that cuts off to transparency beyond the ends (#4410) 2026-09-14 12:58:32 +02:00
Keavon Chambers
ba5b25112b Build radio widget entries from choice type metadata so variants display their icons (#4408)
* Build radio widget entries from choice type metadata so variants display their icons

* Route the node properties enum radio through the shared choice type entry builder
2026-09-14 12:58:29 +02:00
Keavon Chambers
4da366acf1 Rename gradient type to gradient form (#4405)
* Rename gradient type to gradient form

* Update the demo art for the gradient form rename

* Say form not type in the Gradient Form node's doc comment
2026-09-14 12:58:26 +02:00
Keavon Chambers
167da6a210 Rename spread method to gradient spread so it matches the other gradient attribute names (#4404)
* Rename spread method to gradient spread so it matches the other gradient attribute names

* Keep the legacy gradient struct's spread method field name matching its on-disk key
2026-09-14 12:58:24 +02:00
Keavon Chambers
27f1e8a65b Move the gradient-focused nodes from the Color category to a new Gradient category (#4403) 2026-09-14 12:58:23 +02:00
Keavon Chambers
c5cb466e28 Move the gradient spread method into GradientRamp and the color picker popover (#4402)
* Add a spread method field to GradientRamp, carried at runtime as the gradient item's attribute

* Retire the Fill node's spread method input, folding its value into the gradient ramps on document upgrade

* Add an Ends spread method radio to the color picker popover, replacing the Gradient tool's control bar radio

* Update the demo art
2026-09-14 12:58:22 +02:00
Keavon Chambers
360321e0ce Wrap serialized gradient stops in a new GradientRamp struct and unify FillChoice (#4400)
* Introduce the GradientRamp exchange struct as the serialized TaggedValue::Gradient payload

* Unify FillChoice and FillChoiceUI into one enum generic over color format, carrying GradientRamp stops

* Rename the TaggedValue::Gradient variant to GradientRamp to match its payload

* Move the Color variant into the tagged_value macro list since its stored and wire forms match
2026-09-14 12:58:19 +02:00
Keavon Chambers
86d4106592 Rework Gradient into a newtype of List<Color> with optional position and midpoint attributes (#4397)
* Rework Gradient into a newtype of List<Color> with optional position and midpoint attributes

* Fix Vello stopless-gradient fallback coverage, empty legacy gradient tables, the node docs gradient swatch, NaN position elision, and wired setter input overwrites
2026-09-14 12:58:16 +02:00
Keavon Chambers
b78e4b107e Remove custom (de)serializers from the DashPattern and BoxCorners TaggedValue variants (#4394)
Replace the DashPattern and BoxCorners custom serde impls with storage-shaped Vec<f64> TaggedValue payloads
2026-09-14 12:58:15 +02:00
Keavon Chambers
69148d1b36 Replace raw node input indices with compile-time parameter symbols (#4387)
* Remove the dead InputAccessor traits and the uncallable test helper built on them

* Replace raw node input indices with macro-generated parameter symbols across the editor

* Audit dynamic input index usage, converting to parameter symbols and named input position constants

* Abstract the remaining input index plumbing behind ParameterRef APIs and accessors

* Build SetInputValue messages as struct literals to keep message enums impl-free

* Delete the typed parameter markers in favor of explicit-output test introspection

* Wire the interpolation control path input per chain node type

* Return no input when a parameter symbol is read against the wrong node's parameter view
2026-09-14 12:58:14 +02:00
urisinger
b42b00febe Move the math expression parser from Pest to Chumsky and add more features (#2685)
Rewrite the math-parser library using a chumsky-based lexer and parser, adding functions, comparisons, logic, and conditionals
2026-09-14 12:57:20 +02:00
Keavon Chambers
c77359bedf Add a Connect Cells option to the 'Grid' node (#4374)
Add a Connect Cells option to the Grid node
2026-09-14 12:57:19 +02:00
Keavon Chambers
24ba1e047c Box big enum variants to satisfy Clippy's lint warnings (#4292)
* Box the `value` field of `NodeGraphMessage::SetInputValue`

* Box the `ExecutionResponse` variant of `NodeGraphUpdate`

* Box the `Layer` variant of `NodeTypeClickTargets`

* Box the `Scope` variant of `ParsedValueSource`
2026-09-14 12:57:18 +02:00
Keavon Chambers
31239f77c6 Make the 'Angle Between' node report the signed angle and fix its zero-vector output (#4362) 2026-09-14 12:57:10 +02:00
Keavon Chambers
85dd39c35b New nodes: 'Sign', 'Distance', 'Cross Product', and 'Lerp' (#4361) 2026-09-14 12:57:09 +02:00
Keavon Chambers
28f8325a64 Add Vec2 support to the scalar math operator nodes (#4360)
* Add Vec2 support to the scalar math operator nodes

* Support the scalar-with-Vec2 operand order in the Exponent, Root, Logarithm, Min, Max, and Clamp nodes

* Detect an f32 base of e in the Logarithm node despite inexact widening to f64
2026-09-14 12:57:09 +02:00
Keavon Chambers
5dbcdaf0c2 Fix the 'Divide' node dividing partially-zero Vec2 denominators and the 'Logarithm' node misdetecting base e (#4359) 2026-09-14 12:57:08 +02:00
Keavon Chambers
83d24251d7 Rename the nodes 'Length' -> 'Magnitude', 'Flatten Path' -> 'Combine Paths', 'Vec2 Value' -> 'Combine Vec2', and add a new 'Vec2 Value' node (#4349)
* Rename the node 'Length' -> 'Magnitude'

* Rename the node 'Flatten Path' -> 'Combine Paths'

* Replace the node 'Vec2 Value' with 'Combine Vec2' and add a new 'Vec2 Value' that's actually a vec2

* Update demo artwork
2026-09-14 12:57:07 +02:00
Keavon Chambers
095f169b2f New nodes: 'Voronoi Cells', 'Tesselate', and 'Relax Points' (#4345) 2026-09-14 12:57:06 +02:00
Keavon Chambers
cba642a7a1 New nodes: Sum, Average, Minimum, Maximum, Any, All (#4344)
Co-authored-by: Dennis Kobert <dennis@kobert.dev>
2026-09-14 12:57:05 +02:00
Keavon Chambers
67690d22d4 Convert the node catalog to rank-polymorphic kernels, materialize stored values as ranked wires, and display wire rank in the graph
Co-authored-by:    Dennis Kobert <dennis@kobert.dev>
2026-09-14 12:57:05 +02:00
Keavon Chambers
5bc41c4c58 Reshape the node catalog: rename the list access nodes, split Text to Vector, reinstate Upload Texture as a proto node, and delete the vestigial debug nodes 2026-09-14 12:57:04 +02:00
Keavon Chambers
7ddab438d1 Split Fill's optional transform into a has-transform toggle and add the DashPattern and BoxCorners value types 2026-09-14 12:57:03 +02:00
Keavon Chambers
6acc0638e4 Add Graphic::None and store paint choices as plain color, gradient, and no-paint values 2026-09-14 12:57:02 +02:00
Keavon Chambers
fd7f67b3e9 Rename GradientStops to Gradient and the legacy Gradient/Fill structs to LegacyGradient/LegacyFill 2026-09-14 12:57:01 +02:00
Dennis Kobert
21eae1e2a1 Carry eight dropped columns through flatten_graphic 2026-09-14 12:57:00 +02:00
Dennis Kobert
9311c957c4 Carry four dropped columns through the flatten path kernels 2026-09-14 12:56:56 +02:00
Dennis Kobert
5599f1d652 Give VectorRow a top lane and thread it through the walk recursion 2026-09-14 12:56:55 +02:00
Dennis Kobert
413547401e Carry the boolean operation kernels through lane 0 map_element 2026-09-14 12:56:54 +02:00
Dennis Kobert
04966278d4 Build a gathered subject's copy plan on collapse and reject an empty carry 2026-09-14 12:56:54 +02:00
Dennis Kobert
5035fae83b Adopt map_element in the mirror kernels 2026-09-14 12:53:18 +02:00
Dennis Kobert
b54c1a45b0 Adopt map_element in the assign colors kernels and drop the dead carried_lane_attrs helper 2026-09-14 12:53:18 +02:00
Dennis Kobert
aed7855002 Add a map_element primitive to Lane and teach the node macro to emit it 2026-09-14 12:53:17 +02:00
Dennis Kobert
1a20718a3b Box the largest message and update payloads 2026-09-14 12:53:17 +02:00
Dennis Kobert
8281d082f4 Drop redundant conversions, assertions and struct updates 2026-09-14 12:53:15 +02:00
Dennis Kobert
aa20c2c167 Elide the arena lifetimes that the signatures do not need 2026-09-14 12:53:14 +02:00
Dennis Kobert
4f9402dad6 Explain why the selective color and spline loops index by range 2026-09-14 12:53:13 +02:00
Dennis Kobert
f27d90d152 Fold attribute names through monitors and skip coercing name inputs 2026-09-14 12:53:11 +02:00
Dennis Kobert
53608ae7bf Row a reading input's element generic instead of erasing it 2026-09-14 12:53:11 +02:00
Dennis Kobert
93d9b595ef Name a type's live spelling beside its static one 2026-09-14 12:53:00 +02:00
Dennis Kobert
0a4288eca6 Read a named attribute at each value type it can hold
One read node per value type, mirroring master's read family. A name
means one value type, so there is no coercion between them: master's
number read silently widened integers, and these refuse instead, which
is the same rule the write side already enforces.

Each takes any record wire through the opaque reading input and serves
the name's own default where the attribute is absent, so the value
carries the declared type either way.

The gradient enums join the value-type rows now that a family exists to
read them at.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-09 12:36:00 +00:00
Dennis Kobert
5baeb8fd46 Accept any record wire on an input read only for its attributes
An element generic declared on a reading input, absent from the output
and from every other input, has nowhere to go and nothing to be: the
node reads its declared attributes and never the element. That is an
attr-to-element map, so it accepts any upstream record wire.

The blessing is inferred rather than marked, since the signature already
says it. The two substrate pieces were both in place: the element rides
as the byte-carried token, so the registry takes one generic row instead
of a row per element type, and the reads resolve against the input's own
layout as they always have. Only the passthrough rule stood in the way,
in the three places that enforced it.

A generic the output carries, or one on an input with no reads, is
unchanged and still owes an implementations list.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-09 12:15:40 +00:00
Dennis Kobert
f04d439b33 Name the attribute read for the type it reads
The read is a number read, not a read of whatever the name holds: our
model has no coercion, so a name written at another value type is a graph
error rather than a conversion. The name says so.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-09 11:35:38 +00:00
Dennis Kobert
6e22d6a412 Serve a declared name's census default on an absent read
An absent read of a name the census declares now serves that name's own
default rather than its value type's, which is the rule for a declared
name. The census stages it exactly as it fills any absent field, as the
declared default's bytes, so the read reuses the census's own mechanism
instead of a second one; the compiler takes them when the name folds and
`set_layout` installs them beside the offset.

A name the census does not declare keeps the value type's default, which
is that case's own rule. One name carries one value type, checked when
the name folds, so the row's value type and width agree with the read's.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-09 11:13:41 +00:00
Dennis Kobert
5eb80721dd Resolve a named read's offset when the graph compiles
The fold already holds the name and the read input's finished layout, so
the offset falls out there rather than at construction: `RecordLayout`
carries the resolved numbers and `set_layout` copies them into the read
slots. Constructors are untouched, and census-marker reads keep their
current installation.

A read meets the value type the name was written at, so a disagreement
between a read here and a write upstream is the same graph error as two
writes disagreeing; the one-name-one-type check now spans reads and
writes together. An absent attribute stays absent and the read serves
the forced default rather than reporting it.

`read_attribute` is the catalog's get half, typed and never `Option` at
the kernel boundary, with the name declared exactly as the write side
declares it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-09 10:50:08 +00:00