Repository navigation
Shapes: edit gradient color and opacity stops (#612) - #694
Open
tylerjenningsw wants to merge 2 commits into
Open
tylerjenningsw wants to merge 2 commits into
tylerjenningsw wants to merge 2 commits into
Conversation
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.
…ses only the picker (storytold#612) The stop colour now uses widgets::srgb_color_button, the After Effects-style picker every colour input opens (storytold#638): hex field, HSB/RGB fields, OK and Cancel, sRGB as the project stores colours. The stop keeps its alpha. The dialog Escape handler only stepped aside for egui popups, and this picker isn't one, so in a modal dialog Escape with the picker open closed the dialog too. The picker now marks the pass it was open in (color_picker::open_recently), and the handler leaves Escape to it: Escape restores the colour the picker opened with and closes only the picker. Tests: ui_gradient_editor clicks inside the picker's colour field over the modal editor, types a hex code, closes the picker by clicking outside it and saves the stop; a new test checks that Escape and the picker's Cancel restore the stop's colour and keep the editor and its other edits. That test fails without the Escape change. ui_color_hex still passes.
tylerjenningsw
force-pushed
the
enhance/gradient-editor
branch
from
October 11, 2026 03:43
d987fc6 to
5c1484b
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #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.
What it does
prop.setat the composition time it opened, snapped to the nearest frame, withtimeBase: "comp". Offset and stretched layers therefore get the keyframe where it was opened. OK with no change does nothing, so it never adds a keyframe.prop.editGradient {layer?, path|prop, comp?}is a command, so the control channel and MCP can open the editor. It checks the target is a gradient property before the UI opens anything, so a wrong target is an error, not success.Shared colour picker
The dialog Escape handler only stepped aside for egui popups, and the shared picker isn't one, so in a modal dialog Escape with the picker open closed the dialog as well. The picker now marks the pass it was open in (
color_picker::open_recently), and the handler leaves Escape to it. This is in its own commit. A test with the change reverted fails: Escape closes the editor.Model
Gradient::color_at/opacity_atsample one track each.sample()multiplies opacity in, so feeding its result into a new stop would apply opacity twice (50% would become 25%).Not in this PR
Checks (Windows 10, Rust 1.95, release; rebased onto
mainat9a7d3e7, fresh build)cargo fmt --check: passes.cargo +1.95 clippy -p effectcraft-keyframe -p effectcraft-engine -p effectcraft-ui-egui --no-deps --all-targets --release -- -D warnings: passes.effectcraft-keyframeunit tests: 33/33. New: per-track sampling with no double opacity, the typed one-stop and RGBA round trip.ui-eguiunit testsgradient_editor(4/4: stops stay in order and selected while moving, sampling, the baseline comparison, the warning rule) andi18n(catalogs): pass.ui_gradient_value(1/1): fails onmainwith "no automation id timeline.prop.…value: the Timeline's Edit Gradient… isn't clickable", and passes here. It uses only APIs that exist onmain.ui_gradient_editor(12/12):prop.editGradienterrors fromexecute_checkedand through the UIui_project_delete(11/11) andui_color_hex(8/8, the shared picker's own tests).snapshotexample) of the editor opened byprop.editGradienton a rectangle's Gradient Fill.cargo xtask ciwasn't run locally: it takes over 2.5 hours on this machine. On Windows it also stops on two failures that happen identically onmain:effectcraft-cli'srender_out_is_relative_to_the_working_directory(a\\?\path prefix) andtext'sstyle_variations_change_advances_and_outlines(depends on an installed system font).