Shapes: edit gradient color and opacity stops (#612)

The Timeline's "Edit Gradient…" on a gradient property (Gradient Fill /
Gradient Stroke ▸ Colors, Gradient Overlay) only painted its label. It now
opens a Gradient Editor (prop.editGradient): opacity stops above a preview
bar and colour stops below. Click to add a stop (it takes that track's
own value there), drag or type a Location to move it, set its opacity or
colour (egui's colour picker), Delete removes it (never the last of a
track, never while typing). The tracks stay in order while editing and the
selection follows its stop.

The editor works on a draft. OK sets the property once with prop.set at
the composition time it opened, snapped to the frame, with
timeBase: "comp" (offset and stretched layers get the key where it was
opened): one undo step, and nothing at all when the draft is unchanged, so
OK adds no keyframe. Cancel and Escape change nothing; Escape with the
picker open closes only the picker. On an animated gradient only the
keyframe at that time changes; when its stop counts no longer match a
neighbouring keyframe's (gradients only blend with equal counts) the
editor says so. The draft is saved in the typed form, so one colour stop
and each stop's RGBA survive.

prop.editGradient checks its target is a gradient property before the UI
opens anything, so agents get an error for a wrong one. New Gradient
color_at / opacity_at sample one track each (sample() multiplies opacity
in, which would apply it twice to a new stop).

Tests: ui_gradient_value (fails on main: the value had no automation id),
ui_gradient_editor (11), gradient_editor and keyframe unit tests.
This commit is contained in:
tylerjenningsw committed 2026-10-10 22:22:13 -04:00
1 parent 9a7d3e7699
commit ec1bc8cc99
13 files changed
+1133 -3

No files matched your search

+13
View File
@@ -129,6 +129,19 @@ The most important missing piece: it turns every other estimate here into a meas
the prompt, with their layers, in one undo step, for single items, multiple selections and
folder contents. Nothing happens with an empty selection, in other panels, while typing or with
a dialog open, and the next Delete still asks.
- Regression evidence for [#612](https://github.com/storytold/effectcraft/issues/612): the
`ui_gradient_value` and `ui_gradient_editor` input tests, checked headlessly on Windows, open
the Gradient Editor from the Timeline's "Edit Gradient…" on a shape layer's Gradient Fill. They
check that OK sets the edited stops (added, dragged, recoloured in the picker, down to a single
colour stop) in one undo step, at the composition time the editor opened (also on offset and
stretched layers), and that OK without a change, Cancel and Escape change nothing; Escape with
the picker open closes only the picker. On an animated gradient only the keyframe at that time
changes, with a warning when its stop counts no longer match a neighbour's. Delete never
removes the last stop, a layer or a stop while typing; a stop moved past another by its
Location keeps its selection and fields; a layer deleted while editing is reported; and
`prop.editGradient` is an error for a target that isn't a gradient. Unit tests in `keyframe`
and `gradient_editor` cover per-track sampling (no double opacity), the typed one-stop round
trip, and stops staying in order, and selected, while they move.
- Regression evidence for the reports of 6 October, checked headlessly on Windows: real pointer
drags in `ui_drag_drop` (Project items into the Timeline between layers and at a time, and onto
the viewer; an effect onto a layer in the viewer: #85, #88, #89), `ui_render_queue` (a template