@weasel-js/core 1.11.0 → 1.11.1
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 +427 -0
- package/README.md +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 +7 -3
- package/dist/barrel/interactions.js +5 -4
- package/dist/barrel/paths.js +3 -3
- package/dist/barrel/renderer.js +3 -2
- package/dist/barrel/routing.js +6 -11
- package/dist/barrel/scene.js +8 -5
- package/dist/barrel/viewport.js +4 -3
- package/dist/canvas/Canvas.js +3 -1
- package/dist/canvas/Canvas.js.map +1 -1
- package/dist/canvas/SceneCanvas/SceneCanvasInput.js +17 -3
- package/dist/canvas/SceneCanvas/SceneCanvasInput.js.map +1 -1
- package/dist/canvas/SceneCanvas/builtinToolSets.js +30 -0
- package/dist/canvas/SceneCanvas/builtinToolSets.js.map +1 -0
- package/dist/canvas/SceneCanvas/canvasPassThrough.js +1 -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/toolRegistry.js +8 -4
- package/dist/canvas/SceneCanvas/toolRegistry.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 +93 -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 +8 -8
- 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/useSceneCanvasLayers.js +13 -2
- package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneCanvasTools.js +1 -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 +5 -3
- 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 +3 -4
- package/dist/canvas/SceneCanvas/useSceneStandardActions.js.map +1 -1
- package/dist/canvas/SceneCanvas.js +16 -14
- 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/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/deps/editAnchors.js +9 -113
- package/dist/canvas/deps/editAnchors.js.map +1 -1
- package/dist/canvas/deps/insert.js +4 -2
- package/dist/canvas/deps/insert.js.map +1 -1
- package/dist/canvas/deps/pathEditCommits.js +193 -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 +29 -3
- package/dist/canvas/drawnBounds.js.map +1 -1
- package/dist/canvas/nodeShapes/derivedPainter.js +9 -1
- package/dist/canvas/nodeShapes/derivedPainter.js.map +1 -1
- package/dist/canvas/nodeShapes/pathPainter.js +3 -2
- package/dist/canvas/nodeShapes/pathPainter.js.map +1 -1
- package/dist/canvas/nodeShapes/shapePainter.js +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/renderDebugSnapshot.js +1 -0
- package/dist/canvas/renderDebugSnapshot.js.map +1 -1
- package/dist/canvas/renderSceneToPixels.js +6 -5
- package/dist/canvas/renderSceneToPixels.js.map +1 -1
- package/dist/canvas/sceneAdapter.js.map +1 -1
- package/dist/canvas/useCanvasPaint.js +2 -1
- package/dist/canvas/useCanvasPaint.js.map +1 -1
- package/dist/canvas/useInFlightBounds.js +52 -0
- package/dist/canvas/useInFlightBounds.js.map +1 -0
- package/dist/canvas/useViewHelpers.js +7 -9
- package/dist/canvas/useViewHelpers.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 +164 -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/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/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 +7 -1
- 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/historyFacade.js +1 -0
- package/dist/core/scene/historyFacade.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/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-BHuoMs1o.d.ts} +1 -1
- 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-BpZNOv7q.d.ts} +114 -892
- 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/paths/index.js +2 -2
- package/dist/features/paths/pathEditExtension.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/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 +701 -696
- package/dist/index.js +35 -29
- 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/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/bendSegment.js +1 -1
- package/dist/interactions/actions/defaults/bendSegment.js.map +1 -1
- package/dist/interactions/actions/defaults/createPaintAction.js +1 -1
- package/dist/interactions/actions/defaults/delete.js +48 -39
- package/dist/interactions/actions/defaults/delete.js.map +1 -1
- package/dist/interactions/actions/defaults/duplicate.js +1 -1
- package/dist/interactions/actions/defaults/group.js +2 -2
- package/dist/interactions/actions/defaults/ingest.js +7 -5
- package/dist/interactions/actions/defaults/ingest.js.map +1 -1
- package/dist/interactions/actions/defaults/nudge.js +13 -38
- package/dist/interactions/actions/defaults/nudge.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 +3 -6
- 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 +6 -4
- 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/session.js +5 -1
- package/dist/interactions/actions/insert/session.js.map +1 -1
- package/dist/interactions/actions/move/action.js +8 -4
- 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/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/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 +13 -2
- 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 +5 -6
- 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/kitSettingsSchema.js +0 -4
- package/dist/kitSettingsSchema.js.map +1 -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/pen/penHandle.js +3 -5
- package/dist/tools/builtin/pen/penHandle.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/version.js +1 -1
- package/package.json +35 -25
- package/dist/canvas/SceneCanvas/useBuiltinRigTools.js +0 -65
- package/dist/canvas/SceneCanvas/useBuiltinRigTools.js.map +0 -1
- package/dist/tools/builtin/bone/boneActions.js +0 -156
- package/dist/tools/builtin/bone/boneActions.js.map +0 -1
- package/dist/tools/builtin/bone/boneOverlay.js +0 -71
- package/dist/tools/builtin/bone/boneOverlay.js.map +0 -1
- package/dist/tools/builtin/bone/placedRig.js +0 -28
- package/dist/tools/builtin/bone/placedRig.js.map +0 -1
- package/dist/tools/builtin/bone/rigEditState.js +0 -30
- package/dist/tools/builtin/bone/rigEditState.js.map +0 -1
- package/dist/tools/builtin/bone/useBoneTool.js +0 -125
- package/dist/tools/builtin/bone/useBoneTool.js.map +0 -1
- package/dist/tools/builtin/weight/useWeightTool.js +0 -101
- package/dist/tools/builtin/weight/useWeightTool.js.map +0 -1
- package/dist/tools/builtin/weight/weightActions.js +0 -140
- package/dist/tools/builtin/weight/weightActions.js.map +0 -1
- package/dist/tools/builtin/weight/weightOverlay.js +0 -78
- package/dist/tools/builtin/weight/weightOverlay.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"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;
|
|
@@ -193,7 +190,7 @@ var editAnchorsAction = inPlane({
|
|
|
193
190
|
if (anchorInfo.part === "controlIn" && !origin.inHandle) return {};
|
|
194
191
|
if (anchorInfo.part === "controlOut" && !origin.outHandle) return {};
|
|
195
192
|
let active = false;
|
|
196
|
-
const preview = pathEditPreview(dep, editingId, () => active ? scratch.currentPose : null, () => active ? scratch.others : []);
|
|
193
|
+
const preview = pathEditPreview(dep, editingId, () => active ? { path: scratch.currentPose } : null, () => active ? scratch.others : []);
|
|
197
194
|
if (!preview) return {};
|
|
198
195
|
const dragging = draggedByPress(dep, anchorInfo, roleHeld(ctx, "selection.add"));
|
|
199
196
|
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 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 ? { 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";
|
|
@@ -159,7 +160,8 @@ var flipAction = {
|
|
|
159
160
|
"poseDescriptor",
|
|
160
161
|
"pointer",
|
|
161
162
|
"view",
|
|
162
|
-
"boundsIncludeStroke"
|
|
163
|
+
"boundsIncludeStroke",
|
|
164
|
+
"transformFollowers"
|
|
163
165
|
],
|
|
164
166
|
invoker: {
|
|
165
167
|
timing: "immediate",
|
|
@@ -168,7 +170,7 @@ var flipAction = {
|
|
|
168
170
|
const pivot = params?.pivot ?? "each";
|
|
169
171
|
const selection = deps.selection;
|
|
170
172
|
const scene = deps.scene;
|
|
171
|
-
const applyOps = deps
|
|
173
|
+
const applyOps = transformApplyOps(deps);
|
|
172
174
|
const geometryProjection = deps.geometryProjection;
|
|
173
175
|
if (!selection || !scene) return;
|
|
174
176
|
flipSelection(selection, scene, axis, pivot, applyOps, geometryProjection, poseDescriptorOf(deps.poseDescriptor), params, deps.pointer, (frame) => drawnBoxes(deps, frame));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action.js","names":[],"sources":["../../../../src/interactions/actions/flip/action.ts"],"sourcesContent":["import type { NodeId, Scene } from 'core/scene/types';\nimport type { Bounds } from 'core/viewport/fitViewToBounds';\nimport { shapeSources } from '../selectionSubtree';\nimport type { Op } from 'core/ops/types';\nimport { multiply, rotate, translate, type Affine } from '@weasel-js/geom';\nimport { createTransformOp } from 'core/ops/transform';\nimport type { PoseDescriptor } from '../resize/geometry';\nimport { poseDescriptorOf } from '../poseDescriptorDep';\nimport {\n flipPoseAboutBounds,\n flipPoseViaDescriptor,\n type FlipAxis,\n type FlipPivot,\n} from './helpers';\nimport { unionAABB } from 'core/geometry/unionBounds';\nimport { drawnBoxes, type DrawnBoxes } from '../drawnBoxes';\nimport { isNoInkExtents } from 'core/geometry/inkExtents';\nimport { scenePoseFrame, type PoseFrame } from '../poseFrame';\nimport { actionReferenceSources, resolveSpatialReference } from '../spatialReference';\nimport type { PointerContextValue } from '@weasel-js/routing/react';\nimport type { RectPose } from 'core/scene/types';\nimport type { Action } from '@weasel-js/routing';\nimport { defaultCommitAdapter } from '../defaultCommitAdapter';\nimport { requiresSelection } from '../defaults/requiresSelection';\nimport type { SelectionApi } from 'core/selection/useSelection';\nimport { geometryDataOp, type GeometryProjection } from '../geometryProjection';\nimport { icon } from '../../../icons.gen';\n\n/**\n * The world mirror about `axis` through the center of `pivotWorld`, written in\n * the frame `id` stores its data in. `geometryProjection.transform` is given\n * the affine the node's own pose underwent, and data-held geometry is local —\n * so a world mirror has to be conjugated by the frame or an asymmetric shape\n * reflects across the wrong line while its pose lands correctly.\n *\n * The frame's turn comes back as the rotation on a rebased zero-size pose at\n * the pivot point, so no composition strategy has to expose one.\n */\nfunction localMirror(\n axis: FlipAxis,\n frame: PoseFrame<unknown>,\n id: Parameters<PoseFrame<unknown>['local']>[0],\n pivotWorld: { x: number; y: number; width: number; height: number },\n): Affine {\n const at = frame.local(id, {\n x: pivotWorld.x + pivotWorld.width / 2,\n y: pivotWorld.y + pivotWorld.height / 2,\n width: 0,\n height: 0,\n rotation: 0,\n }) as RectPose;\n const theta = at.rotation ?? 0;\n const mirror: Affine = axis === 'x' ? [-1, 0, 0, 1, 0, 0] : [1, 0, 0, -1, 0, 0];\n const turned = multiply(multiply(rotate(theta), mirror), rotate(-theta));\n return multiply(translate(at.x, at.y), multiply(turned, translate(-at.x, -at.y)));\n}\n\n/**\n * Flip the current selection in `scene` along `axis`, as one undo entry.\n *\n * Pivot: `'each'` (per-item own AABB) unless the caller passes `'union'`,\n * which mirrors every pose about the selection's *visual* union AABB — the\n * rotated ink extents — so items swap sides as well as reflect, or a\n * `SpatialReference`, which mirrors about the center of what it names. A rotated\n * member's own mirrored position needs no expansion: `axisAlignedBounds`\n * keeps the stored box's center, so mirroring either box lands the same place.\n */\nfunction flipSelection(\n selection: SelectionApi,\n scene: Scene<unknown, string, unknown>,\n axis: FlipAxis,\n pivot: FlipPivot,\n applyOps: ((ops: Op[], label: string) => void) | undefined,\n geometryProjection: GeometryProjection | undefined,\n geom: PoseDescriptor<unknown>,\n params: Record<string, unknown> | undefined,\n pointer: PointerContextValue | undefined,\n boxesOver: (frame: PoseFrame<unknown>) => DrawnBoxes,\n): void {\n const selected = selection.get();\n if (selected.length === 0) return;\n const frame = scenePoseFrame(scene);\n const boxes = boxesOver(frame);\n\n // A group whose pose derives from its children mirrors by mirroring them,\n // about the group's own box where each selected node flips in place.\n const ids: NodeId[] = [];\n const ownPivot = new Map<string, Bounds>();\n for (const id of selected) {\n const members = shapeSources(scene, [id]) as NodeId[];\n const stoodIn = members.length !== 1 || members[0] !== id;\n const box = stoodIn ? boxes.aabb(id, frame.world(id)) : null;\n for (const member of members) {\n if (ids.includes(member)) continue;\n ids.push(member);\n if (box) ownPivot.set(member, box);\n }\n }\n\n const worlds = new Map<string, unknown>();\n for (const id of ids) {\n if (scene.get(id) === undefined) continue;\n const world = frame.world(id);\n worlds.set(id as string, world);\n // A shape whose ink reaches past its box unevenly flips in place about\n // the box it is drawn with, so that box stays put.\n if (!ownPivot.has(id as string) && !isNoInkExtents(boxes.extents(id, world))) {\n ownPivot.set(id as string, boxes.aabb(id, world));\n }\n }\n let sharedPivot: ReturnType<typeof unionAABB> = null;\n if (pivot === 'union') {\n sharedPivot = unionAABB([...worlds].map(([id, p]) => boxes.aabb(id, p)));\n } else if (pivot !== 'each') {\n sharedPivot = resolveSpatialReference(pivot, actionReferenceSources(params, pointer, scene, frame, boxes));\n if (sharedPivot === null) return;\n }\n\n const ops: Op[] = [];\n for (const id of ids) {\n const node = scene.get(id);\n if (!node) continue;\n const world = worlds.get(id as string)!;\n const about = sharedPivot ?? ownPivot.get(id as string) ?? null;\n const flipped = about\n ? flipPoseAboutBounds(world, axis, geom, about)\n : flipPoseViaDescriptor(world, axis, geom);\n ops.push(createTransformOp<unknown>({\n id: id as string,\n from: node.pose,\n to: frame.local(id, flipped),\n label: 'Flip',\n }));\n // Mirror the data-held geometry about the SAME pivot the pose flip uses.\n // A pose-only flip of a bare-AABB pose is identity, so this data op is\n // the only way an asymmetric shape actually mirrors.\n const g = about ?? geom.getBounds(world);\n const dataOp = geometryDataOp(\n geometryProjection,\n { id: id as string, data: node.data, pose: node.pose },\n localMirror(axis, frame, id, g),\n 'Flip',\n );\n if (dataOp) ops.push(dataOp);\n }\n if (ops.length === 0) return;\n\n if (applyOps) applyOps(ops, 'Flip');\n else scene.applyBatch(ops, 'Flip', defaultCommitAdapter(scene, selection.adapterMethods));\n}\n\n/**\n * Flips the selection. `params.axis` (`'x'` | `'y'`, default `'x'`) picks the\n * direction, and the optional `params.pivot` (a `FlipPivot`, default `'each'`)\n * picks what it mirrors about.\n */\nexport const flipAction: Action & { requires: string[] } = {\n id: 'flip',\n label: 'Flip',\n group: 'flip',\n tags: ['mirror'],\n variants: [\n { key: 'x', label: 'Flip Horizontal', icon: icon('flipX'), params: { axis: 'x' } },\n { key: 'y', label: 'Flip Vertical', icon: icon('flipY'), params: { axis: 'y' } },\n ],\n defaultBinding: [\n { spec: { kind: 'key', key: ['h', 'H'], mods: { shift: true } }, opts: { params: { axis: 'x' } } },\n { spec: { kind: 'key', key: ['v', 'V'], mods: { shift: true } }, opts: { params: { axis: 'y' } } },\n ],\n eligible: { capability: 'transforms-selection' },\n requires: ['selection', 'scene', 'applyOps', 'geometryProjection', 'poseDescriptor', 'pointer', 'view', 'boundsIncludeStroke'],\n invoker: {\n timing: 'immediate',\n run: (deps, params) => {\n const axis = (params?.axis as FlipAxis | undefined) ?? 'x';\n const pivot = (params?.pivot as FlipPivot | undefined) ?? 'each';\n const selection = deps.selection;\n const scene = deps.scene;\n const applyOps = deps.applyOps;\n const geometryProjection = deps.geometryProjection;\n if (!selection || !scene) return;\n flipSelection(\n selection, scene, axis, pivot, applyOps, geometryProjection,\n poseDescriptorOf(deps.poseDescriptor),\n params, deps.pointer,\n (frame) => drawnBoxes(deps, frame),\n );\n },\n },\n enabled: requiresSelection,\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"action.js","names":[],"sources":["../../../../src/interactions/actions/flip/action.ts"],"sourcesContent":["import type { NodeId, Scene } from 'core/scene/types';\nimport type { Bounds } from 'core/viewport/fitViewToBounds';\nimport { shapeSources } from '../selectionSubtree';\nimport type { Op } from 'core/ops/types';\nimport { multiply, rotate, translate, type Affine } from '@weasel-js/geom';\nimport { createTransformOp } from 'core/ops/transform';\nimport type { PoseDescriptor } from '../resize/geometry';\nimport { poseDescriptorOf } from '../poseDescriptorDep';\nimport {\n flipPoseAboutBounds,\n flipPoseViaDescriptor,\n type FlipAxis,\n type FlipPivot,\n} from './helpers';\nimport { unionAABB } from 'core/geometry/unionBounds';\nimport { drawnBoxes, type DrawnBoxes } from '../drawnBoxes';\nimport { isNoInkExtents } from 'core/geometry/inkExtents';\nimport { scenePoseFrame, type PoseFrame } from '../poseFrame';\nimport { actionReferenceSources, resolveSpatialReference } from '../spatialReference';\nimport type { PointerContextValue } from '@weasel-js/routing/react';\nimport type { RectPose } from 'core/scene/types';\nimport type { Action } from '@weasel-js/routing';\nimport { defaultCommitAdapter } from '../defaultCommitAdapter';\nimport { transformApplyOps } from '../transformFinish';\nimport { requiresSelection } from '../defaults/requiresSelection';\nimport type { SelectionApi } from 'core/selection/useSelection';\nimport { geometryDataOp, type GeometryProjection } from '../geometryProjection';\nimport { icon } from '../../../icons.gen';\n\n/**\n * The world mirror about `axis` through the center of `pivotWorld`, written in\n * the frame `id` stores its data in. `geometryProjection.transform` is given\n * the affine the node's own pose underwent, and data-held geometry is local —\n * so a world mirror has to be conjugated by the frame or an asymmetric shape\n * reflects across the wrong line while its pose lands correctly.\n *\n * The frame's turn comes back as the rotation on a rebased zero-size pose at\n * the pivot point, so no composition strategy has to expose one.\n */\nfunction localMirror(\n axis: FlipAxis,\n frame: PoseFrame<unknown>,\n id: Parameters<PoseFrame<unknown>['local']>[0],\n pivotWorld: { x: number; y: number; width: number; height: number },\n): Affine {\n const at = frame.local(id, {\n x: pivotWorld.x + pivotWorld.width / 2,\n y: pivotWorld.y + pivotWorld.height / 2,\n width: 0,\n height: 0,\n rotation: 0,\n }) as RectPose;\n const theta = at.rotation ?? 0;\n const mirror: Affine = axis === 'x' ? [-1, 0, 0, 1, 0, 0] : [1, 0, 0, -1, 0, 0];\n const turned = multiply(multiply(rotate(theta), mirror), rotate(-theta));\n return multiply(translate(at.x, at.y), multiply(turned, translate(-at.x, -at.y)));\n}\n\n/**\n * Flip the current selection in `scene` along `axis`, as one undo entry.\n *\n * Pivot: `'each'` (per-item own AABB) unless the caller passes `'union'`,\n * which mirrors every pose about the selection's *visual* union AABB — the\n * rotated ink extents — so items swap sides as well as reflect, or a\n * `SpatialReference`, which mirrors about the center of what it names. A rotated\n * member's own mirrored position needs no expansion: `axisAlignedBounds`\n * keeps the stored box's center, so mirroring either box lands the same place.\n */\nfunction flipSelection(\n selection: SelectionApi,\n scene: Scene<unknown, string, unknown>,\n axis: FlipAxis,\n pivot: FlipPivot,\n applyOps: ((ops: Op[], label: string) => void) | undefined,\n geometryProjection: GeometryProjection | undefined,\n geom: PoseDescriptor<unknown>,\n params: Record<string, unknown> | undefined,\n pointer: PointerContextValue | undefined,\n boxesOver: (frame: PoseFrame<unknown>) => DrawnBoxes,\n): void {\n const selected = selection.get();\n if (selected.length === 0) return;\n const frame = scenePoseFrame(scene);\n const boxes = boxesOver(frame);\n\n // A group whose pose derives from its children mirrors by mirroring them,\n // about the group's own box where each selected node flips in place.\n const ids: NodeId[] = [];\n const ownPivot = new Map<string, Bounds>();\n for (const id of selected) {\n const members = shapeSources(scene, [id]) as NodeId[];\n const stoodIn = members.length !== 1 || members[0] !== id;\n const box = stoodIn ? boxes.aabb(id, frame.world(id)) : null;\n for (const member of members) {\n if (ids.includes(member)) continue;\n ids.push(member);\n if (box) ownPivot.set(member, box);\n }\n }\n\n const worlds = new Map<string, unknown>();\n for (const id of ids) {\n if (scene.get(id) === undefined) continue;\n const world = frame.world(id);\n worlds.set(id as string, world);\n // A shape whose ink reaches past its box unevenly flips in place about\n // the box it is drawn with, so that box stays put.\n if (!ownPivot.has(id as string) && !isNoInkExtents(boxes.extents(id, world))) {\n ownPivot.set(id as string, boxes.aabb(id, world));\n }\n }\n let sharedPivot: ReturnType<typeof unionAABB> = null;\n if (pivot === 'union') {\n sharedPivot = unionAABB([...worlds].map(([id, p]) => boxes.aabb(id, p)));\n } else if (pivot !== 'each') {\n sharedPivot = resolveSpatialReference(pivot, actionReferenceSources(params, pointer, scene, frame, boxes));\n if (sharedPivot === null) return;\n }\n\n const ops: Op[] = [];\n for (const id of ids) {\n const node = scene.get(id);\n if (!node) continue;\n const world = worlds.get(id as string)!;\n const about = sharedPivot ?? ownPivot.get(id as string) ?? null;\n const flipped = about\n ? flipPoseAboutBounds(world, axis, geom, about)\n : flipPoseViaDescriptor(world, axis, geom);\n ops.push(createTransformOp<unknown>({\n id: id as string,\n from: node.pose,\n to: frame.local(id, flipped),\n label: 'Flip',\n }));\n // Mirror the data-held geometry about the SAME pivot the pose flip uses.\n // A pose-only flip of a bare-AABB pose is identity, so this data op is\n // the only way an asymmetric shape actually mirrors.\n const g = about ?? geom.getBounds(world);\n const dataOp = geometryDataOp(\n geometryProjection,\n { id: id as string, data: node.data, pose: node.pose },\n localMirror(axis, frame, id, g),\n 'Flip',\n );\n if (dataOp) ops.push(dataOp);\n }\n if (ops.length === 0) return;\n\n if (applyOps) applyOps(ops, 'Flip');\n else scene.applyBatch(ops, 'Flip', defaultCommitAdapter(scene, selection.adapterMethods));\n}\n\n/**\n * Flips the selection. `params.axis` (`'x'` | `'y'`, default `'x'`) picks the\n * direction, and the optional `params.pivot` (a `FlipPivot`, default `'each'`)\n * picks what it mirrors about.\n */\nexport const flipAction: Action & { requires: string[] } = {\n id: 'flip',\n label: 'Flip',\n group: 'flip',\n tags: ['mirror'],\n variants: [\n { key: 'x', label: 'Flip Horizontal', icon: icon('flipX'), params: { axis: 'x' } },\n { key: 'y', label: 'Flip Vertical', icon: icon('flipY'), params: { axis: 'y' } },\n ],\n defaultBinding: [\n { spec: { kind: 'key', key: ['h', 'H'], mods: { shift: true } }, opts: { params: { axis: 'x' } } },\n { spec: { kind: 'key', key: ['v', 'V'], mods: { shift: true } }, opts: { params: { axis: 'y' } } },\n ],\n eligible: { capability: 'transforms-selection' },\n requires: [\n 'selection', 'scene', 'applyOps', 'geometryProjection', 'poseDescriptor', 'pointer', 'view', 'boundsIncludeStroke',\n 'transformFollowers',\n ],\n invoker: {\n timing: 'immediate',\n run: (deps, params) => {\n const axis = (params?.axis as FlipAxis | undefined) ?? 'x';\n const pivot = (params?.pivot as FlipPivot | undefined) ?? 'each';\n const selection = deps.selection;\n const scene = deps.scene;\n const applyOps = transformApplyOps(deps);\n const geometryProjection = deps.geometryProjection;\n if (!selection || !scene) return;\n flipSelection(\n selection, scene, axis, pivot, applyOps, geometryProjection,\n poseDescriptorOf(deps.poseDescriptor),\n params, deps.pointer,\n (frame) => drawnBoxes(deps, frame),\n );\n },\n },\n enabled: requiresSelection,\n};\n"],"mappings":"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"}
|
|
@@ -31,12 +31,15 @@ function readGestureLifecycle(source, defaultLabel, behaviors = []) {
|
|
|
31
31
|
}
|
|
32
32
|
};
|
|
33
33
|
}
|
|
34
|
-
/** Commit a gesture's ops
|
|
34
|
+
/** Commit a gesture's ops, finished by `target.finish` when it has one:
|
|
35
|
+
* untracked when transient, else through the
|
|
35
36
|
* consumer `applyOps` hook when one is wired, else into the scene's history.
|
|
36
37
|
* Returns whether the commit landed: false when a container refused what
|
|
37
38
|
* the ops brought it, which the scene reverts. A consumer's `applyOps` may
|
|
38
39
|
* keep the document elsewhere, so it is taken at its word. */
|
|
39
|
-
function commitGestureOps(target, lifecycle,
|
|
40
|
+
function commitGestureOps(target, lifecycle, given) {
|
|
41
|
+
const ops = target.finish ? target.finish(given, lifecycle.labelFor(given)) : given;
|
|
42
|
+
if (!ops) return false;
|
|
40
43
|
if (lifecycle.transient) {
|
|
41
44
|
try {
|
|
42
45
|
target.scene.untracked(() => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gestureLifecycle.js","names":[],"sources":["../../../src/interactions/actions/gestureLifecycle.ts"],"sourcesContent":["/**\n * The lifecycle the ongoing transform actions (`move`, `resize`, `rotate`)\n * share: what their committed batch is called in history, whether it is\n * recorded at all, and the callbacks fired as the gesture opens and closes.\n *\n * Move and rotate read it from their binding's params; resize reads it from\n * the `resizePolicy` dep, where the rest of its options already live.\n */\nimport type { Op } from 'core/ops/types';\nimport { SceneArrivalRefused } from 'core/scene/arrivals';\nimport type { Scene } from 'core/scene/types';\nimport type { BehaviorEnd } from 'interactions/gestures/types';\nimport type { NodeId, PoseHold } from 'core/scene/types';\n\n/** The lifecycle options, as a binding's params or the resize policy carry\n * them. */\nexport interface GestureLifecycleOptions {\n /** History label for the committed batch. Unset, the batch takes its first\n * op's label (a layout drop or a behavior names its own), else the\n * action's. */\n label?: string;\n /** Commit through `scene.untracked`: the edit lands, but no undo entry\n * records it and the consumer `applyOps` hook is bypassed. Unset, any\n * behavior's `defaultTransient: true` turns it on. */\n transient?: boolean;\n /** Fired once the gesture starts changing poses, with the ids it moves. */\n onGestureStart?(ids: string[]): void;\n /** Fired once per `onGestureStart`: `true` when the gesture wrote to the\n * document, `false` on cancel, abort, or a release with nothing to write. */\n onGestureEnd?(committed: boolean): void;\n}\n\n/** The params entries for {@link GestureLifecycleOptions}, with the unset\n * keys left out. */\nexport function gestureLifecycleParams(o: GestureLifecycleOptions): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n if (o.label !== undefined) out.label = o.label;\n if (o.transient !== undefined) out.transient = o.transient;\n if (o.onGestureStart) out.onGestureStart = o.onGestureStart;\n if (o.onGestureEnd) out.onGestureEnd = o.onGestureEnd;\n return out;\n}\n\n/** A gesture's resolved lifecycle. `start` and `end` fire their callbacks at\n * most once each, and `end` only after `start`. */\nexport interface GestureLifecycle {\n /** The label ops built by the action itself carry. */\n readonly label: string;\n /** The history label for committing `ops`. */\n labelFor(ops: readonly Op[]): string;\n readonly transient: boolean;\n start(ids: readonly string[]): void;\n end(committed: boolean): void;\n}\n\nexport function readGestureLifecycle(\n source: GestureLifecycleOptions | Record<string, unknown> | undefined,\n defaultLabel: string,\n behaviors: readonly { defaultTransient?: boolean }[] = [],\n): GestureLifecycle {\n const o = (source ?? {}) as GestureLifecycleOptions;\n let started = false;\n let ended = false;\n return {\n label: o.label ?? defaultLabel,\n labelFor: (ops) => o.label ?? ops[0]?.label ?? defaultLabel,\n transient: o.transient ?? behaviors.some((b) => b.defaultTransient === true),\n start(ids) {\n if (started) return;\n started = true;\n o.onGestureStart?.([...ids]);\n },\n end(committed) {\n if (!started || ended) return;\n ended = true;\n o.onGestureEnd?.(committed);\n },\n };\n}\n\n/** Commit a gesture's ops: untracked when transient, else through the\n * consumer `applyOps` hook when one is wired, else into the scene's history.\n * Returns whether the commit landed: false when a container refused what\n * the ops brought it, which the scene reverts. A consumer's `applyOps` may\n * keep the document elsewhere, so it is taken at its word. */\nexport function commitGestureOps(\n target: {\n scene: Scene<unknown, string, unknown>;\n applyOps?: (ops: Op[], label: string) => void;\n adapter: unknown;\n },\n lifecycle: GestureLifecycle,\n ops: Op[],\n): boolean {\n if (lifecycle.transient) {\n try {\n target.scene.untracked(() => {\n for (const op of ops) op.apply(target.adapter);\n });\n } catch (err) {\n // `untracked` lets a refused arrival out; `applyBatch` swallows it.\n if (!(err instanceof SceneArrivalRefused)) throw err;\n return false;\n }\n return true;\n }\n const label = lifecycle.labelFor(ops);\n if (!target.applyOps) return target.scene.applyBatch(ops, label, target.adapter);\n target.applyOps(ops, label);\n return true;\n}\n\n/** The trailing argument of {@link reduceBehaviorEnd}: what `TEnd` adds to\n * `BehaviorEnd`, required exactly when it adds something. */\ntype OwnEndFields<TEnd extends BehaviorEnd> = keyof Omit<TEnd, keyof BehaviorEnd> extends never\n ? [own?: Omit<TEnd, keyof BehaviorEnd>]\n : [own: Omit<TEnd, keyof BehaviorEnd>];\n\n/** Runs every behavior's `onEnd` in order; the first that answers decides the\n * commit and later answers are ignored. `null` aborts, `Op[]` claims it (an\n * empty array included), and `undefined` means every behavior deferred to the\n * action's own commit. An action whose behaviors take more than a plain\n * `BehaviorEnd` passes the rest as `own`; each `onEnd` gets it beside\n * `answered`. One that throws does not stop the rest, which are told the\n * commit is decided; its error is rethrown after, so nothing commits. */\nexport function reduceBehaviorEnd<TCtx, TEnd extends BehaviorEnd = BehaviorEnd>(\n behaviors: readonly { onEnd?(ctx: TCtx, end: TEnd): Op[] | null | void }[],\n ctx: TCtx,\n ...[own]: OwnEndFields<TEnd>\n): Op[] | null | undefined {\n let answer: Op[] | null | undefined;\n let threw = false;\n runEvery(behaviors, (b) => {\n try {\n const r = b.onEnd?.(ctx, { ...own, answered: threw || answer !== undefined } as TEnd);\n if (answer === undefined && r !== undefined) answer = r;\n } catch (err) {\n threw = true;\n throw err;\n }\n });\n return answer;\n}\n\n/** Runs `step` for every item, a throwing one included, then rethrows the\n * first error. For steps that each release something of their own. */\nfunction runEvery<T>(items: readonly T[], step: (item: T) => void): void {\n const errors: unknown[] = [];\n for (const item of items) {\n try {\n step(item);\n } catch (err) {\n errors.push(err);\n }\n }\n if (errors.length > 0) throw errors[0];\n}\n\n/** Runs every behavior's `onCancel`, for a gesture closing without a commit.\n * One that throws does not stop the rest; its error is rethrown after. */\nexport function runBehaviorCancel<TCtx>(\n behaviors: readonly { onCancel?(ctx: TCtx): void }[],\n ctx: TCtx,\n): void {\n runEvery(behaviors, (b) => b.onCancel?.(ctx));\n}\n\n/** Runs every behavior's `onSettled`, once the gesture's commit has landed or\n * its cancel has run. One that throws does not stop the rest; its error is\n * rethrown after. */\nexport function runBehaviorSettled<TCtx>(\n behaviors: readonly { onSettled?(ctx: TCtx, committed: boolean): void }[],\n ctx: TCtx,\n committed: boolean,\n): void {\n runEvery(behaviors, (b) => b.onSettled?.(ctx, committed));\n}\n\n/** What {@link closeGesture} closes. */\nexport interface ClosingGesture<TCtx> {\n hold: PoseHold<unknown>;\n /** The action's own buffer of this frame's poses, emptied at the close. */\n previews: Map<NodeId, unknown>;\n behaviors: readonly { onSettled?(ctx: TCtx, committed: boolean): void }[];\n ctx: TCtx;\n lifecycle: GestureLifecycle;\n}\n\n/**\n * The close a transform action runs from its `finally`, commit or cancel:\n * drop the preview overrides, tell the behaviors, then fire `onGestureEnd`,\n * which fires even when a behavior's `onSettled` throws; the first error is\n * rethrown.\n */\nexport function closeGesture<TCtx>(gesture: ClosingGesture<TCtx>, committed: boolean): void {\n gesture.hold.drop();\n gesture.previews.clear();\n runEvery([\n () => runBehaviorSettled(gesture.behaviors, gesture.ctx, committed),\n () => gesture.lifecycle.end(committed),\n ], (step) => step());\n}\n"],"mappings":";;;;;AAkCA,SAAgB,uBAAuB,GAAqD;CAC1F,MAAM,MAA+B,CAAC;CACtC,IAAI,EAAE,UAAU,QAAW,IAAI,QAAQ,EAAE;CACzC,IAAI,EAAE,cAAc,QAAW,IAAI,YAAY,EAAE;CACjD,IAAI,EAAE,gBAAgB,IAAI,iBAAiB,EAAE;CAC7C,IAAI,EAAE,cAAc,IAAI,eAAe,EAAE;CACzC,OAAO;AACT;AAcA,SAAgB,qBACd,QACA,cACA,YAAuD,CAAC,GACtC;CAClB,MAAM,IAAK,UAAU,CAAC;CACtB,IAAI,UAAU;CACd,IAAI,QAAQ;CACZ,OAAO;EACL,OAAO,EAAE,SAAS;EAClB,WAAW,QAAQ,EAAE,SAAS,IAAI,EAAE,EAAE,SAAS;EAC/C,WAAW,EAAE,aAAa,UAAU,MAAM,MAAM,EAAE,qBAAqB,IAAI;EAC3E,MAAM,KAAK;GACT,IAAI,SAAS;GACb,UAAU;GACV,EAAE,iBAAiB,CAAC,GAAG,GAAG,CAAC;EAC7B;EACA,IAAI,WAAW;GACb,IAAI,CAAC,WAAW,OAAO;GACvB,QAAQ;GACR,EAAE,eAAe,SAAS;EAC5B;CACF;AACF;;;;;;AAOA,SAAgB,iBACd,QAKA,WACA,KACS;CACT,IAAI,UAAU,WAAW;EACvB,IAAI;GACF,OAAO,MAAM,gBAAgB;IAC3B,KAAK,MAAM,MAAM,KAAK,GAAG,MAAM,OAAO,OAAO;GAC/C,CAAC;EACH,SAAS,KAAK;GAEZ,IAAI,EAAE,eAAe,sBAAsB,MAAM;GACjD,OAAO;EACT;EACA,OAAO;CACT;CACA,MAAM,QAAQ,UAAU,SAAS,GAAG;CACpC,IAAI,CAAC,OAAO,UAAU,OAAO,OAAO,MAAM,WAAW,KAAK,OAAO,OAAO,OAAO;CAC/E,OAAO,SAAS,KAAK,KAAK;CAC1B,OAAO;AACT;;;;;;;;AAeA,SAAgB,kBACd,WACA,KACA,GAAG,CAAC,MACqB;CACzB,IAAI;CACJ,IAAI,QAAQ;CACZ,SAAS,YAAY,MAAM;EACzB,IAAI;GACF,MAAM,IAAI,EAAE,QAAQ,KAAK;IAAE,GAAG;IAAK,UAAU,SAAS,WAAW;GAAU,CAAS;GACpF,IAAI,WAAW,UAAa,MAAM,QAAW,SAAS;EACxD,SAAS,KAAK;GACZ,QAAQ;GACR,MAAM;EACR;CACF,CAAC;CACD,OAAO;AACT;;;AAIA,SAAS,SAAY,OAAqB,MAA+B;CACvE,MAAM,SAAoB,CAAC;CAC3B,KAAK,MAAM,QAAQ,OACjB,IAAI;EACF,KAAK,IAAI;CACX,SAAS,KAAK;EACZ,OAAO,KAAK,GAAG;CACjB;CAEF,IAAI,OAAO,SAAS,GAAG,MAAM,OAAO;AACtC;;;AAIA,SAAgB,kBACd,WACA,KACM;CACN,SAAS,YAAY,MAAM,EAAE,WAAW,GAAG,CAAC;AAC9C;;;;AAKA,SAAgB,mBACd,WACA,KACA,WACM;CACN,SAAS,YAAY,MAAM,EAAE,YAAY,KAAK,SAAS,CAAC;AAC1D;;;;;;;AAkBA,SAAgB,aAAmB,SAA+B,WAA0B;CAC1F,QAAQ,KAAK,KAAK;CAClB,QAAQ,SAAS,MAAM;CACvB,SAAS,OACD,mBAAmB,QAAQ,WAAW,QAAQ,KAAK,SAAS,SAC5D,QAAQ,UAAU,IAAI,SAAS,CACvC,IAAI,SAAS,KAAK,CAAC;AACrB"}
|
|
1
|
+
{"version":3,"file":"gestureLifecycle.js","names":[],"sources":["../../../src/interactions/actions/gestureLifecycle.ts"],"sourcesContent":["/**\n * The lifecycle the ongoing transform actions (`move`, `resize`, `rotate`)\n * share: what their committed batch is called in history, whether it is\n * recorded at all, and the callbacks fired as the gesture opens and closes.\n *\n * Move and rotate read it from their binding's params; resize reads it from\n * the `resizePolicy` dep, where the rest of its options already live.\n */\nimport type { Op } from 'core/ops/types';\nimport { SceneArrivalRefused } from 'core/scene/arrivals';\nimport type { Scene } from 'core/scene/types';\nimport type { BehaviorEnd } from 'interactions/gestures/types';\nimport type { NodeId, PoseHold } from 'core/scene/types';\nimport type { TransformFinisher } from './transformFinish';\n\n/** The lifecycle options, as a binding's params or the resize policy carry\n * them. */\nexport interface GestureLifecycleOptions {\n /** History label for the committed batch. Unset, the batch takes its first\n * op's label (a layout drop or a behavior names its own), else the\n * action's. */\n label?: string;\n /** Commit through `scene.untracked`: the edit lands, but no undo entry\n * records it and the consumer `applyOps` hook is bypassed. Unset, any\n * behavior's `defaultTransient: true` turns it on. */\n transient?: boolean;\n /** Fired once the gesture starts changing poses, with the ids it moves. */\n onGestureStart?(ids: string[]): void;\n /** Fired once per `onGestureStart`: `true` when the gesture wrote to the\n * document, `false` on cancel, abort, or a release with nothing to write. */\n onGestureEnd?(committed: boolean): void;\n}\n\n/** The params entries for {@link GestureLifecycleOptions}, with the unset\n * keys left out. */\nexport function gestureLifecycleParams(o: GestureLifecycleOptions): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n if (o.label !== undefined) out.label = o.label;\n if (o.transient !== undefined) out.transient = o.transient;\n if (o.onGestureStart) out.onGestureStart = o.onGestureStart;\n if (o.onGestureEnd) out.onGestureEnd = o.onGestureEnd;\n return out;\n}\n\n/** A gesture's resolved lifecycle. `start` and `end` fire their callbacks at\n * most once each, and `end` only after `start`. */\nexport interface GestureLifecycle {\n /** The label ops built by the action itself carry. */\n readonly label: string;\n /** The history label for committing `ops`. */\n labelFor(ops: readonly Op[]): string;\n readonly transient: boolean;\n start(ids: readonly string[]): void;\n end(committed: boolean): void;\n}\n\nexport function readGestureLifecycle(\n source: GestureLifecycleOptions | Record<string, unknown> | undefined,\n defaultLabel: string,\n behaviors: readonly { defaultTransient?: boolean }[] = [],\n): GestureLifecycle {\n const o = (source ?? {}) as GestureLifecycleOptions;\n let started = false;\n let ended = false;\n return {\n label: o.label ?? defaultLabel,\n labelFor: (ops) => o.label ?? ops[0]?.label ?? defaultLabel,\n transient: o.transient ?? behaviors.some((b) => b.defaultTransient === true),\n start(ids) {\n if (started) return;\n started = true;\n o.onGestureStart?.([...ids]);\n },\n end(committed) {\n if (!started || ended) return;\n ended = true;\n o.onGestureEnd?.(committed);\n },\n };\n}\n\n/** Commit a gesture's ops, finished by `target.finish` when it has one:\n * untracked when transient, else through the\n * consumer `applyOps` hook when one is wired, else into the scene's history.\n * Returns whether the commit landed: false when a container refused what\n * the ops brought it, which the scene reverts. A consumer's `applyOps` may\n * keep the document elsewhere, so it is taken at its word. */\nexport function commitGestureOps(\n target: {\n scene: Scene<unknown, string, unknown>;\n applyOps?: (ops: Op[], label: string) => void;\n adapter: unknown;\n finish?: TransformFinisher;\n },\n lifecycle: GestureLifecycle,\n given: Op[],\n): boolean {\n const ops = target.finish ? target.finish(given, lifecycle.labelFor(given)) : given;\n if (!ops) return false;\n if (lifecycle.transient) {\n try {\n target.scene.untracked(() => {\n for (const op of ops) op.apply(target.adapter);\n });\n } catch (err) {\n // `untracked` lets a refused arrival out; `applyBatch` swallows it.\n if (!(err instanceof SceneArrivalRefused)) throw err;\n return false;\n }\n return true;\n }\n const label = lifecycle.labelFor(ops);\n if (!target.applyOps) return target.scene.applyBatch(ops, label, target.adapter);\n target.applyOps(ops, label);\n return true;\n}\n\n/** The trailing argument of {@link reduceBehaviorEnd}: what `TEnd` adds to\n * `BehaviorEnd`, required exactly when it adds something. */\ntype OwnEndFields<TEnd extends BehaviorEnd> = keyof Omit<TEnd, keyof BehaviorEnd> extends never\n ? [own?: Omit<TEnd, keyof BehaviorEnd>]\n : [own: Omit<TEnd, keyof BehaviorEnd>];\n\n/** Runs every behavior's `onEnd` in order; the first that answers decides the\n * commit and later answers are ignored. `null` aborts, `Op[]` claims it (an\n * empty array included), and `undefined` means every behavior deferred to the\n * action's own commit. An action whose behaviors take more than a plain\n * `BehaviorEnd` passes the rest as `own`; each `onEnd` gets it beside\n * `answered`. One that throws does not stop the rest, which are told the\n * commit is decided; its error is rethrown after, so nothing commits. */\nexport function reduceBehaviorEnd<TCtx, TEnd extends BehaviorEnd = BehaviorEnd>(\n behaviors: readonly { onEnd?(ctx: TCtx, end: TEnd): Op[] | null | void }[],\n ctx: TCtx,\n ...[own]: OwnEndFields<TEnd>\n): Op[] | null | undefined {\n let answer: Op[] | null | undefined;\n let threw = false;\n runEvery(behaviors, (b) => {\n try {\n const r = b.onEnd?.(ctx, { ...own, answered: threw || answer !== undefined } as TEnd);\n if (answer === undefined && r !== undefined) answer = r;\n } catch (err) {\n threw = true;\n throw err;\n }\n });\n return answer;\n}\n\n/** Runs `step` for every item, a throwing one included, then rethrows the\n * first error. For steps that each release something of their own. */\nfunction runEvery<T>(items: readonly T[], step: (item: T) => void): void {\n const errors: unknown[] = [];\n for (const item of items) {\n try {\n step(item);\n } catch (err) {\n errors.push(err);\n }\n }\n if (errors.length > 0) throw errors[0];\n}\n\n/** Runs every behavior's `onCancel`, for a gesture closing without a commit.\n * One that throws does not stop the rest; its error is rethrown after. */\nexport function runBehaviorCancel<TCtx>(\n behaviors: readonly { onCancel?(ctx: TCtx): void }[],\n ctx: TCtx,\n): void {\n runEvery(behaviors, (b) => b.onCancel?.(ctx));\n}\n\n/** Runs every behavior's `onSettled`, once the gesture's commit has landed or\n * its cancel has run. One that throws does not stop the rest; its error is\n * rethrown after. */\nexport function runBehaviorSettled<TCtx>(\n behaviors: readonly { onSettled?(ctx: TCtx, committed: boolean): void }[],\n ctx: TCtx,\n committed: boolean,\n): void {\n runEvery(behaviors, (b) => b.onSettled?.(ctx, committed));\n}\n\n/** What {@link closeGesture} closes. */\nexport interface ClosingGesture<TCtx> {\n hold: PoseHold<unknown>;\n /** The action's own buffer of this frame's poses, emptied at the close. */\n previews: Map<NodeId, unknown>;\n behaviors: readonly { onSettled?(ctx: TCtx, committed: boolean): void }[];\n ctx: TCtx;\n lifecycle: GestureLifecycle;\n}\n\n/**\n * The close a transform action runs from its `finally`, commit or cancel:\n * drop the preview overrides, tell the behaviors, then fire `onGestureEnd`,\n * which fires even when a behavior's `onSettled` throws; the first error is\n * rethrown.\n */\nexport function closeGesture<TCtx>(gesture: ClosingGesture<TCtx>, committed: boolean): void {\n gesture.hold.drop();\n gesture.previews.clear();\n runEvery([\n () => runBehaviorSettled(gesture.behaviors, gesture.ctx, committed),\n () => gesture.lifecycle.end(committed),\n ], (step) => step());\n}\n"],"mappings":";;;;;AAmCA,SAAgB,uBAAuB,GAAqD;CAC1F,MAAM,MAA+B,CAAC;CACtC,IAAI,EAAE,UAAU,QAAW,IAAI,QAAQ,EAAE;CACzC,IAAI,EAAE,cAAc,QAAW,IAAI,YAAY,EAAE;CACjD,IAAI,EAAE,gBAAgB,IAAI,iBAAiB,EAAE;CAC7C,IAAI,EAAE,cAAc,IAAI,eAAe,EAAE;CACzC,OAAO;AACT;AAcA,SAAgB,qBACd,QACA,cACA,YAAuD,CAAC,GACtC;CAClB,MAAM,IAAK,UAAU,CAAC;CACtB,IAAI,UAAU;CACd,IAAI,QAAQ;CACZ,OAAO;EACL,OAAO,EAAE,SAAS;EAClB,WAAW,QAAQ,EAAE,SAAS,IAAI,EAAE,EAAE,SAAS;EAC/C,WAAW,EAAE,aAAa,UAAU,MAAM,MAAM,EAAE,qBAAqB,IAAI;EAC3E,MAAM,KAAK;GACT,IAAI,SAAS;GACb,UAAU;GACV,EAAE,iBAAiB,CAAC,GAAG,GAAG,CAAC;EAC7B;EACA,IAAI,WAAW;GACb,IAAI,CAAC,WAAW,OAAO;GACvB,QAAQ;GACR,EAAE,eAAe,SAAS;EAC5B;CACF;AACF;;;;;;;AAQA,SAAgB,iBACd,QAMA,WACA,OACS;CACT,MAAM,MAAM,OAAO,SAAS,OAAO,OAAO,OAAO,UAAU,SAAS,KAAK,CAAC,IAAI;CAC9E,IAAI,CAAC,KAAK,OAAO;CACjB,IAAI,UAAU,WAAW;EACvB,IAAI;GACF,OAAO,MAAM,gBAAgB;IAC3B,KAAK,MAAM,MAAM,KAAK,GAAG,MAAM,OAAO,OAAO;GAC/C,CAAC;EACH,SAAS,KAAK;GAEZ,IAAI,EAAE,eAAe,sBAAsB,MAAM;GACjD,OAAO;EACT;EACA,OAAO;CACT;CACA,MAAM,QAAQ,UAAU,SAAS,GAAG;CACpC,IAAI,CAAC,OAAO,UAAU,OAAO,OAAO,MAAM,WAAW,KAAK,OAAO,OAAO,OAAO;CAC/E,OAAO,SAAS,KAAK,KAAK;CAC1B,OAAO;AACT;;;;;;;;AAeA,SAAgB,kBACd,WACA,KACA,GAAG,CAAC,MACqB;CACzB,IAAI;CACJ,IAAI,QAAQ;CACZ,SAAS,YAAY,MAAM;EACzB,IAAI;GACF,MAAM,IAAI,EAAE,QAAQ,KAAK;IAAE,GAAG;IAAK,UAAU,SAAS,WAAW;GAAU,CAAS;GACpF,IAAI,WAAW,UAAa,MAAM,QAAW,SAAS;EACxD,SAAS,KAAK;GACZ,QAAQ;GACR,MAAM;EACR;CACF,CAAC;CACD,OAAO;AACT;;;AAIA,SAAS,SAAY,OAAqB,MAA+B;CACvE,MAAM,SAAoB,CAAC;CAC3B,KAAK,MAAM,QAAQ,OACjB,IAAI;EACF,KAAK,IAAI;CACX,SAAS,KAAK;EACZ,OAAO,KAAK,GAAG;CACjB;CAEF,IAAI,OAAO,SAAS,GAAG,MAAM,OAAO;AACtC;;;AAIA,SAAgB,kBACd,WACA,KACM;CACN,SAAS,YAAY,MAAM,EAAE,WAAW,GAAG,CAAC;AAC9C;;;;AAKA,SAAgB,mBACd,WACA,KACA,WACM;CACN,SAAS,YAAY,MAAM,EAAE,YAAY,KAAK,SAAS,CAAC;AAC1D;;;;;;;AAkBA,SAAgB,aAAmB,SAA+B,WAA0B;CAC1F,QAAQ,KAAK,KAAK;CAClB,QAAQ,SAAS,MAAM;CACvB,SAAS,OACD,mBAAmB,QAAQ,WAAW,QAAQ,KAAK,SAAS,SAC5D,QAAQ,UAAU,IAAI,SAAS,CACvC,IAAI,SAAS,KAAK,CAAC;AACrB"}
|