Finalize and unify the design of the 'Morph' and 'Blend' nodes (#3974)

* Fix Morph node transform interpolation and preservation in the table

* Fix click target positions for Morph's nested layers by pre-compensating upstream_data transforms

* Redesign Morph node (v3) with control path input and uniformly spaced progression, and fix Stroke::lerp interpolation weights

* Add migration from Morph node v2 to v3

* Redesign the 'Blend Shapes' node behavior and subgraph definition

* Add the Layer > Blend menu entry to easily set up a blend

* Optimize the Morph node

* Refactor the Morph node to remove the roundtrip through BezPath

* Fine-tune Morph node Bezier order promotion and handle interpolation

* Add the Layer > Morph menu bar entry

* Fix NaN and guard against other potential NaN bugs breaking the editor

* Add InterpolationDistribution parameter to Morph with weighted progression, swap parameter orders, and rename shear to skew

* Add the Reverse parameter to the Morph node

* Update the order of the inputs to Blend Shapes for consistency with Morph

* Make Layer > Morph create the Morph Path control layer

* Fix migrations

* Move 10 to a constant

* Avoid division by 0 in the Blend Shapes node internals

* Rename nodes 'Blend' -> 'Mix' and 'Blend Shapes' to 'Blend'

* Fix a crash encountered while testing

* Final code review

* Make domain push dupe checks debug-only and use push_unchecked in the Morph node

* Pre-allocate for pushes to the vector domains

* Add fast path at t=0

* Inline reserve()

* Set up the control path layer above not below, and starting collapsed

* Review fixes

---------

Co-authored-by: Timon <me@timon.zip>
This commit is contained in:
Keavon Chambers
2026-04-03 20:45:58 -07:00
committed by GitHub
co-authored by Timon
parent 7077e877f9
commit 4360359d60
23 changed files with 986 additions and 364 deletions
+4
View File
@@ -154,6 +154,8 @@ import HistoryRedo from "/../branding/assets/icon-16px-solid/history-redo.svg";
import HistoryUndo from "/../branding/assets/icon-16px-solid/history-undo.svg";
import IconsGrid from "/../branding/assets/icon-16px-solid/icons-grid.svg";
import Image from "/../branding/assets/icon-16px-solid/image.svg";
import InterpolationBlend from "/../branding/assets/icon-16px-solid/interpolation-blend.svg";
import InterpolationMorph from "/../branding/assets/icon-16px-solid/interpolation-morph.svg";
import Layer from "/../branding/assets/icon-16px-solid/layer.svg";
import License from "/../branding/assets/icon-16px-solid/license.svg";
import NewLayer from "/../branding/assets/icon-16px-solid/new-layer.svg";
@@ -271,6 +273,8 @@ const SOLID_16PX = {
HistoryUndo: { svg: HistoryUndo, size: 16 },
IconsGrid: { svg: IconsGrid, size: 16 },
Image: { svg: Image, size: 16 },
InterpolationBlend: { svg: InterpolationBlend, size: 16 },
InterpolationMorph: { svg: InterpolationMorph, size: 16 },
Layer: { svg: Layer, size: 16 },
License: { svg: License, size: 16 },
NewLayer: { svg: NewLayer, size: 16 },