@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,5 +1,6 @@
|
|
|
1
1
|
import { scenePoseFrame } from "../poseFrame.js";
|
|
2
2
|
import { poseDescriptorOf } from "../poseDescriptorDep.js";
|
|
3
|
+
import { transformFinisher } from "../transformFinish.js";
|
|
3
4
|
import { translateEach } from "../selectionSubtree.js";
|
|
4
5
|
import { drawnBoxes } from "../drawnBoxes.js";
|
|
5
6
|
import { planDistribute } from "./plan.js";
|
|
@@ -27,7 +28,7 @@ var ICON_FOR = {
|
|
|
27
28
|
* translated in world and each result is stored back in its own parent's
|
|
28
29
|
* frame.
|
|
29
30
|
*/
|
|
30
|
-
function distributeSelection(selection, scene, axis, mode, geom, boxesOver) {
|
|
31
|
+
function distributeSelection(selection, scene, axis, mode, geom, boxesOver, finish) {
|
|
31
32
|
const ids = selection.get();
|
|
32
33
|
if (ids.length < 3) return;
|
|
33
34
|
const frame = scenePoseFrame(scene);
|
|
@@ -49,7 +50,7 @@ function distributeSelection(selection, scene, axis, mode, geom, boxesOver) {
|
|
|
49
50
|
dy: axis === "y" ? delta : 0
|
|
50
51
|
};
|
|
51
52
|
});
|
|
52
|
-
scene.batch("Distribute", () => translateEach(scene, frame, geom, moves));
|
|
53
|
+
scene.batch("Distribute", () => translateEach(scene, frame, geom, moves, finish, "Distribute"));
|
|
53
54
|
}
|
|
54
55
|
function makeDistributeAction(axis) {
|
|
55
56
|
return {
|
|
@@ -63,7 +64,8 @@ function makeDistributeAction(axis) {
|
|
|
63
64
|
"scene",
|
|
64
65
|
"poseDescriptor",
|
|
65
66
|
"view",
|
|
66
|
-
"boundsIncludeStroke"
|
|
67
|
+
"boundsIncludeStroke",
|
|
68
|
+
"transformFollowers"
|
|
67
69
|
],
|
|
68
70
|
invoker: {
|
|
69
71
|
timing: "immediate",
|
|
@@ -71,7 +73,7 @@ function makeDistributeAction(axis) {
|
|
|
71
73
|
const selection = deps.selection;
|
|
72
74
|
const scene = deps.scene;
|
|
73
75
|
if (!selection || !scene) return;
|
|
74
|
-
distributeSelection(selection, scene, axis, params?.mode ?? "centers", poseDescriptorOf(deps.poseDescriptor), (frame) => drawnBoxes(deps, frame));
|
|
76
|
+
distributeSelection(selection, scene, axis, params?.mode ?? "centers", poseDescriptorOf(deps.poseDescriptor), (frame) => drawnBoxes(deps, frame), transformFinisher(deps));
|
|
75
77
|
}
|
|
76
78
|
},
|
|
77
79
|
enabled: (deps) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action.js","names":[],"sources":["../../../../src/interactions/actions/distribute/action.tsx"],"sourcesContent":["import type { IconRef } from '@weasel-js/icons';\nimport type { Scene } from 'core/scene/types';\nimport type { PoseDescriptor } from '../resize/geometry';\nimport { poseDescriptorOf } from '../poseDescriptorDep';\nimport { drawnBoxes, type DrawnBoxes } from '../drawnBoxes';\nimport type { DistributeAxis, DistributeMode } from './distribute';\nimport { planDistribute } from './plan';\nimport { scenePoseFrame, type PoseFrame } from '../poseFrame';\nimport { translateEach } from '../selectionSubtree';\nimport type { Action } from '@weasel-js/routing';\nimport { ActionDisabledReason } from '@weasel-js/routing';\nimport type { SelectionApi } from 'core/selection/useSelection';\nimport type { ImmediateInvoker } from '@weasel-js/routing';\nimport { icon } from '../../../icons.gen';\n\nconst ID_FOR: Record<DistributeAxis, string> = { x: 'distribute.horizontal', y: 'distribute.vertical' };\nconst LABEL_FOR: Record<DistributeAxis, string> = { x: 'Distribute Horizontally', y: 'Distribute Vertically' };\nconst ICON_FOR: Record<DistributeAxis, IconRef> = {\n x: icon('distributeHorizontal'),\n y: icon('distributeVertical'),\n};\n\n// ---------------------------------------------------------------------------\n// Shared helper for descriptor invokers\n// ---------------------------------------------------------------------------\n\n/**\n * Apply a distribute operation to the current selection via the Scene API.\n * Reads poses through the `poseDescriptor` dep; `mode` comes from the\n * binding's `params.mode`.\n *\n * The span being divided is a world span, so the bounds are read and\n * translated in world and each result is stored back in its own parent's\n * frame.\n */\nfunction distributeSelection(\n selection: SelectionApi,\n scene: Scene<unknown, string, unknown>,\n axis: DistributeAxis,\n mode: DistributeMode,\n geom: PoseDescriptor<unknown>,\n boxesOver: (frame: PoseFrame<unknown>) => DrawnBoxes,\n): void {\n const ids = selection.get();\n if (ids.length < 3) return;\n const frame = scenePoseFrame(scene);\n const boxes = boxesOver(frame);\n\n const items = ids.map((id) => {\n const pose = frame.world(id);\n return { id, pose, b: boxes.aabb(id, pose) };\n });\n const targets = planDistribute(items.map((it) => it.b), axis, mode);\n\n const moves = items.map((it, i) => {\n const delta = targets[i] - (axis === 'x' ? it.b.x : it.b.y);\n return { id: it.id, dx: axis === 'x' ? delta : 0, dy: axis === 'y' ? delta : 0 };\n });\n scene.batch('Distribute', () => translateEach(scene, frame, geom, moves));\n}\n\n// ---------------------------------------------------------------------------\n// Static descriptors\n// ---------------------------------------------------------------------------\n\nfunction makeDistributeAction(axis: DistributeAxis): Action {\n return {\n id: ID_FOR[axis],\n label: LABEL_FOR[axis],\n icon: ICON_FOR[axis],\n group: 'distribute',\n eligible: { capability: 'transforms-selection' },\n requires: ['selection', 'scene', 'poseDescriptor', 'view', 'boundsIncludeStroke'],\n // No default keybindings. Wire bindings explicitly via the actions registry.\n invoker: {\n timing: 'immediate',\n run: (deps, params) => {\n const selection = deps.selection;\n const scene = deps.scene;\n if (!selection || !scene) return;\n const mode = (params?.mode as DistributeMode | undefined) ?? 'centers';\n distributeSelection(\n selection, scene, axis, mode, poseDescriptorOf(deps.poseDescriptor), (frame) => drawnBoxes(deps, frame),\n );\n },\n } satisfies ImmediateInvoker,\n // Deps-aware, matching `distributeSelection`'s own `ids.length < 3` guard:\n // a constant disabled reason greys the entry out forever (see\n // `requiresSelection`).\n enabled: (deps) => {\n const selection = deps?.selection;\n const count = selection?.get().length ?? 0;\n return count >= 3 ? true : ActionDisabledReason.SelectionRequired;\n },\n };\n}\n\n/** Static descriptor for distribute-horizontal. */\nexport const distributeHorizontalAction = makeDistributeAction('x');\n/** Static descriptor for distribute-vertical. */\nexport const distributeVerticalAction = makeDistributeAction('y');\n\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"action.js","names":[],"sources":["../../../../src/interactions/actions/distribute/action.tsx"],"sourcesContent":["import type { IconRef } from '@weasel-js/icons';\nimport type { Scene } from 'core/scene/types';\nimport type { PoseDescriptor } from '../resize/geometry';\nimport { poseDescriptorOf } from '../poseDescriptorDep';\nimport { drawnBoxes, type DrawnBoxes } from '../drawnBoxes';\nimport type { DistributeAxis, DistributeMode } from './distribute';\nimport { planDistribute } from './plan';\nimport { scenePoseFrame, type PoseFrame } from '../poseFrame';\nimport { translateEach } from '../selectionSubtree';\nimport { transformFinisher, type TransformFinisher } from '../transformFinish';\nimport type { Action } from '@weasel-js/routing';\nimport { ActionDisabledReason } from '@weasel-js/routing';\nimport type { SelectionApi } from 'core/selection/useSelection';\nimport type { ImmediateInvoker } from '@weasel-js/routing';\nimport { icon } from '../../../icons.gen';\n\nconst ID_FOR: Record<DistributeAxis, string> = { x: 'distribute.horizontal', y: 'distribute.vertical' };\nconst LABEL_FOR: Record<DistributeAxis, string> = { x: 'Distribute Horizontally', y: 'Distribute Vertically' };\nconst ICON_FOR: Record<DistributeAxis, IconRef> = {\n x: icon('distributeHorizontal'),\n y: icon('distributeVertical'),\n};\n\n// ---------------------------------------------------------------------------\n// Shared helper for descriptor invokers\n// ---------------------------------------------------------------------------\n\n/**\n * Apply a distribute operation to the current selection via the Scene API.\n * Reads poses through the `poseDescriptor` dep; `mode` comes from the\n * binding's `params.mode`.\n *\n * The span being divided is a world span, so the bounds are read and\n * translated in world and each result is stored back in its own parent's\n * frame.\n */\nfunction distributeSelection(\n selection: SelectionApi,\n scene: Scene<unknown, string, unknown>,\n axis: DistributeAxis,\n mode: DistributeMode,\n geom: PoseDescriptor<unknown>,\n boxesOver: (frame: PoseFrame<unknown>) => DrawnBoxes,\n finish?: TransformFinisher,\n): void {\n const ids = selection.get();\n if (ids.length < 3) return;\n const frame = scenePoseFrame(scene);\n const boxes = boxesOver(frame);\n\n const items = ids.map((id) => {\n const pose = frame.world(id);\n return { id, pose, b: boxes.aabb(id, pose) };\n });\n const targets = planDistribute(items.map((it) => it.b), axis, mode);\n\n const moves = items.map((it, i) => {\n const delta = targets[i] - (axis === 'x' ? it.b.x : it.b.y);\n return { id: it.id, dx: axis === 'x' ? delta : 0, dy: axis === 'y' ? delta : 0 };\n });\n scene.batch('Distribute', () => translateEach(scene, frame, geom, moves, finish, 'Distribute'));\n}\n\n// ---------------------------------------------------------------------------\n// Static descriptors\n// ---------------------------------------------------------------------------\n\nfunction makeDistributeAction(axis: DistributeAxis): Action {\n return {\n id: ID_FOR[axis],\n label: LABEL_FOR[axis],\n icon: ICON_FOR[axis],\n group: 'distribute',\n eligible: { capability: 'transforms-selection' },\n requires: ['selection', 'scene', 'poseDescriptor', 'view', 'boundsIncludeStroke', 'transformFollowers'],\n // No default keybindings. Wire bindings explicitly via the actions registry.\n invoker: {\n timing: 'immediate',\n run: (deps, params) => {\n const selection = deps.selection;\n const scene = deps.scene;\n if (!selection || !scene) return;\n const mode = (params?.mode as DistributeMode | undefined) ?? 'centers';\n distributeSelection(\n selection, scene, axis, mode, poseDescriptorOf(deps.poseDescriptor), (frame) => drawnBoxes(deps, frame),\n transformFinisher(deps),\n );\n },\n } satisfies ImmediateInvoker,\n // Deps-aware, matching `distributeSelection`'s own `ids.length < 3` guard:\n // a constant disabled reason greys the entry out forever (see\n // `requiresSelection`).\n enabled: (deps) => {\n const selection = deps?.selection;\n const count = selection?.get().length ?? 0;\n return count >= 3 ? true : ActionDisabledReason.SelectionRequired;\n },\n };\n}\n\n/** Static descriptor for distribute-horizontal. */\nexport const distributeHorizontalAction = makeDistributeAction('x');\n/** Static descriptor for distribute-vertical. */\nexport const distributeVerticalAction = makeDistributeAction('y');\n\n"],"mappings":"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CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAqB,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAClD,CAAA,CAAA;AACF,CAAA,CAAA;AACF;;AAGA,CAAA,CAAA,CAAA,CAAa,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAA6B,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAqB,CAAA,CAAA,CAAG,CAAA;;AAElE,CAAA,CAAA,CAAA,CAAa,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAA6B,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAqB,CAAA,CAAA,CAAG,CAAA"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { axisAlignedBounds } from "../../core/geometry/unionBounds.js";
|
|
2
2
|
import { drawnBoundsOf, inkExtentsOf } from "../../canvas/drawnBounds.js";
|
|
3
|
+
import { drawnBoundsScene } from "../../canvas/derivedPath.js";
|
|
3
4
|
import { scenePoseFrame } from "./poseFrame.js";
|
|
4
5
|
import { poseDescriptorOf } from "./poseDescriptorDep.js";
|
|
5
6
|
|
|
@@ -8,7 +9,7 @@ var NO_SCENE = { get: () => void 0 };
|
|
|
8
9
|
/** The {@link DrawnBoxes} over `deps.scene`. Pass the action's own `frame`
|
|
9
10
|
* when it has one, so container members are read the way it reads them. */
|
|
10
11
|
function drawnBoxes(deps, frame) {
|
|
11
|
-
const scene = deps.scene
|
|
12
|
+
const scene = deps.scene ? drawnBoundsScene(deps.scene) : NO_SCENE;
|
|
12
13
|
const descriptor = poseDescriptorOf(deps.poseDescriptor);
|
|
13
14
|
const view = deps.view?.get();
|
|
14
15
|
let worlds = frame;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drawnBoxes.js","names":[],"sources":["../../../src/interactions/actions/drawnBoxes.ts"],"sourcesContent":["import type { ActionDeps } from '@weasel-js/routing';\nimport { drawnBoundsOf, inkExtentsOf, type DrawnBoundsOptions, type DrawnBoundsScene } from 'canvas/drawnBounds';\nimport type { InkExtents } from 'core/geometry/inkExtents';\nimport { axisAlignedBounds } from 'core/geometry/unionBounds';\nimport type { NodeId } from 'core/scene/types';\nimport type { Bounds } from 'core/viewport/fitViewToBounds';\nimport { poseDescriptorOf } from './poseDescriptorDep';\nimport { scenePoseFrame, type PoseFrame } from './poseFrame';\n\nconst NO_SCENE: DrawnBoundsScene = { get: () => undefined };\n\n/** `drawnBoundsOf` bound to an action's deps: the box each id is shown with\n * at a world pose, stroke included unless the canvas opted out. */\nexport interface DrawnBoxes {\n /** In the frame the pose is drawn in. */\n framed(id: NodeId | string, pose: unknown): Bounds;\n /** The axis-aligned box a turned node covers. */\n aabb(id: NodeId | string, pose: unknown): Bounds;\n /** How far the ink reaches past the pose box, in the box's own frame. */\n extents(id: NodeId | string, pose: unknown): InkExtents;\n}\n\n/** The {@link DrawnBoxes} over `deps.scene`. Pass the action's own `frame`\n * when it has one, so container members are read the way it reads them. */\nexport function drawnBoxes(\n deps: Pick<ActionDeps, 'scene' | 'poseDescriptor' | 'view' | 'boundsIncludeStroke'>,\n frame?: PoseFrame<unknown>,\n): DrawnBoxes {\n const scene: DrawnBoundsScene = deps.scene
|
|
1
|
+
{"version":3,"file":"drawnBoxes.js","names":[],"sources":["../../../src/interactions/actions/drawnBoxes.ts"],"sourcesContent":["import type { ActionDeps } from '@weasel-js/routing';\nimport { drawnBoundsOf, inkExtentsOf, type DrawnBoundsOptions, type DrawnBoundsScene } from 'canvas/drawnBounds';\nimport { drawnBoundsScene } from 'canvas/derivedPath';\nimport type { InkExtents } from 'core/geometry/inkExtents';\nimport { axisAlignedBounds } from 'core/geometry/unionBounds';\nimport type { NodeId } from 'core/scene/types';\nimport type { Bounds } from 'core/viewport/fitViewToBounds';\nimport { poseDescriptorOf } from './poseDescriptorDep';\nimport { scenePoseFrame, type PoseFrame } from './poseFrame';\n\nconst NO_SCENE: DrawnBoundsScene = { get: () => undefined };\n\n/** `drawnBoundsOf` bound to an action's deps: the box each id is shown with\n * at a world pose, stroke included unless the canvas opted out. */\nexport interface DrawnBoxes {\n /** In the frame the pose is drawn in. */\n framed(id: NodeId | string, pose: unknown): Bounds;\n /** The axis-aligned box a turned node covers. */\n aabb(id: NodeId | string, pose: unknown): Bounds;\n /** How far the ink reaches past the pose box, in the box's own frame. */\n extents(id: NodeId | string, pose: unknown): InkExtents;\n}\n\n/** The {@link DrawnBoxes} over `deps.scene`. Pass the action's own `frame`\n * when it has one, so container members are read the way it reads them. */\nexport function drawnBoxes(\n deps: Pick<ActionDeps, 'scene' | 'poseDescriptor' | 'view' | 'boundsIncludeStroke'>,\n frame?: PoseFrame<unknown>,\n): DrawnBoxes {\n const scene: DrawnBoundsScene = deps.scene ? drawnBoundsScene(deps.scene) : NO_SCENE;\n const descriptor = poseDescriptorOf(deps.poseDescriptor);\n const view = deps.view?.get();\n let worlds = frame;\n const opts: DrawnBoundsOptions = {\n descriptor,\n worldPoseOf: (id) => (worlds ??= scenePoseFrame(deps.scene!)).world(id),\n includeStroke: deps.boundsIncludeStroke ?? true,\n ...(view ? { scale: view.scale } : {}),\n };\n const framed = (id: NodeId | string, pose: unknown): Bounds =>\n drawnBoundsOf(scene, id as NodeId, pose, opts);\n return {\n framed,\n aabb: (id, pose) => axisAlignedBounds(framed(id, pose)),\n extents: (id, pose) => inkExtentsOf(scene, id as NodeId, pose, opts),\n };\n}\n"],"mappings":";;;;;;;AAUA,IAAM,WAA6B,EAAE,WAAW,OAAU;;;AAe1D,SAAgB,WACd,MACA,OACY;CACZ,MAAM,QAA0B,KAAK,QAAQ,iBAAiB,KAAK,KAAK,IAAI;CAC5E,MAAM,aAAa,iBAAiB,KAAK,cAAc;CACvD,MAAM,OAAO,KAAK,MAAM,IAAI;CAC5B,IAAI,SAAS;CACb,MAAM,OAA2B;EAC/B;EACA,cAAc,QAAQ,WAAW,eAAe,KAAK,KAAM,EAAA,CAAG,MAAM,EAAE;EACtE,eAAe,KAAK,uBAAuB;EAC3C,GAAI,OAAO,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;CACtC;CACA,MAAM,UAAU,IAAqB,SACnC,cAAc,OAAO,IAAc,MAAM,IAAI;CAC/C,OAAO;EACL;EACA,OAAO,IAAI,SAAS,kBAAkB,OAAO,IAAI,IAAI,CAAC;EACtD,UAAU,IAAI,SAAS,aAAa,OAAO,IAAc,MAAM,IAAI;CACrE;AACF"}
|
|
@@ -5,7 +5,7 @@ import { inputSession } from "../../../features/snap/session2d.js";
|
|
|
5
5
|
import { pathEditToolActive } from "../defaults/pathEditTools.js";
|
|
6
6
|
import { HANDLE_LOCK_ROLES, lockHandle, locksInForce } from "./handleDrag.js";
|
|
7
7
|
import { locksOf } from "./params.js";
|
|
8
|
-
import { pathEditPreview } from "./preview.js";
|
|
8
|
+
import { finishPathEditFrame, pathEditPreview } from "./preview.js";
|
|
9
9
|
import { claimWheel, dragWeights, endExtensionDrags, extensionOverlays, placeHandle, startExtensionDrags, translateWeighted } from "./extensionDrags.js";
|
|
10
10
|
import { editedPathSymmetries } from "./symmetry.js";
|
|
11
11
|
import { anchorAt, editAnchorSetTracked, moveHandleSymmetric, moveHandleTo, pathAwayFromAnchors, pathToAnchors, translateAnchorsSymmetric } from "@weasel-js/geom";
|
|
@@ -80,10 +80,7 @@ var paramsOf = (opts) => resolveParams(opts?.params) ?? {};
|
|
|
80
80
|
function track(scratch, next) {
|
|
81
81
|
if (!next) return;
|
|
82
82
|
const { dep, id } = scratch;
|
|
83
|
-
const done = dep
|
|
84
|
-
path: next.path,
|
|
85
|
-
others: []
|
|
86
|
-
};
|
|
83
|
+
const done = finishPathEditFrame(dep, id, next.path, next.origins);
|
|
87
84
|
if (!done) return;
|
|
88
85
|
scratch.currentPose = done.path;
|
|
89
86
|
scratch.others = done.others;
|
|
@@ -163,10 +160,13 @@ var editAnchorsAction = inPlane({
|
|
|
163
160
|
id: "editAnchors",
|
|
164
161
|
label: "Edit Anchors",
|
|
165
162
|
tags: pathOperationTags("drag"),
|
|
166
|
-
defaultBinding: {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
163
|
+
defaultBinding: [{
|
|
164
|
+
spec: {
|
|
165
|
+
kind: "drag",
|
|
166
|
+
target: { kindOf: isAnchorOrControl }
|
|
167
|
+
},
|
|
168
|
+
opts: { id: "editAnchors.drag" }
|
|
169
|
+
}],
|
|
170
170
|
eligible: { capability: "edits-anchors" },
|
|
171
171
|
modifierRoles: EDIT_ANCHORS_ROLES,
|
|
172
172
|
requires: [
|
|
@@ -193,7 +193,7 @@ var editAnchorsAction = inPlane({
|
|
|
193
193
|
if (anchorInfo.part === "controlIn" && !origin.inHandle) return {};
|
|
194
194
|
if (anchorInfo.part === "controlOut" && !origin.outHandle) return {};
|
|
195
195
|
let active = false;
|
|
196
|
-
const preview = pathEditPreview(dep, editingId, () => active ? scratch.currentPose : null, () => active ? scratch.others : []);
|
|
196
|
+
const preview = pathEditPreview(dep, editingId, () => active ? { path: scratch.currentPose } : null, () => active ? scratch.others : []);
|
|
197
197
|
if (!preview) return {};
|
|
198
198
|
const dragging = draggedByPress(dep, anchorInfo, roleHeld(ctx, "selection.add"));
|
|
199
199
|
const scratch = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action.js","names":[],"sources":["../../../../src/interactions/actions/edit-anchors/action.ts"],"sourcesContent":["/**\n * `editAnchorsAction` — ongoing Action descriptor for editing polygon anchors.\n *\n * - **Press** selects. Bare press replaces the anchor selection; Shift\n * toggles the pressed anchor in or out of it. Pressing an anchor that\n * is already part of a multi-anchor selection leaves the selection\n * alone, so you can grab a set and move it.\n * - **Drag** then moves whatever the press left selected — one anchor,\n * or every selected anchor together. The pressed anchor snaps through\n * the `snap` dep's `point` session, to what the drag leaves still of the\n * path and to the canvas's targets; Shift holds it to the axes and\n * diagonals through its press, and Ctrl suspends the snap.\n * - **Dragging a control handle** moves just that handle, mirroring the\n * opposite one while the anchor is smooth. Alt breaks the mirror; Shift\n * holds the handle to the angle it had at the press, changing only its\n * length; Mod (Cmd or Ctrl) holds its length, changing only its angle;\n * both freeze it. The `editAnchors` dep's `handleLocks`, or else the\n * `handleLock` param ({@link EditAnchorsParams}), holds a lock with no\n * modifier. The lock in force draws its guide as a `polyline` overlay\n * of role `lock`: the line, or the circle round the anchor.\n * - **Path-edit extensions shape the drag** through their `drag`: anchors\n * that follow an anchor drag by a share of it, where a dragged handle\n * goes after the locks, the wheel mid-drag, and overlays of their own.\n * - **Every frame is finished** by the dep's `finishEdit`, so what a\n * path-edit extension keeps true holds while the drag runs.\n * - **Under a `pathSymmetry` dep**, on a path that is its own image under\n * some of its transforms, every image of what is dragged follows it.\n *\n * Selection lives on the `editAnchors` dep (flat anchor indices) rather\n * than in this handle's scratch, because the keyboard actions\n * (`nudgeAnchors`, `deleteAnchors`) and the overlay all need to read it\n * between gestures.\n *\n * Operational when the consumer wires the `editAnchors` dep, and\n * `buildAffordanceAt` with a `getAnchorState` thunk so the dispatcher\n * classifies anchor/control-handle hits as `anchor:N`, `controlIn:N`, or\n * `controlOut:N` affordances on pointerdown. On any other affordance `start`\n * returns `{}` so other bindings can handle the drag.\n */\n\nimport type { Action } from '@weasel-js/routing';\nimport type { BindingOpts, InvocationCtx, OngoingHandle, OngoingOverlay } from '@weasel-js/routing';\nimport type { EditAnchorsDep, SnapDep } from '../depSchema';\nimport type { SnapBegin, SnapMods, SnapSession } from '../snapDep';\nimport { inputSession } from 'features/snap/session2d';\nimport { SNAP_ROLES, snapMods } from 'features/snap/roles';\nimport { ActionDisabledReason, isAnchorOrControl, resolveParams, roleReader, type ModifierRoles } from '@weasel-js/routing';\nimport {\n anchorAt,\n editAnchorSetTracked,\n moveHandleSymmetric,\n moveHandleTo,\n pathAwayFromAnchors,\n translateAnchorsSymmetric,\n type AnchorSet,\n type AnchorSymmetry,\n type PenAnchor,\n type PointOrigin,\n} from '@weasel-js/geom';\nimport { pathToAnchors, type PolygonPath } from '@weasel-js/geom';\nimport { inPlane, editingLayer } from '../planeInput';\nimport { HANDLE_LOCK_ROLES, lockHandle, locksInForce, type HandlePress } from './handleDrag';\nimport { locksOf, type EditAnchorsParams } from './params';\nimport { pathEditPreview } from './preview';\nimport {\n claimWheel, dragWeights, endExtensionDrags, extensionOverlays, placeHandle, startExtensionDrags, translateWeighted,\n} from './extensionDrags';\nimport type { PathEditDrag } from 'features/paths/pathEditExtension';\nimport { pathEditToolActive } from '../defaults/pathEditTools';\nimport { editedPathSymmetries } from './symmetry';\nimport { pathOperationTags } from '../pathGestureTags';\n\n/**\n * Parse an anchor affordance kind — `'anchor:N'` | `'controlIn:N'` |\n * `'controlOut:N'`, where N is the flat anchor index — or `null` when the\n * affordance is not an anchor kind.\n */\nfunction parseAnchorAffordance(\n kind: string,\n): { anchorIndex: number; part: 'anchor' | 'controlIn' | 'controlOut' } | null {\n const m = kind.match(/^(anchor|controlIn|controlOut):(\\d+)$/);\n if (!m) return null;\n return {\n anchorIndex: parseInt(m[2], 10),\n part: m[1] as 'anchor' | 'controlIn' | 'controlOut',\n };\n}\n\n/**\n * Resolve what a press on `anchorIndex` should leave selected.\n *\n * Shift toggles. A bare press on an anchor that's already part of the\n * selection keeps the selection intact (so the drag moves the whole set);\n * a bare press anywhere else collapses to just that anchor.\n */\nexport function selectionAfterAnchorPress(\n current: ReadonlySet<number>,\n anchorIndex: number,\n additive: boolean,\n): Set<number> {\n if (additive) {\n const next = new Set(current);\n if (next.has(anchorIndex)) next.delete(anchorIndex);\n else next.add(anchorIndex);\n return next;\n }\n if (current.has(anchorIndex) && current.size > 1) return new Set(current);\n return new Set([anchorIndex]);\n}\n\ninterface EditAnchorsScratch {\n dep: EditAnchorsDep;\n id: string;\n anchorIndex: number;\n /** `'anchor'` drags on-curve points (and their handles) by a delta.\n * `'controlIn'` / `'controlOut'` drag one control point to an absolute\n * world coord. */\n part: 'anchor' | 'controlIn' | 'controlOut';\n /** Anchors this drag moves — the pressed one, or the whole anchor\n * selection when the press landed inside it. Flat indices. */\n dragging: readonly number[];\n /** World position of the pressed anchor at drag start; the drag delta is\n * measured from here rather than accumulated per move, so the geometry\n * is always derived from `originPose` in one step. */\n anchorOrigin: { x: number; y: number };\n /** The anchor and the dragged control handle at the press, for a handle drag. */\n handlePress: HandlePress | null;\n /** The guide the lock in force drew at the last move. */\n guide: OngoingOverlay | null;\n /** The path-edit extensions' shares of this drag. */\n drags: readonly PathEditDrag[];\n /** The last move, to redo when an extension claims the wheel. */\n lastMove: InvocationCtx | null;\n originPose: PolygonPath;\n currentPose: PolygonPath;\n /** The transforms `originPose` is its own image under, read at the press. */\n symmetries: readonly AnchorSymmetry[];\n /** Where each point of `currentPose` came from in `originPose`. */\n origins?: readonly (PointOrigin | null)[];\n /** Other nodes' world paths the finished edit moves with it. */\n others: readonly { id: string; path: PolygonPath }[];\n}\n\ntype Point = { x: number; y: number };\n\n/**\n * An anchor drag's snap: a `point` session, begun on the first move, for\n * where the pressed anchor goes. The edited path offers no targets but what\n * the drag leaves still of it, and Shift holds the anchor to the axes and\n * diagonals through its press.\n */\nfunction anchorDragSnap(\n snap: SnapDep | undefined,\n press: { id: string; origin: Point; originPose: PolygonPath; dragging: readonly number[] },\n): { at(world: Point, mods: SnapMods): Point; end(): void } {\n let session: SnapSession | null = null;\n return {\n at(world, mods) {\n if (!session) {\n const { path, anchors } = pathAwayFromAnchors(press.originPose, press.dragging);\n const req: SnapBegin = {\n gesture: 'point', press: press.origin, ids: [press.id],\n also: { paths: [path], anchors }, constrain: 'axis',\n };\n session = snap?.begin(req) ?? inputSession(req);\n }\n return session.at(world, mods).point;\n },\n end() {\n session?.end();\n session = null;\n },\n };\n}\n\nconst paramsOf = (opts: BindingOpts | undefined): EditAnchorsParams =>\n (resolveParams(opts?.params) ?? {}) as EditAnchorsParams;\n\n/** Take `next` as the frame to show, finished by the dep. A frame it cannot\n * finish is dropped, so the path stays at the last one it could. */\nfunction track(scratch: EditAnchorsScratch, next: ReturnType<typeof editAnchorSetTracked>): void {\n if (!next) return;\n const { dep, id } = scratch;\n const done = dep.finishEdit ? dep.finishEdit(id, next.path, next.origins) : { path: next.path, others: [] };\n if (!done) return;\n scratch.currentPose = done.path as PolygonPath;\n scratch.others = done.others as EditAnchorsScratch['others'];\n scratch.origins = next.origins;\n}\n\n/** The anchor and the handle a press on `part` grabbed; null for an anchor press. */\nfunction handlePressOf(\n origin: PenAnchor,\n part: EditAnchorsScratch['part'],\n): HandlePress | null {\n const handle = part === 'controlIn' ? origin.inHandle : part === 'controlOut' ? origin.outHandle : undefined;\n return handle ? { anchor: { x: origin.x, y: origin.y }, handle: { ...handle } } : null;\n}\n\n/** Move the dragged anchors to follow `to`, and the anchors the extensions\n * weight by their shares. A weighted drag moves no symmetric images. */\nfunction moveAnchors(scratch: EditAnchorsScratch, to: Point): void {\n if (scratch.dragging.length === 0) return;\n const dx = to.x - scratch.anchorOrigin.x;\n const dy = to.y - scratch.anchorOrigin.y;\n const weights = dragWeights(scratch.drags, scratch.dragging);\n track(scratch, editAnchorSetTracked(scratch.originPose, (set) => {\n if (weights) translateWeighted(set, weights, dx, dy);\n else translateAnchorsSymmetric(set, scratch.dragging, dx, dy, scratch.symmetries);\n }));\n}\n\n/** The modifiers `editAnchors` reads while it runs: Shift on the press adds\n * to the anchor selection, Alt breaks a smooth anchor's mirror, the handle\n * locks, and Shift holds an anchor drag to the axes and diagonals. An anchor\n * drag also reads `snap.suspend` at its default key, Ctrl, which is not\n * declared here because on a handle Ctrl holds the length. */\nexport const EDIT_ANCHORS_ROLES = {\n 'selection.add': { label: 'Add to the anchor selection', keys: ['shift'] },\n 'mirror.break': { label: \"Break the handles' mirror\", keys: ['alt'] },\n ...HANDLE_LOCK_ROLES,\n 'snap.constrain': SNAP_ROLES['snap.constrain'],\n} as const satisfies ModifierRoles;\n\nconst roleHeld = roleReader(EDIT_ANCHORS_ROLES);\n\n/** Move the dragged handle toward the pointer, under the locks in force, then\n * wherever the extensions place it. */\nfunction moveHandle(scratch: EditAnchorsScratch, ctx: InvocationCtx, params: EditAnchorsParams): void {\n const side = scratch.part === 'controlIn' ? 'in' : 'out';\n // Modifiers and held locks are read live, so either can change mid-drag.\n const held = (ctx.deps.editAnchors ?? scratch.dep).handleLocks ?? locksOf(params.handleLock);\n const locks = locksInForce(held, ctx);\n const locked = scratch.handlePress ? lockHandle(scratch.handlePress, ctx.world, locks) : { to: ctx.world, guide: null };\n scratch.guide = locked.guide;\n const to = placeHandle(scratch.drags, locked.to, { locks });\n const alt = roleHeld(ctx, 'mirror.break');\n const move = scratch.symmetries.length > 0\n ? (set: AnchorSet) => moveHandleSymmetric(set, scratch.anchorIndex, side, to.x, to.y, alt, scratch.symmetries)\n : (set: AnchorSet) => moveHandleTo(set, scratch.anchorIndex, side, to.x, to.y, alt);\n track(scratch, editAnchorSetTracked(scratch.originPose, move));\n}\n\n/**\n * What a press drags, the selection updated first, before any move: a handle\n * press drags its anchor's handle; an anchor press selects as\n * {@link selectionAfterAnchorPress} says and drags what it left selected —\n * nothing when Shift took the pressed anchor out of it.\n */\nfunction draggedByPress(\n dep: EditAnchorsDep,\n press: { anchorIndex: number; part: EditAnchorsScratch['part'] },\n shift: boolean,\n): readonly number[] {\n if (press.part !== 'anchor') return [press.anchorIndex];\n const next = selectionAfterAnchorPress(dep.selectedAnchors, press.anchorIndex, shift);\n dep.setSelectedAnchors(next);\n return next.has(press.anchorIndex) ? [...next] : [];\n}\n\n/** Static descriptor for the `editAnchors` Action. */\nexport const editAnchorsAction: Action & { requires: string[] } = inPlane({\n id: 'editAnchors',\n label: 'Edit Anchors',\n tags: pathOperationTags('drag'),\n defaultBinding: {\n kind: 'drag',\n // Only matches drags whose pointerdown hit an anchor or control handle.\n // Ties moveAction's `selected-body` on specificity and registers after\n // it, so move declines these presses in `start`.\n target: { kindOf: isAnchorOrControl },\n },\n eligible: { capability: 'edits-anchors' },\n modifierRoles: EDIT_ANCHORS_ROLES,\n requires: ['selection', 'editAnchors', 'pathSymmetry', 'snap'],\n invoker: {\n timing: 'ongoing',\n start(ctx: InvocationCtx, opts): OngoingHandle {\n const dep = ctx.deps.editAnchors;\n if (!dep) return {};\n\n const affordance = ctx.drag?.affordance;\n if (!affordance) {\n // No affordance hit → this drag doesn't target an anchor handle.\n // Let other bindings handle it (the handle returns {}, dispatcher moves on).\n return {};\n }\n\n const anchorInfo = parseAnchorAffordance(affordance.kind);\n if (!anchorInfo) {\n // Affordance is a non-anchor kind (e.g. resize handle, rotate handle).\n return {};\n }\n\n const { editingId } = dep;\n // World-coord polygon. For pose-as-polygon nodes this equals\n // node.pose; for data.path nodes it's pathInWorld-projected (translate +\n // rotation) so the anchor world coords match what the user clicked.\n const worldPath = dep.getEditablePath(editingId) as PolygonPath | undefined;\n if (!worldPath || worldPath.kind !== 'polygon') return {};\n\n // Decode once to validate the affordance index against the actual\n // geometry and to read the press origin. A stale affordance (the\n // path changed between pointerdown and now) fails here rather than\n // silently editing whichever anchor now holds that index.\n const decoded = pathToAnchors(worldPath) as AnchorSet;\n const origin = anchorAt(decoded, anchorInfo.anchorIndex);\n if (!origin) return {};\n if (anchorInfo.part === 'controlIn' && !origin.inHandle) return {};\n if (anchorInfo.part === 'controlOut' && !origin.outHandle) return {};\n\n let active = false;\n const preview = pathEditPreview(\n dep, editingId, () => (active ? scratch.currentPose : null), () => (active ? scratch.others : []),\n );\n if (!preview) return {};\n\n const dragging = draggedByPress(dep, anchorInfo, roleHeld(ctx, 'selection.add'));\n\n const scratch: EditAnchorsScratch = {\n dep,\n id: editingId,\n anchorIndex: anchorInfo.anchorIndex,\n part: anchorInfo.part,\n dragging,\n anchorOrigin: { x: origin.x, y: origin.y },\n handlePress: handlePressOf(origin, anchorInfo.part),\n guide: null,\n drags: startExtensionDrags(dep.extensions, {\n id: editingId,\n node: dep.getNodeShape(editingId),\n path: worldPath,\n anchors: decoded,\n part: anchorInfo.part,\n anchorIndex: anchorInfo.anchorIndex,\n dragging: anchorInfo.part === 'anchor' ? dragging : [],\n scale: ctx.deps.view?.get().scale,\n ...(ctx.deps.snap ? { snap: ctx.deps.snap } : {}),\n }),\n lastMove: null,\n originPose: worldPath,\n currentPose: worldPath,\n symmetries: editedPathSymmetries(ctx.deps.pathSymmetry, editingId, decoded),\n others: [],\n };\n const snapAnchor = anchorDragSnap(ctx.deps.snap, {\n id: editingId, origin: scratch.anchorOrigin, originPose: worldPath, dragging,\n });\n\n const move = (moveCtx: InvocationCtx): void => {\n scratch.lastMove = moveCtx;\n if (scratch.part !== 'anchor') return moveHandle(scratch, moveCtx, paramsOf(opts));\n moveAnchors(scratch, snapAnchor.at(moveCtx.world, snapMods(moveCtx)));\n };\n\n return {\n kind: 'edit-anchors',\n onMove(moveCtx: InvocationCtx): void {\n move(moveCtx);\n active = true;\n },\n onWheel(wheelCtx: InvocationCtx): boolean {\n if (!wheelCtx.wheel || !claimWheel(scratch.drags, wheelCtx.wheel)) return false;\n if (scratch.lastMove) move(scratch.lastMove);\n return true;\n },\n overlay(): readonly OngoingOverlay[] | null {\n if (!active) return null;\n const extra = scratch.drags.length > 0\n ? extensionOverlays(scratch.drags, pathToAnchors(scratch.currentPose) as AnchorSet)\n : [];\n const all = scratch.guide ? [scratch.guide, ...extra] : extra;\n return all.length > 0 ? all : null;\n },\n onEnd(_endCtx: InvocationCtx, reason: 'commit' | 'cancel'): void {\n active = false;\n try {\n if (reason === 'cancel' || scratch.originPose === scratch.currentPose) return;\n scratch.dep.applyEdit(scratch.id, scratch.currentPose, 'Edit anchors', scratch.origins);\n } finally {\n snapAnchor.end();\n endExtensionDrags(scratch.drags);\n }\n },\n previewIds: preview.previewIds,\n previewPose: preview.previewPose,\n previewData: preview.previewData,\n };\n },\n },\n // A path-edit tool has the drag.\n enabled: (deps) => (pathEditToolActive(deps) ? ActionDisabledReason.NotApplicable : true),\n}, editingLayer);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"action.js","names":[],"sources":["../../../../src/interactions/actions/edit-anchors/action.ts"],"sourcesContent":["/**\n * `editAnchorsAction` — ongoing Action descriptor for editing polygon anchors.\n *\n * - **Press** selects. Bare press replaces the anchor selection; Shift\n * toggles the pressed anchor in or out of it. Pressing an anchor that\n * is already part of a multi-anchor selection leaves the selection\n * alone, so you can grab a set and move it.\n * - **Drag** then moves whatever the press left selected — one anchor,\n * or every selected anchor together. The pressed anchor snaps through\n * the `snap` dep's `point` session, to what the drag leaves still of the\n * path and to the canvas's targets; Shift holds it to the axes and\n * diagonals through its press, and Ctrl suspends the snap.\n * - **Dragging a control handle** moves just that handle, mirroring the\n * opposite one while the anchor is smooth. Alt breaks the mirror; Shift\n * holds the handle to the angle it had at the press, changing only its\n * length; Mod (Cmd or Ctrl) holds its length, changing only its angle;\n * both freeze it. The `editAnchors` dep's `handleLocks`, or else the\n * `handleLock` param ({@link EditAnchorsParams}), holds a lock with no\n * modifier. The lock in force draws its guide as a `polyline` overlay\n * of role `lock`: the line, or the circle round the anchor.\n * - **Path-edit extensions shape the drag** through their `drag`: anchors\n * that follow an anchor drag by a share of it, where a dragged handle\n * goes after the locks, the wheel mid-drag, and overlays of their own.\n * - **Every frame is finished** by the dep's `finishEdit`, so what a\n * path-edit extension keeps true holds while the drag runs.\n * - **Under a `pathSymmetry` dep**, on a path that is its own image under\n * some of its transforms, every image of what is dragged follows it.\n *\n * Selection lives on the `editAnchors` dep (flat anchor indices) rather\n * than in this handle's scratch, because the keyboard actions\n * (`nudgeAnchors`, `deleteAnchors`) and the overlay all need to read it\n * between gestures.\n *\n * Operational when the consumer wires the `editAnchors` dep, and\n * `buildAffordanceAt` with a `getAnchorState` thunk so the dispatcher\n * classifies anchor/control-handle hits as `anchor:N`, `controlIn:N`, or\n * `controlOut:N` affordances on pointerdown. On any other affordance `start`\n * returns `{}` so other bindings can handle the drag.\n */\n\nimport type { Action } from '@weasel-js/routing';\nimport type { BindingOpts, InvocationCtx, OngoingHandle, OngoingOverlay } from '@weasel-js/routing';\nimport type { EditAnchorsDep, SnapDep } from '../depSchema';\nimport type { SnapBegin, SnapMods, SnapSession } from '../snapDep';\nimport { inputSession } from 'features/snap/session2d';\nimport { SNAP_ROLES, snapMods } from 'features/snap/roles';\nimport { ActionDisabledReason, isAnchorOrControl, resolveParams, roleReader, type ModifierRoles } from '@weasel-js/routing';\nimport {\n anchorAt,\n editAnchorSetTracked,\n moveHandleSymmetric,\n moveHandleTo,\n pathAwayFromAnchors,\n translateAnchorsSymmetric,\n type AnchorSet,\n type AnchorSymmetry,\n type PenAnchor,\n type PointOrigin,\n} from '@weasel-js/geom';\nimport { pathToAnchors, type PolygonPath } from '@weasel-js/geom';\nimport { inPlane, editingLayer } from '../planeInput';\nimport { HANDLE_LOCK_ROLES, lockHandle, locksInForce, type HandlePress } from './handleDrag';\nimport { locksOf, type EditAnchorsParams } from './params';\nimport { finishPathEditFrame, pathEditPreview } from './preview';\nimport {\n claimWheel, dragWeights, endExtensionDrags, extensionOverlays, placeHandle, startExtensionDrags, translateWeighted,\n} from './extensionDrags';\nimport type { PathEditDrag } from 'features/paths/pathEditExtension';\nimport { pathEditToolActive } from '../defaults/pathEditTools';\nimport { editedPathSymmetries } from './symmetry';\nimport { pathOperationTags } from '../pathGestureTags';\n\n/**\n * Parse an anchor affordance kind — `'anchor:N'` | `'controlIn:N'` |\n * `'controlOut:N'`, where N is the flat anchor index — or `null` when the\n * affordance is not an anchor kind.\n */\nfunction parseAnchorAffordance(\n kind: string,\n): { anchorIndex: number; part: 'anchor' | 'controlIn' | 'controlOut' } | null {\n const m = kind.match(/^(anchor|controlIn|controlOut):(\\d+)$/);\n if (!m) return null;\n return {\n anchorIndex: parseInt(m[2], 10),\n part: m[1] as 'anchor' | 'controlIn' | 'controlOut',\n };\n}\n\n/**\n * Resolve what a press on `anchorIndex` should leave selected.\n *\n * Shift toggles. A bare press on an anchor that's already part of the\n * selection keeps the selection intact (so the drag moves the whole set);\n * a bare press anywhere else collapses to just that anchor.\n */\nexport function selectionAfterAnchorPress(\n current: ReadonlySet<number>,\n anchorIndex: number,\n additive: boolean,\n): Set<number> {\n if (additive) {\n const next = new Set(current);\n if (next.has(anchorIndex)) next.delete(anchorIndex);\n else next.add(anchorIndex);\n return next;\n }\n if (current.has(anchorIndex) && current.size > 1) return new Set(current);\n return new Set([anchorIndex]);\n}\n\ninterface EditAnchorsScratch {\n dep: EditAnchorsDep;\n id: string;\n anchorIndex: number;\n /** `'anchor'` drags on-curve points (and their handles) by a delta.\n * `'controlIn'` / `'controlOut'` drag one control point to an absolute\n * world coord. */\n part: 'anchor' | 'controlIn' | 'controlOut';\n /** Anchors this drag moves — the pressed one, or the whole anchor\n * selection when the press landed inside it. Flat indices. */\n dragging: readonly number[];\n /** World position of the pressed anchor at drag start; the drag delta is\n * measured from here rather than accumulated per move, so the geometry\n * is always derived from `originPose` in one step. */\n anchorOrigin: { x: number; y: number };\n /** The anchor and the dragged control handle at the press, for a handle drag. */\n handlePress: HandlePress | null;\n /** The guide the lock in force drew at the last move. */\n guide: OngoingOverlay | null;\n /** The path-edit extensions' shares of this drag. */\n drags: readonly PathEditDrag[];\n /** The last move, to redo when an extension claims the wheel. */\n lastMove: InvocationCtx | null;\n originPose: PolygonPath;\n currentPose: PolygonPath;\n /** The transforms `originPose` is its own image under, read at the press. */\n symmetries: readonly AnchorSymmetry[];\n /** Where each point of `currentPose` came from in `originPose`. */\n origins?: readonly (PointOrigin | null)[];\n /** Other nodes' world paths the finished edit moves with it. */\n others: readonly { id: string; path: PolygonPath }[];\n}\n\ntype Point = { x: number; y: number };\n\n/**\n * An anchor drag's snap: a `point` session, begun on the first move, for\n * where the pressed anchor goes. The edited path offers no targets but what\n * the drag leaves still of it, and Shift holds the anchor to the axes and\n * diagonals through its press.\n */\nfunction anchorDragSnap(\n snap: SnapDep | undefined,\n press: { id: string; origin: Point; originPose: PolygonPath; dragging: readonly number[] },\n): { at(world: Point, mods: SnapMods): Point; end(): void } {\n let session: SnapSession | null = null;\n return {\n at(world, mods) {\n if (!session) {\n const { path, anchors } = pathAwayFromAnchors(press.originPose, press.dragging);\n const req: SnapBegin = {\n gesture: 'point', press: press.origin, ids: [press.id],\n also: { paths: [path], anchors }, constrain: 'axis',\n };\n session = snap?.begin(req) ?? inputSession(req);\n }\n return session.at(world, mods).point;\n },\n end() {\n session?.end();\n session = null;\n },\n };\n}\n\nconst paramsOf = (opts: BindingOpts | undefined): EditAnchorsParams =>\n (resolveParams(opts?.params) ?? {}) as EditAnchorsParams;\n\n/** Take `next` as the frame to show, finished by the dep. A frame it cannot\n * finish is dropped, so the path stays at the last one it could. */\nfunction track(scratch: EditAnchorsScratch, next: ReturnType<typeof editAnchorSetTracked>): void {\n if (!next) return;\n const { dep, id } = scratch;\n const done = finishPathEditFrame(dep, id, next.path, next.origins);\n if (!done) return;\n scratch.currentPose = done.path as PolygonPath;\n scratch.others = done.others as EditAnchorsScratch['others'];\n scratch.origins = next.origins;\n}\n\n/** The anchor and the handle a press on `part` grabbed; null for an anchor press. */\nfunction handlePressOf(\n origin: PenAnchor,\n part: EditAnchorsScratch['part'],\n): HandlePress | null {\n const handle = part === 'controlIn' ? origin.inHandle : part === 'controlOut' ? origin.outHandle : undefined;\n return handle ? { anchor: { x: origin.x, y: origin.y }, handle: { ...handle } } : null;\n}\n\n/** Move the dragged anchors to follow `to`, and the anchors the extensions\n * weight by their shares. A weighted drag moves no symmetric images. */\nfunction moveAnchors(scratch: EditAnchorsScratch, to: Point): void {\n if (scratch.dragging.length === 0) return;\n const dx = to.x - scratch.anchorOrigin.x;\n const dy = to.y - scratch.anchorOrigin.y;\n const weights = dragWeights(scratch.drags, scratch.dragging);\n track(scratch, editAnchorSetTracked(scratch.originPose, (set) => {\n if (weights) translateWeighted(set, weights, dx, dy);\n else translateAnchorsSymmetric(set, scratch.dragging, dx, dy, scratch.symmetries);\n }));\n}\n\n/** The modifiers `editAnchors` reads while it runs: Shift on the press adds\n * to the anchor selection, Alt breaks a smooth anchor's mirror, the handle\n * locks, and Shift holds an anchor drag to the axes and diagonals. An anchor\n * drag also reads `snap.suspend` at its default key, Ctrl, which is not\n * declared here because on a handle Ctrl holds the length. */\nexport const EDIT_ANCHORS_ROLES = {\n 'selection.add': { label: 'Add to the anchor selection', keys: ['shift'] },\n 'mirror.break': { label: \"Break the handles' mirror\", keys: ['alt'] },\n ...HANDLE_LOCK_ROLES,\n 'snap.constrain': SNAP_ROLES['snap.constrain'],\n} as const satisfies ModifierRoles;\n\nconst roleHeld = roleReader(EDIT_ANCHORS_ROLES);\n\n/** Move the dragged handle toward the pointer, under the locks in force, then\n * wherever the extensions place it. */\nfunction moveHandle(scratch: EditAnchorsScratch, ctx: InvocationCtx, params: EditAnchorsParams): void {\n const side = scratch.part === 'controlIn' ? 'in' : 'out';\n // Modifiers and held locks are read live, so either can change mid-drag.\n const held = (ctx.deps.editAnchors ?? scratch.dep).handleLocks ?? locksOf(params.handleLock);\n const locks = locksInForce(held, ctx);\n const locked = scratch.handlePress ? lockHandle(scratch.handlePress, ctx.world, locks) : { to: ctx.world, guide: null };\n scratch.guide = locked.guide;\n const to = placeHandle(scratch.drags, locked.to, { locks });\n const alt = roleHeld(ctx, 'mirror.break');\n const move = scratch.symmetries.length > 0\n ? (set: AnchorSet) => moveHandleSymmetric(set, scratch.anchorIndex, side, to.x, to.y, alt, scratch.symmetries)\n : (set: AnchorSet) => moveHandleTo(set, scratch.anchorIndex, side, to.x, to.y, alt);\n track(scratch, editAnchorSetTracked(scratch.originPose, move));\n}\n\n/**\n * What a press drags, the selection updated first, before any move: a handle\n * press drags its anchor's handle; an anchor press selects as\n * {@link selectionAfterAnchorPress} says and drags what it left selected —\n * nothing when Shift took the pressed anchor out of it.\n */\nfunction draggedByPress(\n dep: EditAnchorsDep,\n press: { anchorIndex: number; part: EditAnchorsScratch['part'] },\n shift: boolean,\n): readonly number[] {\n if (press.part !== 'anchor') return [press.anchorIndex];\n const next = selectionAfterAnchorPress(dep.selectedAnchors, press.anchorIndex, shift);\n dep.setSelectedAnchors(next);\n return next.has(press.anchorIndex) ? [...next] : [];\n}\n\n/** Static descriptor for the `editAnchors` Action. */\nexport const editAnchorsAction: Action & { requires: string[] } = inPlane({\n id: 'editAnchors',\n label: 'Edit Anchors',\n tags: pathOperationTags('drag'),\n defaultBinding: [{\n spec: {\n kind: 'drag',\n // Only matches drags whose pointerdown hit an anchor or control handle.\n // Ties moveAction's `selected-body` on specificity and registers after\n // it, so move declines these presses in `start`.\n target: { kindOf: isAnchorOrControl },\n },\n opts: { id: 'editAnchors.drag' },\n }],\n eligible: { capability: 'edits-anchors' },\n modifierRoles: EDIT_ANCHORS_ROLES,\n requires: ['selection', 'editAnchors', 'pathSymmetry', 'snap'],\n invoker: {\n timing: 'ongoing',\n start(ctx: InvocationCtx, opts): OngoingHandle {\n const dep = ctx.deps.editAnchors;\n if (!dep) return {};\n\n const affordance = ctx.drag?.affordance;\n if (!affordance) {\n // No affordance hit → this drag doesn't target an anchor handle.\n // Let other bindings handle it (the handle returns {}, dispatcher moves on).\n return {};\n }\n\n const anchorInfo = parseAnchorAffordance(affordance.kind);\n if (!anchorInfo) {\n // Affordance is a non-anchor kind (e.g. resize handle, rotate handle).\n return {};\n }\n\n const { editingId } = dep;\n // World-coord polygon. For pose-as-polygon nodes this equals\n // node.pose; for data.path nodes it's pathInWorld-projected (translate +\n // rotation) so the anchor world coords match what the user clicked.\n const worldPath = dep.getEditablePath(editingId) as PolygonPath | undefined;\n if (!worldPath || worldPath.kind !== 'polygon') return {};\n\n // Decode once to validate the affordance index against the actual\n // geometry and to read the press origin. A stale affordance (the\n // path changed between pointerdown and now) fails here rather than\n // silently editing whichever anchor now holds that index.\n const decoded = pathToAnchors(worldPath) as AnchorSet;\n const origin = anchorAt(decoded, anchorInfo.anchorIndex);\n if (!origin) return {};\n if (anchorInfo.part === 'controlIn' && !origin.inHandle) return {};\n if (anchorInfo.part === 'controlOut' && !origin.outHandle) return {};\n\n let active = false;\n const preview = pathEditPreview(\n dep, editingId, () => (active ? { path: scratch.currentPose } : null), () => (active ? scratch.others : []),\n );\n if (!preview) return {};\n\n const dragging = draggedByPress(dep, anchorInfo, roleHeld(ctx, 'selection.add'));\n\n const scratch: EditAnchorsScratch = {\n dep,\n id: editingId,\n anchorIndex: anchorInfo.anchorIndex,\n part: anchorInfo.part,\n dragging,\n anchorOrigin: { x: origin.x, y: origin.y },\n handlePress: handlePressOf(origin, anchorInfo.part),\n guide: null,\n drags: startExtensionDrags(dep.extensions, {\n id: editingId,\n node: dep.getNodeShape(editingId),\n path: worldPath,\n anchors: decoded,\n part: anchorInfo.part,\n anchorIndex: anchorInfo.anchorIndex,\n dragging: anchorInfo.part === 'anchor' ? dragging : [],\n scale: ctx.deps.view?.get().scale,\n ...(ctx.deps.snap ? { snap: ctx.deps.snap } : {}),\n }),\n lastMove: null,\n originPose: worldPath,\n currentPose: worldPath,\n symmetries: editedPathSymmetries(ctx.deps.pathSymmetry, editingId, decoded),\n others: [],\n };\n const snapAnchor = anchorDragSnap(ctx.deps.snap, {\n id: editingId, origin: scratch.anchorOrigin, originPose: worldPath, dragging,\n });\n\n const move = (moveCtx: InvocationCtx): void => {\n scratch.lastMove = moveCtx;\n if (scratch.part !== 'anchor') return moveHandle(scratch, moveCtx, paramsOf(opts));\n moveAnchors(scratch, snapAnchor.at(moveCtx.world, snapMods(moveCtx)));\n };\n\n return {\n kind: 'edit-anchors',\n onMove(moveCtx: InvocationCtx): void {\n move(moveCtx);\n active = true;\n },\n onWheel(wheelCtx: InvocationCtx): boolean {\n if (!wheelCtx.wheel || !claimWheel(scratch.drags, wheelCtx.wheel)) return false;\n if (scratch.lastMove) move(scratch.lastMove);\n return true;\n },\n overlay(): readonly OngoingOverlay[] | null {\n if (!active) return null;\n const extra = scratch.drags.length > 0\n ? extensionOverlays(scratch.drags, pathToAnchors(scratch.currentPose) as AnchorSet)\n : [];\n const all = scratch.guide ? [scratch.guide, ...extra] : extra;\n return all.length > 0 ? all : null;\n },\n onEnd(_endCtx: InvocationCtx, reason: 'commit' | 'cancel'): void {\n active = false;\n try {\n if (reason === 'cancel' || scratch.originPose === scratch.currentPose) return;\n scratch.dep.applyEdit(scratch.id, scratch.currentPose, 'Edit anchors', scratch.origins);\n } finally {\n snapAnchor.end();\n endExtensionDrags(scratch.drags);\n }\n },\n previewIds: preview.previewIds,\n previewPose: preview.previewPose,\n previewData: preview.previewData,\n };\n },\n },\n // A path-edit tool has the drag.\n enabled: (deps) => (pathEditToolActive(deps) ? ActionDisabledReason.NotApplicable : true),\n}, editingLayer);\n"],"mappings":"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"}
|
|
@@ -1,17 +1,31 @@
|
|
|
1
1
|
import { storeEditablePath } from "../../../features/paths/editablePath.js";
|
|
2
2
|
|
|
3
3
|
//#region src/interactions/actions/edit-anchors/preview.ts
|
|
4
|
+
/** `path`, a frame of an edit of `id`, finished by the dep's `finishEdit` as
|
|
5
|
+
* committing it would be: its path and the other nodes' that move with it.
|
|
6
|
+
* Null when an extension cannot finish it. */
|
|
7
|
+
function finishPathEditFrame(dep, id, path, origins) {
|
|
8
|
+
return dep.finishEdit ? dep.finishEdit(id, path, origins) : {
|
|
9
|
+
path,
|
|
10
|
+
others: []
|
|
11
|
+
};
|
|
12
|
+
}
|
|
4
13
|
/**
|
|
5
14
|
* Preview ghosts for a drag that reshapes the path in edit mode. `current`
|
|
6
|
-
* answers the
|
|
7
|
-
*
|
|
8
|
-
*
|
|
15
|
+
* answers the frame to show, or null while there is nothing to preview yet.
|
|
16
|
+
* Each frame is finished as committing it would be
|
|
17
|
+
* ({@link finishPathEditFrame}), so the node's constraints and the nodes
|
|
18
|
+
* linked to it show as they will commit; a frame that cannot be finished
|
|
19
|
+
* commits nothing, and shows nothing. A drag that finishes its own frames
|
|
20
|
+
* passes `finished`, the world-space paths of the other nodes its frame
|
|
21
|
+
* moves, and its frames are shown as they are. Null when the node stores its
|
|
22
|
+
* path in neither supported place.
|
|
9
23
|
*
|
|
10
|
-
* The ghost is what committing
|
|
24
|
+
* The ghost is what committing the frame would store (`storeEditablePath`),
|
|
11
25
|
* so a path drawn from a form is drawn again from the edited form on every
|
|
12
26
|
* move.
|
|
13
27
|
*/
|
|
14
|
-
function pathEditPreview(dep, id, current,
|
|
28
|
+
function pathEditPreview(dep, id, current, finished) {
|
|
15
29
|
const storageKind = dep.getStorageKind(id);
|
|
16
30
|
if (storageKind !== "pose" && storageKind !== "data") return null;
|
|
17
31
|
const origin = dep.getNodeShape(id) ?? (storageKind === "pose" ? {
|
|
@@ -19,10 +33,26 @@ function pathEditPreview(dep, id, current, others = () => []) {
|
|
|
19
33
|
data: void 0
|
|
20
34
|
} : null);
|
|
21
35
|
if (!origin) return null;
|
|
36
|
+
let lastFrame = null;
|
|
37
|
+
let lastFinished = null;
|
|
38
|
+
const shown = () => {
|
|
39
|
+
const frame = current();
|
|
40
|
+
if (!frame) return null;
|
|
41
|
+
if (finished) return {
|
|
42
|
+
path: frame.path,
|
|
43
|
+
others: finished()
|
|
44
|
+
};
|
|
45
|
+
if (frame.path !== lastFrame) {
|
|
46
|
+
lastFrame = frame.path;
|
|
47
|
+
lastFinished = finishPathEditFrame(dep, id, frame.path, frame.origins);
|
|
48
|
+
}
|
|
49
|
+
return lastFinished;
|
|
50
|
+
};
|
|
51
|
+
const others = () => shown()?.others ?? [];
|
|
22
52
|
let lastPath = null;
|
|
23
53
|
let lastStored = null;
|
|
24
54
|
const stored = (pid) => {
|
|
25
|
-
const path = pid === id ?
|
|
55
|
+
const path = pid === id ? shown()?.path : null;
|
|
26
56
|
if (!path) return null;
|
|
27
57
|
if (path !== lastPath) {
|
|
28
58
|
lastPath = path;
|
|
@@ -50,7 +80,10 @@ function pathEditPreview(dep, id, current, others = () => []) {
|
|
|
50
80
|
};
|
|
51
81
|
return {
|
|
52
82
|
storageKind,
|
|
53
|
-
previewIds: () =>
|
|
83
|
+
previewIds: () => {
|
|
84
|
+
const frame = shown();
|
|
85
|
+
return frame ? [id, ...frame.others.map((o) => o.id)] : null;
|
|
86
|
+
},
|
|
54
87
|
previewPose: (pid) => (pid === id ? stored(pid)?.pose : storedOther(pid)?.to.pose) ?? null,
|
|
55
88
|
previewData: (pid) => {
|
|
56
89
|
if (pid !== id) {
|
|
@@ -64,5 +97,5 @@ function pathEditPreview(dep, id, current, others = () => []) {
|
|
|
64
97
|
}
|
|
65
98
|
|
|
66
99
|
//#endregion
|
|
67
|
-
export { pathEditPreview };
|
|
100
|
+
export { finishPathEditFrame, pathEditPreview };
|
|
68
101
|
//# sourceMappingURL=preview.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preview.js","names":[],"sources":["../../../../src/interactions/actions/edit-anchors/preview.ts"],"sourcesContent":["import type { OngoingHandle } from '@weasel-js/routing';\nimport type { EditAnchorsDep } from '../depSchema';\nimport type { PolygonPath } from '@weasel-js/geom';\nimport { storeEditablePath, type EditableShape } from 'features/paths/editablePath';\n\n/** Where the edited polygon lives on its node: the pose itself, or `data.path`\n * under a rect pose. */\nexport type PathStorageKind = 'pose' | 'data';\n\n/** The preview half of an ongoing path edit, captured at press. */\nexport interface PathEditPreview {\n storageKind: PathStorageKind;\n previewIds: NonNullable<OngoingHandle['previewIds']>;\n previewPose: NonNullable<OngoingHandle['previewPose']>;\n previewData: NonNullable<OngoingHandle['previewData']>;\n}\n\n/**\n * Preview ghosts for a drag that reshapes the path in edit mode. `current`\n * answers the
|
|
1
|
+
{"version":3,"file":"preview.js","names":[],"sources":["../../../../src/interactions/actions/edit-anchors/preview.ts"],"sourcesContent":["import type { OngoingHandle } from '@weasel-js/routing';\nimport type { EditAnchorsDep } from '../depSchema';\nimport type { FinishedEditFrame } from '../editAnchorsDep';\nimport type { PointOrigin, PolygonPath } from '@weasel-js/geom';\nimport { storeEditablePath, type EditableShape } from 'features/paths/editablePath';\n\n/** Where the edited polygon lives on its node: the pose itself, or `data.path`\n * under a rect pose. */\nexport type PathStorageKind = 'pose' | 'data';\n\n/** The preview half of an ongoing path edit, captured at press. */\nexport interface PathEditPreview {\n storageKind: PathStorageKind;\n previewIds: NonNullable<OngoingHandle['previewIds']>;\n previewPose: NonNullable<OngoingHandle['previewPose']>;\n previewData: NonNullable<OngoingHandle['previewData']>;\n}\n\n/** One frame of a drag that reshapes the path in edit mode: the world-space\n * polygon it makes, and where each of its points came from when the drag\n * knows (`editAnchorSetTracked`). */\nexport interface PathEditFrame {\n path: PolygonPath;\n origins?: readonly (PointOrigin | null)[];\n}\n\ntype ShownFrame = { path: PolygonPath; others: readonly { id: string; path: PolygonPath }[] };\n\n/** `path`, a frame of an edit of `id`, finished by the dep's `finishEdit` as\n * committing it would be: its path and the other nodes' that move with it.\n * Null when an extension cannot finish it. */\nexport function finishPathEditFrame(\n dep: EditAnchorsDep,\n id: string,\n path: PolygonPath,\n origins?: readonly (PointOrigin | null)[],\n): FinishedEditFrame | null {\n return dep.finishEdit ? dep.finishEdit(id, path, origins) : { path, others: [] };\n}\n\n/**\n * Preview ghosts for a drag that reshapes the path in edit mode. `current`\n * answers the frame to show, or null while there is nothing to preview yet.\n * Each frame is finished as committing it would be\n * ({@link finishPathEditFrame}), so the node's constraints and the nodes\n * linked to it show as they will commit; a frame that cannot be finished\n * commits nothing, and shows nothing. A drag that finishes its own frames\n * passes `finished`, the world-space paths of the other nodes its frame\n * moves, and its frames are shown as they are. Null when the node stores its\n * path in neither supported place.\n *\n * The ghost is what committing the frame would store (`storeEditablePath`),\n * so a path drawn from a form is drawn again from the edited form on every\n * move.\n */\nexport function pathEditPreview(\n dep: EditAnchorsDep,\n id: string,\n current: () => PathEditFrame | null,\n finished?: () => readonly { id: string; path: PolygonPath }[],\n): PathEditPreview | null {\n const storageKind = dep.getStorageKind(id);\n if (storageKind !== 'pose' && storageKind !== 'data') return null;\n // The node as it was at the press, which every ghost is stored from. A dep\n // that hands out no shape still says a pose-stored polygon is the pose.\n const origin = dep.getNodeShape(id)\n ?? (storageKind === 'pose' ? { pose: dep.getEditablePath(id), data: undefined } : null);\n if (!origin) return null;\n\n // Each frame is finished once, however many times the dispatcher asks for it.\n let lastFrame: PolygonPath | null = null;\n let lastFinished: ShownFrame | null = null;\n const shown = (): ShownFrame | null => {\n const frame = current();\n if (!frame) return null;\n if (finished) return { path: frame.path, others: finished() };\n if (frame.path !== lastFrame) {\n lastFrame = frame.path;\n lastFinished = finishPathEditFrame(dep, id, frame.path, frame.origins) as ShownFrame | null;\n }\n return lastFinished;\n };\n const others = () => shown()?.others ?? [];\n\n // previewPose and previewData are both asked each frame; store once per path.\n let lastPath: PolygonPath | null = null;\n let lastStored: EditableShape | null = null;\n const stored = (pid: string): EditableShape | null => {\n const path = pid === id ? shown()?.path : null;\n if (!path) return null;\n if (path !== lastPath) {\n lastPath = path;\n lastStored = storeEditablePath(origin, path, dep.extensions);\n }\n return lastStored;\n };\n\n // Another node's ghost, stored from that node as the press found it, once per path.\n const otherOrigins = new Map<string, EditableShape | null>();\n const otherStored = new Map<string, { path: PolygonPath; stored: EditableShape | null }>();\n const storedOther = (pid: string): { from: EditableShape; to: EditableShape } | null => {\n const path = others().find((o) => o.id === pid)?.path;\n if (!path) return null;\n if (!otherOrigins.has(pid)) otherOrigins.set(pid, dep.getNodeShape(pid));\n const from = otherOrigins.get(pid);\n if (!from) return null;\n let hit = otherStored.get(pid);\n if (hit?.path !== path) otherStored.set(pid, (hit = { path, stored: storeEditablePath(from, path, dep.extensions) }));\n return hit.stored ? { from, to: hit.stored } : null;\n };\n\n return {\n storageKind,\n previewIds: () => {\n const frame = shown();\n return frame ? [id, ...frame.others.map((o) => o.id)] : null;\n },\n previewPose: (pid: string): unknown | null =>\n (pid === id ? stored(pid)?.pose : storedOther(pid)?.to.pose) ?? null,\n previewData: (pid: string): unknown | null => {\n if (pid !== id) {\n const o = storedOther(pid);\n return o && o.to.data !== o.from.data ? o.to.data : null;\n }\n const next = stored(pid);\n return next && next.data !== origin.data ? next.data : null;\n },\n };\n}\n"],"mappings":";;;;;;AA+BA,SAAgB,oBACd,KACA,IACA,MACA,SAC0B;CAC1B,OAAO,IAAI,aAAa,IAAI,WAAW,IAAI,MAAM,OAAO,IAAI;EAAE;EAAM,QAAQ,CAAC;CAAE;AACjF;;;;;;;;;;;;;;;;AAiBA,SAAgB,gBACd,KACA,IACA,SACA,UACwB;CACxB,MAAM,cAAc,IAAI,eAAe,EAAE;CACzC,IAAI,gBAAgB,UAAU,gBAAgB,QAAQ,OAAO;CAG7D,MAAM,SAAS,IAAI,aAAa,EAAE,MAC5B,gBAAgB,SAAS;EAAE,MAAM,IAAI,gBAAgB,EAAE;EAAG,MAAM;CAAU,IAAI;CACpF,IAAI,CAAC,QAAQ,OAAO;CAGpB,IAAI,YAAgC;CACpC,IAAI,eAAkC;CACtC,MAAM,cAAiC;EACrC,MAAM,QAAQ,QAAQ;EACtB,IAAI,CAAC,OAAO,OAAO;EACnB,IAAI,UAAU,OAAO;GAAE,MAAM,MAAM;GAAM,QAAQ,SAAS;EAAE;EAC5D,IAAI,MAAM,SAAS,WAAW;GAC5B,YAAY,MAAM;GAClB,eAAe,oBAAoB,KAAK,IAAI,MAAM,MAAM,MAAM,OAAO;EACvE;EACA,OAAO;CACT;CACA,MAAM,eAAe,MAAM,CAAC,EAAE,UAAU,CAAC;CAGzC,IAAI,WAA+B;CACnC,IAAI,aAAmC;CACvC,MAAM,UAAU,QAAsC;EACpD,MAAM,OAAO,QAAQ,KAAK,MAAM,CAAC,EAAE,OAAO;EAC1C,IAAI,CAAC,MAAM,OAAO;EAClB,IAAI,SAAS,UAAU;GACrB,WAAW;GACX,aAAa,kBAAkB,QAAQ,MAAM,IAAI,UAAU;EAC7D;EACA,OAAO;CACT;CAGA,MAAM,+BAAe,IAAI,IAAkC;CAC3D,MAAM,8BAAc,IAAI,IAAiE;CACzF,MAAM,eAAe,QAAmE;EACtF,MAAM,OAAO,OAAO,CAAC,CAAC,MAAM,MAAM,EAAE,OAAO,GAAG,CAAC,EAAE;EACjD,IAAI,CAAC,MAAM,OAAO;EAClB,IAAI,CAAC,aAAa,IAAI,GAAG,GAAG,aAAa,IAAI,KAAK,IAAI,aAAa,GAAG,CAAC;EACvE,MAAM,OAAO,aAAa,IAAI,GAAG;EACjC,IAAI,CAAC,MAAM,OAAO;EAClB,IAAI,MAAM,YAAY,IAAI,GAAG;EAC7B,IAAI,KAAK,SAAS,MAAM,YAAY,IAAI,KAAM,MAAM;GAAE;GAAM,QAAQ,kBAAkB,MAAM,MAAM,IAAI,UAAU;EAAE,CAAE;EACpH,OAAO,IAAI,SAAS;GAAE;GAAM,IAAI,IAAI;EAAO,IAAI;CACjD;CAEA,OAAO;EACL;EACA,kBAAkB;GAChB,MAAM,QAAQ,MAAM;GACpB,OAAO,QAAQ,CAAC,IAAI,GAAG,MAAM,OAAO,KAAK,MAAM,EAAE,EAAE,CAAC,IAAI;EAC1D;EACA,cAAc,SACX,QAAQ,KAAK,OAAO,GAAG,CAAC,EAAE,OAAO,YAAY,GAAG,CAAC,EAAE,GAAG,SAAS;EAClE,cAAc,QAAgC;GAC5C,IAAI,QAAQ,IAAI;IACd,MAAM,IAAI,YAAY,GAAG;IACzB,OAAO,KAAK,EAAE,GAAG,SAAS,EAAE,KAAK,OAAO,EAAE,GAAG,OAAO;GACtD;GACA,MAAM,OAAO,OAAO,GAAG;GACvB,OAAO,QAAQ,KAAK,SAAS,OAAO,OAAO,KAAK,OAAO;EACzD;CACF;AACF"}
|
|
@@ -2,11 +2,12 @@ import { unionAABB } from "../../../core/geometry/unionBounds.js";
|
|
|
2
2
|
import { isNoInkExtents } from "../../../core/geometry/inkExtents.js";
|
|
3
3
|
import { scenePoseFrame } from "../poseFrame.js";
|
|
4
4
|
import { poseDescriptorOf } from "../poseDescriptorDep.js";
|
|
5
|
-
import {
|
|
5
|
+
import { defaultCommitAdapter } from "../defaultCommitAdapter.js";
|
|
6
|
+
import { transformApplyOps } from "../transformFinish.js";
|
|
6
7
|
import { createTransformOp } from "../../../core/ops/transform.js";
|
|
8
|
+
import { shapeSources } from "../selectionSubtree.js";
|
|
7
9
|
import { geometryDataOp } from "../geometryProjection.js";
|
|
8
10
|
import { drawnBoxes } from "../drawnBoxes.js";
|
|
9
|
-
import { defaultCommitAdapter } from "../defaultCommitAdapter.js";
|
|
10
11
|
import { flipPoseAboutBounds, flipPoseViaDescriptor } from "./helpers.js";
|
|
11
12
|
import { actionReferenceSources, resolveSpatialReference } from "../spatialReference.js";
|
|
12
13
|
import { requiresSelection } from "../defaults/requiresSelection.js";
|
|
@@ -141,14 +142,20 @@ var flipAction = {
|
|
|
141
142
|
key: ["h", "H"],
|
|
142
143
|
mods: { shift: true }
|
|
143
144
|
},
|
|
144
|
-
opts: {
|
|
145
|
+
opts: {
|
|
146
|
+
id: "flip.x",
|
|
147
|
+
params: { axis: "x" }
|
|
148
|
+
}
|
|
145
149
|
}, {
|
|
146
150
|
spec: {
|
|
147
151
|
kind: "key",
|
|
148
152
|
key: ["v", "V"],
|
|
149
153
|
mods: { shift: true }
|
|
150
154
|
},
|
|
151
|
-
opts: {
|
|
155
|
+
opts: {
|
|
156
|
+
id: "flip.y",
|
|
157
|
+
params: { axis: "y" }
|
|
158
|
+
}
|
|
152
159
|
}],
|
|
153
160
|
eligible: { capability: "transforms-selection" },
|
|
154
161
|
requires: [
|
|
@@ -159,7 +166,8 @@ var flipAction = {
|
|
|
159
166
|
"poseDescriptor",
|
|
160
167
|
"pointer",
|
|
161
168
|
"view",
|
|
162
|
-
"boundsIncludeStroke"
|
|
169
|
+
"boundsIncludeStroke",
|
|
170
|
+
"transformFollowers"
|
|
163
171
|
],
|
|
164
172
|
invoker: {
|
|
165
173
|
timing: "immediate",
|
|
@@ -168,7 +176,7 @@ var flipAction = {
|
|
|
168
176
|
const pivot = params?.pivot ?? "each";
|
|
169
177
|
const selection = deps.selection;
|
|
170
178
|
const scene = deps.scene;
|
|
171
|
-
const applyOps = deps
|
|
179
|
+
const applyOps = transformApplyOps(deps);
|
|
172
180
|
const geometryProjection = deps.geometryProjection;
|
|
173
181
|
if (!selection || !scene) return;
|
|
174
182
|
flipSelection(selection, scene, axis, pivot, applyOps, geometryProjection, poseDescriptorOf(deps.poseDescriptor), params, deps.pointer, (frame) => drawnBoxes(deps, frame));
|