Mutable scratch shared across pen-tool gestures. The hook keeps a stable
reference to a single instance and initScratch returns it on every call,
so click-by-click state survives gesture boundaries and the preview layer
can read the same object.
The pen creates paths and nothing else
Reshaping an existing path is anchor editing: double-click a path to
enter edit mode, then use the editAnchors / insertPathAnchor /
nudgeAnchors / deleteAnchors / marqueeAnchors / cutPathAtAnchor
Actions.
The pen used to carry a second, private implementation of all of that,
with its own scratch mode, hit-test override, overlay, and undo
plumbing. It was reachable only through a getPathObj option whose
contract required pose.kind to be 'polygon' or 'rect' — which no
kit-created node has, including the ones the pen itself creates. So it
was dead in every consumer while shadowing the live implementation, and
the two had drifted. Its geometry now lives in
features/paths/anchorEdits.ts, driven by those Actions.
Mutable scratch shared across pen-tool gestures. The hook keeps a stable reference to a single instance and
initScratchreturns it on every call, so click-by-click state survives gesture boundaries and the preview layer can read the same object.The pen creates paths and nothing else
Reshaping an existing path is anchor editing: double-click a path to enter edit mode, then use the
editAnchors/insertPathAnchor/nudgeAnchors/deleteAnchors/marqueeAnchors/cutPathAtAnchorActions.The pen used to carry a second, private implementation of all of that, with its own scratch mode, hit-test override, overlay, and undo plumbing. It was reachable only through a
getPathObjoption whose contract requiredpose.kindto be'polygon'or'rect'— which no kit-created node has, including the ones the pen itself creates. So it was dead in every consumer while shadowing the live implementation, and the two had drifted. Its geometry now lives infeatures/paths/anchorEdits.ts, driven by those Actions.