Repository navigation
V3: Mesh Gradient rework (presets, canvas points, shuffle, simple distortion, looping motion) - #201
Conversation
…e, simple distortion and looping motion The old presets were high-frequency warps with tonemapped colors, so they read as oily blotches rather than a mesh gradient, and the names did not match the results. Eight new presets (Peach, Lagoon, Dusk, Citrus, Mint, Aurora, Ink, Basement) are soft color fields with exact colors and light grain, and a new gradient now starts from Peach. Each color point shows on the canvas while the layer is selected: drag to move it (Shift locks the axis), double-click to pick its color, Alt-drag to change its reach. Shuffle replaces Randomize: it builds a harmonious OKLCH palette (analogous, split complementary, triad or monochrome with a dark and a light anchor) or reuses a preset palette, lays the points out evenly, and keeps distortion, motion and finish. Distortion gains a Simple mode with Softness, Warp and Detail, which give each point a soft core so low-weight points no longer form hard dots; the raw controls live under Advanced. Motion gets styles (Drift, Breathe, Swirl, Flow) built from whole harmonics of the timeline duration, which passes now receive through updateTimelineDuration in the editor and the runtime, so a video export loops without a seam. Saved gradients migrate to Advanced with their Original motion and old preset ids fall back to Custom, so they render exactly as before.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
…otif colors, and mark Mesh Gradient as reworked - Painted brush masks stay inside their saved bounds, and an empty brush mask hides the layer - The runtime accepts every inner effect the editor offers, so exported Blob Tracking projects keep them - Pattern motif images rebuild when the palette changes - Mesh Gradient shows the orange reworked dot
|
| let offset: Node = vec2(0, 0) | ||
| if (original) offset = legacyOffset | ||
| else if (drift) offset = driftOffset |
There was a problem hiding this comment.
Saved gradients change appearance
Legacy gradients with animate: false now use off, which drops the fixed point offsets the old shader applied even at time zero. Reopening those gradients moves their colors and breaks the promised saved appearance. Preserve the old offsets for legacy disabled animation in both the editor and runtime.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/renderer/gradient-pass.ts
Line: 537-539
Comment:
**Saved gradients change appearance**
Legacy gradients with `animate: false` now use `off`, which drops the fixed point offsets the old shader applied even at time zero. Reopening those gradients moves their colors and breaks the promised saved appearance. Preserve the old offsets for legacy disabled animation in both the editor and runtime.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.| const cycles = Math.max(1, Math.round((this.motionSpeed * this.loopSeconds) / 2)) | ||
| this.loopPhaseUniform.value = (Math.PI * 2 * cycles) / this.loopSeconds |
There was a problem hiding this comment.
Setting motionSpeed to zero does not stop Drift, Breathe, Swirl, or Flow. updateLoopPhase still assigns one full cycle, while needsContinuousRender reports no animation. With another animated layer present, the gradient keeps moving; otherwise it can jump when an edit redraws the canvas. Set the phase rate to zero at zero speed in both copies.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/renderer/gradient-pass.ts
Line: 369-370
Comment:
**Zero speed still moves**
Setting `motionSpeed` to zero does not stop Drift, Breathe, Swirl, or Flow. `updateLoopPhase` still assigns one full cycle, while `needsContinuousRender` reports no animation. With another animated layer present, the gradient keeps moving; otherwise it can jump when an edit redraws the canvas. Set the phase rate to zero at zero speed in both copies.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.| useEditorStore.getState().beginInteractiveEdit() | ||
| event.currentTarget.setPointerCapture(event.pointerId) |
There was a problem hiding this comment.
Interrupted drags leave edits open
The overlay closes a point drag only through pointer events. If the selected layer changes, the overlay becomes disabled, or the component unmounts during a drag, removing the captured circle can leave the edit open. Later changes then stop getting separate undo steps. Add cleanup that calls endInteractiveEdit for an unfinished drag, as GeometryHandles already does.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/components/editor/gradient-points-overlay.tsx
Line: 127-128
Comment:
**Interrupted drags leave edits open**
The overlay closes a point drag only through pointer events. If the selected layer changes, the overlay becomes disabled, or the component unmounts during a drag, removing the captured circle can leave the edit open. Later changes then stop getting separate undo steps. Add cleanup that calls `endInteractiveEdit` for an unfinished drag, as `GeometryHandles` already does.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.| const order = shuffled(colors, random) | ||
| const positions = spreadPoints(5, random) | ||
| const params: LayerParameterValues = { preset: "custom", activePoints: count } | ||
| for (let index = 0; index < 5; index += 1) { | ||
| params[`point${index + 1}Color`] = order[index] ?? "#ffffff" |
There was a problem hiding this comment.
Shuffle drops a palette anchor
Four-point shuffles can discard the dark or light anchor. The generated palette has five colors, then shuffled can put either anchor in point five even though activePoints is four. This leaves some palettes with less contrast. Keep both anchors among the active points before shuffling their positions.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/lib/editor/mesh-gradient.ts
Line: 280-284
Comment:
**Shuffle drops a palette anchor**
Four-point shuffles can discard the dark or light anchor. The generated palette has five colors, then `shuffled` can put either anchor in point five even though `activePoints` is four. This leaves some palettes with less contrast. Keep both anchors among the active points before shuffling their positions.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Stacked on #150.
What changes
updateTimelineDurationhook (editor and runtime).Compatibility
Saved gradients migrate to Advanced with their Original motion and old preset ids fall back to Custom, so they render exactly as before. The runtime treats gradients without the new params the same way.
Verified
#00ff88; Shuffle changed the palette and kept softness, warp and motion.sunset, no new params) loads as Advanced / Original / Custom.CI does not run on stacked PRs; it runs once this lands in #150.
🤖 Generated with Claude Code