@weasel-js/core 1.11.0 → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +611 -0
- package/README.md +1 -1
- package/dist/WeaselProvider.js +1 -1
- package/dist/affordances/pathAnchors.js +10 -6
- package/dist/affordances/pathAnchors.js.map +1 -1
- package/dist/animation/index.js +3 -3
- package/dist/animation/rig/bindRig.js +1 -1
- package/dist/animation/rig/rigNode.js.map +1 -1
- package/dist/barrel/canvas.js +9 -3
- package/dist/barrel/interactions.js +5 -4
- package/dist/barrel/paint.js +4 -4
- package/dist/barrel/paths.js +10 -6
- package/dist/barrel/renderer.js +5 -3
- package/dist/barrel/routing.js +7 -12
- package/dist/barrel/scene.js +9 -5
- package/dist/barrel/text.js +2 -2
- package/dist/barrel/viewport.js +9 -4
- package/dist/canvas/Canvas.js +5 -2
- package/dist/canvas/Canvas.js.map +1 -1
- package/dist/canvas/CanvasView.js +23 -34
- package/dist/canvas/CanvasView.js.map +1 -1
- package/dist/canvas/ModalityHud.js +1 -1
- package/dist/canvas/NodeShape.js +4 -1
- package/dist/canvas/NodeShape.js.map +1 -1
- package/dist/canvas/SceneCanvas/ActionsProviderIfRoot.js +1 -1
- package/dist/canvas/SceneCanvas/DepRegistryProviderIfRoot.js +1 -1
- package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js +1 -1
- package/dist/canvas/SceneCanvas/SceneCanvasInput.js +17 -3
- package/dist/canvas/SceneCanvas/SceneCanvasInput.js.map +1 -1
- package/dist/canvas/SceneCanvas/SurfaceDeclarations.js +23 -0
- package/dist/canvas/SceneCanvas/SurfaceDeclarations.js.map +1 -0
- package/dist/canvas/SceneCanvas/builtinToolSets.js +30 -0
- package/dist/canvas/SceneCanvas/builtinToolSets.js.map +1 -0
- package/dist/canvas/SceneCanvas/canvasPassThrough.js +2 -0
- package/dist/canvas/SceneCanvas/canvasPassThrough.js.map +1 -1
- package/dist/canvas/SceneCanvas/coordTrace.js +5 -16
- package/dist/canvas/SceneCanvas/coordTrace.js.map +1 -1
- package/dist/canvas/SceneCanvas/defaultNodeProperties.js +5 -0
- package/dist/canvas/SceneCanvas/defaultNodeProperties.js.map +1 -1
- package/dist/canvas/SceneCanvas/features.js +45 -5
- package/dist/canvas/SceneCanvas/features.js.map +1 -1
- package/dist/canvas/SceneCanvas/props.js +1 -11
- package/dist/canvas/SceneCanvas/props.js.map +1 -1
- package/dist/canvas/SceneCanvas/scenePointQuery.js +7 -3
- package/dist/canvas/SceneCanvas/scenePointQuery.js.map +1 -1
- package/dist/canvas/SceneCanvas/toolRegistry.js +8 -4
- package/dist/canvas/SceneCanvas/toolRegistry.js.map +1 -1
- package/dist/canvas/SceneCanvas/useActionTunings.js +6 -1
- package/dist/canvas/SceneCanvas/useActionTunings.js.map +1 -1
- package/dist/canvas/SceneCanvas/useActionsPropResolver.js +1 -11
- package/dist/canvas/SceneCanvas/useActionsPropResolver.js.map +1 -1
- package/dist/canvas/SceneCanvas/useBuiltinShapeTools.js.map +1 -1
- package/dist/canvas/SceneCanvas/useBuiltinTools.js +2 -9
- package/dist/canvas/SceneCanvas/useBuiltinTools.js.map +1 -1
- package/dist/canvas/SceneCanvas/useCanvasDevtoolsRoot.js +94 -0
- package/dist/canvas/SceneCanvas/useCanvasDevtoolsRoot.js.map +1 -0
- package/dist/canvas/SceneCanvas/useCanvasSelection.js +7 -2
- package/dist/canvas/SceneCanvas/useCanvasSelection.js.map +1 -1
- package/dist/canvas/SceneCanvas/useCanvasTools.js +15 -10
- package/dist/canvas/SceneCanvas/useCanvasTools.js.map +1 -1
- package/dist/canvas/SceneCanvas/useNodeKinds.js +1 -1
- package/dist/canvas/SceneCanvas/useNodeKinds.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneCanvasHandle.js +9 -3
- package/dist/canvas/SceneCanvas/useSceneCanvasHandle.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js +23 -4
- package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneCanvasTools.js +2 -3
- package/dist/canvas/SceneCanvas/useSceneCanvasTools.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneChrome.js +6 -7
- package/dist/canvas/SceneCanvas/useSceneChrome.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneGestureDispatcher.js +24 -7
- package/dist/canvas/SceneCanvas/useSceneGestureDispatcher.js.map +1 -1
- package/dist/canvas/SceneCanvas/useScenePicking.js +2 -3
- package/dist/canvas/SceneCanvas/useScenePicking.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneSelectTool.js +2 -1
- package/dist/canvas/SceneCanvas/useSceneSelectTool.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneStandardActions.js +5 -5
- package/dist/canvas/SceneCanvas/useSceneStandardActions.js.map +1 -1
- package/dist/canvas/SceneCanvas.js +27 -24
- package/dist/canvas/SceneCanvas.js.map +1 -1
- package/dist/canvas/SurfaceCanvas.js +5 -22
- package/dist/canvas/SurfaceCanvas.js.map +1 -1
- package/dist/canvas/ViewMarker.js +35 -0
- package/dist/canvas/ViewMarker.js.map +1 -0
- package/dist/canvas/canvasRenderer.js +9 -5
- package/dist/canvas/canvasRenderer.js.map +1 -1
- package/dist/canvas/contextAttributes.js +14 -0
- package/dist/canvas/contextAttributes.js.map +1 -0
- package/dist/canvas/defaultDrawOne.js +2 -0
- package/dist/canvas/defaultDrawOne.js.map +1 -1
- package/dist/canvas/deps/booleans.js +2 -1
- package/dist/canvas/deps/booleans.js.map +1 -1
- package/dist/canvas/deps/editAnchors.js +9 -113
- package/dist/canvas/deps/editAnchors.js.map +1 -1
- package/dist/canvas/deps/hitTestArea.js +2 -2
- package/dist/canvas/deps/hitTestArea.js.map +1 -1
- package/dist/canvas/deps/insert.js +10 -4
- package/dist/canvas/deps/insert.js.map +1 -1
- package/dist/canvas/deps/pathEditCommits.js +189 -0
- package/dist/canvas/deps/pathEditCommits.js.map +1 -0
- package/dist/canvas/deps/snap.js +12 -9
- package/dist/canvas/deps/snap.js.map +1 -1
- package/dist/canvas/deps/transformFollowers.js +20 -0
- package/dist/canvas/deps/transformFollowers.js.map +1 -0
- package/dist/canvas/derivedPath.js +20 -1
- package/dist/canvas/derivedPath.js.map +1 -1
- package/dist/canvas/drawnBounds.js +38 -4
- package/dist/canvas/drawnBounds.js.map +1 -1
- package/dist/canvas/inheritedPaints.js +44 -0
- package/dist/canvas/inheritedPaints.js.map +1 -0
- package/dist/canvas/nodeShapes/derivedPainter.js +23 -16
- package/dist/canvas/nodeShapes/derivedPainter.js.map +1 -1
- package/dist/canvas/nodeShapes/nodePaint.js +13 -34
- package/dist/canvas/nodeShapes/nodePaint.js.map +1 -1
- package/dist/canvas/nodeShapes/pathPainter.js +12 -10
- package/dist/canvas/nodeShapes/pathPainter.js.map +1 -1
- package/dist/canvas/nodeShapes/rectFallbackPainter.js +4 -5
- package/dist/canvas/nodeShapes/rectFallbackPainter.js.map +1 -1
- package/dist/canvas/nodeShapes/shapePainter.js +12 -11
- package/dist/canvas/nodeShapes/shapePainter.js.map +1 -1
- package/dist/canvas/nodeShapes/textPainter.js +13 -12
- package/dist/canvas/nodeShapes/textPainter.js.map +1 -1
- package/dist/canvas/overlayRoleStrokes.js +12 -0
- package/dist/canvas/overlayRoleStrokes.js.map +1 -1
- package/dist/canvas/pathOverlay.js +27 -7
- package/dist/canvas/pathOverlay.js.map +1 -1
- package/dist/canvas/pickReach.js +3 -3
- package/dist/canvas/pickReach.js.map +1 -1
- package/dist/canvas/pickWalk.js +3 -1
- package/dist/canvas/pickWalk.js.map +1 -1
- package/dist/canvas/renderDebugSnapshot.js +1 -0
- package/dist/canvas/renderDebugSnapshot.js.map +1 -1
- package/dist/canvas/renderSceneToPixels.js +7 -6
- package/dist/canvas/renderSceneToPixels.js.map +1 -1
- package/dist/canvas/sceneAdapter.js.map +1 -1
- package/dist/canvas/sceneSlotWiring.js +2 -1
- package/dist/canvas/sceneSlotWiring.js.map +1 -1
- package/dist/canvas/sceneViewRender.js +2 -1
- package/dist/canvas/sceneViewRender.js.map +1 -1
- package/dist/canvas/surfaceContribution.js +12 -8
- package/dist/canvas/surfaceContribution.js.map +1 -1
- package/dist/canvas/useCanvasPaint.js +2 -1
- package/dist/canvas/useCanvasPaint.js.map +1 -1
- package/dist/canvas/useCanvasView.js +4 -2
- package/dist/canvas/useCanvasView.js.map +1 -1
- package/dist/canvas/useInFlightBounds.js +52 -0
- package/dist/canvas/useInFlightBounds.js.map +1 -0
- package/dist/canvas/useLayerStack.js +6 -2
- package/dist/canvas/useLayerStack.js.map +1 -1
- package/dist/canvas/useViewAim.js +121 -0
- package/dist/canvas/useViewAim.js.map +1 -0
- package/dist/canvas/useViewHelpers.js +7 -9
- package/dist/canvas/useViewHelpers.js.map +1 -1
- package/dist/canvas/useViewNesting.js +3 -2
- package/dist/canvas/useViewNesting.js.map +1 -1
- package/dist/canvas/useViewRegistrySurface.js +4 -2
- package/dist/canvas/useViewRegistrySurface.js.map +1 -1
- package/dist/canvas/viewMarkers.js +63 -0
- package/dist/canvas/viewMarkers.js.map +1 -0
- package/dist/canvas/viewRegistry.js +27 -1
- package/dist/canvas/viewRegistry.js.map +1 -1
- package/dist/clipboard.d.ts +3 -2
- package/dist/{clone-DZDrfIlU.d.ts → clone-C3e0OTuF.d.ts} +8 -21
- package/dist/clone.d.ts +4 -3
- package/dist/core/geometry/autoPoseDescriptor.js +1 -1
- package/dist/core/ops/setDependsOn.js +37 -0
- package/dist/core/ops/setDependsOn.js.map +1 -0
- package/dist/core/ops/writtenBy.js +53 -0
- package/dist/core/ops/writtenBy.js.map +1 -0
- package/dist/core/pages/fitViewToPage.js +12 -1
- package/dist/core/pages/fitViewToPage.js.map +1 -1
- package/dist/core/pages/pageEdits.js +163 -0
- package/dist/core/pages/pageEdits.js.map +1 -0
- package/dist/core/pages/pages.js +30 -1
- package/dist/core/pages/pages.js.map +1 -1
- package/dist/core/paint/meshKindLazy.js +59 -2
- package/dist/core/paint/meshKindLazy.js.map +1 -1
- package/dist/core/scene/NodeRouting.js +8 -3
- package/dist/core/scene/NodeRouting.js.map +1 -1
- package/dist/core/scene/arrivalWindow.js.map +1 -1
- package/dist/core/scene/carryDescendants.js +51 -0
- package/dist/core/scene/carryDescendants.js.map +1 -0
- package/dist/core/scene/clipNothing.js +13 -0
- package/dist/core/scene/clipNothing.js.map +1 -0
- package/dist/core/scene/depMemo.js +11 -3
- package/dist/core/scene/depMemo.js.map +1 -1
- package/dist/core/scene/dependents.js +7 -1
- package/dist/core/scene/dependents.js.map +1 -1
- package/dist/core/scene/derivedParts.js +10 -11
- package/dist/core/scene/derivedParts.js.map +1 -1
- package/dist/core/scene/docValues.js +57 -0
- package/dist/core/scene/docValues.js.map +1 -0
- package/dist/core/scene/editPass.js +111 -0
- package/dist/core/scene/editPass.js.map +1 -0
- package/dist/core/scene/effectivePose.js +13 -2
- package/dist/core/scene/effectivePose.js.map +1 -1
- package/dist/core/scene/fieldEdits.js +4 -1
- package/dist/core/scene/fieldEdits.js.map +1 -1
- package/dist/core/scene/fontReads.js +37 -0
- package/dist/core/scene/fontReads.js.map +1 -0
- package/dist/core/scene/historyFacade.js +1 -0
- package/dist/core/scene/historyFacade.js.map +1 -1
- package/dist/core/scene/inheritedPaint.js +75 -0
- package/dist/core/scene/inheritedPaint.js.map +1 -0
- package/dist/core/scene/kitRegistry.js +5 -0
- package/dist/core/scene/kitRegistry.js.map +1 -1
- package/dist/core/scene/layoutPass.js +28 -3
- package/dist/core/scene/layoutPass.js.map +1 -1
- package/dist/core/scene/nodeMemo.js +15 -7
- package/dist/core/scene/nodeMemo.js.map +1 -1
- package/dist/core/scene/pathEffects/blend.js.map +1 -1
- package/dist/core/scene/pathEffects/derive.js +7 -2
- package/dist/core/scene/pathEffects/derive.js.map +1 -1
- package/dist/core/scene/pathEffects/effects.js +3 -1
- package/dist/core/scene/pathEffects/effects.js.map +1 -1
- package/dist/core/scene/pathEffects/textAlong.js +95 -0
- package/dist/core/scene/pathEffects/textAlong.js.map +1 -0
- package/dist/core/scene/recorder.js +28 -19
- package/dist/core/scene/recorder.js.map +1 -1
- package/dist/core/scene/scene.js +15 -9
- package/dist/core/scene/scene.js.map +1 -1
- package/dist/core/scene/sceneChanges.js +13 -0
- package/dist/core/scene/sceneChanges.js.map +1 -0
- package/dist/core/scene/sceneEdits.js +8 -1
- package/dist/core/scene/sceneEdits.js.map +1 -1
- package/dist/core/scene/sceneMutators.js +1 -0
- package/dist/core/scene/sceneMutators.js.map +1 -1
- package/dist/core/scene/sceneRecording.js +20 -3
- package/dist/core/scene/sceneRecording.js.map +1 -1
- package/dist/core/scene/sceneSelection.js +4 -1
- package/dist/core/scene/sceneSelection.js.map +1 -1
- package/dist/core/scene/sceneState.js +11 -5
- package/dist/core/scene/sceneState.js.map +1 -1
- package/dist/core/scene/serialization.js +5 -3
- package/dist/core/scene/serialization.js.map +1 -1
- package/dist/core/scene/types.js.map +1 -1
- package/dist/core/scene/unitScopes.js +19 -1
- package/dist/core/scene/unitScopes.js.map +1 -1
- package/dist/core/selection/usePublishSceneSelection.js +6 -12
- package/dist/core/selection/usePublishSceneSelection.js.map +1 -1
- package/dist/core/shapeKinds.js +25 -11
- package/dist/core/shapeKinds.js.map +1 -1
- package/dist/{cornerHandles-Camw_yeu.d.ts → cornerHandles-p8fDIAKt.d.ts} +3 -2
- package/dist/debug/createDebugOverlayLayer.js +16 -111
- package/dist/debug/createDebugOverlayLayer.js.map +1 -1
- package/dist/debug/createDebugSink.js +2 -1
- package/dist/debug/createDebugSink.js.map +1 -1
- package/dist/debug/defaultTheme.js +4 -2
- package/dist/debug/defaultTheme.js.map +1 -1
- package/dist/debug/features.js +17 -0
- package/dist/debug/features.js.map +1 -0
- package/dist/debug/overlayPanels.js +117 -0
- package/dist/debug/overlayPanels.js.map +1 -0
- package/dist/debug/parseDebugFlags.js +4 -13
- package/dist/debug/parseDebugFlags.js.map +1 -1
- package/dist/{depSchema-Cgfu_G9s.d.ts → depSchema-mG19aEdD.d.ts} +174 -904
- package/dist/devtools/handlers.js +112 -0
- package/dist/devtools/handlers.js.map +1 -0
- package/dist/devtools/history.js +71 -0
- package/dist/devtools/history.js.map +1 -0
- package/dist/devtools/hook.js +74 -0
- package/dist/devtools/hook.js.map +1 -0
- package/dist/devtools/label.js +25 -0
- package/dist/devtools/label.js.map +1 -0
- package/dist/devtools/notices.js +58 -0
- package/dist/devtools/notices.js.map +1 -0
- package/dist/devtools/protocol.js +7 -0
- package/dist/devtools/protocol.js.map +1 -0
- package/dist/devtools/registry.js +90 -0
- package/dist/devtools/registry.js.map +1 -0
- package/dist/devtools/root.js +80 -0
- package/dist/devtools/root.js.map +1 -0
- package/dist/devtools/serialize.js +86 -0
- package/dist/devtools/serialize.js.map +1 -0
- package/dist/devtools/session.js +111 -0
- package/dist/devtools/session.js.map +1 -0
- package/dist/devtools/transport.js +67 -0
- package/dist/devtools/transport.js.map +1 -0
- package/dist/devtools/useDevtoolsRoot.js +81 -0
- package/dist/devtools/useDevtoolsRoot.js.map +1 -0
- package/dist/devtools-protocol.d.ts +435 -0
- package/dist/devtools-protocol.js +7 -0
- package/dist/devtools.d.ts +8 -0
- package/dist/devtools.js +12 -0
- package/dist/devtools.js.map +1 -0
- package/dist/features/chrome-caps/useHoverTracking.js +16 -10
- package/dist/features/chrome-caps/useHoverTracking.js.map +1 -1
- package/dist/features/ingestion/contentHandlers.js +25 -2
- package/dist/features/ingestion/contentHandlers.js.map +1 -1
- package/dist/features/measure/measureCommands.js +7 -5
- package/dist/features/measure/measureCommands.js.map +1 -1
- package/dist/features/measure/measureContribution.js +4 -2
- package/dist/features/measure/measureContribution.js.map +1 -1
- package/dist/features/modes/modeTriggers.js +7 -3
- package/dist/features/modes/modeTriggers.js.map +1 -1
- package/dist/features/pathEffects/effectSources.js +60 -0
- package/dist/features/pathEffects/effectSources.js.map +1 -0
- package/dist/features/pathEffects/readSource.js +17 -1
- package/dist/features/pathEffects/readSource.js.map +1 -1
- package/dist/features/pathEffects/textItems.js +53 -0
- package/dist/features/pathEffects/textItems.js.map +1 -0
- package/dist/features/pathEffects/useEffectSourcesLayer.js +57 -0
- package/dist/features/pathEffects/useEffectSourcesLayer.js.map +1 -0
- package/dist/features/paths/index.js +2 -2
- package/dist/features/paths/pathEditExtension.js.map +1 -1
- package/dist/features/paths/pathEditState.js +5 -2
- package/dist/features/paths/pathEditState.js.map +1 -1
- package/dist/features/paths/pathSnap/pathSnapSource.js +5 -5
- package/dist/features/paths/pathSnap/pathSnapSource.js.map +1 -1
- package/dist/features/paths/pathSnap/sceneIndex.js +10 -3
- package/dist/features/paths/pathSnap/sceneIndex.js.map +1 -1
- package/dist/features/selection/selectionPose.js +4 -1
- package/dist/features/selection/selectionPose.js.map +1 -1
- package/dist/features/snap/gather.js +9 -1
- package/dist/features/snap/gather.js.map +1 -1
- package/dist/features/snap/lazySession.js +17 -0
- package/dist/features/snap/lazySession.js.map +1 -0
- package/dist/features/snap/marks.js.map +1 -1
- package/dist/features/snap/probes2d.js +27 -19
- package/dist/features/snap/probes2d.js.map +1 -1
- package/dist/features/snap/readoutLayer.js.map +1 -1
- package/dist/features/snap/roles.js +2 -1
- package/dist/features/snap/roles.js.map +1 -1
- package/dist/features/snap/rotationSource.js +25 -8
- package/dist/features/snap/rotationSource.js.map +1 -1
- package/dist/features/snap/sceneSession2d.js +6 -4
- package/dist/features/snap/sceneSession2d.js.map +1 -1
- package/dist/features/snap/session2d.js +37 -23
- package/dist/features/snap/session2d.js.map +1 -1
- package/dist/features/snap/spanSnap.js +5 -2
- package/dist/features/snap/spanSnap.js.map +1 -1
- package/dist/features/text/sceneTextDrafts.js +65 -0
- package/dist/features/text/sceneTextDrafts.js.map +1 -0
- package/dist/features/text/textHitAt.js +31 -2
- package/dist/features/text/textHitAt.js.map +1 -1
- package/dist/features/text/useSceneTextEdit.js +22 -18
- package/dist/features/text/useSceneTextEdit.js.map +1 -1
- package/dist/features/viewports/aim.js +105 -0
- package/dist/features/viewports/aim.js.map +1 -0
- package/dist/features/viewports/viewMarker.js +82 -0
- package/dist/features/viewports/viewMarker.js.map +1 -0
- package/dist/features/viewports/viewMarkerDrag.js +55 -0
- package/dist/features/viewports/viewMarkerDrag.js.map +1 -0
- package/dist/icons.table.js +1 -1
- package/dist/icons.table.js.map +1 -1
- package/dist/icons.table.json +0 -10
- package/dist/index.d.ts +1198 -894
- package/dist/index.js +55 -38
- package/dist/interactions/actions/align/action.js +6 -4
- package/dist/interactions/actions/align/action.js.map +1 -1
- package/dist/interactions/actions/align/align.js.map +1 -1
- package/dist/interactions/actions/booleans/action.js +7 -1
- package/dist/interactions/actions/booleans/action.js.map +1 -1
- package/dist/interactions/actions/booleans/booleans.js +2 -1
- package/dist/interactions/actions/booleans/booleans.js.map +1 -1
- package/dist/interactions/actions/booleans/operands.js +6 -5
- package/dist/interactions/actions/booleans/operands.js.map +1 -1
- package/dist/interactions/actions/clipboard/action.js +27 -17
- package/dist/interactions/actions/clipboard/action.js.map +1 -1
- package/dist/interactions/actions/clone/action.js +1 -1
- package/dist/interactions/actions/clone/behaviors.js +4 -4
- package/dist/interactions/actions/clone/behaviors.js.map +1 -1
- package/dist/interactions/actions/defaults/anchorEditing.js +44 -23
- package/dist/interactions/actions/defaults/anchorEditing.js.map +1 -1
- package/dist/interactions/actions/defaults/anchorJoin.js +12 -6
- package/dist/interactions/actions/defaults/anchorJoin.js.map +1 -1
- package/dist/interactions/actions/defaults/bendSegment.js +8 -5
- package/dist/interactions/actions/defaults/bendSegment.js.map +1 -1
- package/dist/interactions/actions/defaults/cancelGesture.js +11 -8
- package/dist/interactions/actions/defaults/cancelGesture.js.map +1 -1
- package/dist/interactions/actions/defaults/contextMenu.js +17 -8
- package/dist/interactions/actions/defaults/contextMenu.js.map +1 -1
- package/dist/interactions/actions/defaults/createPaintAction.js +2 -2
- package/dist/interactions/actions/defaults/createPaintAction.js.map +1 -1
- package/dist/interactions/actions/defaults/delete.js +64 -41
- package/dist/interactions/actions/defaults/delete.js.map +1 -1
- package/dist/interactions/actions/defaults/duplicate.js +12 -9
- package/dist/interactions/actions/defaults/duplicate.js.map +1 -1
- package/dist/interactions/actions/defaults/enterPathEdit.js +19 -9
- package/dist/interactions/actions/defaults/enterPathEdit.js.map +1 -1
- package/dist/interactions/actions/defaults/escape.js +11 -8
- package/dist/interactions/actions/defaults/escape.js.map +1 -1
- package/dist/interactions/actions/defaults/exitPathEdit.js +7 -4
- package/dist/interactions/actions/defaults/exitPathEdit.js.map +1 -1
- package/dist/interactions/actions/defaults/group.js +21 -15
- package/dist/interactions/actions/defaults/group.js.map +1 -1
- package/dist/interactions/actions/defaults/ingest.js +17 -9
- package/dist/interactions/actions/defaults/ingest.js.map +1 -1
- package/dist/interactions/actions/defaults/insertPathAnchor.js +7 -4
- package/dist/interactions/actions/defaults/insertPathAnchor.js.map +1 -1
- package/dist/interactions/actions/defaults/nudge.js +21 -40
- package/dist/interactions/actions/defaults/nudge.js.map +1 -1
- package/dist/interactions/actions/defaults/pathEditTools.js +11 -8
- package/dist/interactions/actions/defaults/pathEditTools.js.map +1 -1
- package/dist/interactions/actions/defaults/pinchZoom.js +7 -4
- package/dist/interactions/actions/defaults/pinchZoom.js.map +1 -1
- package/dist/interactions/actions/defaults/reorder.js +24 -6
- package/dist/interactions/actions/defaults/reorder.js.map +1 -1
- package/dist/interactions/actions/defaults/selectAll.js +8 -5
- package/dist/interactions/actions/defaults/selectAll.js.map +1 -1
- package/dist/interactions/actions/defaults/setFill.js +7 -3
- package/dist/interactions/actions/defaults/setFill.js.map +1 -1
- package/dist/interactions/actions/defaults/setFillOpacity.js +1 -1
- package/dist/interactions/actions/defaults/setStroke.js +12 -11
- package/dist/interactions/actions/defaults/setStroke.js.map +1 -1
- package/dist/interactions/actions/defaults/setStrokeOpacity.js +1 -1
- package/dist/interactions/actions/defaults/toolActivate.js +7 -1
- package/dist/interactions/actions/defaults/toolActivate.js.map +1 -1
- package/dist/interactions/actions/defaults/toolResetToDefault.js +7 -4
- package/dist/interactions/actions/defaults/toolResetToDefault.js.map +1 -1
- package/dist/interactions/actions/defaults/undoRedo.js +19 -13
- package/dist/interactions/actions/defaults/undoRedo.js.map +1 -1
- package/dist/interactions/actions/defaults/viewportWheelPan.js +16 -7
- package/dist/interactions/actions/defaults/viewportWheelPan.js.map +1 -1
- package/dist/interactions/actions/defaults/viewportZoom.js +24 -6
- package/dist/interactions/actions/defaults/viewportZoom.js.map +1 -1
- package/dist/interactions/actions/distribute/action.js +6 -4
- package/dist/interactions/actions/distribute/action.js.map +1 -1
- package/dist/interactions/actions/drawnBoxes.js +2 -1
- package/dist/interactions/actions/drawnBoxes.js.map +1 -1
- package/dist/interactions/actions/edit-anchors/action.js +10 -10
- package/dist/interactions/actions/edit-anchors/action.js.map +1 -1
- package/dist/interactions/actions/edit-anchors/preview.js +41 -8
- package/dist/interactions/actions/edit-anchors/preview.js.map +1 -1
- package/dist/interactions/actions/flip/action.js +14 -6
- package/dist/interactions/actions/flip/action.js.map +1 -1
- package/dist/interactions/actions/gestureLifecycle.js +5 -2
- package/dist/interactions/actions/gestureLifecycle.js.map +1 -1
- package/dist/interactions/actions/insert/action.js +1 -2
- package/dist/interactions/actions/insert/action.js.map +1 -1
- package/dist/interactions/actions/insert/commit.js +1 -1
- package/dist/interactions/actions/insert/parent.js +11 -0
- package/dist/interactions/actions/insert/parent.js.map +1 -0
- package/dist/interactions/actions/insert/placeAction.js +7 -2
- package/dist/interactions/actions/insert/placeAction.js.map +1 -1
- package/dist/interactions/actions/insert/repositionAction.js +2 -1
- package/dist/interactions/actions/insert/repositionAction.js.map +1 -1
- package/dist/interactions/actions/insert/session.js +5 -1
- package/dist/interactions/actions/insert/session.js.map +1 -1
- package/dist/interactions/actions/move/action.js +15 -8
- package/dist/interactions/actions/move/action.js.map +1 -1
- package/dist/interactions/actions/move/behaviors/layoutDrop.js +0 -1
- package/dist/interactions/actions/move/behaviors/layoutDrop.js.map +1 -1
- package/dist/interactions/actions/move/behaviors/snapToContainer.js +1 -1
- package/dist/interactions/actions/move/capture.js +1 -1
- package/dist/interactions/actions/move/commit/index.js +0 -2
- package/dist/interactions/actions/move/commit/index.js.map +1 -1
- package/dist/interactions/actions/move/commit/layoutDrop.js +2 -2
- package/dist/interactions/actions/move/commit/layoutRelease.js +2 -2
- package/dist/interactions/actions/move/commit/reparent.js +11 -5
- package/dist/interactions/actions/move/commit/reparent.js.map +1 -1
- package/dist/interactions/actions/move/frame.js +4 -10
- package/dist/interactions/actions/move/frame.js.map +1 -1
- package/dist/interactions/actions/move/landedDescendants.js +20 -17
- package/dist/interactions/actions/move/landedDescendants.js.map +1 -1
- package/dist/interactions/actions/move/layout/container.js +2 -1
- package/dist/interactions/actions/move/layout/container.js.map +1 -1
- package/dist/interactions/actions/move/layout/dragged.js +1 -1
- package/dist/interactions/actions/move/layout/dropPass.js +18 -1
- package/dist/interactions/actions/move/layout/dropPass.js.map +1 -1
- package/dist/interactions/actions/move/layout/exits.js +5 -5
- package/dist/interactions/actions/move/layout/exits.js.map +1 -1
- package/dist/interactions/actions/move/session.js +14 -3
- package/dist/interactions/actions/move/session.js.map +1 -1
- package/dist/interactions/actions/move/translate.js +8 -37
- package/dist/interactions/actions/move/translate.js.map +1 -1
- package/dist/interactions/actions/moveNodes.js +87 -0
- package/dist/interactions/actions/moveNodes.js.map +1 -0
- package/dist/interactions/actions/outlines/createOutlinesAction.js +8 -5
- package/dist/interactions/actions/outlines/createOutlinesAction.js.map +1 -1
- package/dist/interactions/actions/outlines/outlineStroke.js +5 -3
- package/dist/interactions/actions/outlines/outlineStroke.js.map +1 -1
- package/dist/interactions/actions/pathCommands/cutJoin.js +8 -5
- package/dist/interactions/actions/pathCommands/cutJoin.js.map +1 -1
- package/dist/interactions/actions/planeInput.js.map +1 -1
- package/dist/interactions/actions/resize/action.js +83 -72
- package/dist/interactions/actions/resize/action.js.map +1 -1
- package/dist/interactions/actions/resize/commit.js +2 -1
- package/dist/interactions/actions/resize/commit.js.map +1 -1
- package/dist/interactions/actions/resize/cornerHandles.js +2 -1
- package/dist/interactions/actions/resize/cornerHandles.js.map +1 -1
- package/dist/interactions/actions/resize/session.js +2 -0
- package/dist/interactions/actions/resize/session.js.map +1 -1
- package/dist/interactions/actions/resolvePreviews.js +3 -3
- package/dist/interactions/actions/resolvePreviews.js.map +1 -1
- package/dist/interactions/actions/rotate/action.js +7 -4
- package/dist/interactions/actions/rotate/action.js.map +1 -1
- package/dist/interactions/actions/rotate/commit.js +2 -1
- package/dist/interactions/actions/rotate/commit.js.map +1 -1
- package/dist/interactions/actions/rotate/session.js +2 -0
- package/dist/interactions/actions/rotate/session.js.map +1 -1
- package/dist/interactions/actions/selectionSubtree.js +25 -9
- package/dist/interactions/actions/selectionSubtree.js.map +1 -1
- package/dist/interactions/actions/testUtils.js.map +1 -1
- package/dist/interactions/actions/transform-again/action.js +13 -11
- package/dist/interactions/actions/transform-again/action.js.map +1 -1
- package/dist/interactions/actions/transformFinish.js +106 -0
- package/dist/interactions/actions/transformFinish.js.map +1 -0
- package/dist/json.d.ts +4 -0
- package/dist/json.js +3 -0
- package/dist/kitSettingsSchema.js +8 -5
- package/dist/kitSettingsSchema.js.map +1 -1
- package/dist/{math-CrJULaZI.d.ts → math-B56zxVs5.d.ts} +10 -1
- package/dist/math.d.ts +1 -1
- package/dist/math.js +2 -1
- package/dist/move.d.ts +5 -4
- package/dist/{options-p9GZMXbY.d.ts → options-DBxEryYq.d.ts} +1 -1
- package/dist/resize.d.ts +4 -3
- package/dist/routing.d.ts +1 -1
- package/dist/routing.js +2 -2
- package/dist/test-hook/createTestHook.js +1 -1
- package/dist/test-hook/createTestHook.js.map +1 -1
- package/dist/test-hook/useTestHook.js +2 -1
- package/dist/test-hook/useTestHook.js.map +1 -1
- package/dist/test-seams.d.ts +9 -5
- package/dist/tools/builtin/ellipse/useEllipseTool.js +1 -0
- package/dist/tools/builtin/ellipse/useEllipseTool.js.map +1 -1
- package/dist/tools/builtin/eyedropper/useEyedropperTool.js +2 -1
- package/dist/tools/builtin/eyedropper/useEyedropperTool.js.map +1 -1
- package/dist/tools/builtin/hand/dragPanContribution.js +4 -1
- package/dist/tools/builtin/hand/dragPanContribution.js.map +1 -1
- package/dist/tools/builtin/hand/useHandTool.js +7 -4
- package/dist/tools/builtin/hand/useHandTool.js.map +1 -1
- package/dist/tools/builtin/image/useImageTool.js +1 -0
- package/dist/tools/builtin/image/useImageTool.js.map +1 -1
- package/dist/tools/builtin/lasso/useLassoTool.js +1 -0
- package/dist/tools/builtin/lasso/useLassoTool.js.map +1 -1
- package/dist/tools/builtin/line/useLineTool.js +1 -0
- package/dist/tools/builtin/line/useLineTool.js.map +1 -1
- package/dist/tools/builtin/measure/useMeasureTool.js +12 -5
- package/dist/tools/builtin/measure/useMeasureTool.js.map +1 -1
- package/dist/tools/builtin/pen/penHandle.js +3 -5
- package/dist/tools/builtin/pen/penHandle.js.map +1 -1
- package/dist/tools/builtin/pen/usePenTool.js +14 -6
- package/dist/tools/builtin/pen/usePenTool.js.map +1 -1
- package/dist/tools/builtin/pencil/usePencilTool.js +1 -0
- package/dist/tools/builtin/pencil/usePencilTool.js.map +1 -1
- package/dist/tools/builtin/polygon/usePolygonTool.js +13 -4
- package/dist/tools/builtin/polygon/usePolygonTool.js.map +1 -1
- package/dist/tools/builtin/rect/useRectTool.js +1 -0
- package/dist/tools/builtin/rect/useRectTool.js.map +1 -1
- package/dist/tools/builtin/select/adapterPointQuery.js +3 -2
- package/dist/tools/builtin/select/adapterPointQuery.js.map +1 -1
- package/dist/tools/builtin/select/pressDecision.js +32 -0
- package/dist/tools/builtin/select/pressDecision.js.map +1 -0
- package/dist/tools/builtin/select/selectionContributions.js +22 -13
- package/dist/tools/builtin/select/selectionContributions.js.map +1 -1
- package/dist/tools/builtin/select/useSelectTool.js +13 -10
- package/dist/tools/builtin/select/useSelectTool.js.map +1 -1
- package/dist/tools/builtin/slice/useSliceTool.js +22 -8
- package/dist/tools/builtin/slice/useSliceTool.js.map +1 -1
- package/dist/tools/builtin/star/useStarTool.js +13 -4
- package/dist/tools/builtin/star/useStarTool.js.map +1 -1
- package/dist/tools/builtin/sticky/stickyNode.js +4 -1
- package/dist/tools/builtin/sticky/stickyNode.js.map +1 -1
- package/dist/tools/builtin/sticky/useStickyTool.js +10 -5
- package/dist/tools/builtin/sticky/useStickyTool.js.map +1 -1
- package/dist/tools/builtin/text/useTextTool.js +3 -1
- package/dist/tools/builtin/text/useTextTool.js.map +1 -1
- package/dist/tools/index.js +26 -0
- package/dist/{types-CHVXGfYm.d.ts → types-7puAuVD2.d.ts} +3 -262
- package/dist/types-BN9hbdMI.d.ts +184 -0
- package/dist/types-CniVctmk.d.ts +949 -0
- package/dist/types-oFeQ5VjV.d.ts +264 -0
- package/dist/util/paint.js +1 -3
- package/dist/util/paint.js.map +1 -1
- package/dist/version.js +1 -1
- package/package.json +39 -25
- package/dist/canvas/SceneCanvas/useBuiltinRigTools.js +0 -65
- package/dist/canvas/SceneCanvas/useBuiltinRigTools.js.map +0 -1
- package/dist/tools/builtin/bone/boneActions.js +0 -156
- package/dist/tools/builtin/bone/boneActions.js.map +0 -1
- package/dist/tools/builtin/bone/boneOverlay.js +0 -71
- package/dist/tools/builtin/bone/boneOverlay.js.map +0 -1
- package/dist/tools/builtin/bone/placedRig.js +0 -28
- package/dist/tools/builtin/bone/placedRig.js.map +0 -1
- package/dist/tools/builtin/bone/rigEditState.js +0 -30
- package/dist/tools/builtin/bone/rigEditState.js.map +0 -1
- package/dist/tools/builtin/bone/useBoneTool.js +0 -125
- package/dist/tools/builtin/bone/useBoneTool.js.map +0 -1
- package/dist/tools/builtin/weight/useWeightTool.js +0 -101
- package/dist/tools/builtin/weight/useWeightTool.js.map +0 -1
- package/dist/tools/builtin/weight/weightActions.js +0 -140
- package/dist/tools/builtin/weight/weightActions.js.map +0 -1
- package/dist/tools/builtin/weight/weightOverlay.js +0 -78
- package/dist/tools/builtin/weight/weightOverlay.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.js","names":[],"sources":["../../../../src/interactions/actions/move/session.ts"],"sourcesContent":["import type { BindingOpts, InvocationCtx } from '@weasel-js/routing';\nimport { DRAG_THRESHOLD_PX, isPathEditPart, resolveParams } from '@weasel-js/routing';\nimport type { Op } from 'core/ops/types';\nimport type { NodeId, Scene } from 'core/scene/types';\nimport type { PoseDescriptor } from 'core/geometry/poseDescriptor';\nimport type { PoseComposition } from 'core/scene/composePose';\nimport { gestureReaders, type GestureReaders } from '../../gestures/shared/screenTolerance';\nimport type { GestureContext, MoveBehavior } from '../../gestures/types';\nimport type { LayoutDep, NodeAtPointDep } from '../depSchema';\nimport type { GeometryProjection } from '../geometryProjection';\nimport { commitGestureOps, readGestureLifecycle, type GestureLifecycle } from '../gestureLifecycle';\nimport { nodeDescriptors, poseDescriptorOf } from '../poseDescriptorDep';\nimport { moveSources } from '../selectionSubtree';\nimport { layoutDrop } from './behaviors/layoutDrop';\nimport { reparentOnDrop } from './behaviors/reparentOnDrop';\nimport { buildGestureContext, captureFrames, capturePlaneRefs, captureStartPoses } from './capture';\nimport { moveGestureAdapter, type MoveGestureAdapter } from './gestureAdapter';\nimport type { SnapSession } from '../snapDep';\n\n/** Allowed values for the `reparentOnDrop` binding param. `'off'` (the\n * default) preserves the legacy translate-only commit. `'top'` lands the\n * moved node at the top of the container under the cursor. `'above'`\n * lands it immediately above the hit sibling in z-order (falls back to\n * `'top'` semantics when the hit is itself a container or when the hit\n * and moved node share no parent). */\nexport type ReparentOnDrop = 'off' | 'top' | 'above';\n\n/** What a move captured at press. Nothing here changes during the drag. */\nexport interface MoveSession {\n readonly scene: Scene<unknown, string, unknown>;\n /** The drag roots. */\n readonly ids: readonly NodeId[];\n /** Descendants of the roots, previewed along with them. */\n readonly cascadeIds: readonly NodeId[];\n /** Start pose of every root and descendant. */\n readonly startPoses: ReadonlyMap<NodeId, unknown>;\n /** Ids whose frame is itself moving, so they ride it and are not translated. */\n readonly carried: ReadonlySet<NodeId>;\n /** For each moved id stored under a frame: its world pose and the frame's, at press. */\n readonly frames: ReadonlyMap<NodeId, { world: unknown; frameWorld: unknown }>;\n /** Ids grabbed mid-glide, with how far the pose shown stood from the document's. */\n readonly caught: ReadonlyMap<NodeId, { dx: number; dy: number }>;\n /** Per layer on another plane than the edited one: a point of its first root, in both. */\n readonly planeRefs: ReadonlyMap<string, { own: { x: number; y: number }; edited: { x: number; y: number } }>;\n readonly view: unknown;\n readonly projection: PoseDescriptor<unknown>;\n readonly descriptorOf: (id: NodeId | string) => PoseDescriptor<unknown>;\n readonly pc: PoseComposition<unknown>;\n /** The binding's behaviors, then the ones the action adds: a layout drop\n * when the `layout` dep is present, and reparent-on-drop. */\n readonly behaviors: readonly MoveBehavior<unknown>[];\n /** Reused across the drag; behaviors mutate its `scratch`. */\n readonly gestureCtx: GestureContext<unknown>;\n readonly adapter: MoveGestureAdapter<unknown>;\n readonly layout: LayoutDep | undefined;\n readonly applyOps?: (ops: Op[], label: string) => void;\n readonly geometryProjection?: GeometryProjection;\n readonly lifecycle: GestureLifecycle;\n readonly nodeAtPoint: NodeAtPointDep | undefined;\n /** Read at release: a binding's params may be a thunk. */\n readonly reparentOnDrop: () => ReparentOnDrop;\n readonly dragThresholdPx: number;\n /** The drag's snapping; null when the `snap` dep runs no sessions. */\n readonly snap: SnapSession | null;\n /** The press, in the coordinates the drag's delta is measured in. */\n readonly press: { x: number; y: number };\n}\n\n/** What one `onMove` produced. Replaced, not mutated, by the next. */\nexport interface MoveFrame {\n readonly delta: { dx: number; dy: number };\n /** Stored-frame pose of every displaced id, roots and descendants, and of\n * any other id a behavior posed. */\n readonly previews: Map<NodeId, unknown>;\n /** Ids the behaviors asked to have painted at full opacity. */\n readonly opaque: ReadonlySet<NodeId>;\n}\n\n/** What the behaviors the action builds itself read of the drag they belong\n * to. Neither is readable from `onStart`, which runs before the session\n * exists. */\nexport interface MoveGesture {\n session(): MoveSession;\n /** The latest frame: the previous one while an `onMove` is running. */\n frame(): MoveFrame;\n}\n\n/** Capture a drag at press. Null when there is nothing to move. Runs each\n * behavior's `onStart`. `frame` reads the drag's latest frame, for the\n * behaviors appended to the binding's own. */\nexport function beginMove(\n ctx: InvocationCtx,\n opts: BindingOpts | undefined,\n frame: () => MoveFrame,\n): { session: MoveSession; readers: GestureReaders } | null {\n const selection = ctx.deps.selection;\n const scene = ctx.deps.scene;\n const projection = poseDescriptorOf(ctx.deps.poseDescriptor);\n const layout = ctx.deps.layout;\n const applyOps = ctx.deps.applyOps;\n const geometryProjection = ctx.deps.geometryProjection;\n\n if (!selection || !scene) return null;\n const pc = scene.composition;\n // Anchors, segments, and balance grips sit on the selected body, and this binding ties the\n // path-edit drags' on specificity; with no mode registry to filter move out, declining is what\n // lets them through.\n if (isPathEditPart(ctx.drag?.affordance)) return null;\n\n const params = resolveParams(opts?.params);\n const expandIds = params?.['expandIds'] as ((ids: string[]) => string[]) | undefined;\n const selected = [...selection.get()] as string[];\n const ids = moveSources(scene, expandIds ? expandIds(selected) : selected) as NodeId[];\n if (ids.length === 0) return null;\n\n const reflow = layout?.reflow ?? null;\n const { startPoses, cascadeIds, caught } = captureStartPoses(scene, ids, reflow, projection);\n const { carried, frames } = captureFrames(scene, ids, startPoses);\n\n // Everything a move does beyond translating is a behavior: the binding's\n // own, then the layout drop, then reparent-on-drop. On release the first to\n // answer owns the commit, so each preempts the ones after it.\n const gesture: MoveGesture = { session: () => session, frame };\n const behaviors: MoveBehavior<unknown>[] = [\n ...((opts?.behaviors ?? []) as MoveBehavior<unknown>[]),\n ...(layout ? [layoutDrop(gesture)] : []),\n reparentOnDrop(gesture),\n ];\n const dragThresholdPx = (params?.['dragThresholdPx'] as number | undefined)\n ?? ctx.deps.kitSettings?.get('gestures.dragPx') ?? DRAG_THRESHOLD_PX;\n const lifecycle = readGestureLifecycle(params, 'Move', behaviors);\n // A behavior that commits after the gesture has ended, a coast coming to\n // rest, lands its batch the way the gesture's own commit does.\n const adapter = moveGestureAdapter<unknown>(scene, (ops, _label, through) =>\n commitGestureOps({ scene, applyOps, adapter: through }, lifecycle, ops), selection.adapterMethods);\n const readers = gestureReaders(ctx.deps);\n const gestureCtx = buildGestureContext(ctx, scene, ids, startPoses, adapter, readers);\n for (const b of behaviors) b.onStart?.(gestureCtx);\n\n const press = ctx.drag?.start ?? ctx.world;\n const session: MoveSession = {\n startPoses,\n ids,\n cascadeIds,\n carried,\n frames,\n scene,\n view: ctx.deps.view,\n planeRefs: capturePlaneRefs(scene, ids, ctx.deps.view, frames, startPoses, projection),\n caught,\n projection,\n descriptorOf: nodeDescriptors(scene, projection),\n behaviors,\n gestureCtx,\n adapter,\n layout,\n pc,\n applyOps,\n geometryProjection,\n lifecycle,\n nodeAtPoint: ctx.deps.nodeAtPoint,\n reparentOnDrop: () => (resolveParams(opts?.params)?.['reparentOnDrop'] as ReparentOnDrop | undefined) ?? 'off',\n dragThresholdPx,\n snap: ctx.deps.snap?.begin({ gesture: 'move', ids, press, constrain: 'axis' }) ?? null,\n press,\n };\n return { session, readers };\n}\n"],"mappings":";;;;;;;;;;;;;;AA0FA,SAAgB,UACd,KACA,MACA,OAC0D;CAC1D,MAAM,YAAY,IAAI,KAAK;CAC3B,MAAM,QAAQ,IAAI,KAAK;CACvB,MAAM,aAAa,iBAAiB,IAAI,KAAK,cAAc;CAC3D,MAAM,SAAS,IAAI,KAAK;CACxB,MAAM,WAAW,IAAI,KAAK;CAC1B,MAAM,qBAAqB,IAAI,KAAK;CAEpC,IAAI,CAAC,aAAa,CAAC,OAAO,OAAO;CACjC,MAAM,KAAK,MAAM;CAIjB,IAAI,eAAe,IAAI,MAAM,UAAU,GAAG,OAAO;CAEjD,MAAM,SAAS,cAAc,MAAM,MAAM;CACzC,MAAM,YAAY,SAAS;CAC3B,MAAM,WAAW,CAAC,GAAG,UAAU,IAAI,CAAC;CACpC,MAAM,MAAM,YAAY,OAAO,YAAY,UAAU,QAAQ,IAAI,QAAQ;CACzE,IAAI,IAAI,WAAW,GAAG,OAAO;CAE7B,MAAM,SAAS,QAAQ,UAAU;CACjC,MAAM,EAAE,YAAY,YAAY,WAAW,kBAAkB,OAAO,KAAK,QAAQ,UAAU;CAC3F,MAAM,EAAE,SAAS,WAAW,cAAc,OAAO,KAAK,UAAU;CAKhE,MAAM,UAAuB;EAAE,eAAe;EAAS;CAAM;CAC7D,MAAM,YAAqC;EACzC,GAAK,MAAM,aAAa,CAAC;EACzB,GAAI,SAAS,CAAC,WAAW,OAAO,CAAC,IAAI,CAAC;EACtC,eAAe,OAAO;CACxB;CACA,MAAM,kBAAmB,SAAS,sBAC7B,IAAI,KAAK,aAAa,IAAI,iBAAiB,KAAK;CACrD,MAAM,YAAY,qBAAqB,QAAQ,QAAQ,SAAS;CAGhE,MAAM,UAAU,mBAA4B,QAAQ,KAAK,QAAQ,YAC/D,iBAAiB;EAAE;EAAO;EAAU,SAAS;CAAQ,GAAG,WAAW,GAAG,GAAG,UAAU,cAAc;CACnG,MAAM,UAAU,eAAe,IAAI,IAAI;CACvC,MAAM,aAAa,oBAAoB,KAAK,OAAO,KAAK,YAAY,SAAS,OAAO;CACpF,KAAK,MAAM,KAAK,WAAW,EAAE,UAAU,UAAU;CAEjD,MAAM,QAAQ,IAAI,MAAM,SAAS,IAAI;CACrC,MAAM,UAAuB;EAC3B;EACA;EACA;EACA;EACA;EACA;EACA,MAAM,IAAI,KAAK;EACf,WAAW,iBAAiB,OAAO,KAAK,IAAI,KAAK,MAAM,QAAQ,YAAY,UAAU;EACrF;EACA;EACA,cAAc,gBAAgB,OAAO,UAAU;EAC/C;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,aAAa,IAAI,KAAK;EACtB,sBAAuB,cAAc,MAAM,MAAM,CAAC,GAAG,qBAAoD;EACzG;EACA,MAAM,IAAI,KAAK,MAAM,MAAM;GAAE,SAAS;GAAQ;GAAK;GAAO,WAAW;EAAO,CAAC,KAAK;EAClF;CACF;CACA,OAAO;EAAE;EAAS;CAAQ;AAC5B"}
|
|
1
|
+
{"version":3,"file":"session.js","names":[],"sources":["../../../../src/interactions/actions/move/session.ts"],"sourcesContent":["import type { BindingOpts, InvocationCtx } from '@weasel-js/routing';\nimport { DRAG_THRESHOLD_PX, isPathEditPart, resolveParams } from '@weasel-js/routing';\nimport type { Op } from 'core/ops/types';\nimport type { NodeId, Scene } from 'core/scene/types';\nimport type { PoseDescriptor } from 'core/geometry/poseDescriptor';\nimport type { PoseComposition } from 'core/scene/composePose';\nimport { gestureReaders, type GestureReaders } from '../../gestures/shared/screenTolerance';\nimport type { GestureContext, MoveBehavior } from '../../gestures/types';\nimport type { CanDropIntoDep, LayoutDep, NodeAtPointDep } from '../depSchema';\nimport type { GeometryProjection } from '../geometryProjection';\nimport { commitGestureOps, readGestureLifecycle, type GestureLifecycle } from '../gestureLifecycle';\nimport { transformFinisher, type TransformFinisher } from '../transformFinish';\nimport { nodeDescriptors, poseDescriptorOf } from '../poseDescriptorDep';\nimport { moveSources } from '../selectionSubtree';\nimport { layoutDrop } from './behaviors/layoutDrop';\nimport { reparentOnDrop } from './behaviors/reparentOnDrop';\nimport { buildGestureContext, captureFrames, capturePlaneRefs, captureStartPoses } from './capture';\nimport { moveGestureAdapter, type MoveGestureAdapter } from './gestureAdapter';\nimport type { SnapSession } from '../snapDep';\nimport { lazySnapSession } from 'features/snap/lazySession';\n\n/** Allowed values for the `reparentOnDrop` binding param. `'off'` (the\n * default) preserves the legacy translate-only commit. `'top'` lands the\n * moved node at the top of the container under the cursor. `'above'`\n * lands it immediately above the hit sibling in z-order (falls back to\n * `'top'` semantics when the hit is itself a container or when the hit\n * and moved node share no parent). */\nexport type ReparentOnDrop = 'off' | 'top' | 'above';\n\n/** What a move captured at press. Nothing here changes during the drag. */\nexport interface MoveSession {\n readonly scene: Scene<unknown, string, unknown>;\n /** The drag roots. */\n readonly ids: readonly NodeId[];\n /** Descendants of the roots, previewed along with them. */\n readonly cascadeIds: readonly NodeId[];\n /** Start pose of every root and descendant. */\n readonly startPoses: ReadonlyMap<NodeId, unknown>;\n /** Ids whose frame is itself moving, so they ride it and are not translated. */\n readonly carried: ReadonlySet<NodeId>;\n /** For each moved id stored under a frame: its world pose and the frame's, at press. */\n readonly frames: ReadonlyMap<NodeId, { world: unknown; frameWorld: unknown }>;\n /** Ids grabbed mid-glide, with how far the pose shown stood from the document's. */\n readonly caught: ReadonlyMap<NodeId, { dx: number; dy: number }>;\n /** Per layer on another plane than the edited one: a point of its first root, in both. */\n readonly planeRefs: ReadonlyMap<string, { own: { x: number; y: number }; edited: { x: number; y: number } }>;\n readonly view: unknown;\n readonly projection: PoseDescriptor<unknown>;\n readonly descriptorOf: (id: NodeId | string) => PoseDescriptor<unknown>;\n readonly pc: PoseComposition<unknown>;\n /** The binding's behaviors, then the ones the action adds: a layout drop\n * when the `layout` dep is present, and reparent-on-drop. */\n readonly behaviors: readonly MoveBehavior<unknown>[];\n /** Reused across the drag; behaviors mutate its `scratch`. */\n readonly gestureCtx: GestureContext<unknown>;\n readonly adapter: MoveGestureAdapter<unknown>;\n readonly layout: LayoutDep | undefined;\n readonly applyOps?: (ops: Op[], label: string) => void;\n /** Finishes the committed batch with the other nodes that change with it. */\n readonly finish?: TransformFinisher;\n readonly geometryProjection?: GeometryProjection;\n readonly lifecycle: GestureLifecycle;\n readonly nodeAtPoint: NodeAtPointDep | undefined;\n /** Whether a container admits the dragged roots; every one does when absent. */\n readonly admits: (parent: NodeId) => boolean;\n /** Read at release: a binding's params may be a thunk. */\n readonly reparentOnDrop: () => ReparentOnDrop;\n readonly dragThresholdPx: number;\n /** The drag's snapping, begun once the drag passes its threshold; null\n * with no `snap` dep. */\n readonly snap: SnapSession | null;\n /** The press, in the coordinates the drag's delta is measured in. */\n readonly press: { x: number; y: number };\n}\n\n/** What one `onMove` produced. Replaced, not mutated, by the next. */\nexport interface MoveFrame {\n readonly delta: { dx: number; dy: number };\n /** Stored-frame pose of every displaced id, roots and descendants, and of\n * any other id a behavior posed. */\n readonly previews: Map<NodeId, unknown>;\n /** Ids the behaviors asked to have painted at full opacity. */\n readonly opaque: ReadonlySet<NodeId>;\n}\n\n/** What the behaviors the action builds itself read of the drag they belong\n * to. Neither is readable from `onStart`, which runs before the session\n * exists. */\nexport interface MoveGesture {\n session(): MoveSession;\n /** The latest frame: the previous one while an `onMove` is running. */\n frame(): MoveFrame;\n}\n\nfunction admitsOf(\n canDropInto: CanDropIntoDep | undefined,\n ids: readonly NodeId[],\n): (parent: NodeId) => boolean {\n if (canDropInto === undefined) return () => true;\n const roots = ids as readonly string[];\n return (parent) => canDropInto(parent as string, roots);\n}\n\n/** Capture a drag at press. Null when there is nothing to move. Runs each\n * behavior's `onStart`. `frame` reads the drag's latest frame, for the\n * behaviors appended to the binding's own. */\nexport function beginMove(\n ctx: InvocationCtx,\n opts: BindingOpts | undefined,\n frame: () => MoveFrame,\n): { session: MoveSession; readers: GestureReaders } | null {\n const selection = ctx.deps.selection;\n const scene = ctx.deps.scene;\n const projection = poseDescriptorOf(ctx.deps.poseDescriptor);\n const layout = ctx.deps.layout;\n const applyOps = ctx.deps.applyOps;\n const geometryProjection = ctx.deps.geometryProjection;\n const finish = transformFinisher(ctx.deps);\n\n if (!selection || !scene) return null;\n const pc = scene.composition;\n // Anchors, segments, and balance grips sit on the selected body, and this binding ties the\n // path-edit drags' on specificity; with no mode registry to filter move out, declining is what\n // lets them through.\n if (isPathEditPart(ctx.drag?.affordance)) return null;\n\n const params = resolveParams(opts?.params);\n const expandIds = params?.['expandIds'] as ((ids: string[]) => string[]) | undefined;\n const selected = [...selection.get()] as string[];\n const ids = moveSources(scene, expandIds ? expandIds(selected) : selected) as NodeId[];\n if (ids.length === 0) return null;\n\n const reflow = layout?.reflow ?? null;\n const { startPoses, cascadeIds, caught } = captureStartPoses(scene, ids, reflow, projection);\n const { carried, frames } = captureFrames(scene, ids, startPoses);\n\n // Everything a move does beyond translating is a behavior: the binding's\n // own, then the layout drop, then reparent-on-drop. On release the first to\n // answer owns the commit, so each preempts the ones after it.\n const gesture: MoveGesture = { session: () => session, frame };\n const behaviors: MoveBehavior<unknown>[] = [\n ...((opts?.behaviors ?? []) as MoveBehavior<unknown>[]),\n ...(layout ? [layoutDrop(gesture)] : []),\n reparentOnDrop(gesture),\n ];\n const dragThresholdPx = (params?.['dragThresholdPx'] as number | undefined)\n ?? ctx.deps.kitSettings?.get('gestures.dragPx') ?? DRAG_THRESHOLD_PX;\n const lifecycle = readGestureLifecycle(params, 'Move', behaviors);\n // A behavior that commits after the gesture has ended, a coast coming to\n // rest, lands its batch the way the gesture's own commit does.\n const adapter = moveGestureAdapter<unknown>(scene, (ops, _label, through) =>\n commitGestureOps({ scene, applyOps, adapter: through, finish }, lifecycle, ops), selection.adapterMethods);\n const readers = gestureReaders(ctx.deps);\n const gestureCtx = buildGestureContext(ctx, scene, ids, startPoses, adapter, readers);\n for (const b of behaviors) b.onStart?.(gestureCtx);\n\n const press = ctx.drag?.start ?? ctx.world;\n const session: MoveSession = {\n startPoses,\n ids,\n cascadeIds,\n carried,\n frames,\n scene,\n view: ctx.deps.view,\n planeRefs: capturePlaneRefs(scene, ids, ctx.deps.view, frames, startPoses, projection),\n caught,\n projection,\n descriptorOf: nodeDescriptors(scene, projection),\n behaviors,\n gestureCtx,\n adapter,\n layout,\n pc,\n applyOps,\n finish,\n geometryProjection,\n lifecycle,\n nodeAtPoint: ctx.deps.nodeAtPoint,\n admits: admitsOf(ctx.deps.canDropInto, ids),\n reparentOnDrop: () => (resolveParams(opts?.params)?.['reparentOnDrop'] as ReparentOnDrop | undefined) ?? 'off',\n dragThresholdPx,\n snap: lazySnapSession(ctx.deps.snap, { gesture: 'move', ids, press, constrain: 'axis' }),\n press,\n };\n return { session, readers };\n}\n"],"mappings":";;;;;;;;;;;;;AA8FA,SAAS,SACP,aACA,KAC6B;CAC7B,IAAI,gBAAgB,QAAW,aAAa;CAC5C,MAAM,QAAQ;CACd,QAAQ,WAAW,YAAY,QAAkB,KAAK;AACxD;;;;AAKA,SAAgB,UACd,KACA,MACA,OAC0D;CAC1D,MAAM,YAAY,IAAI,KAAK;CAC3B,MAAM,QAAQ,IAAI,KAAK;CACvB,MAAM,aAAa,iBAAiB,IAAI,KAAK,cAAc;CAC3D,MAAM,SAAS,IAAI,KAAK;CACxB,MAAM,WAAW,IAAI,KAAK;CAC1B,MAAM,qBAAqB,IAAI,KAAK;CACpC,MAAM,SAAS,kBAAkB,IAAI,IAAI;CAEzC,IAAI,CAAC,aAAa,CAAC,OAAO,OAAO;CACjC,MAAM,KAAK,MAAM;CAIjB,IAAI,eAAe,IAAI,MAAM,UAAU,GAAG,OAAO;CAEjD,MAAM,SAAS,cAAc,MAAM,MAAM;CACzC,MAAM,YAAY,SAAS;CAC3B,MAAM,WAAW,CAAC,GAAG,UAAU,IAAI,CAAC;CACpC,MAAM,MAAM,YAAY,OAAO,YAAY,UAAU,QAAQ,IAAI,QAAQ;CACzE,IAAI,IAAI,WAAW,GAAG,OAAO;CAE7B,MAAM,SAAS,QAAQ,UAAU;CACjC,MAAM,EAAE,YAAY,YAAY,WAAW,kBAAkB,OAAO,KAAK,QAAQ,UAAU;CAC3F,MAAM,EAAE,SAAS,WAAW,cAAc,OAAO,KAAK,UAAU;CAKhE,MAAM,UAAuB;EAAE,eAAe;EAAS;CAAM;CAC7D,MAAM,YAAqC;EACzC,GAAK,MAAM,aAAa,CAAC;EACzB,GAAI,SAAS,CAAC,WAAW,OAAO,CAAC,IAAI,CAAC;EACtC,eAAe,OAAO;CACxB;CACA,MAAM,kBAAmB,SAAS,sBAC7B,IAAI,KAAK,aAAa,IAAI,iBAAiB,KAAK;CACrD,MAAM,YAAY,qBAAqB,QAAQ,QAAQ,SAAS;CAGhE,MAAM,UAAU,mBAA4B,QAAQ,KAAK,QAAQ,YAC/D,iBAAiB;EAAE;EAAO;EAAU,SAAS;EAAS;CAAO,GAAG,WAAW,GAAG,GAAG,UAAU,cAAc;CAC3G,MAAM,UAAU,eAAe,IAAI,IAAI;CACvC,MAAM,aAAa,oBAAoB,KAAK,OAAO,KAAK,YAAY,SAAS,OAAO;CACpF,KAAK,MAAM,KAAK,WAAW,EAAE,UAAU,UAAU;CAEjD,MAAM,QAAQ,IAAI,MAAM,SAAS,IAAI;CACrC,MAAM,UAAuB;EAC3B;EACA;EACA;EACA;EACA;EACA;EACA,MAAM,IAAI,KAAK;EACf,WAAW,iBAAiB,OAAO,KAAK,IAAI,KAAK,MAAM,QAAQ,YAAY,UAAU;EACrF;EACA;EACA,cAAc,gBAAgB,OAAO,UAAU;EAC/C;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,aAAa,IAAI,KAAK;EACtB,QAAQ,SAAS,IAAI,KAAK,aAAa,GAAG;EAC1C,sBAAuB,cAAc,MAAM,MAAM,CAAC,GAAG,qBAAoD;EACzG;EACA,MAAM,gBAAgB,IAAI,KAAK,MAAM;GAAE,SAAS;GAAQ;GAAK;GAAO,WAAW;EAAO,CAAC;EACvF;CACF;CACA,OAAO;EAAE;EAAS;CAAQ;AAC5B"}
|
|
@@ -1,48 +1,19 @@
|
|
|
1
|
-
import { translatePoseViaDescriptor } from "../../../core/geometry/poseDescriptor.js";
|
|
2
|
-
import { createTransformOp } from "../../../core/ops/transform.js";
|
|
3
1
|
import { localDelta } from "./delta.js";
|
|
4
|
-
import {
|
|
2
|
+
import { translateNodeOps } from "../moveNodes.js";
|
|
5
3
|
|
|
6
4
|
//#region src/interactions/actions/move/translate.ts
|
|
7
5
|
/** The default translate commit: one transform op per id, plus the data-held
|
|
8
6
|
* geometry op when the `geometryProjection` seam is wired. */
|
|
9
7
|
function translateOps(session, ids, delta) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
if (!session.startPoses.has(id) || session.carried.has(id)) continue;
|
|
13
|
-
const node = session.scene.get(id);
|
|
14
|
-
if (!node) continue;
|
|
8
|
+
return translateNodeOps(session.scene, ids, (id) => {
|
|
9
|
+
if (!session.startPoses.has(id) || session.carried.has(id)) return null;
|
|
15
10
|
const l = localDelta(session, id, delta.dx, delta.dy);
|
|
16
11
|
const c = session.caught.get(id);
|
|
17
|
-
|
|
18
|
-
l.dx
|
|
19
|
-
l.dy
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
1,
|
|
23
|
-
0,
|
|
24
|
-
0,
|
|
25
|
-
1,
|
|
26
|
-
l.dx,
|
|
27
|
-
l.dy
|
|
28
|
-
];
|
|
29
|
-
const authored = node.pose;
|
|
30
|
-
ops.push(createTransformOp({
|
|
31
|
-
id,
|
|
32
|
-
from: authored,
|
|
33
|
-
to: translatePoseViaDescriptor(authored, l.dx, l.dy, session.descriptorOf(id)),
|
|
34
|
-
label: session.lifecycle.label
|
|
35
|
-
}));
|
|
36
|
-
if (session.geometryProjection) {
|
|
37
|
-
const dataOp = geometryDataOp(session.geometryProjection, {
|
|
38
|
-
id,
|
|
39
|
-
data: node.data,
|
|
40
|
-
pose: authored
|
|
41
|
-
}, m, session.lifecycle.label);
|
|
42
|
-
if (dataOp) ops.push(dataOp);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
return ops;
|
|
12
|
+
return c ? {
|
|
13
|
+
dx: l.dx + c.dx,
|
|
14
|
+
dy: l.dy + c.dy
|
|
15
|
+
} : l;
|
|
16
|
+
}, session.descriptorOf, session.geometryProjection, session.lifecycle.label);
|
|
46
17
|
}
|
|
47
18
|
/** The default translate commit for the dragged roots among `roots` and the
|
|
48
19
|
* descendants that follow them. Anything else in `roots` is ignored. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"translate.js","names":[],"sources":["../../../../src/interactions/actions/move/translate.ts"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"file":"translate.js","names":[],"sources":["../../../../src/interactions/actions/move/translate.ts"],"sourcesContent":["import type { Op } from 'core/ops/types';\nimport type { NodeId } from 'core/scene/types';\nimport { translateNodeOps } from '../moveNodes';\nimport { localDelta } from './delta';\nimport type { MoveSession } from './session';\n\n/** The default translate commit: one transform op per id, plus the data-held\n * geometry op when the `geometryProjection` seam is wired. */\nexport function translateOps(session: MoveSession, ids: Iterable<NodeId>, delta: { dx: number; dy: number }): Op[] {\n return translateNodeOps(\n session.scene,\n ids,\n (id) => {\n if (!session.startPoses.has(id) || session.carried.has(id)) return null;\n const l = localDelta(session, id, delta.dx, delta.dy);\n const c = session.caught.get(id);\n return c ? { dx: l.dx + c.dx, dy: l.dy + c.dy } : l;\n },\n session.descriptorOf,\n session.geometryProjection,\n session.lifecycle.label,\n );\n}\n\n/** The default translate commit for the dragged roots among `roots` and the\n * descendants that follow them. Anything else in `roots` is ignored. */\nexport function rootTranslateOps(session: MoveSession, roots: Iterable<string>, delta: { dx: number; dy: number }): Op[] {\n const wanted = new Set<string>(roots);\n const others = new Set<NodeId>(session.ids.filter((id) => !wanted.has(id)));\n return translateOps(session, unreleasedIds(session, others), delta);\n}\n\n/** Selected roots no source layout claimed on release, plus the descendants\n * that follow them — the part of the selection the translate commit owns. */\nexport function unreleasedIds(session: MoveSession, released: Set<NodeId>): NodeId[] {\n const selected = new Set<NodeId>(session.ids);\n const out: NodeId[] = session.ids.filter((id) => !released.has(id));\n for (const id of session.cascadeIds) {\n let cur = session.scene.get(id)?.parent ?? null;\n let claimed = false;\n while (cur) {\n if (released.has(cur)) { claimed = true; break; }\n if (selected.has(cur)) break;\n cur = session.scene.get(cur)?.parent ?? null;\n }\n if (!claimed) out.push(id);\n }\n return out;\n}\n"],"mappings":";;;;;;AAQA,SAAgB,aAAa,SAAsB,KAAuB,OAAyC;CACjH,OAAO,iBACL,QAAQ,OACR,MACC,OAAO;EACN,IAAI,CAAC,QAAQ,WAAW,IAAI,EAAE,KAAK,QAAQ,QAAQ,IAAI,EAAE,GAAG,OAAO;EACnE,MAAM,IAAI,WAAW,SAAS,IAAI,MAAM,IAAI,MAAM,EAAE;EACpD,MAAM,IAAI,QAAQ,OAAO,IAAI,EAAE;EAC/B,OAAO,IAAI;GAAE,IAAI,EAAE,KAAK,EAAE;GAAI,IAAI,EAAE,KAAK,EAAE;EAAG,IAAI;CACpD,GACA,QAAQ,cACR,QAAQ,oBACR,QAAQ,UAAU,KACpB;AACF;;;AAIA,SAAgB,iBAAiB,SAAsB,OAAyB,OAAyC;CACvH,MAAM,SAAS,IAAI,IAAY,KAAK;CAEpC,OAAO,aAAa,SAAS,cAAc,SAAS,IADjC,IAAY,QAAQ,IAAI,QAAQ,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,CACrB,CAAM,GAAG,KAAK;AACpE;;;AAIA,SAAgB,cAAc,SAAsB,UAAiC;CACnF,MAAM,WAAW,IAAI,IAAY,QAAQ,GAAG;CAC5C,MAAM,MAAgB,QAAQ,IAAI,QAAQ,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC;CAClE,KAAK,MAAM,MAAM,QAAQ,YAAY;EACnC,IAAI,MAAM,QAAQ,MAAM,IAAI,EAAE,CAAC,EAAE,UAAU;EAC3C,IAAI,UAAU;EACd,OAAO,KAAK;GACV,IAAI,SAAS,IAAI,GAAG,GAAG;IAAE,UAAU;IAAM;GAAO;GAChD,IAAI,SAAS,IAAI,GAAG,GAAG;GACvB,MAAM,QAAQ,MAAM,IAAI,GAAG,CAAC,EAAE,UAAU;EAC1C;EACA,IAAI,CAAC,SAAS,IAAI,KAAK,EAAE;CAC3B;CACA,OAAO;AACT"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { translatePoseViaDescriptor } from "../../core/geometry/poseDescriptor.js";
|
|
2
|
+
import { scenePoseFrame } from "./poseFrame.js";
|
|
3
|
+
import { nodeDescriptors, poseDescriptorOf } from "./poseDescriptorDep.js";
|
|
4
|
+
import { commitTransformOps } from "./transformFinish.js";
|
|
5
|
+
import { createTransformOp } from "../../core/ops/transform.js";
|
|
6
|
+
import { moveSources, storedDelta, translateTargets } from "./selectionSubtree.js";
|
|
7
|
+
import { geometryDataOp } from "./geometryProjection.js";
|
|
8
|
+
|
|
9
|
+
//#region src/interactions/actions/moveNodes.ts
|
|
10
|
+
/** The deps {@link moveNodes} reads; an action calling it declares these. */
|
|
11
|
+
var MOVE_NODES_REQUIRES = [
|
|
12
|
+
"scene",
|
|
13
|
+
"selection",
|
|
14
|
+
"applyOps",
|
|
15
|
+
"poseDescriptor",
|
|
16
|
+
"geometryProjection",
|
|
17
|
+
"transformFollowers"
|
|
18
|
+
];
|
|
19
|
+
/**
|
|
20
|
+
* One transform op per id, translating its authored pose by the stored-frame
|
|
21
|
+
* delta `deltaOf` gives it, plus its data-held geometry's op when a
|
|
22
|
+
* `geometryProjection` is wired. An id `deltaOf` answers null for is skipped.
|
|
23
|
+
* Every translate commit — a drag, a nudge, {@link moveNodes} — builds its ops here.
|
|
24
|
+
*/
|
|
25
|
+
function translateNodeOps(scene, ids, deltaOf, descriptorOf, geometryProjection, label) {
|
|
26
|
+
const ops = [];
|
|
27
|
+
for (const id of ids) {
|
|
28
|
+
const node = scene.get(id);
|
|
29
|
+
if (!node) continue;
|
|
30
|
+
const l = deltaOf(id);
|
|
31
|
+
if (!l) continue;
|
|
32
|
+
const from = node.pose;
|
|
33
|
+
ops.push(createTransformOp({
|
|
34
|
+
id,
|
|
35
|
+
from,
|
|
36
|
+
to: translatePoseViaDescriptor(from, l.dx, l.dy, descriptorOf(id)),
|
|
37
|
+
label
|
|
38
|
+
}));
|
|
39
|
+
const m = [
|
|
40
|
+
1,
|
|
41
|
+
0,
|
|
42
|
+
0,
|
|
43
|
+
1,
|
|
44
|
+
l.dx,
|
|
45
|
+
l.dy
|
|
46
|
+
];
|
|
47
|
+
const dataOp = geometryDataOp(geometryProjection, {
|
|
48
|
+
id,
|
|
49
|
+
data: node.data,
|
|
50
|
+
pose: from
|
|
51
|
+
}, m, label);
|
|
52
|
+
if (dataOp) ops.push(dataOp);
|
|
53
|
+
}
|
|
54
|
+
return ops;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The ops that move `ids` by `delta` the way a drag of them commits: each id
|
|
58
|
+
* that is not itself derived (a derived one is moved through what it derives
|
|
59
|
+
* from) and every descendant not carried by a moving frame, each translated in
|
|
60
|
+
* the frame it is stored in. `delta` is in the coordinates a gesture's points
|
|
61
|
+
* are — world on a 2D canvas — and the `poseDescriptor` dep turns it into each
|
|
62
|
+
* pose's translation, so a 3D host's descriptor lands it on the node's plane.
|
|
63
|
+
*/
|
|
64
|
+
function moveNodesOps(scene, ids, delta, deps, label = "Move") {
|
|
65
|
+
const { dx, dy } = delta;
|
|
66
|
+
if (dx === 0 && dy === 0) return [];
|
|
67
|
+
const descriptorOf = nodeDescriptors(scene, poseDescriptorOf(deps?.poseDescriptor));
|
|
68
|
+
const frame = scenePoseFrame(scene);
|
|
69
|
+
return translateNodeOps(scene, translateTargets(scene, frame, moveSources(scene, ids)), (id) => storedDelta(frame, descriptorOf(id), id, dx, dy), descriptorOf, deps?.geometryProjection, label);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Move `ids` by `delta` the way a drag of them commits ({@link moveNodesOps}),
|
|
73
|
+
* finished by the `transformFollowers` and committed as one undo entry through
|
|
74
|
+
* `applyOps`, else the scene. Inside an open `scene.batch` it joins that
|
|
75
|
+
* batch's entry. Returns whether anything moved. A caller running as an
|
|
76
|
+
* action declares {@link MOVE_NODES_REQUIRES}.
|
|
77
|
+
*/
|
|
78
|
+
function moveNodes(deps, ids, delta, label = "Move") {
|
|
79
|
+
const scene = deps.scene;
|
|
80
|
+
if (!scene) return false;
|
|
81
|
+
const ops = moveNodesOps(scene, ids, delta, deps, label);
|
|
82
|
+
return ops.length > 0 && commitTransformOps(deps, ops, label);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
//#endregion
|
|
86
|
+
export { MOVE_NODES_REQUIRES, moveNodes, moveNodesOps, translateNodeOps };
|
|
87
|
+
//# sourceMappingURL=moveNodes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"moveNodes.js","names":[],"sources":["../../../src/interactions/actions/moveNodes.ts"],"sourcesContent":["import type { ActionDeps } from '@weasel-js/routing';\nimport type { Affine } from '@weasel-js/geom';\nimport { translatePoseViaDescriptor, type PoseDescriptor } from 'core/geometry/poseDescriptor';\nimport { createTransformOp } from 'core/ops/transform';\nimport type { Op } from 'core/ops/types';\nimport type { NodeId, Scene } from 'core/scene/types';\nimport { geometryDataOp, type GeometryProjection } from './geometryProjection';\nimport { nodeDescriptors, poseDescriptorOf } from './poseDescriptorDep';\nimport { scenePoseFrame } from './poseFrame';\nimport { moveSources, storedDelta, translateTargets } from './selectionSubtree';\nimport { commitTransformOps } from './transformFinish';\n\ntype AnyScene = Scene<unknown, string, unknown>;\n\n/** The deps {@link moveNodes} reads; an action calling it declares these. */\nexport const MOVE_NODES_REQUIRES = [\n 'scene', 'selection', 'applyOps', 'poseDescriptor', 'geometryProjection', 'transformFollowers',\n] as const;\n\n/**\n * One transform op per id, translating its authored pose by the stored-frame\n * delta `deltaOf` gives it, plus its data-held geometry's op when a\n * `geometryProjection` is wired. An id `deltaOf` answers null for is skipped.\n * Every translate commit — a drag, a nudge, {@link moveNodes} — builds its ops here.\n */\nexport function translateNodeOps(\n scene: AnyScene,\n ids: Iterable<NodeId>,\n deltaOf: (id: NodeId) => { dx: number; dy: number } | null,\n descriptorOf: (id: NodeId) => PoseDescriptor<unknown>,\n geometryProjection: GeometryProjection | undefined,\n label: string,\n): Op[] {\n const ops: Op[] = [];\n for (const id of ids) {\n const node = scene.get(id);\n if (!node) continue;\n const l = deltaOf(id);\n if (!l) continue;\n // The authored pose, not the effective one: a derived node's effective\n // pose is its derivation, and writing that back would lose the\n // placeholder undo restores.\n const from = node.pose;\n ops.push(createTransformOp<unknown>({\n id: id as string,\n from,\n to: translatePoseViaDescriptor(from, l.dx, l.dy, descriptorOf(id)),\n label,\n }));\n const m: Affine = [1, 0, 0, 1, l.dx, l.dy];\n const dataOp = geometryDataOp(geometryProjection, { id: id as string, data: node.data, pose: from }, m, label);\n if (dataOp) ops.push(dataOp);\n }\n return ops;\n}\n\n/**\n * The ops that move `ids` by `delta` the way a drag of them commits: each id\n * that is not itself derived (a derived one is moved through what it derives\n * from) and every descendant not carried by a moving frame, each translated in\n * the frame it is stored in. `delta` is in the coordinates a gesture's points\n * are — world on a 2D canvas — and the `poseDescriptor` dep turns it into each\n * pose's translation, so a 3D host's descriptor lands it on the node's plane.\n */\nexport function moveNodesOps(\n scene: AnyScene,\n ids: readonly string[],\n delta: { dx: number; dy: number },\n deps?: Pick<ActionDeps, 'poseDescriptor' | 'geometryProjection'>,\n label = 'Move',\n): Op[] {\n const { dx, dy } = delta;\n if (dx === 0 && dy === 0) return [];\n const descriptorOf = nodeDescriptors(scene, poseDescriptorOf(deps?.poseDescriptor));\n const frame = scenePoseFrame(scene);\n const targets = translateTargets(scene, frame, moveSources(scene, ids));\n return translateNodeOps(\n scene,\n targets,\n (id) => storedDelta(frame, descriptorOf(id), id, dx, dy),\n descriptorOf,\n deps?.geometryProjection,\n label,\n );\n}\n\n/**\n * Move `ids` by `delta` the way a drag of them commits ({@link moveNodesOps}),\n * finished by the `transformFollowers` and committed as one undo entry through\n * `applyOps`, else the scene. Inside an open `scene.batch` it joins that\n * batch's entry. Returns whether anything moved. A caller running as an\n * action declares {@link MOVE_NODES_REQUIRES}.\n */\nexport function moveNodes(\n deps: ActionDeps,\n ids: readonly string[],\n delta: { dx: number; dy: number },\n label = 'Move',\n): boolean {\n const scene = deps.scene as AnyScene | undefined;\n if (!scene) return false;\n const ops = moveNodesOps(scene, ids, delta, deps, label);\n return ops.length > 0 && commitTransformOps(deps, ops, label);\n}\n"],"mappings":";;;;;;;;;;AAeA,IAAa,sBAAsB;CACjC;CAAS;CAAa;CAAY;CAAkB;CAAsB;AAC5E;;;;;;;AAQA,SAAgB,iBACd,OACA,KACA,SACA,cACA,oBACA,OACM;CACN,MAAM,MAAY,CAAC;CACnB,KAAK,MAAM,MAAM,KAAK;EACpB,MAAM,OAAO,MAAM,IAAI,EAAE;EACzB,IAAI,CAAC,MAAM;EACX,MAAM,IAAI,QAAQ,EAAE;EACpB,IAAI,CAAC,GAAG;EAIR,MAAM,OAAO,KAAK;EAClB,IAAI,KAAK,kBAA2B;GAC9B;GACJ;GACA,IAAI,2BAA2B,MAAM,EAAE,IAAI,EAAE,IAAI,aAAa,EAAE,CAAC;GACjE;EACF,CAAC,CAAC;EACF,MAAM,IAAY;GAAC;GAAG;GAAG;GAAG;GAAG,EAAE;GAAI,EAAE;EAAE;EACzC,MAAM,SAAS,eAAe,oBAAoB;GAAM;GAAc,MAAM,KAAK;GAAM,MAAM;EAAK,GAAG,GAAG,KAAK;EAC7G,IAAI,QAAQ,IAAI,KAAK,MAAM;CAC7B;CACA,OAAO;AACT;;;;;;;;;AAUA,SAAgB,aACd,OACA,KACA,OACA,MACA,QAAQ,QACF;CACN,MAAM,EAAE,IAAI,OAAO;CACnB,IAAI,OAAO,KAAK,OAAO,GAAG,OAAO,CAAC;CAClC,MAAM,eAAe,gBAAgB,OAAO,iBAAiB,MAAM,cAAc,CAAC;CAClF,MAAM,QAAQ,eAAe,KAAK;CAElC,OAAO,iBACL,OAFc,iBAAiB,OAAO,OAAO,YAAY,OAAO,GAAG,CAGnE,IACC,OAAO,YAAY,OAAO,aAAa,EAAE,GAAG,IAAI,IAAI,EAAE,GACvD,cACA,MAAM,oBACN,KACF;AACF;;;;;;;;AASA,SAAgB,UACd,MACA,KACA,OACA,QAAQ,QACC;CACT,MAAM,QAAQ,KAAK;CACnB,IAAI,CAAC,OAAO,OAAO;CACnB,MAAM,MAAM,aAAa,OAAO,KAAK,OAAO,MAAM,KAAK;CACvD,OAAO,IAAI,SAAS,KAAK,mBAAmB,MAAM,KAAK,KAAK;AAC9D"}
|
|
@@ -36,11 +36,14 @@ var createOutlinesAction = {
|
|
|
36
36
|
label: "Create Outlines",
|
|
37
37
|
icon: /* @icon */ "core:createOutlines",
|
|
38
38
|
group: "text",
|
|
39
|
-
defaultBinding: {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
39
|
+
defaultBinding: [{
|
|
40
|
+
spec: {
|
|
41
|
+
kind: "key",
|
|
42
|
+
key: "Enter",
|
|
43
|
+
mods: { mod: true }
|
|
44
|
+
},
|
|
45
|
+
opts: { id: "createOutlines.key" }
|
|
46
|
+
}],
|
|
44
47
|
eligible: { capability: "creates-shapes" },
|
|
45
48
|
requires: ["selection", "createOutlinesAdapter"],
|
|
46
49
|
invoker: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createOutlinesAction.js","names":[],"sources":["../../../../src/interactions/actions/outlines/createOutlinesAction.tsx"],"sourcesContent":["import type { Action, ImmediateInvoker } from '@weasel-js/routing';\nimport { ActionDisabledReason } from '@weasel-js/routing';\nimport type { NodeId } from 'core/scene/types';\nimport { loadTextOutlines, type TextNodeSource, type TextOutlinesError } from '@weasel-js/text';\nimport {\n applyCreateOutlines, type CreateOutlinesAdapter, type CreateOutlinesResult,\n} from './createOutlines';\nimport { icon } from '../../../icons.gen';\n\n/** What an outline conversion answers when a text face had no outlines. */\ntype OutlinesFailure = { kind: 'failed'; error: TextOutlinesError };\n\n/**\n * Run `apply`, an outline conversion of `adapter`'s selection, waiting first\n * for any face whose outlines are registered but not yet loaded — a face is\n * parsed on first use, so the first conversion in a session would otherwise\n * fail. Warns under `tag` with the reason when the selection still cannot be\n * converted.\n */\nexport async function withTextOutlines<R extends { kind: string } | OutlinesFailure>(\n adapter: CreateOutlinesAdapter,\n apply: () => R,\n tag: string,\n): Promise<R> {\n const failure = (r: R): TextOutlinesError | null => (r.kind === 'failed' ? (r as OutlinesFailure).error : null);\n let result = apply();\n if (failure(result)?.reason === 'outlines-loading') {\n const texts = [...adapter.getSelection()]\n .map((id) => adapter.getTextSource(id as NodeId))\n .filter((t): t is TextNodeSource => t !== undefined);\n await Promise.all(texts.map((t) => loadTextOutlines(t.data)));\n result = apply();\n }\n const error = failure(result);\n if (error) console.warn(`[${tag}] ${error.message}`);\n return result;\n}\n\n/** {@link applyCreateOutlines} through {@link withTextOutlines}. */\nexport function runCreateOutlines(adapter: CreateOutlinesAdapter): Promise<CreateOutlinesResult> {\n return withTextOutlines(adapter, () => applyCreateOutlines(adapter), 'createOutlines');\n}\n\n/**\n * Static descriptor for Create Outlines: replace the selected\n * text nodes with path nodes carrying their glyph outlines. Reads the\n * `createOutlinesAdapter` dep, published with `useCreateOutlinesAdapter`.\n */\nexport const createOutlinesAction: Action = {\n id: 'createOutlines',\n label: 'Create Outlines',\n icon: icon('createOutlines'),\n group: 'text',\n // Affinity's Convert to Curves; Illustrator's Mod+Shift+O is Chrome's bookmark manager.\n defaultBinding: { kind: 'key', key: 'Enter', mods: { mod: true } },\n eligible: { capability: 'creates-shapes' },\n requires: ['selection', 'createOutlinesAdapter'],\n invoker: {\n timing: 'immediate',\n run: (deps) => {\n const adapter = deps.createOutlinesAdapter;\n if (adapter) void runCreateOutlines(adapter);\n },\n } satisfies ImmediateInvoker,\n enabled: (deps) => {\n const ids = deps?.selection?.get() ?? [];\n if (ids.length === 0) return ActionDisabledReason.SelectionRequired;\n const adapter = deps?.createOutlinesAdapter;\n return adapter && ids.some((id) => adapter.getTextSource(id) !== undefined)\n ? true\n : ActionDisabledReason.NotApplicable;\n },\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"createOutlinesAction.js","names":[],"sources":["../../../../src/interactions/actions/outlines/createOutlinesAction.tsx"],"sourcesContent":["import type { Action, ImmediateInvoker } from '@weasel-js/routing';\nimport { ActionDisabledReason } from '@weasel-js/routing';\nimport type { NodeId } from 'core/scene/types';\nimport { loadTextOutlines, type TextNodeSource, type TextOutlinesError } from '@weasel-js/text';\nimport {\n applyCreateOutlines, type CreateOutlinesAdapter, type CreateOutlinesResult,\n} from './createOutlines';\nimport { icon } from '../../../icons.gen';\n\n/** What an outline conversion answers when a text face had no outlines. */\ntype OutlinesFailure = { kind: 'failed'; error: TextOutlinesError };\n\n/**\n * Run `apply`, an outline conversion of `adapter`'s selection, waiting first\n * for any face whose outlines are registered but not yet loaded — a face is\n * parsed on first use, so the first conversion in a session would otherwise\n * fail. Warns under `tag` with the reason when the selection still cannot be\n * converted.\n */\nexport async function withTextOutlines<R extends { kind: string } | OutlinesFailure>(\n adapter: CreateOutlinesAdapter,\n apply: () => R,\n tag: string,\n): Promise<R> {\n const failure = (r: R): TextOutlinesError | null => (r.kind === 'failed' ? (r as OutlinesFailure).error : null);\n let result = apply();\n if (failure(result)?.reason === 'outlines-loading') {\n const texts = [...adapter.getSelection()]\n .map((id) => adapter.getTextSource(id as NodeId))\n .filter((t): t is TextNodeSource => t !== undefined);\n await Promise.all(texts.map((t) => loadTextOutlines(t.data)));\n result = apply();\n }\n const error = failure(result);\n if (error) console.warn(`[${tag}] ${error.message}`);\n return result;\n}\n\n/** {@link applyCreateOutlines} through {@link withTextOutlines}. */\nexport function runCreateOutlines(adapter: CreateOutlinesAdapter): Promise<CreateOutlinesResult> {\n return withTextOutlines(adapter, () => applyCreateOutlines(adapter), 'createOutlines');\n}\n\n/**\n * Static descriptor for Create Outlines: replace the selected\n * text nodes with path nodes carrying their glyph outlines. Reads the\n * `createOutlinesAdapter` dep, published with `useCreateOutlinesAdapter`.\n */\nexport const createOutlinesAction: Action = {\n id: 'createOutlines',\n label: 'Create Outlines',\n icon: icon('createOutlines'),\n group: 'text',\n // Affinity's Convert to Curves; Illustrator's Mod+Shift+O is Chrome's bookmark manager.\n defaultBinding: [{ spec: { kind: 'key', key: 'Enter', mods: { mod: true } }, opts: { id: 'createOutlines.key' } }],\n eligible: { capability: 'creates-shapes' },\n requires: ['selection', 'createOutlinesAdapter'],\n invoker: {\n timing: 'immediate',\n run: (deps) => {\n const adapter = deps.createOutlinesAdapter;\n if (adapter) void runCreateOutlines(adapter);\n },\n } satisfies ImmediateInvoker,\n enabled: (deps) => {\n const ids = deps?.selection?.get() ?? [];\n if (ids.length === 0) return ActionDisabledReason.SelectionRequired;\n const adapter = deps?.createOutlinesAdapter;\n return adapter && ids.some((id) => adapter.getTextSource(id) !== undefined)\n ? true\n : ActionDisabledReason.NotApplicable;\n },\n};\n"],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { strokeRegion } from "./strokeRegion.js";
|
|
2
2
|
import { replaceWithPaths } from "./replaceWithPaths.js";
|
|
3
|
+
import { resolveFill, resolveStroke } from "@weasel-js/paint";
|
|
3
4
|
import { TextOutlinesError, textToPathsByPaint } from "@weasel-js/text";
|
|
4
5
|
|
|
5
6
|
//#region src/interactions/actions/outlines/outlineStroke.ts
|
|
@@ -44,7 +45,8 @@ function applyOutlineStroke(adapter, opts = {}) {
|
|
|
44
45
|
const paths = [];
|
|
45
46
|
let outlined = false;
|
|
46
47
|
for (const { path, fill, stroke } of paintedPaths(adapter, id)) {
|
|
47
|
-
const
|
|
48
|
+
const painted = resolveStroke(stroke);
|
|
49
|
+
const outline = painted === null ? null : strokeRegion(path, painted, frame, opts);
|
|
48
50
|
if (!outline || outline.commands.length === 0) {
|
|
49
51
|
paths.push(stroke ? {
|
|
50
52
|
path,
|
|
@@ -57,13 +59,13 @@ function applyOutlineStroke(adapter, opts = {}) {
|
|
|
57
59
|
continue;
|
|
58
60
|
}
|
|
59
61
|
outlined = true;
|
|
60
|
-
if (fill !== null) paths.push({
|
|
62
|
+
if (resolveFill(fill) !== null) paths.push({
|
|
61
63
|
path,
|
|
62
64
|
fill
|
|
63
65
|
});
|
|
64
66
|
paths.push({
|
|
65
67
|
path: outline,
|
|
66
|
-
fill: { paint:
|
|
68
|
+
fill: { paint: painted.paint }
|
|
67
69
|
});
|
|
68
70
|
}
|
|
69
71
|
if (outlined) converted.push({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"outlineStroke.js","names":[],"sources":["../../../../src/interactions/actions/outlines/outlineStroke.ts"],"sourcesContent":["/**\n * Outline Stroke: replace each selected stroked path, or stroked text, with\n * the region its stroke covers, as a path filled in the stroke's paint. A node\n * that is also filled keeps its fill as a path of its own underneath. One\n * undoable batch; the replacement takes the node's slot.\n */\nimport { textToPathsByPaint, TextOutlinesError, type TextNodeSource } from '@weasel-js/text';\nimport type { NodeId } from 'core/scene/types';\nimport type { CreateOutlinesAdapter } from './createOutlines';\nimport { replaceWithPaths, type PaintedPath } from './replaceWithPaths';\nimport { strokeRegion, type StrokeRegionOptions } from './strokeRegion';\n\n/** Outcome of {@link applyOutlineStroke}. */\nexport type OutlineStrokeResult =\n /** `resultIds` are what replaced the stroked nodes at their level — a\n * path, a container, or a run of flat paths each — and are now selected in\n * their place. */\n | { kind: 'applied'; resultIds: string[] }\n /** Nothing selected is a path or text with a stroke that has width. */\n | { kind: 'noop'; reason: 'no-stroke' }\n /** Some selected stroked text has no outline geometry; nothing was changed. */\n | { kind: 'failed'; reason: 'text-outlines'; error: TextOutlinesError };\n\n/** Whether a text node wears a stroke anywhere: its own, or a run's. */\nexport function textIsStroked(text: TextNodeSource | undefined): boolean {\n return text != null && (text.data.stroke != null || !!text.data.runs?.some((r) => r.stroke != null));\n}\n\n/** What the adapter knows of `id` as painted world paths: a path node's one,\n * or a text node's glyphs by paint. Throws as `textToPathsByPaint` does. */\nfunction paintedPaths(adapter: CreateOutlinesAdapter, id: NodeId): PaintedPath[] {\n const path = adapter.getWorldPath?.(id);\n if (path) {\n const paint = adapter.getPaint?.(id);\n return paint ? [{ path, ...paint }] : [];\n }\n const text = adapter.getTextSource(id);\n // Text with no stroke stays text: its outlines are not read, so a face\n // without them fails only the text this would convert.\n if (!text || !textIsStroked(text)) return [];\n return textToPathsByPaint(text.data, text.pose);\n}\n\n/**\n * Outline the stroke of every stroked path and stroked text in the selection,\n * as one batch labeled \"Outline Stroke\". Other selected nodes are left alone\n * and stay selected. Each stroke is outlined in the frame it is drawn in: see\n * {@link strokeRegion}. All or nothing: if a stroked text's face cannot\n * supply outlines the scene is untouched and the error comes back.\n */\nexport function applyOutlineStroke(\n adapter: CreateOutlinesAdapter,\n opts: StrokeRegionOptions = {},\n): OutlineStrokeResult {\n const sel = [...adapter.getSelection()] as NodeId[];\n const converted: { id: NodeId; paths: PaintedPath[] }[] = [];\n try {\n for (const id of sel) {\n const frame = adapter.getStrokeFrame?.(id);\n const paths: PaintedPath[] = [];\n let outlined = false;\n for (const { path, fill, stroke } of paintedPaths(adapter, id)) {\n const
|
|
1
|
+
{"version":3,"file":"outlineStroke.js","names":[],"sources":["../../../../src/interactions/actions/outlines/outlineStroke.ts"],"sourcesContent":["/**\n * Outline Stroke: replace each selected stroked path, or stroked text, with\n * the region its stroke covers, as a path filled in the stroke's paint. A node\n * that is also filled keeps its fill as a path of its own underneath. One\n * undoable batch; the replacement takes the node's slot.\n */\nimport { textToPathsByPaint, TextOutlinesError, type TextNodeSource } from '@weasel-js/text';\nimport { resolveFill, resolveStroke } from '@weasel-js/paint';\nimport type { NodeId } from 'core/scene/types';\nimport type { CreateOutlinesAdapter } from './createOutlines';\nimport { replaceWithPaths, type PaintedPath } from './replaceWithPaths';\nimport { strokeRegion, type StrokeRegionOptions } from './strokeRegion';\n\n/** Outcome of {@link applyOutlineStroke}. */\nexport type OutlineStrokeResult =\n /** `resultIds` are what replaced the stroked nodes at their level — a\n * path, a container, or a run of flat paths each — and are now selected in\n * their place. */\n | { kind: 'applied'; resultIds: string[] }\n /** Nothing selected is a path or text with a stroke that has width. */\n | { kind: 'noop'; reason: 'no-stroke' }\n /** Some selected stroked text has no outline geometry; nothing was changed. */\n | { kind: 'failed'; reason: 'text-outlines'; error: TextOutlinesError };\n\n/** Whether a text node wears a stroke anywhere: its own, or a run's. */\nexport function textIsStroked(text: TextNodeSource | undefined): boolean {\n return text != null && (text.data.stroke != null || !!text.data.runs?.some((r) => r.stroke != null));\n}\n\n/** What the adapter knows of `id` as painted world paths: a path node's one,\n * or a text node's glyphs by paint. Throws as `textToPathsByPaint` does. */\nfunction paintedPaths(adapter: CreateOutlinesAdapter, id: NodeId): PaintedPath[] {\n const path = adapter.getWorldPath?.(id);\n if (path) {\n const paint = adapter.getPaint?.(id);\n return paint ? [{ path, ...paint }] : [];\n }\n const text = adapter.getTextSource(id);\n // Text with no stroke stays text: its outlines are not read, so a face\n // without them fails only the text this would convert.\n if (!text || !textIsStroked(text)) return [];\n return textToPathsByPaint(text.data, text.pose);\n}\n\n/**\n * Outline the stroke of every stroked path and stroked text in the selection,\n * as one batch labeled \"Outline Stroke\". Other selected nodes are left alone\n * and stay selected. Each stroke is outlined in the frame it is drawn in: see\n * {@link strokeRegion}. All or nothing: if a stroked text's face cannot\n * supply outlines the scene is untouched and the error comes back.\n */\nexport function applyOutlineStroke(\n adapter: CreateOutlinesAdapter,\n opts: StrokeRegionOptions = {},\n): OutlineStrokeResult {\n const sel = [...adapter.getSelection()] as NodeId[];\n const converted: { id: NodeId; paths: PaintedPath[] }[] = [];\n try {\n for (const id of sel) {\n const frame = adapter.getStrokeFrame?.(id);\n const paths: PaintedPath[] = [];\n let outlined = false;\n for (const { path, fill, stroke } of paintedPaths(adapter, id)) {\n const painted = resolveStroke(stroke);\n const outline = painted === null ? null : strokeRegion(path, painted, frame, opts);\n if (!outline || outline.commands.length === 0) {\n paths.push(stroke ? { path, fill, stroke } : { path, fill });\n continue;\n }\n outlined = true;\n if (resolveFill(fill) !== null) paths.push({ path, fill });\n paths.push({ path: outline, fill: { paint: painted!.paint } });\n }\n if (outlined) converted.push({ id, paths });\n }\n } catch (err) {\n if (err instanceof TextOutlinesError) return { kind: 'failed', reason: 'text-outlines', error: err };\n throw err;\n }\n if (converted.length === 0) return { kind: 'noop', reason: 'no-stroke' };\n const replaced = replaceWithPaths(adapter, sel, converted, 'Outline Stroke');\n return { kind: 'applied', resultIds: converted.flatMap((c) => replaced.get(c.id)!) };\n}\n"],"mappings":";;;;;;;;;;;;;AAyBA,SAAgB,cAAc,MAA2C;CACvE,OAAO,QAAQ,SAAS,KAAK,KAAK,UAAU,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM,MAAM,MAAM,EAAE,UAAU,IAAI;AACpG;;;AAIA,SAAS,aAAa,SAAgC,IAA2B;CAC/E,MAAM,OAAO,QAAQ,eAAe,EAAE;CACtC,IAAI,MAAM;EACR,MAAM,QAAQ,QAAQ,WAAW,EAAE;EACnC,OAAO,QAAQ,CAAC;GAAE;GAAM,GAAG;EAAM,CAAC,IAAI,CAAC;CACzC;CACA,MAAM,OAAO,QAAQ,cAAc,EAAE;CAGrC,IAAI,CAAC,QAAQ,CAAC,cAAc,IAAI,GAAG,OAAO,CAAC;CAC3C,OAAO,mBAAmB,KAAK,MAAM,KAAK,IAAI;AAChD;;;;;;;;AASA,SAAgB,mBACd,SACA,OAA4B,CAAC,GACR;CACrB,MAAM,MAAM,CAAC,GAAG,QAAQ,aAAa,CAAC;CACtC,MAAM,YAAoD,CAAC;CAC3D,IAAI;EACF,KAAK,MAAM,MAAM,KAAK;GACpB,MAAM,QAAQ,QAAQ,iBAAiB,EAAE;GACzC,MAAM,QAAuB,CAAC;GAC9B,IAAI,WAAW;GACf,KAAK,MAAM,EAAE,MAAM,MAAM,YAAY,aAAa,SAAS,EAAE,GAAG;IAC9D,MAAM,UAAU,cAAc,MAAM;IACpC,MAAM,UAAU,YAAY,OAAO,OAAO,aAAa,MAAM,SAAS,OAAO,IAAI;IACjF,IAAI,CAAC,WAAW,QAAQ,SAAS,WAAW,GAAG;KAC7C,MAAM,KAAK,SAAS;MAAE;MAAM;MAAM;KAAO,IAAI;MAAE;MAAM;KAAK,CAAC;KAC3D;IACF;IACA,WAAW;IACX,IAAI,YAAY,IAAI,MAAM,MAAM,MAAM,KAAK;KAAE;KAAM;IAAK,CAAC;IACzD,MAAM,KAAK;KAAE,MAAM;KAAS,MAAM,EAAE,OAAO,QAAS,MAAM;IAAE,CAAC;GAC/D;GACA,IAAI,UAAU,UAAU,KAAK;IAAE;IAAI;GAAM,CAAC;EAC5C;CACF,SAAS,KAAK;EACZ,IAAI,eAAe,mBAAmB,OAAO;GAAE,MAAM;GAAU,QAAQ;GAAiB,OAAO;EAAI;EACnG,MAAM;CACR;CACA,IAAI,UAAU,WAAW,GAAG,OAAO;EAAE,MAAM;EAAQ,QAAQ;CAAY;CACvE,MAAM,WAAW,iBAAiB,SAAS,KAAK,WAAW,gBAAgB;CAC3E,OAAO;EAAE,MAAM;EAAW,WAAW,UAAU,SAAS,MAAM,SAAS,IAAI,EAAE,EAAE,CAAE;CAAE;AACrF"}
|
|
@@ -137,11 +137,14 @@ var joinPathsAction = joinPathsCommand({
|
|
|
137
137
|
id: "joinPaths",
|
|
138
138
|
label: "Join",
|
|
139
139
|
icon: /* @icon */ "core:join",
|
|
140
|
-
defaultBinding: {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
140
|
+
defaultBinding: [{
|
|
141
|
+
spec: {
|
|
142
|
+
kind: "key",
|
|
143
|
+
key: "j",
|
|
144
|
+
mods: { mod: true }
|
|
145
|
+
},
|
|
146
|
+
opts: { id: "joinPaths.key" }
|
|
147
|
+
}]
|
|
145
148
|
}, () => ({}));
|
|
146
149
|
|
|
147
150
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cutJoin.js","names":[],"sources":["../../../../src/interactions/actions/pathCommands/cutJoin.ts"],"sourcesContent":["/**\n * Cut at Crossings and Join: the path commands that change how many paths\n * there are. Join spans a gap straight; `joinPathsCommand` builds a join that\n * spans it some other way.\n */\nimport type { Action, ActionDeps, ImmediateInvoker } from '@weasel-js/routing';\nimport { ActionDisabledReason } from '@weasel-js/routing';\nimport {\n anchorsToPath, closestOpenEnds, joinSubpathEnds, pathToAnchors, type AnchorSet, type JoinOptions,\n type PolygonPath,\n} from '@weasel-js/geom';\nimport { snipPathsAtCrossings } from '@weasel-js/geom/booleans';\nimport type { Op } from 'core/ops/types';\nimport {\n deleteNode, insertAt, pathCopy, reshapeOps, selectedPathNodes, slotOf, type PathNode,\n} from './pathNodes';\nimport { commitOps } from '../defaultCommitAdapter';\nimport { pathOperationTags } from '../pathGestureTags';\nimport { icon } from '../../../icons.gen';\n\nconst CUT_LABEL = 'Cut at Crossings';\n\n/**\n * Cut every selected path wherever another selected path\n * crosses it (`snipPathsAtCrossings`): each cut path is replaced, in its\n * slot, by its pieces, which take its paint, and the pieces are selected.\n */\nexport const snipAtCrossingsAction: Action & { requires: string[] } = {\n id: 'snipAtCrossings',\n label: CUT_LABEL,\n icon: icon('cutAtCrossings'),\n group: 'path',\n tags: pathOperationTags('command'),\n eligible: { capability: 'creates-shapes' },\n requires: ['selection', 'scene', 'applyOps'],\n invoker: {\n timing: 'immediate',\n run: (deps) => {\n const scene = deps.scene;\n const nodes = selectedPathNodes(deps);\n if (!scene || nodes.length < 2) return;\n const pieces = snipPathsAtCrossings(nodes.map((n) => n.path));\n const cut = nodes\n .map((node, i) => ({ node, pieces: pieces[i], at: slotOf(scene, node.id) }))\n .filter((c): c is { node: PathNode; pieces: PolygonPath[]; at: number } => c.pieces !== null)\n .sort((a, b) => b.at - a.at);\n if (cut.length === 0) return;\n const ops: Op[] = [];\n const made = new Map<string, string[]>();\n for (const { node, pieces: runs, at } of cut) {\n ops.push(deleteNode(scene, node.node, CUT_LABEL));\n const copies = runs.flatMap((p) => pathCopy(scene, node.node, p) ?? []);\n copies.forEach((copy, k) => ops.push(insertAt(copy, at < 0 ? at : at + k, CUT_LABEL)));\n made.set(node.id, copies.map((c) => c.id));\n }\n commitOps(deps, ops, CUT_LABEL);\n const selected = deps.selection?.get() ?? [];\n deps.selection?.set(selected.flatMap((id) => made.get(id) ?? [id]) as never);\n },\n } satisfies ImmediateInvoker,\n enabled: (deps) => (selectedPathNodes(deps).length >= 2 ? true : ActionDisabledReason.SelectionRequired),\n};\n\n/** What a join would do to the selection, or null when it cannot. */\nexport interface JoinPlan {\n keep: PathNode;\n drop: PathNode | null;\n path: PolygonPath;\n}\n\n/**\n * One selected path: close its one open subpath, or join the two nearest\n * ends of its open subpaths. Two: join the nearest pair of open ends, one on\n * each, into the first selected, which takes in the second's other subpaths.\n * `options` says how ends apart are spanned (`joinSubpathEnds`).\n */\nexport function planJoin(nodes: readonly PathNode[], options: JoinOptions = {}): JoinPlan | null {\n if (nodes.length === 0 || nodes.length > 2) return null;\n const [keep, drop = null] = nodes;\n const a = pathToAnchors(keep.path) as AnchorSet;\n const set: AnchorSet = drop\n ? (() => {\n const b = pathToAnchors(drop.path);\n return { anchors: [...a.anchors, ...b.anchors], closed: [...a.closed, ...b.closed] };\n })()\n : a;\n const fromKeep = a.anchors.length;\n const open = set.anchors.flatMap((sub, s) => (!set.closed[s] && sub.length >= 2 ? [s] : []));\n let joined: boolean;\n if (!drop && open.length === 1) {\n joined = joinSubpathEnds(set, { sub: open[0], end: 'first' }, { sub: open[0], end: 'last' }, options);\n } else {\n const ends = closestOpenEnds(set, (p, q) => !drop || (p.sub < fromKeep) !== (q.sub < fromKeep));\n joined = ends !== null && joinSubpathEnds(set, ends[0], ends[1], options);\n }\n if (!joined) return null;\n return { keep, drop, path: anchorsToPath(set.anchors, set.closed, keep.path) };\n}\n\n\n/** A command joining the selected paths by {@link planJoin} as one undo step,\n * spanning gaps as `options` reads from its params. Disabled in path edit,\n * where joins act on the selected anchors. */\nexport function joinPathsCommand(\n base: Pick<Action, 'id' | 'label' | 'icon' | 'defaultBinding'>,\n options: (params: Record<string, unknown> | undefined) => JoinOptions,\n): Action & { requires: string[] } {\n const plan = (deps: ActionDeps | undefined, params?: Record<string, unknown>) => planJoin(selectedPathNodes(deps), options(params));\n return {\n ...base,\n group: 'path',\n tags: pathOperationTags('command'),\n eligible: { capability: 'creates-shapes' },\n requires: ['selection', 'scene', 'applyOps', 'editAnchors'],\n invoker: {\n timing: 'immediate',\n run: (deps, params) => {\n const scene = deps.scene;\n if (deps.editAnchors?.editingId) return;\n const made = plan(deps, params);\n if (!scene || !made) return;\n const ops = reshapeOps(made.keep.node, made.path, base.label);\n if (made.drop) ops.push(deleteNode(scene, made.drop.node, base.label));\n commitOps(deps, ops, base.label);\n deps.selection?.set([made.keep.id] as never);\n },\n } satisfies ImmediateInvoker,\n enabled: (deps?: ActionDeps) => {\n // In path edit these are the selected anchors' commands.\n if (deps?.editAnchors?.editingId) return ActionDisabledReason.NotApplicable;\n if (selectedPathNodes(deps).length === 0) return ActionDisabledReason.SelectionRequired;\n return plan(deps) ? true : ActionDisabledReason.NotApplicable;\n },\n };\n}\n\n/**\n * Join open paths: close a selected path's open end to its\n * start, or connect two selected paths at their nearest open ends into one\n * (`planJoin`). Ends that meet merge into one anchor; ends apart are bridged\n * straight. In path edit, `joinAnchors` joins the two selected anchors\n * instead.\n */\nexport const joinPathsAction = joinPathsCommand(\n { id: 'joinPaths', label: 'Join', icon: icon('join'), defaultBinding: { kind: 'key', key: 'j', mods: { mod: true } } },\n () => ({}),\n);\n\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cutJoin.js","names":[],"sources":["../../../../src/interactions/actions/pathCommands/cutJoin.ts"],"sourcesContent":["/**\n * Cut at Crossings and Join: the path commands that change how many paths\n * there are. Join spans a gap straight; `joinPathsCommand` builds a join that\n * spans it some other way.\n */\nimport type { Action, ActionDeps, ImmediateInvoker } from '@weasel-js/routing';\nimport { ActionDisabledReason } from '@weasel-js/routing';\nimport {\n anchorsToPath, closestOpenEnds, joinSubpathEnds, pathToAnchors, type AnchorSet, type JoinOptions,\n type PolygonPath,\n} from '@weasel-js/geom';\nimport { snipPathsAtCrossings } from '@weasel-js/geom/booleans';\nimport type { Op } from 'core/ops/types';\nimport {\n deleteNode, insertAt, pathCopy, reshapeOps, selectedPathNodes, slotOf, type PathNode,\n} from './pathNodes';\nimport { commitOps } from '../defaultCommitAdapter';\nimport { pathOperationTags } from '../pathGestureTags';\nimport { icon } from '../../../icons.gen';\n\nconst CUT_LABEL = 'Cut at Crossings';\n\n/**\n * Cut every selected path wherever another selected path\n * crosses it (`snipPathsAtCrossings`): each cut path is replaced, in its\n * slot, by its pieces, which take its paint, and the pieces are selected.\n */\nexport const snipAtCrossingsAction: Action & { requires: string[] } = {\n id: 'snipAtCrossings',\n label: CUT_LABEL,\n icon: icon('cutAtCrossings'),\n group: 'path',\n tags: pathOperationTags('command'),\n eligible: { capability: 'creates-shapes' },\n requires: ['selection', 'scene', 'applyOps'],\n invoker: {\n timing: 'immediate',\n run: (deps) => {\n const scene = deps.scene;\n const nodes = selectedPathNodes(deps);\n if (!scene || nodes.length < 2) return;\n const pieces = snipPathsAtCrossings(nodes.map((n) => n.path));\n const cut = nodes\n .map((node, i) => ({ node, pieces: pieces[i], at: slotOf(scene, node.id) }))\n .filter((c): c is { node: PathNode; pieces: PolygonPath[]; at: number } => c.pieces !== null)\n .sort((a, b) => b.at - a.at);\n if (cut.length === 0) return;\n const ops: Op[] = [];\n const made = new Map<string, string[]>();\n for (const { node, pieces: runs, at } of cut) {\n ops.push(deleteNode(scene, node.node, CUT_LABEL));\n const copies = runs.flatMap((p) => pathCopy(scene, node.node, p) ?? []);\n copies.forEach((copy, k) => ops.push(insertAt(copy, at < 0 ? at : at + k, CUT_LABEL)));\n made.set(node.id, copies.map((c) => c.id));\n }\n commitOps(deps, ops, CUT_LABEL);\n const selected = deps.selection?.get() ?? [];\n deps.selection?.set(selected.flatMap((id) => made.get(id) ?? [id]) as never);\n },\n } satisfies ImmediateInvoker,\n enabled: (deps) => (selectedPathNodes(deps).length >= 2 ? true : ActionDisabledReason.SelectionRequired),\n};\n\n/** What a join would do to the selection, or null when it cannot. */\nexport interface JoinPlan {\n keep: PathNode;\n drop: PathNode | null;\n path: PolygonPath;\n}\n\n/**\n * One selected path: close its one open subpath, or join the two nearest\n * ends of its open subpaths. Two: join the nearest pair of open ends, one on\n * each, into the first selected, which takes in the second's other subpaths.\n * `options` says how ends apart are spanned (`joinSubpathEnds`).\n */\nexport function planJoin(nodes: readonly PathNode[], options: JoinOptions = {}): JoinPlan | null {\n if (nodes.length === 0 || nodes.length > 2) return null;\n const [keep, drop = null] = nodes;\n const a = pathToAnchors(keep.path) as AnchorSet;\n const set: AnchorSet = drop\n ? (() => {\n const b = pathToAnchors(drop.path);\n return { anchors: [...a.anchors, ...b.anchors], closed: [...a.closed, ...b.closed] };\n })()\n : a;\n const fromKeep = a.anchors.length;\n const open = set.anchors.flatMap((sub, s) => (!set.closed[s] && sub.length >= 2 ? [s] : []));\n let joined: boolean;\n if (!drop && open.length === 1) {\n joined = joinSubpathEnds(set, { sub: open[0], end: 'first' }, { sub: open[0], end: 'last' }, options);\n } else {\n const ends = closestOpenEnds(set, (p, q) => !drop || (p.sub < fromKeep) !== (q.sub < fromKeep));\n joined = ends !== null && joinSubpathEnds(set, ends[0], ends[1], options);\n }\n if (!joined) return null;\n return { keep, drop, path: anchorsToPath(set.anchors, set.closed, keep.path) };\n}\n\n\n/** A command joining the selected paths by {@link planJoin} as one undo step,\n * spanning gaps as `options` reads from its params. Disabled in path edit,\n * where joins act on the selected anchors. */\nexport function joinPathsCommand(\n base: Pick<Action, 'id' | 'label' | 'icon' | 'defaultBinding'>,\n options: (params: Record<string, unknown> | undefined) => JoinOptions,\n): Action & { requires: string[] } {\n const plan = (deps: ActionDeps | undefined, params?: Record<string, unknown>) => planJoin(selectedPathNodes(deps), options(params));\n return {\n ...base,\n group: 'path',\n tags: pathOperationTags('command'),\n eligible: { capability: 'creates-shapes' },\n requires: ['selection', 'scene', 'applyOps', 'editAnchors'],\n invoker: {\n timing: 'immediate',\n run: (deps, params) => {\n const scene = deps.scene;\n if (deps.editAnchors?.editingId) return;\n const made = plan(deps, params);\n if (!scene || !made) return;\n const ops = reshapeOps(made.keep.node, made.path, base.label);\n if (made.drop) ops.push(deleteNode(scene, made.drop.node, base.label));\n commitOps(deps, ops, base.label);\n deps.selection?.set([made.keep.id] as never);\n },\n } satisfies ImmediateInvoker,\n enabled: (deps?: ActionDeps) => {\n // In path edit these are the selected anchors' commands.\n if (deps?.editAnchors?.editingId) return ActionDisabledReason.NotApplicable;\n if (selectedPathNodes(deps).length === 0) return ActionDisabledReason.SelectionRequired;\n return plan(deps) ? true : ActionDisabledReason.NotApplicable;\n },\n };\n}\n\n/**\n * Join open paths: close a selected path's open end to its\n * start, or connect two selected paths at their nearest open ends into one\n * (`planJoin`). Ends that meet merge into one anchor; ends apart are bridged\n * straight. In path edit, `joinAnchors` joins the two selected anchors\n * instead.\n */\nexport const joinPathsAction = joinPathsCommand(\n { id: 'joinPaths', label: 'Join', icon: icon('join'), defaultBinding: [{ spec: { kind: 'key', key: 'j', mods: { mod: true } }, opts: { id: 'joinPaths.key' } }] },\n () => ({}),\n);\n\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"planeInput.js","names":[],"sources":["../../../src/interactions/actions/planeInput.ts"],"sourcesContent":["/**\n * Editing a node on a parallax plane.\n *\n * The dispatcher hands every action the camera's world. A node on a layer\n * carrying `parallax` stores its pose in its plane's world, which the camera's\n * reaches through a `PlaneMap` that changes with the camera. An editing action\n * pairs the pointer with the pose it edits, so the two have to be in one world.\n *\n * `inPlane` wraps an action so its input is carried into the plane of the\n * layer it edits before the action reads it, and the chrome it publishes back\n * comes out in the camera's world. A dep that answers in world points\n * (`nodeAtPoint`, `snap`) keeps speaking the camera's world, and the seam\n * converts at its boundary.\n *\n * A selection can span planes. The edit is measured in one of them, and a\n * node on another is carried into it as the gesture starts and back out\n * through `planeOf` as it is now.\n *\n * The map is read afresh on every call: a camera panning under a held drag, or\n * a plane whose factors are being animated, moves the node with the pointer.\n */\nimport type {\n Action, ActionDeps, AffordanceHit, BindingOpts, DragSample, InvocationCtx, OngoingHandle,\n OngoingOverlay,\n} from '@weasel-js/routing';\nimport type { Scene } from 'core/scene/types';\nimport { asNodeId } from 'core/scene/types';\nimport {\n deriveParallaxView, fromPlane, planeMap, planeToPlane, rectFromPlane, rectToPlane, toPlane,\n type ParallaxOpts, type PlaneMap,\n} from 'core/viewport/parallax';\nimport type { View } from 'core/viewport/view';\nimport type { PoseDescriptor } from 'core/geometry/poseDescriptor';\nimport type { NodeAtPointDep, SnapDep, ViewApi } from './depSchema';\nimport type { SnapBegin } from './snapDep';\n\ntype Point = { x: number; y: number };\n\n/** Which scene layer an invocation edits, read once as it starts. `undefined`\n * means none: the action runs in the camera's world. */\nexport type EditedLayerOf = (deps: ActionDeps, affordance?: AffordanceHit) => string | undefined;\n\nconst layerOfNode = (deps: ActionDeps, id: string | null | undefined): string | undefined =>\n (id ? deps.scene?.get(asNodeId(id))?.layer : undefined);\n\n/** The layer of the node a selection edit acts on: the affordance's target\n * when the drag grabbed one, the first selected node otherwise. A selection\n * spanning planes is edited in that one node's plane. */\nexport const selectionLayer: EditedLayerOf = (deps, affordance) => {\n const selection = deps.selection;\n for (const id of [...(affordance?.targetIds ?? []), ...(selection?.get() ?? [])]) {\n const layer = layerOfNode(deps, id);\n if (layer !== undefined) return layer;\n }\n return undefined;\n};\n\n/** The layer the `insert` dep will put a new node on. */\nexport const insertLayer: EditedLayerOf = (deps) =>\n deps.insert?.layer?.();\n\n/** The layer of the path in anchor-edit mode. */\nexport const editingLayer: EditedLayerOf = (deps) =>\n layerOfNode(deps, deps.editAnchors?.editingId);\n\n/** How the world an invocation edits in maps into the world `layer`'s nodes\n * are stored in, read now. Null when they are the same world. */\nexport function planeOf(view: unknown, layer: string): PlaneMap | null {\n return (view as ViewApi | undefined)?.planeOf?.(layer) ?? null;\n}\n\n/** `m` run backwards; null stays null. */\nexport function invertPlane(m: PlaneMap | null): PlaneMap | null {\n return m && planeToPlane(m, null);\n}\n\n/** `pose` carried through `m`. The map is axis-aligned, so remapping the\n * pose's bounds carries it exactly when the map scales both axes alike. */\nexport function carryPose<P>(d: PoseDescriptor<P>, pose: P, m: PlaneMap | null): P {\n if (m === null) return pose;\n const b = d.getBounds(pose);\n return d.remapBounds(pose, b, rectToPlane(m, b));\n}\n\n/** `action`, with its input carried into the plane of the layer `layerOf`\n * names. An action in a scene with no `parallax` layer, or invoked with no\n * scene or view to read a plane from, runs exactly as it would unwrapped.\n *\n * An immediate action's world point is `params.worldX` / `params.worldY`,\n * the dispatcher's convention for a click; it is carried when present. */\nexport function inPlane<A extends Action>(action: A, layerOf: EditedLayerOf): A {\n const inner = action.invoker;\n if (!inner) return action;\n const declared = action.requires ?? [];\n const requires = [...new Set([...declared, 'scene', 'selection', 'view'])];\n if (inner.timing === 'immediate') {\n return {\n ...action,\n requires,\n invoker: {\n timing: 'immediate',\n run(deps: ActionDeps, params?: Record<string, unknown>): void {\n const plane = livePlane(deps, layerOf(deps), declared, null);\n if (plane === null) return inner.run(deps, params);\n const wx = params?.['worldX'];\n const wy = params?.['worldY'];\n const at = typeof wx === 'number' && typeof wy === 'number'\n ? toPlane(plane.map(), { x: wx, y: wy })\n : null;\n inner.run(plane.deps, at ? { ...params, worldX: at.x, worldY: at.y } : params);\n },\n },\n } as A;\n }\n return {\n ...action,\n requires,\n invoker: {\n timing: 'ongoing',\n start(ctx: InvocationCtx, opts?: BindingOpts): OngoingHandle {\n const plane = livePlane(\n ctx.deps, layerOf(ctx.deps, ctx.drag?.affordance), declared, ctx.drag?.start ?? null,\n );\n if (plane === null) return inner.start(ctx, opts);\n return planeHandle(inner.start(plane.carry(ctx), opts), plane);\n },\n },\n } as A;\n}\n\ninterface LivePlane {\n map(): PlaneMap;\n /** The invocation's deps, speaking the plane's world. */\n deps: ActionDeps;\n /** `ctx` in the plane's world. */\n carry(ctx: InvocationCtx): InvocationCtx;\n}\n\nfunction livePlane(\n bag: ActionDeps,\n layer: string | undefined,\n /** What the wrapped action declared. The dispatcher's dev deps bag throws\n * on any other read, so the seam converts only the deps it can see. */\n declared: readonly string[],\n /** The drag's press point in the camera's world, when there is a drag. */\n pressedAt: Point | null,\n): LivePlane | null {\n const scene = bag.scene as Scene<unknown, string, unknown> | undefined;\n const viewApi = bag.view as ViewApi | undefined;\n if (layer === undefined || !scene || !viewApi) return null;\n if (!scene.layers.some((l) => l.parallax !== undefined)) return null;\n const parallaxOf = (id: string): ParallaxOpts | undefined => scene.layers.find((l) => l.id === id)?.parallax;\n const parallax = (): ParallaxOpts | undefined => parallaxOf(layer);\n\n const IDENTITY: PlaneMap = { scale: { x: 1, y: 1 }, offset: { x: 0, y: 0 } };\n const map = (): PlaneMap => {\n const p = parallax();\n return p ? planeMap(viewApi.get(), p) : IDENTITY;\n };\n\n // A screen-pixel tolerance, and anything else an action reads off the\n // camera, has to be read at the plane's scale.\n const planeView = Object.defineProperties(Object.create(viewApi), {\n get: {\n value: (): View => {\n const p = parallax();\n const camera = viewApi.get();\n return p ? deriveParallaxView(camera, p) : camera;\n },\n },\n plane: { value: map },\n planeOf: {\n value: (id: string): PlaneMap | null => {\n const edited = parallax();\n const own = parallaxOf(id);\n const camera = viewApi.get();\n return planeToPlane(edited ? planeMap(camera, edited) : null, own ? planeMap(camera, own) : null);\n },\n },\n }) as ViewApi;\n\n // Over the dispatcher's bag rather than a copy of it, so every other read\n // still goes through whatever checks the bag makes.\n const deps = Object.create(bag) as typeof bag;\n const override = (name: string, value: unknown) =>\n Object.defineProperty(deps, name, { value, enumerable: true });\n override('view', planeView);\n const nodeAtPoint = declared.includes('nodeAtPoint')\n ? bag.nodeAtPoint as NodeAtPointDep | undefined\n : undefined;\n if (nodeAtPoint) {\n override('nodeAtPoint', ((p, exclude) => nodeAtPoint(fromPlane(map(), p), exclude)) as NodeAtPointDep);\n }\n const snap = declared.includes('snap') ? bag.snap as SnapDep | undefined : undefined;\n if (snap) {\n // A session runs in the plane, and carries the camera's targets into it.\n override('snap', { begin: (req: SnapBegin) => snap.begin({ ...req, plane: map }) } satisfies SnapDep);\n }\n\n // The drag's origin, fixed in the plane at the moment it was pressed,\n // whatever the camera does after.\n const start0 = pressedAt ? toPlane(map(), pressedAt) : null;\n const trail = trailCarrier();\n\n return {\n map,\n deps,\n carry(c) {\n const m = map();\n const out: InvocationCtx = { ...c, world: toPlane(m, c.world) };\n if (c.drag) {\n const start = start0 ?? toPlane(m, c.drag.start);\n const current = toPlane(m, c.drag.current);\n const aff = c.drag.affordance;\n out.drag = {\n ...c.drag,\n start,\n current,\n delta: { x: current.x - start.x, y: current.y - start.y },\n ...(c.drag.points ? { points: trail(c.drag.points, m) } : {}),\n ...(aff?.fixedPoint ? { affordance: { ...aff, fixedPoint: toPlane(m, aff.fixedPoint) } } : {}),\n };\n }\n // The dispatcher hands `onMove` no deps; only `start` has any to carry.\n if (c.deps) out.deps = deps;\n return out;\n },\n };\n}\n\n/** The drag trail in the plane. The dispatcher grows its trail in place, so\n * only the samples added since the last call are mapped — unless the map\n * moved, when every sample is. */\nfunction trailCarrier(): (points: DragSample[], m: PlaneMap) => DragSample[] {\n let src: DragSample[] | null = null;\n let lastMap: PlaneMap | null = null;\n let out: DragSample[] = [];\n return (points, m) => {\n const same = lastMap !== null\n && lastMap.scale.x === m.scale.x && lastMap.scale.y === m.scale.y\n && lastMap.offset.x === m.offset.x && lastMap.offset.y === m.offset.y;\n if (points !== src || !same || points.length < out.length) {\n src = points;\n out = [];\n }\n lastMap = m;\n for (let i = out.length; i < points.length; i++) {\n out.push({ ...points[i], ...toPlane(m, points[i]) });\n }\n // A copy, so a snapshot taken on `onEnd` is not the live accumulator.\n return out.slice();\n };\n}\n\nfunction planeHandle(handle: OngoingHandle, plane: LivePlane): OngoingHandle {\n const out: OngoingHandle = { ...handle };\n if (handle.onMove) out.onMove = (c) => handle.onMove!(plane.carry(c));\n if (handle.onEnd) out.onEnd = (c, reason) => handle.onEnd!(plane.carry(c), reason);\n if (handle.onWheel) out.onWheel = (c) => handle.onWheel!(plane.carry(c));\n if (handle.overlay) {\n out.overlay = () => {\n const ov = handle.overlay!();\n if (!ov) return ov;\n const m = plane.map();\n return Array.isArray(ov)\n ? (ov as readonly OngoingOverlay[]).map((o) => overlayFromPlane(o, m))\n : overlayFromPlane(ov as OngoingOverlay, m);\n };\n }\n return out;\n}\n\n/** An overlay drawn in the plane, in the camera's world: what every painter\n * reads an overlay as. */\nfunction overlayFromPlane(ov: OngoingOverlay, m: PlaneMap): OngoingOverlay {\n const pt = (p: Point) => fromPlane(m, p);\n switch (ov.kind) {\n case 'marquee':\n return { ...ov, start: pt(ov.start), current: pt(ov.current) };\n case 'lasso':\n return { ...ov, vertices: ov.vertices.map(pt), current: pt(ov.current) };\n case 'polyline':\n case 'brush':\n return { ...ov, points: ov.points.map(pt) };\n case 'insertPreview':\n return {\n ...ov,\n bounds: rectFromPlane(m, ov.bounds),\n extras: insertExtrasFromPlane(ov.extras, m),\n ...(ov.anchorPoint ? { anchorPoint: pt(ov.anchorPoint) } : {}),\n };\n }\n}\n\n/** The geometry the kit's insert kinds carry in `extras`, in the camera's\n * world. A consumer kind's extras are opaque, and pass through. */\nfunction insertExtrasFromPlane(extras: unknown, m: PlaneMap): unknown {\n if (extras === null || typeof extras !== 'object') return extras;\n const e = extras as Record<string, unknown>;\n const pt = (p: unknown) => fromPlane(m, p as Point);\n // Radial kinds inscribe in a square, so one scale carries a radius.\n const r = (v: unknown) => (typeof v === 'number' ? v / ((m.scale.x + m.scale.y) / 2) : v);\n const out: Record<string, unknown> = { ...e };\n if (e['a'] && e['b']) { out['a'] = pt(e['a']); out['b'] = pt(e['b']); }\n if (e['center']) out['center'] = pt(e['center']);\n if ('radius' in e) out['radius'] = r(e['radius']);\n if ('outerRadius' in e) out['outerRadius'] = r(e['outerRadius']);\n if (Array.isArray(e['samples'])) {\n out['samples'] = (e['samples'] as DragSample[]).map((s) => ({ ...s, ...pt(s) }));\n }\n return out;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"planeInput.js","names":[],"sources":["../../../src/interactions/actions/planeInput.ts"],"sourcesContent":["/**\n * Editing a node on a parallax plane.\n *\n * The dispatcher hands every action the camera's world. A node on a layer\n * carrying `parallax` stores its pose in its plane's world, which the camera's\n * reaches through a `PlaneMap` that changes with the camera. An editing action\n * pairs the pointer with the pose it edits, so the two have to be in one world.\n *\n * `inPlane` wraps an action so its input is carried into the plane of the\n * layer it edits before the action reads it, and the chrome it publishes back\n * comes out in the camera's world. A dep that answers in world points\n * (`nodeAtPoint`, `snap`) keeps speaking the camera's world, and the seam\n * converts at its boundary.\n *\n * A selection can span planes. The edit is measured in one of them, and a\n * node on another is carried into it as the gesture starts and back out\n * through `planeOf` as it is now.\n *\n * The map is read afresh on every call: a camera panning under a held drag, or\n * a plane whose factors are being animated, moves the node with the pointer.\n */\nimport type {\n Action, ActionDeps, AffordanceHit, BindingOpts, DragSample, InvocationCtx, OngoingHandle,\n OngoingOverlay,\n} from '@weasel-js/routing';\nimport type { Scene } from 'core/scene/types';\nimport { asNodeId } from 'core/scene/types';\nimport {\n deriveParallaxView, fromPlane, planeMap, planeToPlane, rectFromPlane, rectToPlane, toPlane,\n type ParallaxOpts, type PlaneMap,\n} from 'core/viewport/parallax';\nimport type { View } from 'core/viewport/view';\nimport type { PoseDescriptor } from 'core/geometry/poseDescriptor';\nimport type { NodeAtPointDep, SnapDep, ViewApi } from './depSchema';\nimport type { SnapBegin } from './snapDep';\n\ntype Point = { x: number; y: number };\n\n/** Which scene layer an invocation edits, read once as it starts. `undefined`\n * means none: the action runs in the camera's world. */\nexport type EditedLayerOf = (deps: ActionDeps, affordance?: AffordanceHit) => string | undefined;\n\nconst layerOfNode = (deps: ActionDeps, id: string | null | undefined): string | undefined =>\n (id ? deps.scene?.get(asNodeId(id))?.layer : undefined);\n\n/** The layer of the node a selection edit acts on: the affordance's target\n * when the drag grabbed one, the first selected node otherwise. A selection\n * spanning planes is edited in that one node's plane. */\nexport const selectionLayer: EditedLayerOf = (deps, affordance) => {\n const selection = deps.selection;\n for (const id of [...(affordance?.targetIds ?? []), ...(selection?.get() ?? [])]) {\n const layer = layerOfNode(deps, id);\n if (layer !== undefined) return layer;\n }\n return undefined;\n};\n\n/** The layer the `insert` dep will put a new node on. */\nexport const insertLayer: EditedLayerOf = (deps) =>\n deps.insert?.layer?.();\n\n/** The layer of the path in anchor-edit mode. */\nexport const editingLayer: EditedLayerOf = (deps) =>\n layerOfNode(deps, deps.editAnchors?.editingId);\n\n/** How the world an invocation edits in maps into the world `layer`'s nodes\n * are stored in, read now. Null when they are the same world. */\nexport function planeOf(view: unknown, layer: string): PlaneMap | null {\n return (view as ViewApi | undefined)?.planeOf?.(layer) ?? null;\n}\n\n/** `m` run backwards; null stays null. */\nexport function invertPlane(m: PlaneMap | null): PlaneMap | null {\n return m && planeToPlane(m, null);\n}\n\n/** `pose` carried through `m`. The map is axis-aligned, so remapping the\n * pose's bounds carries it exactly when the map scales both axes alike. */\nexport function carryPose<P>(d: PoseDescriptor<P>, pose: P, m: PlaneMap | null): P {\n if (m === null) return pose;\n const b = d.getBounds(pose);\n return d.remapBounds(pose, b, rectToPlane(m, b));\n}\n\n/** `action`, with its input carried into the plane of the layer `layerOf`\n * names. An action in a scene with no `parallax` layer, or invoked with no\n * scene or view to read a plane from, runs exactly as it would unwrapped.\n *\n * An immediate action's world point is `params.worldX` / `params.worldY`,\n * the dispatcher's convention for a click; it is carried when present. */\nexport function inPlane<A extends Action>(action: A, layerOf: EditedLayerOf): A {\n const inner = action.invoker;\n if (!inner) return action;\n const declared = action.requires ?? [];\n const requires = [...new Set([...declared, 'scene', 'selection', 'view'])];\n if (inner.timing === 'immediate') {\n return {\n ...action,\n requires,\n invoker: {\n timing: 'immediate',\n run(deps: ActionDeps, params?: Record<string, unknown>): void {\n const plane = livePlane(deps, layerOf(deps), declared, null);\n if (plane === null) return inner.run(deps, params);\n const wx = params?.['worldX'];\n const wy = params?.['worldY'];\n const at = typeof wx === 'number' && typeof wy === 'number'\n ? toPlane(plane.map(), { x: wx, y: wy })\n : null;\n inner.run(plane.deps, at ? { ...params, worldX: at.x, worldY: at.y } : params);\n },\n },\n } as A;\n }\n return {\n ...action,\n requires,\n invoker: {\n timing: 'ongoing',\n start(ctx: InvocationCtx, opts?: BindingOpts): OngoingHandle {\n const plane = livePlane(\n ctx.deps, layerOf(ctx.deps, ctx.drag?.affordance), declared, ctx.drag?.start ?? null,\n );\n if (plane === null) return inner.start(ctx, opts);\n return planeHandle(inner.start(plane.carry(ctx), opts), plane);\n },\n },\n } as A;\n}\n\ninterface LivePlane {\n map(): PlaneMap;\n /** The invocation's deps, speaking the plane's world. */\n deps: ActionDeps;\n /** `ctx` in the plane's world. */\n carry(ctx: InvocationCtx): InvocationCtx;\n}\n\nfunction livePlane(\n bag: ActionDeps,\n layer: string | undefined,\n /** What the wrapped action declared. The dispatcher's dev deps bag throws\n * on any other read, so the seam converts only the deps it can see. */\n declared: readonly string[],\n /** The drag's press point in the camera's world, when there is a drag. */\n pressedAt: Point | null,\n): LivePlane | null {\n const scene = bag.scene as Scene<unknown, string, unknown> | undefined;\n const viewApi = bag.view as ViewApi | undefined;\n if (layer === undefined || !scene || !viewApi) return null;\n if (!scene.layers.some((l) => l.parallax !== undefined)) return null;\n const parallaxOf = (id: string): ParallaxOpts | undefined => scene.layers.find((l) => l.id === id)?.parallax;\n const parallax = (): ParallaxOpts | undefined => parallaxOf(layer);\n\n const IDENTITY: PlaneMap = { scale: { x: 1, y: 1 }, offset: { x: 0, y: 0 } };\n const map = (): PlaneMap => {\n const p = parallax();\n return p ? planeMap(viewApi.get(), p) : IDENTITY;\n };\n\n // A screen-pixel tolerance, and anything else an action reads off the\n // camera, has to be read at the plane's scale.\n const planeView = Object.defineProperties(Object.create(viewApi), {\n get: {\n value: (): View => {\n const p = parallax();\n const camera = viewApi.get();\n return p ? deriveParallaxView(camera, p) : camera;\n },\n },\n plane: { value: map },\n planeOf: {\n value: (id: string): PlaneMap | null => {\n const edited = parallax();\n const own = parallaxOf(id);\n const camera = viewApi.get();\n return planeToPlane(edited ? planeMap(camera, edited) : null, own ? planeMap(camera, own) : null);\n },\n },\n }) as ViewApi;\n\n // Over the dispatcher's bag rather than a copy of it, so every other read\n // still goes through whatever checks the bag makes.\n const deps = Object.create(bag) as typeof bag;\n const override = (name: string, value: unknown) =>\n Object.defineProperty(deps, name, { value, enumerable: true });\n override('view', planeView);\n const nodeAtPoint = declared.includes('nodeAtPoint')\n ? bag.nodeAtPoint as NodeAtPointDep | undefined\n : undefined;\n if (nodeAtPoint) {\n override('nodeAtPoint', ((p, exclude) => nodeAtPoint(fromPlane(map(), p), exclude)) as NodeAtPointDep);\n }\n const snap = declared.includes('snap') ? bag.snap as SnapDep | undefined : undefined;\n if (snap) {\n // A session runs in the plane; a target the camera draws, a grid or a\n // ruler guide, is carried into it.\n override('snap', { begin: (req: SnapBegin) => snap.begin({ ...req, plane: map }) } satisfies SnapDep);\n }\n\n // The drag's origin, fixed in the plane at the moment it was pressed,\n // whatever the camera does after.\n const start0 = pressedAt ? toPlane(map(), pressedAt) : null;\n const trail = trailCarrier();\n\n return {\n map,\n deps,\n carry(c) {\n const m = map();\n const out: InvocationCtx = { ...c, world: toPlane(m, c.world) };\n if (c.drag) {\n const start = start0 ?? toPlane(m, c.drag.start);\n const current = toPlane(m, c.drag.current);\n const aff = c.drag.affordance;\n out.drag = {\n ...c.drag,\n start,\n current,\n delta: { x: current.x - start.x, y: current.y - start.y },\n ...(c.drag.points ? { points: trail(c.drag.points, m) } : {}),\n ...(aff?.fixedPoint ? { affordance: { ...aff, fixedPoint: toPlane(m, aff.fixedPoint) } } : {}),\n };\n }\n // The dispatcher hands `onMove` no deps; only `start` has any to carry.\n if (c.deps) out.deps = deps;\n return out;\n },\n };\n}\n\n/** The drag trail in the plane. The dispatcher grows its trail in place, so\n * only the samples added since the last call are mapped — unless the map\n * moved, when every sample is. */\nfunction trailCarrier(): (points: DragSample[], m: PlaneMap) => DragSample[] {\n let src: DragSample[] | null = null;\n let lastMap: PlaneMap | null = null;\n let out: DragSample[] = [];\n return (points, m) => {\n const same = lastMap !== null\n && lastMap.scale.x === m.scale.x && lastMap.scale.y === m.scale.y\n && lastMap.offset.x === m.offset.x && lastMap.offset.y === m.offset.y;\n if (points !== src || !same || points.length < out.length) {\n src = points;\n out = [];\n }\n lastMap = m;\n for (let i = out.length; i < points.length; i++) {\n out.push({ ...points[i], ...toPlane(m, points[i]) });\n }\n // A copy, so a snapshot taken on `onEnd` is not the live accumulator.\n return out.slice();\n };\n}\n\nfunction planeHandle(handle: OngoingHandle, plane: LivePlane): OngoingHandle {\n const out: OngoingHandle = { ...handle };\n if (handle.onMove) out.onMove = (c) => handle.onMove!(plane.carry(c));\n if (handle.onEnd) out.onEnd = (c, reason) => handle.onEnd!(plane.carry(c), reason);\n if (handle.onWheel) out.onWheel = (c) => handle.onWheel!(plane.carry(c));\n if (handle.overlay) {\n out.overlay = () => {\n const ov = handle.overlay!();\n if (!ov) return ov;\n const m = plane.map();\n return Array.isArray(ov)\n ? (ov as readonly OngoingOverlay[]).map((o) => overlayFromPlane(o, m))\n : overlayFromPlane(ov as OngoingOverlay, m);\n };\n }\n return out;\n}\n\n/** An overlay drawn in the plane, in the camera's world: what every painter\n * reads an overlay as. */\nfunction overlayFromPlane(ov: OngoingOverlay, m: PlaneMap): OngoingOverlay {\n const pt = (p: Point) => fromPlane(m, p);\n switch (ov.kind) {\n case 'marquee':\n return { ...ov, start: pt(ov.start), current: pt(ov.current) };\n case 'lasso':\n return { ...ov, vertices: ov.vertices.map(pt), current: pt(ov.current) };\n case 'polyline':\n case 'brush':\n return { ...ov, points: ov.points.map(pt) };\n case 'insertPreview':\n return {\n ...ov,\n bounds: rectFromPlane(m, ov.bounds),\n extras: insertExtrasFromPlane(ov.extras, m),\n ...(ov.anchorPoint ? { anchorPoint: pt(ov.anchorPoint) } : {}),\n };\n }\n}\n\n/** The geometry the kit's insert kinds carry in `extras`, in the camera's\n * world. A consumer kind's extras are opaque, and pass through. */\nfunction insertExtrasFromPlane(extras: unknown, m: PlaneMap): unknown {\n if (extras === null || typeof extras !== 'object') return extras;\n const e = extras as Record<string, unknown>;\n const pt = (p: unknown) => fromPlane(m, p as Point);\n // Radial kinds inscribe in a square, so one scale carries a radius.\n const r = (v: unknown) => (typeof v === 'number' ? v / ((m.scale.x + m.scale.y) / 2) : v);\n const out: Record<string, unknown> = { ...e };\n if (e['a'] && e['b']) { out['a'] = pt(e['a']); out['b'] = pt(e['b']); }\n if (e['center']) out['center'] = pt(e['center']);\n if ('radius' in e) out['radius'] = r(e['radius']);\n if ('outerRadius' in e) out['outerRadius'] = r(e['outerRadius']);\n if (Array.isArray(e['samples'])) {\n out['samples'] = (e['samples'] as DragSample[]).map((s) => ({ ...s, ...pt(s) }));\n }\n return out;\n}\n"],"mappings":"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"}
|