@weasel-js/core 1.11.0 → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +611 -0
- package/README.md +1 -1
- package/dist/WeaselProvider.js +1 -1
- package/dist/affordances/pathAnchors.js +10 -6
- package/dist/affordances/pathAnchors.js.map +1 -1
- package/dist/animation/index.js +3 -3
- package/dist/animation/rig/bindRig.js +1 -1
- package/dist/animation/rig/rigNode.js.map +1 -1
- package/dist/barrel/canvas.js +9 -3
- package/dist/barrel/interactions.js +5 -4
- package/dist/barrel/paint.js +4 -4
- package/dist/barrel/paths.js +10 -6
- package/dist/barrel/renderer.js +5 -3
- package/dist/barrel/routing.js +7 -12
- package/dist/barrel/scene.js +9 -5
- package/dist/barrel/text.js +2 -2
- package/dist/barrel/viewport.js +9 -4
- package/dist/canvas/Canvas.js +5 -2
- package/dist/canvas/Canvas.js.map +1 -1
- package/dist/canvas/CanvasView.js +23 -34
- package/dist/canvas/CanvasView.js.map +1 -1
- package/dist/canvas/ModalityHud.js +1 -1
- package/dist/canvas/NodeShape.js +4 -1
- package/dist/canvas/NodeShape.js.map +1 -1
- package/dist/canvas/SceneCanvas/ActionsProviderIfRoot.js +1 -1
- package/dist/canvas/SceneCanvas/DepRegistryProviderIfRoot.js +1 -1
- package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js +1 -1
- package/dist/canvas/SceneCanvas/SceneCanvasInput.js +17 -3
- package/dist/canvas/SceneCanvas/SceneCanvasInput.js.map +1 -1
- package/dist/canvas/SceneCanvas/SurfaceDeclarations.js +23 -0
- package/dist/canvas/SceneCanvas/SurfaceDeclarations.js.map +1 -0
- package/dist/canvas/SceneCanvas/builtinToolSets.js +30 -0
- package/dist/canvas/SceneCanvas/builtinToolSets.js.map +1 -0
- package/dist/canvas/SceneCanvas/canvasPassThrough.js +2 -0
- package/dist/canvas/SceneCanvas/canvasPassThrough.js.map +1 -1
- package/dist/canvas/SceneCanvas/coordTrace.js +5 -16
- package/dist/canvas/SceneCanvas/coordTrace.js.map +1 -1
- package/dist/canvas/SceneCanvas/defaultNodeProperties.js +5 -0
- package/dist/canvas/SceneCanvas/defaultNodeProperties.js.map +1 -1
- package/dist/canvas/SceneCanvas/features.js +45 -5
- package/dist/canvas/SceneCanvas/features.js.map +1 -1
- package/dist/canvas/SceneCanvas/props.js +1 -11
- package/dist/canvas/SceneCanvas/props.js.map +1 -1
- package/dist/canvas/SceneCanvas/scenePointQuery.js +7 -3
- package/dist/canvas/SceneCanvas/scenePointQuery.js.map +1 -1
- package/dist/canvas/SceneCanvas/toolRegistry.js +8 -4
- package/dist/canvas/SceneCanvas/toolRegistry.js.map +1 -1
- package/dist/canvas/SceneCanvas/useActionTunings.js +6 -1
- package/dist/canvas/SceneCanvas/useActionTunings.js.map +1 -1
- package/dist/canvas/SceneCanvas/useActionsPropResolver.js +1 -11
- package/dist/canvas/SceneCanvas/useActionsPropResolver.js.map +1 -1
- package/dist/canvas/SceneCanvas/useBuiltinShapeTools.js.map +1 -1
- package/dist/canvas/SceneCanvas/useBuiltinTools.js +2 -9
- package/dist/canvas/SceneCanvas/useBuiltinTools.js.map +1 -1
- package/dist/canvas/SceneCanvas/useCanvasDevtoolsRoot.js +94 -0
- package/dist/canvas/SceneCanvas/useCanvasDevtoolsRoot.js.map +1 -0
- package/dist/canvas/SceneCanvas/useCanvasSelection.js +7 -2
- package/dist/canvas/SceneCanvas/useCanvasSelection.js.map +1 -1
- package/dist/canvas/SceneCanvas/useCanvasTools.js +15 -10
- package/dist/canvas/SceneCanvas/useCanvasTools.js.map +1 -1
- package/dist/canvas/SceneCanvas/useNodeKinds.js +1 -1
- package/dist/canvas/SceneCanvas/useNodeKinds.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneCanvasHandle.js +9 -3
- package/dist/canvas/SceneCanvas/useSceneCanvasHandle.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js +23 -4
- package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneCanvasTools.js +2 -3
- package/dist/canvas/SceneCanvas/useSceneCanvasTools.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneChrome.js +6 -7
- package/dist/canvas/SceneCanvas/useSceneChrome.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneGestureDispatcher.js +24 -7
- package/dist/canvas/SceneCanvas/useSceneGestureDispatcher.js.map +1 -1
- package/dist/canvas/SceneCanvas/useScenePicking.js +2 -3
- package/dist/canvas/SceneCanvas/useScenePicking.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneSelectTool.js +2 -1
- package/dist/canvas/SceneCanvas/useSceneSelectTool.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneStandardActions.js +5 -5
- package/dist/canvas/SceneCanvas/useSceneStandardActions.js.map +1 -1
- package/dist/canvas/SceneCanvas.js +27 -24
- package/dist/canvas/SceneCanvas.js.map +1 -1
- package/dist/canvas/SurfaceCanvas.js +5 -22
- package/dist/canvas/SurfaceCanvas.js.map +1 -1
- package/dist/canvas/ViewMarker.js +35 -0
- package/dist/canvas/ViewMarker.js.map +1 -0
- package/dist/canvas/canvasRenderer.js +9 -5
- package/dist/canvas/canvasRenderer.js.map +1 -1
- package/dist/canvas/contextAttributes.js +14 -0
- package/dist/canvas/contextAttributes.js.map +1 -0
- package/dist/canvas/defaultDrawOne.js +2 -0
- package/dist/canvas/defaultDrawOne.js.map +1 -1
- package/dist/canvas/deps/booleans.js +2 -1
- package/dist/canvas/deps/booleans.js.map +1 -1
- package/dist/canvas/deps/editAnchors.js +9 -113
- package/dist/canvas/deps/editAnchors.js.map +1 -1
- package/dist/canvas/deps/hitTestArea.js +2 -2
- package/dist/canvas/deps/hitTestArea.js.map +1 -1
- package/dist/canvas/deps/insert.js +10 -4
- package/dist/canvas/deps/insert.js.map +1 -1
- package/dist/canvas/deps/pathEditCommits.js +189 -0
- package/dist/canvas/deps/pathEditCommits.js.map +1 -0
- package/dist/canvas/deps/snap.js +12 -9
- package/dist/canvas/deps/snap.js.map +1 -1
- package/dist/canvas/deps/transformFollowers.js +20 -0
- package/dist/canvas/deps/transformFollowers.js.map +1 -0
- package/dist/canvas/derivedPath.js +20 -1
- package/dist/canvas/derivedPath.js.map +1 -1
- package/dist/canvas/drawnBounds.js +38 -4
- package/dist/canvas/drawnBounds.js.map +1 -1
- package/dist/canvas/inheritedPaints.js +44 -0
- package/dist/canvas/inheritedPaints.js.map +1 -0
- package/dist/canvas/nodeShapes/derivedPainter.js +23 -16
- package/dist/canvas/nodeShapes/derivedPainter.js.map +1 -1
- package/dist/canvas/nodeShapes/nodePaint.js +13 -34
- package/dist/canvas/nodeShapes/nodePaint.js.map +1 -1
- package/dist/canvas/nodeShapes/pathPainter.js +12 -10
- package/dist/canvas/nodeShapes/pathPainter.js.map +1 -1
- package/dist/canvas/nodeShapes/rectFallbackPainter.js +4 -5
- package/dist/canvas/nodeShapes/rectFallbackPainter.js.map +1 -1
- package/dist/canvas/nodeShapes/shapePainter.js +12 -11
- package/dist/canvas/nodeShapes/shapePainter.js.map +1 -1
- package/dist/canvas/nodeShapes/textPainter.js +13 -12
- package/dist/canvas/nodeShapes/textPainter.js.map +1 -1
- package/dist/canvas/overlayRoleStrokes.js +12 -0
- package/dist/canvas/overlayRoleStrokes.js.map +1 -1
- package/dist/canvas/pathOverlay.js +27 -7
- package/dist/canvas/pathOverlay.js.map +1 -1
- package/dist/canvas/pickReach.js +3 -3
- package/dist/canvas/pickReach.js.map +1 -1
- package/dist/canvas/pickWalk.js +3 -1
- package/dist/canvas/pickWalk.js.map +1 -1
- package/dist/canvas/renderDebugSnapshot.js +1 -0
- package/dist/canvas/renderDebugSnapshot.js.map +1 -1
- package/dist/canvas/renderSceneToPixels.js +7 -6
- package/dist/canvas/renderSceneToPixels.js.map +1 -1
- package/dist/canvas/sceneAdapter.js.map +1 -1
- package/dist/canvas/sceneSlotWiring.js +2 -1
- package/dist/canvas/sceneSlotWiring.js.map +1 -1
- package/dist/canvas/sceneViewRender.js +2 -1
- package/dist/canvas/sceneViewRender.js.map +1 -1
- package/dist/canvas/surfaceContribution.js +12 -8
- package/dist/canvas/surfaceContribution.js.map +1 -1
- package/dist/canvas/useCanvasPaint.js +2 -1
- package/dist/canvas/useCanvasPaint.js.map +1 -1
- package/dist/canvas/useCanvasView.js +4 -2
- package/dist/canvas/useCanvasView.js.map +1 -1
- package/dist/canvas/useInFlightBounds.js +52 -0
- package/dist/canvas/useInFlightBounds.js.map +1 -0
- package/dist/canvas/useLayerStack.js +6 -2
- package/dist/canvas/useLayerStack.js.map +1 -1
- package/dist/canvas/useViewAim.js +121 -0
- package/dist/canvas/useViewAim.js.map +1 -0
- package/dist/canvas/useViewHelpers.js +7 -9
- package/dist/canvas/useViewHelpers.js.map +1 -1
- package/dist/canvas/useViewNesting.js +3 -2
- package/dist/canvas/useViewNesting.js.map +1 -1
- package/dist/canvas/useViewRegistrySurface.js +4 -2
- package/dist/canvas/useViewRegistrySurface.js.map +1 -1
- package/dist/canvas/viewMarkers.js +63 -0
- package/dist/canvas/viewMarkers.js.map +1 -0
- package/dist/canvas/viewRegistry.js +27 -1
- package/dist/canvas/viewRegistry.js.map +1 -1
- package/dist/clipboard.d.ts +3 -2
- package/dist/{clone-DZDrfIlU.d.ts → clone-C3e0OTuF.d.ts} +8 -21
- package/dist/clone.d.ts +4 -3
- package/dist/core/geometry/autoPoseDescriptor.js +1 -1
- package/dist/core/ops/setDependsOn.js +37 -0
- package/dist/core/ops/setDependsOn.js.map +1 -0
- package/dist/core/ops/writtenBy.js +53 -0
- package/dist/core/ops/writtenBy.js.map +1 -0
- package/dist/core/pages/fitViewToPage.js +12 -1
- package/dist/core/pages/fitViewToPage.js.map +1 -1
- package/dist/core/pages/pageEdits.js +163 -0
- package/dist/core/pages/pageEdits.js.map +1 -0
- package/dist/core/pages/pages.js +30 -1
- package/dist/core/pages/pages.js.map +1 -1
- package/dist/core/paint/meshKindLazy.js +59 -2
- package/dist/core/paint/meshKindLazy.js.map +1 -1
- package/dist/core/scene/NodeRouting.js +8 -3
- package/dist/core/scene/NodeRouting.js.map +1 -1
- package/dist/core/scene/arrivalWindow.js.map +1 -1
- package/dist/core/scene/carryDescendants.js +51 -0
- package/dist/core/scene/carryDescendants.js.map +1 -0
- package/dist/core/scene/clipNothing.js +13 -0
- package/dist/core/scene/clipNothing.js.map +1 -0
- package/dist/core/scene/depMemo.js +11 -3
- package/dist/core/scene/depMemo.js.map +1 -1
- package/dist/core/scene/dependents.js +7 -1
- package/dist/core/scene/dependents.js.map +1 -1
- package/dist/core/scene/derivedParts.js +10 -11
- package/dist/core/scene/derivedParts.js.map +1 -1
- package/dist/core/scene/docValues.js +57 -0
- package/dist/core/scene/docValues.js.map +1 -0
- package/dist/core/scene/editPass.js +111 -0
- package/dist/core/scene/editPass.js.map +1 -0
- package/dist/core/scene/effectivePose.js +13 -2
- package/dist/core/scene/effectivePose.js.map +1 -1
- package/dist/core/scene/fieldEdits.js +4 -1
- package/dist/core/scene/fieldEdits.js.map +1 -1
- package/dist/core/scene/fontReads.js +37 -0
- package/dist/core/scene/fontReads.js.map +1 -0
- package/dist/core/scene/historyFacade.js +1 -0
- package/dist/core/scene/historyFacade.js.map +1 -1
- package/dist/core/scene/inheritedPaint.js +75 -0
- package/dist/core/scene/inheritedPaint.js.map +1 -0
- package/dist/core/scene/kitRegistry.js +5 -0
- package/dist/core/scene/kitRegistry.js.map +1 -1
- package/dist/core/scene/layoutPass.js +28 -3
- package/dist/core/scene/layoutPass.js.map +1 -1
- package/dist/core/scene/nodeMemo.js +15 -7
- package/dist/core/scene/nodeMemo.js.map +1 -1
- package/dist/core/scene/pathEffects/blend.js.map +1 -1
- package/dist/core/scene/pathEffects/derive.js +7 -2
- package/dist/core/scene/pathEffects/derive.js.map +1 -1
- package/dist/core/scene/pathEffects/effects.js +3 -1
- package/dist/core/scene/pathEffects/effects.js.map +1 -1
- package/dist/core/scene/pathEffects/textAlong.js +95 -0
- package/dist/core/scene/pathEffects/textAlong.js.map +1 -0
- package/dist/core/scene/recorder.js +28 -19
- package/dist/core/scene/recorder.js.map +1 -1
- package/dist/core/scene/scene.js +15 -9
- package/dist/core/scene/scene.js.map +1 -1
- package/dist/core/scene/sceneChanges.js +13 -0
- package/dist/core/scene/sceneChanges.js.map +1 -0
- package/dist/core/scene/sceneEdits.js +8 -1
- package/dist/core/scene/sceneEdits.js.map +1 -1
- package/dist/core/scene/sceneMutators.js +1 -0
- package/dist/core/scene/sceneMutators.js.map +1 -1
- package/dist/core/scene/sceneRecording.js +20 -3
- package/dist/core/scene/sceneRecording.js.map +1 -1
- package/dist/core/scene/sceneSelection.js +4 -1
- package/dist/core/scene/sceneSelection.js.map +1 -1
- package/dist/core/scene/sceneState.js +11 -5
- package/dist/core/scene/sceneState.js.map +1 -1
- package/dist/core/scene/serialization.js +5 -3
- package/dist/core/scene/serialization.js.map +1 -1
- package/dist/core/scene/types.js.map +1 -1
- package/dist/core/scene/unitScopes.js +19 -1
- package/dist/core/scene/unitScopes.js.map +1 -1
- package/dist/core/selection/usePublishSceneSelection.js +6 -12
- package/dist/core/selection/usePublishSceneSelection.js.map +1 -1
- package/dist/core/shapeKinds.js +25 -11
- package/dist/core/shapeKinds.js.map +1 -1
- package/dist/{cornerHandles-Camw_yeu.d.ts → cornerHandles-p8fDIAKt.d.ts} +3 -2
- package/dist/debug/createDebugOverlayLayer.js +16 -111
- package/dist/debug/createDebugOverlayLayer.js.map +1 -1
- package/dist/debug/createDebugSink.js +2 -1
- package/dist/debug/createDebugSink.js.map +1 -1
- package/dist/debug/defaultTheme.js +4 -2
- package/dist/debug/defaultTheme.js.map +1 -1
- package/dist/debug/features.js +17 -0
- package/dist/debug/features.js.map +1 -0
- package/dist/debug/overlayPanels.js +117 -0
- package/dist/debug/overlayPanels.js.map +1 -0
- package/dist/debug/parseDebugFlags.js +4 -13
- package/dist/debug/parseDebugFlags.js.map +1 -1
- package/dist/{depSchema-Cgfu_G9s.d.ts → depSchema-mG19aEdD.d.ts} +174 -904
- package/dist/devtools/handlers.js +112 -0
- package/dist/devtools/handlers.js.map +1 -0
- package/dist/devtools/history.js +71 -0
- package/dist/devtools/history.js.map +1 -0
- package/dist/devtools/hook.js +74 -0
- package/dist/devtools/hook.js.map +1 -0
- package/dist/devtools/label.js +25 -0
- package/dist/devtools/label.js.map +1 -0
- package/dist/devtools/notices.js +58 -0
- package/dist/devtools/notices.js.map +1 -0
- package/dist/devtools/protocol.js +7 -0
- package/dist/devtools/protocol.js.map +1 -0
- package/dist/devtools/registry.js +90 -0
- package/dist/devtools/registry.js.map +1 -0
- package/dist/devtools/root.js +80 -0
- package/dist/devtools/root.js.map +1 -0
- package/dist/devtools/serialize.js +86 -0
- package/dist/devtools/serialize.js.map +1 -0
- package/dist/devtools/session.js +111 -0
- package/dist/devtools/session.js.map +1 -0
- package/dist/devtools/transport.js +67 -0
- package/dist/devtools/transport.js.map +1 -0
- package/dist/devtools/useDevtoolsRoot.js +81 -0
- package/dist/devtools/useDevtoolsRoot.js.map +1 -0
- package/dist/devtools-protocol.d.ts +435 -0
- package/dist/devtools-protocol.js +7 -0
- package/dist/devtools.d.ts +8 -0
- package/dist/devtools.js +12 -0
- package/dist/devtools.js.map +1 -0
- package/dist/features/chrome-caps/useHoverTracking.js +16 -10
- package/dist/features/chrome-caps/useHoverTracking.js.map +1 -1
- package/dist/features/ingestion/contentHandlers.js +25 -2
- package/dist/features/ingestion/contentHandlers.js.map +1 -1
- package/dist/features/measure/measureCommands.js +7 -5
- package/dist/features/measure/measureCommands.js.map +1 -1
- package/dist/features/measure/measureContribution.js +4 -2
- package/dist/features/measure/measureContribution.js.map +1 -1
- package/dist/features/modes/modeTriggers.js +7 -3
- package/dist/features/modes/modeTriggers.js.map +1 -1
- package/dist/features/pathEffects/effectSources.js +60 -0
- package/dist/features/pathEffects/effectSources.js.map +1 -0
- package/dist/features/pathEffects/readSource.js +17 -1
- package/dist/features/pathEffects/readSource.js.map +1 -1
- package/dist/features/pathEffects/textItems.js +53 -0
- package/dist/features/pathEffects/textItems.js.map +1 -0
- package/dist/features/pathEffects/useEffectSourcesLayer.js +57 -0
- package/dist/features/pathEffects/useEffectSourcesLayer.js.map +1 -0
- package/dist/features/paths/index.js +2 -2
- package/dist/features/paths/pathEditExtension.js.map +1 -1
- package/dist/features/paths/pathEditState.js +5 -2
- package/dist/features/paths/pathEditState.js.map +1 -1
- package/dist/features/paths/pathSnap/pathSnapSource.js +5 -5
- package/dist/features/paths/pathSnap/pathSnapSource.js.map +1 -1
- package/dist/features/paths/pathSnap/sceneIndex.js +10 -3
- package/dist/features/paths/pathSnap/sceneIndex.js.map +1 -1
- package/dist/features/selection/selectionPose.js +4 -1
- package/dist/features/selection/selectionPose.js.map +1 -1
- package/dist/features/snap/gather.js +9 -1
- package/dist/features/snap/gather.js.map +1 -1
- package/dist/features/snap/lazySession.js +17 -0
- package/dist/features/snap/lazySession.js.map +1 -0
- package/dist/features/snap/marks.js.map +1 -1
- package/dist/features/snap/probes2d.js +27 -19
- package/dist/features/snap/probes2d.js.map +1 -1
- package/dist/features/snap/readoutLayer.js.map +1 -1
- package/dist/features/snap/roles.js +2 -1
- package/dist/features/snap/roles.js.map +1 -1
- package/dist/features/snap/rotationSource.js +25 -8
- package/dist/features/snap/rotationSource.js.map +1 -1
- package/dist/features/snap/sceneSession2d.js +6 -4
- package/dist/features/snap/sceneSession2d.js.map +1 -1
- package/dist/features/snap/session2d.js +37 -23
- package/dist/features/snap/session2d.js.map +1 -1
- package/dist/features/snap/spanSnap.js +5 -2
- package/dist/features/snap/spanSnap.js.map +1 -1
- package/dist/features/text/sceneTextDrafts.js +65 -0
- package/dist/features/text/sceneTextDrafts.js.map +1 -0
- package/dist/features/text/textHitAt.js +31 -2
- package/dist/features/text/textHitAt.js.map +1 -1
- package/dist/features/text/useSceneTextEdit.js +22 -18
- package/dist/features/text/useSceneTextEdit.js.map +1 -1
- package/dist/features/viewports/aim.js +105 -0
- package/dist/features/viewports/aim.js.map +1 -0
- package/dist/features/viewports/viewMarker.js +82 -0
- package/dist/features/viewports/viewMarker.js.map +1 -0
- package/dist/features/viewports/viewMarkerDrag.js +55 -0
- package/dist/features/viewports/viewMarkerDrag.js.map +1 -0
- package/dist/icons.table.js +1 -1
- package/dist/icons.table.js.map +1 -1
- package/dist/icons.table.json +0 -10
- package/dist/index.d.ts +1198 -894
- package/dist/index.js +55 -38
- package/dist/interactions/actions/align/action.js +6 -4
- package/dist/interactions/actions/align/action.js.map +1 -1
- package/dist/interactions/actions/align/align.js.map +1 -1
- package/dist/interactions/actions/booleans/action.js +7 -1
- package/dist/interactions/actions/booleans/action.js.map +1 -1
- package/dist/interactions/actions/booleans/booleans.js +2 -1
- package/dist/interactions/actions/booleans/booleans.js.map +1 -1
- package/dist/interactions/actions/booleans/operands.js +6 -5
- package/dist/interactions/actions/booleans/operands.js.map +1 -1
- package/dist/interactions/actions/clipboard/action.js +27 -17
- package/dist/interactions/actions/clipboard/action.js.map +1 -1
- package/dist/interactions/actions/clone/action.js +1 -1
- package/dist/interactions/actions/clone/behaviors.js +4 -4
- package/dist/interactions/actions/clone/behaviors.js.map +1 -1
- package/dist/interactions/actions/defaults/anchorEditing.js +44 -23
- package/dist/interactions/actions/defaults/anchorEditing.js.map +1 -1
- package/dist/interactions/actions/defaults/anchorJoin.js +12 -6
- package/dist/interactions/actions/defaults/anchorJoin.js.map +1 -1
- package/dist/interactions/actions/defaults/bendSegment.js +8 -5
- package/dist/interactions/actions/defaults/bendSegment.js.map +1 -1
- package/dist/interactions/actions/defaults/cancelGesture.js +11 -8
- package/dist/interactions/actions/defaults/cancelGesture.js.map +1 -1
- package/dist/interactions/actions/defaults/contextMenu.js +17 -8
- package/dist/interactions/actions/defaults/contextMenu.js.map +1 -1
- package/dist/interactions/actions/defaults/createPaintAction.js +2 -2
- package/dist/interactions/actions/defaults/createPaintAction.js.map +1 -1
- package/dist/interactions/actions/defaults/delete.js +64 -41
- package/dist/interactions/actions/defaults/delete.js.map +1 -1
- package/dist/interactions/actions/defaults/duplicate.js +12 -9
- package/dist/interactions/actions/defaults/duplicate.js.map +1 -1
- package/dist/interactions/actions/defaults/enterPathEdit.js +19 -9
- package/dist/interactions/actions/defaults/enterPathEdit.js.map +1 -1
- package/dist/interactions/actions/defaults/escape.js +11 -8
- package/dist/interactions/actions/defaults/escape.js.map +1 -1
- package/dist/interactions/actions/defaults/exitPathEdit.js +7 -4
- package/dist/interactions/actions/defaults/exitPathEdit.js.map +1 -1
- package/dist/interactions/actions/defaults/group.js +21 -15
- package/dist/interactions/actions/defaults/group.js.map +1 -1
- package/dist/interactions/actions/defaults/ingest.js +17 -9
- package/dist/interactions/actions/defaults/ingest.js.map +1 -1
- package/dist/interactions/actions/defaults/insertPathAnchor.js +7 -4
- package/dist/interactions/actions/defaults/insertPathAnchor.js.map +1 -1
- package/dist/interactions/actions/defaults/nudge.js +21 -40
- package/dist/interactions/actions/defaults/nudge.js.map +1 -1
- package/dist/interactions/actions/defaults/pathEditTools.js +11 -8
- package/dist/interactions/actions/defaults/pathEditTools.js.map +1 -1
- package/dist/interactions/actions/defaults/pinchZoom.js +7 -4
- package/dist/interactions/actions/defaults/pinchZoom.js.map +1 -1
- package/dist/interactions/actions/defaults/reorder.js +24 -6
- package/dist/interactions/actions/defaults/reorder.js.map +1 -1
- package/dist/interactions/actions/defaults/selectAll.js +8 -5
- package/dist/interactions/actions/defaults/selectAll.js.map +1 -1
- package/dist/interactions/actions/defaults/setFill.js +7 -3
- package/dist/interactions/actions/defaults/setFill.js.map +1 -1
- package/dist/interactions/actions/defaults/setFillOpacity.js +1 -1
- package/dist/interactions/actions/defaults/setStroke.js +12 -11
- package/dist/interactions/actions/defaults/setStroke.js.map +1 -1
- package/dist/interactions/actions/defaults/setStrokeOpacity.js +1 -1
- package/dist/interactions/actions/defaults/toolActivate.js +7 -1
- package/dist/interactions/actions/defaults/toolActivate.js.map +1 -1
- package/dist/interactions/actions/defaults/toolResetToDefault.js +7 -4
- package/dist/interactions/actions/defaults/toolResetToDefault.js.map +1 -1
- package/dist/interactions/actions/defaults/undoRedo.js +19 -13
- package/dist/interactions/actions/defaults/undoRedo.js.map +1 -1
- package/dist/interactions/actions/defaults/viewportWheelPan.js +16 -7
- package/dist/interactions/actions/defaults/viewportWheelPan.js.map +1 -1
- package/dist/interactions/actions/defaults/viewportZoom.js +24 -6
- package/dist/interactions/actions/defaults/viewportZoom.js.map +1 -1
- package/dist/interactions/actions/distribute/action.js +6 -4
- package/dist/interactions/actions/distribute/action.js.map +1 -1
- package/dist/interactions/actions/drawnBoxes.js +2 -1
- package/dist/interactions/actions/drawnBoxes.js.map +1 -1
- package/dist/interactions/actions/edit-anchors/action.js +10 -10
- package/dist/interactions/actions/edit-anchors/action.js.map +1 -1
- package/dist/interactions/actions/edit-anchors/preview.js +41 -8
- package/dist/interactions/actions/edit-anchors/preview.js.map +1 -1
- package/dist/interactions/actions/flip/action.js +14 -6
- package/dist/interactions/actions/flip/action.js.map +1 -1
- package/dist/interactions/actions/gestureLifecycle.js +5 -2
- package/dist/interactions/actions/gestureLifecycle.js.map +1 -1
- package/dist/interactions/actions/insert/action.js +1 -2
- package/dist/interactions/actions/insert/action.js.map +1 -1
- package/dist/interactions/actions/insert/commit.js +1 -1
- package/dist/interactions/actions/insert/parent.js +11 -0
- package/dist/interactions/actions/insert/parent.js.map +1 -0
- package/dist/interactions/actions/insert/placeAction.js +7 -2
- package/dist/interactions/actions/insert/placeAction.js.map +1 -1
- package/dist/interactions/actions/insert/repositionAction.js +2 -1
- package/dist/interactions/actions/insert/repositionAction.js.map +1 -1
- package/dist/interactions/actions/insert/session.js +5 -1
- package/dist/interactions/actions/insert/session.js.map +1 -1
- package/dist/interactions/actions/move/action.js +15 -8
- package/dist/interactions/actions/move/action.js.map +1 -1
- package/dist/interactions/actions/move/behaviors/layoutDrop.js +0 -1
- package/dist/interactions/actions/move/behaviors/layoutDrop.js.map +1 -1
- package/dist/interactions/actions/move/behaviors/snapToContainer.js +1 -1
- package/dist/interactions/actions/move/capture.js +1 -1
- package/dist/interactions/actions/move/commit/index.js +0 -2
- package/dist/interactions/actions/move/commit/index.js.map +1 -1
- package/dist/interactions/actions/move/commit/layoutDrop.js +2 -2
- package/dist/interactions/actions/move/commit/layoutRelease.js +2 -2
- package/dist/interactions/actions/move/commit/reparent.js +11 -5
- package/dist/interactions/actions/move/commit/reparent.js.map +1 -1
- package/dist/interactions/actions/move/frame.js +4 -10
- package/dist/interactions/actions/move/frame.js.map +1 -1
- package/dist/interactions/actions/move/landedDescendants.js +20 -17
- package/dist/interactions/actions/move/landedDescendants.js.map +1 -1
- package/dist/interactions/actions/move/layout/container.js +2 -1
- package/dist/interactions/actions/move/layout/container.js.map +1 -1
- package/dist/interactions/actions/move/layout/dragged.js +1 -1
- package/dist/interactions/actions/move/layout/dropPass.js +18 -1
- package/dist/interactions/actions/move/layout/dropPass.js.map +1 -1
- package/dist/interactions/actions/move/layout/exits.js +5 -5
- package/dist/interactions/actions/move/layout/exits.js.map +1 -1
- package/dist/interactions/actions/move/session.js +14 -3
- package/dist/interactions/actions/move/session.js.map +1 -1
- package/dist/interactions/actions/move/translate.js +8 -37
- package/dist/interactions/actions/move/translate.js.map +1 -1
- package/dist/interactions/actions/moveNodes.js +87 -0
- package/dist/interactions/actions/moveNodes.js.map +1 -0
- package/dist/interactions/actions/outlines/createOutlinesAction.js +8 -5
- package/dist/interactions/actions/outlines/createOutlinesAction.js.map +1 -1
- package/dist/interactions/actions/outlines/outlineStroke.js +5 -3
- package/dist/interactions/actions/outlines/outlineStroke.js.map +1 -1
- package/dist/interactions/actions/pathCommands/cutJoin.js +8 -5
- package/dist/interactions/actions/pathCommands/cutJoin.js.map +1 -1
- package/dist/interactions/actions/planeInput.js.map +1 -1
- package/dist/interactions/actions/resize/action.js +83 -72
- package/dist/interactions/actions/resize/action.js.map +1 -1
- package/dist/interactions/actions/resize/commit.js +2 -1
- package/dist/interactions/actions/resize/commit.js.map +1 -1
- package/dist/interactions/actions/resize/cornerHandles.js +2 -1
- package/dist/interactions/actions/resize/cornerHandles.js.map +1 -1
- package/dist/interactions/actions/resize/session.js +2 -0
- package/dist/interactions/actions/resize/session.js.map +1 -1
- package/dist/interactions/actions/resolvePreviews.js +3 -3
- package/dist/interactions/actions/resolvePreviews.js.map +1 -1
- package/dist/interactions/actions/rotate/action.js +7 -4
- package/dist/interactions/actions/rotate/action.js.map +1 -1
- package/dist/interactions/actions/rotate/commit.js +2 -1
- package/dist/interactions/actions/rotate/commit.js.map +1 -1
- package/dist/interactions/actions/rotate/session.js +2 -0
- package/dist/interactions/actions/rotate/session.js.map +1 -1
- package/dist/interactions/actions/selectionSubtree.js +25 -9
- package/dist/interactions/actions/selectionSubtree.js.map +1 -1
- package/dist/interactions/actions/testUtils.js.map +1 -1
- package/dist/interactions/actions/transform-again/action.js +13 -11
- package/dist/interactions/actions/transform-again/action.js.map +1 -1
- package/dist/interactions/actions/transformFinish.js +106 -0
- package/dist/interactions/actions/transformFinish.js.map +1 -0
- package/dist/json.d.ts +4 -0
- package/dist/json.js +3 -0
- package/dist/kitSettingsSchema.js +8 -5
- package/dist/kitSettingsSchema.js.map +1 -1
- package/dist/{math-CrJULaZI.d.ts → math-B56zxVs5.d.ts} +10 -1
- package/dist/math.d.ts +1 -1
- package/dist/math.js +2 -1
- package/dist/move.d.ts +5 -4
- package/dist/{options-p9GZMXbY.d.ts → options-DBxEryYq.d.ts} +1 -1
- package/dist/resize.d.ts +4 -3
- package/dist/routing.d.ts +1 -1
- package/dist/routing.js +2 -2
- package/dist/test-hook/createTestHook.js +1 -1
- package/dist/test-hook/createTestHook.js.map +1 -1
- package/dist/test-hook/useTestHook.js +2 -1
- package/dist/test-hook/useTestHook.js.map +1 -1
- package/dist/test-seams.d.ts +9 -5
- package/dist/tools/builtin/ellipse/useEllipseTool.js +1 -0
- package/dist/tools/builtin/ellipse/useEllipseTool.js.map +1 -1
- package/dist/tools/builtin/eyedropper/useEyedropperTool.js +2 -1
- package/dist/tools/builtin/eyedropper/useEyedropperTool.js.map +1 -1
- package/dist/tools/builtin/hand/dragPanContribution.js +4 -1
- package/dist/tools/builtin/hand/dragPanContribution.js.map +1 -1
- package/dist/tools/builtin/hand/useHandTool.js +7 -4
- package/dist/tools/builtin/hand/useHandTool.js.map +1 -1
- package/dist/tools/builtin/image/useImageTool.js +1 -0
- package/dist/tools/builtin/image/useImageTool.js.map +1 -1
- package/dist/tools/builtin/lasso/useLassoTool.js +1 -0
- package/dist/tools/builtin/lasso/useLassoTool.js.map +1 -1
- package/dist/tools/builtin/line/useLineTool.js +1 -0
- package/dist/tools/builtin/line/useLineTool.js.map +1 -1
- package/dist/tools/builtin/measure/useMeasureTool.js +12 -5
- package/dist/tools/builtin/measure/useMeasureTool.js.map +1 -1
- package/dist/tools/builtin/pen/penHandle.js +3 -5
- package/dist/tools/builtin/pen/penHandle.js.map +1 -1
- package/dist/tools/builtin/pen/usePenTool.js +14 -6
- package/dist/tools/builtin/pen/usePenTool.js.map +1 -1
- package/dist/tools/builtin/pencil/usePencilTool.js +1 -0
- package/dist/tools/builtin/pencil/usePencilTool.js.map +1 -1
- package/dist/tools/builtin/polygon/usePolygonTool.js +13 -4
- package/dist/tools/builtin/polygon/usePolygonTool.js.map +1 -1
- package/dist/tools/builtin/rect/useRectTool.js +1 -0
- package/dist/tools/builtin/rect/useRectTool.js.map +1 -1
- package/dist/tools/builtin/select/adapterPointQuery.js +3 -2
- package/dist/tools/builtin/select/adapterPointQuery.js.map +1 -1
- package/dist/tools/builtin/select/pressDecision.js +32 -0
- package/dist/tools/builtin/select/pressDecision.js.map +1 -0
- package/dist/tools/builtin/select/selectionContributions.js +22 -13
- package/dist/tools/builtin/select/selectionContributions.js.map +1 -1
- package/dist/tools/builtin/select/useSelectTool.js +13 -10
- package/dist/tools/builtin/select/useSelectTool.js.map +1 -1
- package/dist/tools/builtin/slice/useSliceTool.js +22 -8
- package/dist/tools/builtin/slice/useSliceTool.js.map +1 -1
- package/dist/tools/builtin/star/useStarTool.js +13 -4
- package/dist/tools/builtin/star/useStarTool.js.map +1 -1
- package/dist/tools/builtin/sticky/stickyNode.js +4 -1
- package/dist/tools/builtin/sticky/stickyNode.js.map +1 -1
- package/dist/tools/builtin/sticky/useStickyTool.js +10 -5
- package/dist/tools/builtin/sticky/useStickyTool.js.map +1 -1
- package/dist/tools/builtin/text/useTextTool.js +3 -1
- package/dist/tools/builtin/text/useTextTool.js.map +1 -1
- package/dist/tools/index.js +26 -0
- package/dist/{types-CHVXGfYm.d.ts → types-7puAuVD2.d.ts} +3 -262
- package/dist/types-BN9hbdMI.d.ts +184 -0
- package/dist/types-CniVctmk.d.ts +949 -0
- package/dist/types-oFeQ5VjV.d.ts +264 -0
- package/dist/util/paint.js +1 -3
- package/dist/util/paint.js.map +1 -1
- package/dist/version.js +1 -1
- package/package.json +39 -25
- package/dist/canvas/SceneCanvas/useBuiltinRigTools.js +0 -65
- package/dist/canvas/SceneCanvas/useBuiltinRigTools.js.map +0 -1
- package/dist/tools/builtin/bone/boneActions.js +0 -156
- package/dist/tools/builtin/bone/boneActions.js.map +0 -1
- package/dist/tools/builtin/bone/boneOverlay.js +0 -71
- package/dist/tools/builtin/bone/boneOverlay.js.map +0 -1
- package/dist/tools/builtin/bone/placedRig.js +0 -28
- package/dist/tools/builtin/bone/placedRig.js.map +0 -1
- package/dist/tools/builtin/bone/rigEditState.js +0 -30
- package/dist/tools/builtin/bone/rigEditState.js.map +0 -1
- package/dist/tools/builtin/bone/useBoneTool.js +0 -125
- package/dist/tools/builtin/bone/useBoneTool.js.map +0 -1
- package/dist/tools/builtin/weight/useWeightTool.js +0 -101
- package/dist/tools/builtin/weight/useWeightTool.js.map +0 -1
- package/dist/tools/builtin/weight/weightActions.js +0 -140
- package/dist/tools/builtin/weight/weightActions.js.map +0 -1
- package/dist/tools/builtin/weight/weightOverlay.js +0 -78
- package/dist/tools/builtin/weight/weightOverlay.js.map +0 -1
|
@@ -25,8 +25,6 @@ function commitMove(input) {
|
|
|
25
25
|
scene: session.scene,
|
|
26
26
|
projection: session.projection,
|
|
27
27
|
startPoses: session.startPoses,
|
|
28
|
-
carried: session.carried,
|
|
29
|
-
roots: session.ids,
|
|
30
28
|
label: session.lifecycle.label
|
|
31
29
|
}, ops);
|
|
32
30
|
return commitGestureOps(session, session.lifecycle, [...ops, ...followers]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../../../src/interactions/actions/move/commit/index.ts"],"sourcesContent":["import type { Op } from 'core/ops/types';\nimport { commitGestureOps, reduceBehaviorEnd } from '../../gestureLifecycle';\nimport { draggedStoredPose } from '../delta';\nimport { landedDescendantOps } from '../landedDescendants';\nimport type { MoveSession } from '../session';\nimport { rootTranslateOps, translateOps } from '../translate';\n\nexport interface CommitInput {\n session: MoveSession;\n delta: { dx: number; dy: number };\n /** Where the pointer was let go, or the last move's point when the end carried none. */\n at: { x: number; y: number };\n}\n\n/** What the behaviors answer for the commit: ops, `null` to abort, or\n * `undefined` when every one of them leaves it to the default translate. */\nfunction endBehaviors(\n session: MoveSession,\n delta: { dx: number; dy: number },\n at: { x: number; y: number },\n): Op[] | null | undefined {\n const { dx, dy } = delta;\n const gctx = session.gestureCtx;\n for (const [id, ori] of session.startPoses) {\n gctx.current.set(id as string, draggedStoredPose(session, id, ori, dx, dy));\n }\n return reduceBehaviorEnd(session.behaviors, gctx, {\n translateOps: (ids) => rootTranslateOps(session, ids, delta),\n pointer: at,\n });\n}\n\n/** Commit the drag. Returns whether anything reached the document: false\n * when there was nothing to write, or a container refused what it was sent. */\nexport function commitMove(input: CommitInput): boolean {\n const { session, at } = input;\n // Apply the final delta as a single batch → one undo entry.\n const { dx, dy } = input.delta;\n const commitOps = (ops: Op[]): boolean => {\n const followers = landedDescendantOps(\n {\n scene: session.scene,\n projection: session.projection,\n startPoses: session.startPoses,\n
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../../../src/interactions/actions/move/commit/index.ts"],"sourcesContent":["import type { Op } from 'core/ops/types';\nimport { commitGestureOps, reduceBehaviorEnd } from '../../gestureLifecycle';\nimport { draggedStoredPose } from '../delta';\nimport { landedDescendantOps } from '../landedDescendants';\nimport type { MoveSession } from '../session';\nimport { rootTranslateOps, translateOps } from '../translate';\n\nexport interface CommitInput {\n session: MoveSession;\n delta: { dx: number; dy: number };\n /** Where the pointer was let go, or the last move's point when the end carried none. */\n at: { x: number; y: number };\n}\n\n/** What the behaviors answer for the commit: ops, `null` to abort, or\n * `undefined` when every one of them leaves it to the default translate. */\nfunction endBehaviors(\n session: MoveSession,\n delta: { dx: number; dy: number },\n at: { x: number; y: number },\n): Op[] | null | undefined {\n const { dx, dy } = delta;\n const gctx = session.gestureCtx;\n for (const [id, ori] of session.startPoses) {\n gctx.current.set(id as string, draggedStoredPose(session, id, ori, dx, dy));\n }\n return reduceBehaviorEnd(session.behaviors, gctx, {\n translateOps: (ids) => rootTranslateOps(session, ids, delta),\n pointer: at,\n });\n}\n\n/** Commit the drag. Returns whether anything reached the document: false\n * when there was nothing to write, or a container refused what it was sent. */\nexport function commitMove(input: CommitInput): boolean {\n const { session, at } = input;\n // Apply the final delta as a single batch → one undo entry.\n const { dx, dy } = input.delta;\n const commitOps = (ops: Op[]): boolean => {\n const followers = landedDescendantOps(\n {\n scene: session.scene,\n projection: session.projection,\n startPoses: session.startPoses,\n label: session.lifecycle.label,\n },\n ops,\n );\n return commitGestureOps(session, session.lifecycle, [...ops, ...followers]);\n };\n\n // Behavior pipeline owns the commit if any behavior returns non-undefined.\n const answer = endBehaviors(session, { dx, dy }, at);\n if (answer === null) return false; // abort (e.g. snap-back)\n if (answer !== undefined) return commitOps(answer);\n\n // No-op if no movement (sub-threshold drag or zero delta).\n if (dx === 0 && dy === 0) return false;\n\n // No behavior claimed it — translate-only commit, emitted as transform ops\n // so it routes through the consumer `applyOps` hook (consumer history)\n // when present, else the scene's own history. Under scene v1's\n // absolute-pose semantics every node stores world coords\n // independently, so a container drag must explicitly re-stamp every\n // cascaded descendant by the same dx/dy — otherwise children stay at\n // their old absolute positions (visually they snap to the\n // container's former location).\n // Translate the data-held geometry by the same (dx,dy). Opt-in via\n // the geometryProjection seam; a no-op when the dep is absent.\n const ops = translateOps(session, [...session.ids, ...session.cascadeIds], { dx, dy });\n return ops.length > 0 && commitOps(ops);\n}\n"],"mappings":";;;;;;;;AAgBA,SAAS,aACP,SACA,OACA,IACyB;CACzB,MAAM,EAAE,IAAI,OAAO;CACnB,MAAM,OAAO,QAAQ;CACrB,KAAK,MAAM,CAAC,IAAI,QAAQ,QAAQ,YAC9B,KAAK,QAAQ,IAAI,IAAc,kBAAkB,SAAS,IAAI,KAAK,IAAI,EAAE,CAAC;CAE5E,OAAO,kBAAkB,QAAQ,WAAW,MAAM;EAChD,eAAe,QAAQ,iBAAiB,SAAS,KAAK,KAAK;EAC3D,SAAS;CACX,CAAC;AACH;;;AAIA,SAAgB,WAAW,OAA6B;CACtD,MAAM,EAAE,SAAS,OAAO;CAExB,MAAM,EAAE,IAAI,OAAO,MAAM;CACzB,MAAM,aAAa,QAAuB;EACxC,MAAM,YAAY,oBAChB;GACE,OAAO,QAAQ;GACf,YAAY,QAAQ;GACpB,YAAY,QAAQ;GACpB,OAAO,QAAQ,UAAU;EAC3B,GACA,GACF;EACA,OAAO,iBAAiB,SAAS,QAAQ,WAAW,CAAC,GAAG,KAAK,GAAG,SAAS,CAAC;CAC5E;CAGA,MAAM,SAAS,aAAa,SAAS;EAAE;EAAI;CAAG,GAAG,EAAE;CACnD,IAAI,WAAW,MAAM,OAAO;CAC5B,IAAI,WAAW,QAAW,OAAO,UAAU,MAAM;CAGjD,IAAI,OAAO,KAAK,OAAO,GAAG,OAAO;CAYjC,MAAM,MAAM,aAAa,SAAS,CAAC,GAAG,QAAQ,KAAK,GAAG,QAAQ,UAAU,GAAG;EAAE;EAAI;CAAG,CAAC;CACrF,OAAO,IAAI,SAAS,KAAK,UAAU,GAAG;AACxC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { rebaseLocalPose } from "../../../../core/scene/composeFrame.js";
|
|
2
|
+
import { scenePoseAdapter } from "../../../../core/scene/scenePoseAdapter.js";
|
|
2
3
|
import { asNodeId } from "../../../../core/scene/types.js";
|
|
3
|
-
import { createReparentOp } from "../../../../core/ops/reparent.js";
|
|
4
4
|
import { createTransformOp } from "../../../../core/ops/transform.js";
|
|
5
|
-
import {
|
|
5
|
+
import { createReparentOp } from "../../../../core/ops/reparent.js";
|
|
6
6
|
import { rebaseTransformOp } from "./rebase.js";
|
|
7
7
|
|
|
8
8
|
//#region src/interactions/actions/move/commit/layoutDrop.ts
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { composeWorldPose, rebaseLocalPose } from "../../../../core/scene/composeFrame.js";
|
|
2
|
+
import { scenePoseAdapter } from "../../../../core/scene/scenePoseAdapter.js";
|
|
2
3
|
import { asNodeId } from "../../../../core/scene/types.js";
|
|
3
|
-
import { createReparentOp } from "../../../../core/ops/reparent.js";
|
|
4
4
|
import { createTransformOp } from "../../../../core/ops/transform.js";
|
|
5
|
-
import {
|
|
5
|
+
import { createReparentOp } from "../../../../core/ops/reparent.js";
|
|
6
6
|
import { rebaseTransformOp } from "./rebase.js";
|
|
7
7
|
import { draggedWorldPose, grabbedPoseAdapter } from "../delta.js";
|
|
8
8
|
import { groupBySourceContainer } from "../layout/dropPass.js";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { planeToPlane } from "../../../../core/viewport/parallax.js";
|
|
2
2
|
import { rebaseLocalPose } from "../../../../core/scene/composeFrame.js";
|
|
3
|
+
import { scenePoseAdapter } from "../../../../core/scene/scenePoseAdapter.js";
|
|
3
4
|
import { carryPose, planeOf } from "../../planeInput.js";
|
|
4
|
-
import { createReparentOp } from "../../../../core/ops/reparent.js";
|
|
5
5
|
import { createTransformOp } from "../../../../core/ops/transform.js";
|
|
6
|
-
import {
|
|
6
|
+
import { createReparentOp } from "../../../../core/ops/reparent.js";
|
|
7
7
|
import { draggedWorldPose, grabbedPoseAdapter } from "../delta.js";
|
|
8
8
|
import { translateOps } from "../translate.js";
|
|
9
9
|
import { createSetLayerOp } from "../../../../core/ops/setLayer.js";
|
|
@@ -19,15 +19,21 @@ function resolveDropTarget(session, at) {
|
|
|
19
19
|
if (!hit) return null;
|
|
20
20
|
const hitNode = session.scene.get(hit);
|
|
21
21
|
if (!hitNode) return null;
|
|
22
|
-
if (hitNode.kind === "container") return {
|
|
22
|
+
if (hitNode.kind === "container" && session.admits(hit)) return {
|
|
23
23
|
newParent: hit,
|
|
24
24
|
newLayer: hitNode.layer,
|
|
25
25
|
hitSibling: null
|
|
26
26
|
};
|
|
27
|
+
let newParent = hitNode.parent;
|
|
28
|
+
let hitSibling = hit;
|
|
29
|
+
while (newParent !== null && !session.admits(newParent)) {
|
|
30
|
+
hitSibling = newParent;
|
|
31
|
+
newParent = session.scene.get(newParent)?.parent ?? null;
|
|
32
|
+
}
|
|
27
33
|
return {
|
|
28
|
-
newParent
|
|
34
|
+
newParent,
|
|
29
35
|
newLayer: hitNode.layer,
|
|
30
|
-
hitSibling
|
|
36
|
+
hitSibling
|
|
31
37
|
};
|
|
32
38
|
}
|
|
33
39
|
/** Reparent and reposition each moved root as ops, keeping the world pose the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reparent.js","names":[],"sources":["../../../../../src/interactions/actions/move/commit/reparent.ts"],"sourcesContent":["import { createReparentOp } from 'core/ops/reparent';\nimport { createSetLayerOp } from 'core/ops/setLayer';\nimport { createTransformOp } from 'core/ops/transform';\nimport type { Op } from 'core/ops/types';\nimport type { NodeId } from 'core/scene/types';\nimport { planeToPlane } from 'core/viewport/parallax';\nimport { rebaseLocalPose } from 'core/scene/composePose';\nimport { scenePoseAdapter } from 'core/scene/scenePoseAdapter';\nimport { carryPose, planeOf } from '../../planeInput';\nimport { draggedWorldPose, grabbedPoseAdapter } from '../delta';\nimport type { MoveSession, ReparentOnDrop } from '../session';\nimport { translateOps } from '../translate';\n\n/** Resolved drop target — the new parent + layer + (for `'above'` mode)\n * the hit sibling whose z-order position the moved node should land\n * immediately above. `newParent === null` means \"land at the layer\n * root\" (top-level node of `newLayer`). */\nexport interface DropTarget {\n newParent: NodeId | null;\n newLayer: string;\n hitSibling: NodeId | null;\n}\n\n/** Walk the hit chain to find the appropriate drop target. Returns\n * `null` when no reparent should happen (drop on empty canvas, or the\n * only hits are the moved subtree itself). */\nexport function resolveDropTarget(\n session: MoveSession,\n at: { x: number; y: number },\n): DropTarget | null {\n const dep = session.nodeAtPoint;\n if (!dep) return null;\n\n // Exclude moved roots + their descendants. Otherwise we'd happily\n // reparent a node into itself (or under one of its own children).\n const exclude = new Set<NodeId>([...session.ids, ...session.cascadeIds]);\n const hit = dep(at, exclude);\n if (!hit) return null;\n\n const hitNode = session.scene.get(hit);\n if (!hitNode) return null;\n\n // Containers act as drop-INTO targets; leaves act as drop-NEXT-TO\n // targets (parent = leaf's parent). When the leaf has no parent\n // (top-level under a layer), `newParent === null` and the moved\n // subtree lands at the layer root.\n if (hitNode.kind === 'container') {\n return { newParent: hit, newLayer: hitNode.layer, hitSibling: null };\n }\n
|
|
1
|
+
{"version":3,"file":"reparent.js","names":[],"sources":["../../../../../src/interactions/actions/move/commit/reparent.ts"],"sourcesContent":["import { createReparentOp } from 'core/ops/reparent';\nimport { createSetLayerOp } from 'core/ops/setLayer';\nimport { createTransformOp } from 'core/ops/transform';\nimport type { Op } from 'core/ops/types';\nimport type { NodeId } from 'core/scene/types';\nimport { planeToPlane } from 'core/viewport/parallax';\nimport { rebaseLocalPose } from 'core/scene/composePose';\nimport { scenePoseAdapter } from 'core/scene/scenePoseAdapter';\nimport { carryPose, planeOf } from '../../planeInput';\nimport { draggedWorldPose, grabbedPoseAdapter } from '../delta';\nimport type { MoveSession, ReparentOnDrop } from '../session';\nimport { translateOps } from '../translate';\n\n/** Resolved drop target — the new parent + layer + (for `'above'` mode)\n * the hit sibling whose z-order position the moved node should land\n * immediately above. `newParent === null` means \"land at the layer\n * root\" (top-level node of `newLayer`). */\nexport interface DropTarget {\n newParent: NodeId | null;\n newLayer: string;\n hitSibling: NodeId | null;\n}\n\n/** Walk the hit chain to find the appropriate drop target. Returns\n * `null` when no reparent should happen (drop on empty canvas, or the\n * only hits are the moved subtree itself). */\nexport function resolveDropTarget(\n session: MoveSession,\n at: { x: number; y: number },\n): DropTarget | null {\n const dep = session.nodeAtPoint;\n if (!dep) return null;\n\n // Exclude moved roots + their descendants. Otherwise we'd happily\n // reparent a node into itself (or under one of its own children).\n const exclude = new Set<NodeId>([...session.ids, ...session.cascadeIds]);\n const hit = dep(at, exclude);\n if (!hit) return null;\n\n const hitNode = session.scene.get(hit);\n if (!hitNode) return null;\n\n // Containers act as drop-INTO targets; leaves act as drop-NEXT-TO\n // targets (parent = leaf's parent). When the leaf has no parent\n // (top-level under a layer), `newParent === null` and the moved\n // subtree lands at the layer root.\n if (hitNode.kind === 'container' && session.admits(hit)) {\n return { newParent: hit, newLayer: hitNode.layer, hitSibling: null };\n }\n // A container `canDropInto` refuses is a sibling to land beside, inside\n // the nearest container around it that admits the drop.\n let newParent = hitNode.parent;\n let hitSibling: NodeId = hit;\n while (newParent !== null && !session.admits(newParent)) {\n hitSibling = newParent;\n newParent = session.scene.get(newParent)?.parent ?? null;\n }\n return { newParent, newLayer: hitNode.layer, hitSibling };\n}\n\n/** Reparent and reposition each moved root as ops, keeping the world pose the\n * drag showed, then the ops that bring uncarried descendants along. */\nexport function reparentOps(\n session: MoveSession,\n target: DropTarget,\n mode: ReparentOnDrop,\n delta: { dx: number; dy: number },\n): Op[] {\n const { scene, pc, view } = session;\n const adapter = scenePoseAdapter(scene);\n const label = session.lifecycle.label;\n const ops: Op[] = [];\n // The destination's children as each op will find them: an earlier root's\n // landing shifts where a later one goes.\n const siblings = [...(target.newParent === null ? scene.roots : scene.childrenOf(target.newParent))];\n for (const id of session.ids) {\n if (!session.startPoses.has(id)) continue;\n const node = scene.get(id)!;\n const crossing = node.layer !== target.newLayer;\n const world = carryPose(\n session.descriptorOf(id),\n draggedWorldPose(session, grabbedPoseAdapter(session, adapter), id, delta),\n crossing ? planeToPlane(planeOf(view, node.layer), planeOf(view, target.newLayer)) : null,\n );\n const to = rebaseLocalPose(adapter, world, target.newParent as string | null, pc.compose, pc.decompose);\n\n let from = node.parent as string | null;\n if (crossing) {\n // The scene refuses a layer change on a node whose parent is on another layer.\n if (from !== null) {\n ops.push(createReparentOp({\n id: id as string, fromParentId: from, toParentId: null, label, coalesceKey: `reparent:${id}:orphan`,\n }));\n from = null;\n }\n ops.push(createSetLayerOp({ id: id as string, from: node.layer, to: target.newLayer, label }));\n }\n\n const was = siblings.indexOf(id);\n if (was >= 0) siblings.splice(was, 1);\n const hit = mode === 'above' && target.hitSibling\n ? siblings.indexOf(target.hitSibling)\n : -1;\n const toIndex = hit >= 0 ? hit + 1 : undefined;\n if (toIndex === undefined) siblings.push(id);\n else siblings.splice(toIndex, 0, id);\n\n ops.push(createReparentOp({\n id: id as string, fromParentId: from, toParentId: target.newParent as string | null, toIndex, label,\n }));\n ops.push(createTransformOp<unknown>({ id: id as string, from: node.pose, to, label }));\n }\n return [...ops, ...translateOps(session, session.cascadeIds, delta)];\n}\n"],"mappings":";;;;;;;;;;;;;;AA0BA,SAAgB,kBACd,SACA,IACmB;CACnB,MAAM,MAAM,QAAQ;CACpB,IAAI,CAAC,KAAK,OAAO;CAKjB,MAAM,MAAM,IAAI,oBAAI,IADA,IAAY,CAAC,GAAG,QAAQ,KAAK,GAAG,QAAQ,UAAU,CAClD,CAAO;CAC3B,IAAI,CAAC,KAAK,OAAO;CAEjB,MAAM,UAAU,QAAQ,MAAM,IAAI,GAAG;CACrC,IAAI,CAAC,SAAS,OAAO;CAMrB,IAAI,QAAQ,SAAS,eAAe,QAAQ,OAAO,GAAG,GACpD,OAAO;EAAE,WAAW;EAAK,UAAU,QAAQ;EAAO,YAAY;CAAK;CAIrE,IAAI,YAAY,QAAQ;CACxB,IAAI,aAAqB;CACzB,OAAO,cAAc,QAAQ,CAAC,QAAQ,OAAO,SAAS,GAAG;EACvD,aAAa;EACb,YAAY,QAAQ,MAAM,IAAI,SAAS,CAAC,EAAE,UAAU;CACtD;CACA,OAAO;EAAE;EAAW,UAAU,QAAQ;EAAO;CAAW;AAC1D;;;AAIA,SAAgB,YACd,SACA,QACA,MACA,OACM;CACN,MAAM,EAAE,OAAO,IAAI,SAAS;CAC5B,MAAM,UAAU,iBAAiB,KAAK;CACtC,MAAM,QAAQ,QAAQ,UAAU;CAChC,MAAM,MAAY,CAAC;CAGnB,MAAM,WAAW,CAAC,GAAI,OAAO,cAAc,OAAO,MAAM,QAAQ,MAAM,WAAW,OAAO,SAAS,CAAE;CACnG,KAAK,MAAM,MAAM,QAAQ,KAAK;EAC5B,IAAI,CAAC,QAAQ,WAAW,IAAI,EAAE,GAAG;EACjC,MAAM,OAAO,MAAM,IAAI,EAAE;EACzB,MAAM,WAAW,KAAK,UAAU,OAAO;EACvC,MAAM,QAAQ,UACZ,QAAQ,aAAa,EAAE,GACvB,iBAAiB,SAAS,mBAAmB,SAAS,OAAO,GAAG,IAAI,KAAK,GACzE,WAAW,aAAa,QAAQ,MAAM,KAAK,KAAK,GAAG,QAAQ,MAAM,OAAO,QAAQ,CAAC,IAAI,IACvF;EACA,MAAM,KAAK,gBAAgB,SAAS,OAAO,OAAO,WAA4B,GAAG,SAAS,GAAG,SAAS;EAEtG,IAAI,OAAO,KAAK;EAChB,IAAI,UAAU;GAEZ,IAAI,SAAS,MAAM;IACjB,IAAI,KAAK,iBAAiB;KACpB;KAAc,cAAc;KAAM,YAAY;KAAM;KAAO,aAAa,YAAY,GAAG;IAC7F,CAAC,CAAC;IACF,OAAO;GACT;GACA,IAAI,KAAK,iBAAiB;IAAM;IAAc,MAAM,KAAK;IAAO,IAAI,OAAO;IAAU;GAAM,CAAC,CAAC;EAC/F;EAEA,MAAM,MAAM,SAAS,QAAQ,EAAE;EAC/B,IAAI,OAAO,GAAG,SAAS,OAAO,KAAK,CAAC;EACpC,MAAM,MAAM,SAAS,WAAW,OAAO,aACnC,SAAS,QAAQ,OAAO,UAAU,IAClC;EACJ,MAAM,UAAU,OAAO,IAAI,MAAM,IAAI;EACrC,IAAI,YAAY,QAAW,SAAS,KAAK,EAAE;OACtC,SAAS,OAAO,SAAS,GAAG,EAAE;EAEnC,IAAI,KAAK,iBAAiB;GACpB;GAAc,cAAc;GAAM,YAAY,OAAO;GAA4B;GAAS;EAChG,CAAC,CAAC;EACF,IAAI,KAAK,kBAA2B;GAAM;GAAc,MAAM,KAAK;GAAM;GAAI;EAAM,CAAC,CAAC;CACvF;CACA,OAAO,CAAC,GAAG,KAAK,GAAG,aAAa,SAAS,QAAQ,YAAY,KAAK,CAAC;AACrE"}
|
|
@@ -3,9 +3,7 @@ import { pointerStateOf } from "../pointerState.js";
|
|
|
3
3
|
import { snapMods } from "../../../features/snap/roles.js";
|
|
4
4
|
|
|
5
5
|
//#region src/interactions/actions/move/frame.ts
|
|
6
|
-
function foldBehaviors(session, readers, moveCtx,
|
|
7
|
-
let dx = dx0;
|
|
8
|
-
let dy = dy0;
|
|
6
|
+
function foldBehaviors(session, readers, moveCtx, dx, dy) {
|
|
9
7
|
const posed = /* @__PURE__ */ new Map();
|
|
10
8
|
const opaque = /* @__PURE__ */ new Set();
|
|
11
9
|
const gctx = session.gestureCtx;
|
|
@@ -24,16 +22,12 @@ function foldBehaviors(session, readers, moveCtx, dx0, dy0) {
|
|
|
24
22
|
if (!r) continue;
|
|
25
23
|
if (r.poses) for (const [id, pose] of r.poses) posed.set(id, pose);
|
|
26
24
|
if (r.opaque) for (const id of r.opaque) opaque.add(id);
|
|
27
|
-
if (r.transform
|
|
25
|
+
if (r.transform) transform = r.transform;
|
|
28
26
|
if (r.snap !== void 0) gctx.snap = r.snap;
|
|
29
27
|
}
|
|
30
|
-
if (transform.kind === "translate") {
|
|
31
|
-
dx = transform.dx;
|
|
32
|
-
dy = transform.dy;
|
|
33
|
-
}
|
|
34
28
|
return {
|
|
35
|
-
dx,
|
|
36
|
-
dy,
|
|
29
|
+
dx: transform.dx,
|
|
30
|
+
dy: transform.dy,
|
|
37
31
|
posed,
|
|
38
32
|
opaque
|
|
39
33
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frame.js","names":[],"sources":["../../../../src/interactions/actions/move/frame.ts"],"sourcesContent":["import type { InvocationCtx } from '@weasel-js/routing';\nimport { pointerStateOf } from '../pointerState';\nimport type { NodeId } from 'core/scene/types';\nimport type { GestureReaders } from '../../gestures/shared/screenTolerance';\nimport type { BehaviorResult, GroupTransform } from '../../gestures/types';\nimport { draggedStoredPose } from './delta';\nimport { snapMods } from 'features/snap/roles';\nimport type { MoveFrame, MoveSession } from './session';\n\nfunction foldBehaviors(\n session: MoveSession,\n readers: GestureReaders,\n moveCtx: InvocationCtx,\n
|
|
1
|
+
{"version":3,"file":"frame.js","names":[],"sources":["../../../../src/interactions/actions/move/frame.ts"],"sourcesContent":["import type { InvocationCtx } from '@weasel-js/routing';\nimport { pointerStateOf } from '../pointerState';\nimport type { NodeId } from 'core/scene/types';\nimport type { GestureReaders } from '../../gestures/shared/screenTolerance';\nimport type { BehaviorResult, GroupTransform } from '../../gestures/types';\nimport { draggedStoredPose } from './delta';\nimport { snapMods } from 'features/snap/roles';\nimport type { MoveFrame, MoveSession } from './session';\n\nfunction foldBehaviors(\n session: MoveSession,\n readers: GestureReaders,\n moveCtx: InvocationCtx,\n dx: number,\n dy: number,\n): { dx: number; dy: number; posed: Map<NodeId, unknown>; opaque: Set<NodeId> } {\n const posed = new Map<NodeId, unknown>();\n const opaque = new Set<NodeId>();\n const gctx = session.gestureCtx;\n gctx.modifiers = { ...moveCtx.modifiers };\n gctx.pointer = pointerStateOf(moveCtx.drag!.current, moveCtx);\n gctx.view = readers.view();\n gctx.plane = readers.plane();\n // `current` is pre-populated from the raw cursor delta BEFORE\n // any behavior shapes `transform`. Unlike `onEnd`, it is NOT\n // refreshed after each behavior runs — so onMove behaviors\n // should derive position from `origin` + the `proposed`\n // GroupTransform arg, NOT from `ctx.current` (which reflects\n // the unmodified delta at this frame's start).\n for (const [id, ori] of session.startPoses) {\n gctx.current.set(id as string, draggedStoredPose(session, id, ori, dx, dy));\n }\n let transform: GroupTransform = { kind: 'translate', dx, dy };\n for (const b of session.behaviors) {\n const r: BehaviorResult<unknown> | void = b.onMove?.(gctx, transform);\n if (!r) continue;\n if (r.poses) for (const [id, pose] of r.poses) posed.set(id as NodeId, pose);\n if (r.opaque) for (const id of r.opaque) opaque.add(id as NodeId);\n if (r.transform) transform = r.transform;\n if (r.snap !== undefined) gctx.snap = r.snap;\n }\n return { dx: transform.dx, dy: transform.dy, posed, opaque };\n}\n\n/** The pointer's delta, moved so the subject lands on what the snap session\n * holds it to. */\nfunction snapDelta(session: MoveSession, moveCtx: InvocationCtx): { dx: number; dy: number } {\n const d = moveCtx.drag!.delta;\n if (!session.snap) return { dx: d.x, dy: d.y };\n const { press } = session;\n const out = session.snap.at({ x: press.x + d.x, y: press.y + d.y }, snapMods(moveCtx));\n return { dx: out.point.x - press.x, dy: out.point.y - press.y };\n}\n\n/** One move's delta and previews: the pointer's delta as the behaviors shaped\n * it, every displaced id's stored pose under it, and whatever else the\n * behaviors posed. */\nexport function nextFrame(session: MoveSession, readers: GestureReaders, moveCtx: InvocationCtx): MoveFrame {\n const snapped = snapDelta(session, moveCtx);\n const { dx, dy, posed, opaque } = foldBehaviors(session, readers, moveCtx, snapped.dx, snapped.dy);\n\n // The delta stays in the frame — no scene writes, no history entries.\n const delta = { dx, dy };\n // Every displaced id's pose (roots + cascade), published to the scene's\n // overrides by the action.\n const previews = new Map<NodeId, unknown>();\n for (const [id, ori] of session.startPoses) {\n const dragged = draggedStoredPose(session, id, ori, dx, dy);\n previews.set(id, session.carried.has(id) ? dragged : posed.get(id) ?? dragged);\n }\n for (const [id, pose] of posed) if (!session.startPoses.has(id)) previews.set(id, pose);\n return { delta, previews, opaque };\n}\n"],"mappings":";;;;;AASA,SAAS,cACP,SACA,SACA,SACA,IACA,IAC8E;CAC9E,MAAM,wBAAQ,IAAI,IAAqB;CACvC,MAAM,yBAAS,IAAI,IAAY;CAC/B,MAAM,OAAO,QAAQ;CACrB,KAAK,YAAY,EAAE,GAAG,QAAQ,UAAU;CACxC,KAAK,UAAU,eAAe,QAAQ,KAAM,SAAS,OAAO;CAC5D,KAAK,OAAO,QAAQ,KAAK;CACzB,KAAK,QAAQ,QAAQ,MAAM;CAO3B,KAAK,MAAM,CAAC,IAAI,QAAQ,QAAQ,YAC9B,KAAK,QAAQ,IAAI,IAAc,kBAAkB,SAAS,IAAI,KAAK,IAAI,EAAE,CAAC;CAE5E,IAAI,YAA4B;EAAE,MAAM;EAAa;EAAI;CAAG;CAC5D,KAAK,MAAM,KAAK,QAAQ,WAAW;EACjC,MAAM,IAAoC,EAAE,SAAS,MAAM,SAAS;EACpE,IAAI,CAAC,GAAG;EACR,IAAI,EAAE,OAAO,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,OAAO,MAAM,IAAI,IAAc,IAAI;EAC3E,IAAI,EAAE,QAAQ,KAAK,MAAM,MAAM,EAAE,QAAQ,OAAO,IAAI,EAAY;EAChE,IAAI,EAAE,WAAW,YAAY,EAAE;EAC/B,IAAI,EAAE,SAAS,QAAW,KAAK,OAAO,EAAE;CAC1C;CACA,OAAO;EAAE,IAAI,UAAU;EAAI,IAAI,UAAU;EAAI;EAAO;CAAO;AAC7D;;;AAIA,SAAS,UAAU,SAAsB,SAAoD;CAC3F,MAAM,IAAI,QAAQ,KAAM;CACxB,IAAI,CAAC,QAAQ,MAAM,OAAO;EAAE,IAAI,EAAE;EAAG,IAAI,EAAE;CAAE;CAC7C,MAAM,EAAE,UAAU;CAClB,MAAM,MAAM,QAAQ,KAAK,GAAG;EAAE,GAAG,MAAM,IAAI,EAAE;EAAG,GAAG,MAAM,IAAI,EAAE;CAAE,GAAG,SAAS,OAAO,CAAC;CACrF,OAAO;EAAE,IAAI,IAAI,MAAM,IAAI,MAAM;EAAG,IAAI,IAAI,MAAM,IAAI,MAAM;CAAE;AAChE;;;;AAKA,SAAgB,UAAU,SAAsB,SAAyB,SAAmC;CAC1G,MAAM,UAAU,UAAU,SAAS,OAAO;CAC1C,MAAM,EAAE,IAAI,IAAI,OAAO,WAAW,cAAc,SAAS,SAAS,SAAS,QAAQ,IAAI,QAAQ,EAAE;CAGjG,MAAM,QAAQ;EAAE;EAAI;CAAG;CAGvB,MAAM,2BAAW,IAAI,IAAqB;CAC1C,KAAK,MAAM,CAAC,IAAI,QAAQ,QAAQ,YAAY;EAC1C,MAAM,UAAU,kBAAkB,SAAS,IAAI,KAAK,IAAI,EAAE;EAC1D,SAAS,IAAI,IAAI,QAAQ,QAAQ,IAAI,EAAE,IAAI,UAAU,MAAM,IAAI,EAAE,KAAK,OAAO;CAC/E;CACA,KAAK,MAAM,CAAC,IAAI,SAAS,OAAO,IAAI,CAAC,QAAQ,WAAW,IAAI,EAAE,GAAG,SAAS,IAAI,IAAI,IAAI;CACtF,OAAO;EAAE;EAAO;EAAU;CAAO;AACnC"}
|
|
@@ -1,41 +1,44 @@
|
|
|
1
1
|
import { translatePoseViaDescriptor } from "../../../core/geometry/poseDescriptor.js";
|
|
2
|
-
import {
|
|
2
|
+
import { carriedDescendants, sceneCarrySource } from "../../../core/scene/carryDescendants.js";
|
|
3
3
|
import { createTransformOp } from "../../../core/ops/transform.js";
|
|
4
4
|
|
|
5
5
|
//#region src/interactions/actions/move/landedDescendants.ts
|
|
6
6
|
/**
|
|
7
|
-
* Ops that bring
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
7
|
+
* Ops that bring along the descendants of every node `ops` transforms. A
|
|
8
|
+
* layout drop or a behavior places a dragged root somewhere the drag delta
|
|
9
|
+
* does not describe, and a layout shifts siblings to make room, so each
|
|
10
|
+
* descendant moves by its nearest transformed ancestor's landed pose less
|
|
11
|
+
* that ancestor's start pose. A descendant `ops` already writes, or that a
|
|
11
12
|
* moving frame carries, is left alone.
|
|
12
13
|
*/
|
|
13
14
|
function landedDescendantOps(input, ops) {
|
|
14
|
-
const { scene, projection, startPoses,
|
|
15
|
+
const { scene, projection, startPoses, label } = input;
|
|
15
16
|
const landed = /* @__PURE__ */ new Map();
|
|
16
17
|
for (const op of ops) {
|
|
17
18
|
if (op.name !== "transform") continue;
|
|
18
19
|
const a = op.args;
|
|
19
|
-
|
|
20
|
+
const id = a.id;
|
|
21
|
+
landed.set(id, {
|
|
22
|
+
from: landed.get(id)?.from ?? startPoses.get(id) ?? a.from,
|
|
23
|
+
to: a.to
|
|
24
|
+
});
|
|
20
25
|
}
|
|
26
|
+
const source = sceneCarrySource(scene);
|
|
21
27
|
const out = [];
|
|
22
|
-
for (const root of
|
|
23
|
-
|
|
24
|
-
const
|
|
25
|
-
if (to === void 0 || start === void 0) continue;
|
|
26
|
-
const a = projection.getBounds(start);
|
|
28
|
+
for (const [root, { from, to }] of landed) {
|
|
29
|
+
if (from === void 0 || to === void 0) continue;
|
|
30
|
+
const a = projection.getBounds(from);
|
|
27
31
|
const b = projection.getBounds(to);
|
|
28
32
|
const dx = b.x - a.x;
|
|
29
33
|
const dy = b.y - a.y;
|
|
30
34
|
if (dx === 0 && dy === 0) continue;
|
|
31
|
-
|
|
32
|
-
|
|
35
|
+
const carried = carriedDescendants(source, root, (pose) => translatePoseViaDescriptor(pose, dx, dy, projection), (id) => landed.has(id));
|
|
36
|
+
for (const [id, pose] of carried) {
|
|
33
37
|
const node = scene.get(id);
|
|
34
|
-
if (
|
|
35
|
-
out.push(createTransformOp({
|
|
38
|
+
if (node) out.push(createTransformOp({
|
|
36
39
|
id,
|
|
37
40
|
from: node.pose,
|
|
38
|
-
to:
|
|
41
|
+
to: pose,
|
|
39
42
|
label
|
|
40
43
|
}));
|
|
41
44
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"landedDescendants.js","names":[],"sources":["../../../../src/interactions/actions/move/landedDescendants.ts"],"sourcesContent":["import type { NodeId, Scene } from 'core/scene/types';\nimport type { Op } from 'core/ops/types';\nimport { createTransformOp } from 'core/ops/transform';\nimport { translatePoseViaDescriptor, type PoseDescriptor } from 'core/geometry/poseDescriptor';\nimport {
|
|
1
|
+
{"version":3,"file":"landedDescendants.js","names":[],"sources":["../../../../src/interactions/actions/move/landedDescendants.ts"],"sourcesContent":["import type { NodeId, Scene } from 'core/scene/types';\nimport type { Op } from 'core/ops/types';\nimport { createTransformOp } from 'core/ops/transform';\nimport { translatePoseViaDescriptor, type PoseDescriptor } from 'core/geometry/poseDescriptor';\nimport { carriedDescendants, sceneCarrySource } from 'core/scene/carryDescendants';\n\n/** What a move gesture captured at its start, as this pass reads it. */\nexport interface LandedDescendantsInput {\n scene: Scene<unknown, string, unknown>;\n projection: PoseDescriptor<unknown>;\n /** Start pose of every root and descendant. */\n startPoses: ReadonlyMap<NodeId, unknown>;\n label: string;\n}\n\n/**\n * Ops that bring along the descendants of every node `ops` transforms. A\n * layout drop or a behavior places a dragged root somewhere the drag delta\n * does not describe, and a layout shifts siblings to make room, so each\n * descendant moves by its nearest transformed ancestor's landed pose less\n * that ancestor's start pose. A descendant `ops` already writes, or that a\n * moving frame carries, is left alone.\n */\nexport function landedDescendantOps(input: LandedDescendantsInput, ops: readonly Op[]): Op[] {\n const { scene, projection, startPoses, label } = input;\n const landed = new Map<NodeId, { from: unknown; to: unknown }>();\n for (const op of ops) {\n if (op.name !== 'transform') continue;\n const a = op.args as { id: string; from: unknown; to: unknown };\n const id = a.id as NodeId;\n landed.set(id, { from: landed.get(id)?.from ?? startPoses.get(id) ?? a.from, to: a.to });\n }\n const source = sceneCarrySource(scene);\n const out: Op[] = [];\n for (const [root, { from, to }] of landed) {\n if (from === undefined || to === undefined) continue;\n const a = projection.getBounds(from);\n const b = projection.getBounds(to);\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n if (dx === 0 && dy === 0) continue;\n const carried = carriedDescendants(\n source,\n root,\n (pose) => translatePoseViaDescriptor(pose, dx, dy, projection),\n (id) => landed.has(id),\n );\n for (const [id, pose] of carried) {\n const node = scene.get(id);\n if (node) out.push(createTransformOp<unknown>({ id, from: node.pose, to: pose, label }));\n }\n }\n return out;\n}\n"],"mappings":";;;;;;;;;;;;;AAuBA,SAAgB,oBAAoB,OAA+B,KAA0B;CAC3F,MAAM,EAAE,OAAO,YAAY,YAAY,UAAU;CACjD,MAAM,yBAAS,IAAI,IAA4C;CAC/D,KAAK,MAAM,MAAM,KAAK;EACpB,IAAI,GAAG,SAAS,aAAa;EAC7B,MAAM,IAAI,GAAG;EACb,MAAM,KAAK,EAAE;EACb,OAAO,IAAI,IAAI;GAAE,MAAM,OAAO,IAAI,EAAE,CAAC,EAAE,QAAQ,WAAW,IAAI,EAAE,KAAK,EAAE;GAAM,IAAI,EAAE;EAAG,CAAC;CACzF;CACA,MAAM,SAAS,iBAAiB,KAAK;CACrC,MAAM,MAAY,CAAC;CACnB,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,SAAS,QAAQ;EACzC,IAAI,SAAS,UAAa,OAAO,QAAW;EAC5C,MAAM,IAAI,WAAW,UAAU,IAAI;EACnC,MAAM,IAAI,WAAW,UAAU,EAAE;EACjC,MAAM,KAAK,EAAE,IAAI,EAAE;EACnB,MAAM,KAAK,EAAE,IAAI,EAAE;EACnB,IAAI,OAAO,KAAK,OAAO,GAAG;EAC1B,MAAM,UAAU,mBACd,QACA,OACC,SAAS,2BAA2B,MAAM,IAAI,IAAI,UAAU,IAC5D,OAAO,OAAO,IAAI,EAAE,CACvB;EACA,KAAK,MAAM,CAAC,IAAI,SAAS,SAAS;GAChC,MAAM,OAAO,MAAM,IAAI,EAAE;GACzB,IAAI,MAAM,IAAI,KAAK,kBAA2B;IAAE;IAAI,MAAM,KAAK;IAAM,IAAI;IAAM;GAAM,CAAC,CAAC;EACzF;CACF;CACA,OAAO;AACT"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { toPlane } from "../../../../core/viewport/parallax.js";
|
|
2
2
|
import { composeWorldPose } from "../../../../core/scene/composeFrame.js";
|
|
3
3
|
import { poseDescriptorForNode } from "../../../../core/geometry/poseDescriptor.js";
|
|
4
|
-
import { planeOf } from "../../planeInput.js";
|
|
5
4
|
import { scenePoseAdapter } from "../../../../core/scene/scenePoseAdapter.js";
|
|
5
|
+
import { planeOf } from "../../planeInput.js";
|
|
6
6
|
import { carryDragged } from "./dragged.js";
|
|
7
7
|
import { pointInPath } from "@weasel-js/geom";
|
|
8
8
|
|
|
@@ -80,6 +80,7 @@ function pickContainer(session, dragged, center) {
|
|
|
80
80
|
const plane = planeOf(session.view, node.layer);
|
|
81
81
|
const at = plane ? toPlane(plane, center) : center;
|
|
82
82
|
if (!testInside(id, worldPose, worldAABB, layout, at)) return;
|
|
83
|
+
if (!session.admits(id)) return;
|
|
83
84
|
if (layout.acceptsDrop) {
|
|
84
85
|
const arg = {
|
|
85
86
|
id,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"container.js","names":[],"sources":["../../../../../src/interactions/actions/move/layout/container.ts"],"sourcesContent":["import { pointInPath } from '@weasel-js/geom';\nimport type { NodeId, Scene } from 'core/scene/types';\nimport { poseDescriptorForNode } from 'core/geometry/poseDescriptor';\nimport { toPlane, type PlaneMap } from 'core/viewport/parallax';\nimport { composeWorldPose } from 'core/scene/composePose';\nimport { scenePoseAdapter } from 'core/scene/scenePoseAdapter';\nimport type { DropRegion, LayoutContainer, LayoutStrategy } from '../../../../layout/types';\nimport type { LayoutDep } from '../../depSchema';\nimport { planeOf } from '../../planeInput';\nimport type { MoveSession } from '../session';\nimport { carryDragged, type DraggedChild } from './dragged';\n\nexport interface Bounds4 { x: number; y: number; width: number; height: number }\nexport function pointInBounds(b: Bounds4, at: { x: number; y: number }): boolean {\n return at.x >= b.x && at.x < b.x + b.width && at.y >= b.y && at.y < b.y + b.height;\n}\n\ntype Layout = LayoutStrategy<unknown>;\nexport interface Candidate {\n id: NodeId;\n bounds: Bounds4;\n layout: LayoutStrategy<unknown>;\n zPath: number[];\n depth: number;\n /** The edited plane into this container's. */\n plane: PlaneMap | null;\n}\n\n/** Whether a world point falls in a drop region, which is authored relative to\n * the top-left of the container's world bounds. */\nfunction regionContains(\n region: DropRegion,\n bounds: { x: number; y: number },\n point: { x: number; y: number },\n): boolean {\n const local = { x: point.x - bounds.x, y: point.y - bounds.y };\n return typeof region === 'function'\n ? region(local)\n : pointInPath(region, local.x, local.y);\n}\n\nfunction chooseContainer(\n scene: Scene<unknown, string, unknown>,\n mode: NonNullable<LayoutDep['dropTarget']>,\n candidates: readonly Candidate[],\n): Candidate | null {\n let dest: Candidate | null = null;\n if (mode === 'topmost') {\n // Painted last wins, in the scene's own render order — which crosses\n // subtrees and layers, where a sibling-index path cannot.\n const byId = new Map<NodeId, Candidate>(candidates.map((c) => [c.id, c]));\n for (const id of scene.renderOrder()) dest = byId.get(id) ?? dest;\n } else {\n // Deepest wins; sibling-index path breaks ties (higher z = later index).\n for (const c of candidates) {\n if (dest === null) { dest = c; continue; }\n if (c.depth > dest.depth) { dest = c; continue; }\n if (c.depth < dest.depth) continue;\n let cAfter = false;\n for (let i = 0; i < c.zPath.length; i++) {\n if (c.zPath[i] > dest.zPath[i]) { cAfter = true; break; }\n if (c.zPath[i] < dest.zPath[i]) { cAfter = false; break; }\n }\n if (cAfter) dest = c;\n }\n }\n return dest;\n}\n\n/** The layout container that takes the drop at `center`, or null. */\nexport function pickContainer(\n session: MoveSession,\n dragged: readonly DraggedChild[],\n center: { x: number; y: number },\n): Candidate | null {\n const layoutDep = session.layout;\n if (!layoutDep) return null;\n const scene = session.scene;\n const pc = session.pc;\n const poseAdapter = scenePoseAdapter(scene);\n const d = session.projection;\n const draggedIds = new Set<NodeId>(dragged.map((c) => c.id));\n const candidates: Candidate[] = [];\n const mode = layoutDep.dropTarget ?? 'innermost';\n const testInside = (\n id: NodeId, cPose: unknown, aabb: Bounds4, layout: Layout, at: { x: number; y: number },\n ): boolean => {\n const region = layout.dropRegion?.({ id: id as string, bounds: aabb }) ?? null;\n if (region) return regionContains(region, aabb, at);\n if (mode === 'region') return false;\n if (layout.contains) return layout.contains(cPose, at);\n return pointInBounds(aabb, at);\n };\n const consider = (id: NodeId, zPath: number[]): void => {\n const layout = layoutDep.getLayout(id as string);\n if (!layout) return;\n const node = scene.get(id);\n if (!node) return;\n const worldPose = composeWorldPose(poseAdapter, id as string, pc.compose);\n const worldAABB = poseDescriptorForNode(d, node).getBounds(worldPose);\n const plane = planeOf(session.view, node.layer);\n const at = plane ? toPlane(plane, center) : center;\n if (!testInside(id, worldPose, worldAABB, layout, at)) return;\n if (layout.acceptsDrop) {\n const arg: LayoutContainer = { id: id as string, bounds: worldAABB };\n for (const c of dragged) if (!layout.acceptsDrop(arg, carryDragged(session, c, plane).arg)) return;\n }\n candidates.push({\n id,\n bounds: worldAABB,\n layout,\n zPath,\n depth: zPath.length,\n plane,\n });\n };\n const walk = (parentId: NodeId | null, parentPath: number[]): void => {\n const childIds = parentId === null ? scene.roots : scene.childrenOf(parentId);\n for (let i = 0; i < childIds.length; i++) {\n // A dragged root's subtree goes with it: dropping into one of its own\n // descendants would reparent it under itself.\n if (draggedIds.has(childIds[i])) continue;\n const childPath = [...parentPath, i];\n consider(childIds[i], childPath);\n walk(childIds[i], childPath);\n }\n };\n walk(null, []);\n\n return chooseContainer(scene, mode, candidates);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"container.js","names":[],"sources":["../../../../../src/interactions/actions/move/layout/container.ts"],"sourcesContent":["import { pointInPath } from '@weasel-js/geom';\nimport type { NodeId, Scene } from 'core/scene/types';\nimport { poseDescriptorForNode } from 'core/geometry/poseDescriptor';\nimport { toPlane, type PlaneMap } from 'core/viewport/parallax';\nimport { composeWorldPose } from 'core/scene/composePose';\nimport { scenePoseAdapter } from 'core/scene/scenePoseAdapter';\nimport type { DropRegion, LayoutContainer, LayoutStrategy } from '../../../../layout/types';\nimport type { LayoutDep } from '../../depSchema';\nimport { planeOf } from '../../planeInput';\nimport type { MoveSession } from '../session';\nimport { carryDragged, type DraggedChild } from './dragged';\n\nexport interface Bounds4 { x: number; y: number; width: number; height: number }\nexport function pointInBounds(b: Bounds4, at: { x: number; y: number }): boolean {\n return at.x >= b.x && at.x < b.x + b.width && at.y >= b.y && at.y < b.y + b.height;\n}\n\ntype Layout = LayoutStrategy<unknown>;\nexport interface Candidate {\n id: NodeId;\n bounds: Bounds4;\n layout: LayoutStrategy<unknown>;\n zPath: number[];\n depth: number;\n /** The edited plane into this container's. */\n plane: PlaneMap | null;\n}\n\n/** Whether a world point falls in a drop region, which is authored relative to\n * the top-left of the container's world bounds. */\nfunction regionContains(\n region: DropRegion,\n bounds: { x: number; y: number },\n point: { x: number; y: number },\n): boolean {\n const local = { x: point.x - bounds.x, y: point.y - bounds.y };\n return typeof region === 'function'\n ? region(local)\n : pointInPath(region, local.x, local.y);\n}\n\nfunction chooseContainer(\n scene: Scene<unknown, string, unknown>,\n mode: NonNullable<LayoutDep['dropTarget']>,\n candidates: readonly Candidate[],\n): Candidate | null {\n let dest: Candidate | null = null;\n if (mode === 'topmost') {\n // Painted last wins, in the scene's own render order — which crosses\n // subtrees and layers, where a sibling-index path cannot.\n const byId = new Map<NodeId, Candidate>(candidates.map((c) => [c.id, c]));\n for (const id of scene.renderOrder()) dest = byId.get(id) ?? dest;\n } else {\n // Deepest wins; sibling-index path breaks ties (higher z = later index).\n for (const c of candidates) {\n if (dest === null) { dest = c; continue; }\n if (c.depth > dest.depth) { dest = c; continue; }\n if (c.depth < dest.depth) continue;\n let cAfter = false;\n for (let i = 0; i < c.zPath.length; i++) {\n if (c.zPath[i] > dest.zPath[i]) { cAfter = true; break; }\n if (c.zPath[i] < dest.zPath[i]) { cAfter = false; break; }\n }\n if (cAfter) dest = c;\n }\n }\n return dest;\n}\n\n/** The layout container that takes the drop at `center`, or null. */\nexport function pickContainer(\n session: MoveSession,\n dragged: readonly DraggedChild[],\n center: { x: number; y: number },\n): Candidate | null {\n const layoutDep = session.layout;\n if (!layoutDep) return null;\n const scene = session.scene;\n const pc = session.pc;\n const poseAdapter = scenePoseAdapter(scene);\n const d = session.projection;\n const draggedIds = new Set<NodeId>(dragged.map((c) => c.id));\n const candidates: Candidate[] = [];\n const mode = layoutDep.dropTarget ?? 'innermost';\n const testInside = (\n id: NodeId, cPose: unknown, aabb: Bounds4, layout: Layout, at: { x: number; y: number },\n ): boolean => {\n const region = layout.dropRegion?.({ id: id as string, bounds: aabb }) ?? null;\n if (region) return regionContains(region, aabb, at);\n if (mode === 'region') return false;\n if (layout.contains) return layout.contains(cPose, at);\n return pointInBounds(aabb, at);\n };\n const consider = (id: NodeId, zPath: number[]): void => {\n const layout = layoutDep.getLayout(id as string);\n if (!layout) return;\n const node = scene.get(id);\n if (!node) return;\n const worldPose = composeWorldPose(poseAdapter, id as string, pc.compose);\n const worldAABB = poseDescriptorForNode(d, node).getBounds(worldPose);\n const plane = planeOf(session.view, node.layer);\n const at = plane ? toPlane(plane, center) : center;\n if (!testInside(id, worldPose, worldAABB, layout, at)) return;\n if (!session.admits(id)) return;\n if (layout.acceptsDrop) {\n const arg: LayoutContainer = { id: id as string, bounds: worldAABB };\n for (const c of dragged) if (!layout.acceptsDrop(arg, carryDragged(session, c, plane).arg)) return;\n }\n candidates.push({\n id,\n bounds: worldAABB,\n layout,\n zPath,\n depth: zPath.length,\n plane,\n });\n };\n const walk = (parentId: NodeId | null, parentPath: number[]): void => {\n const childIds = parentId === null ? scene.roots : scene.childrenOf(parentId);\n for (let i = 0; i < childIds.length; i++) {\n // A dragged root's subtree goes with it: dropping into one of its own\n // descendants would reparent it under itself.\n if (draggedIds.has(childIds[i])) continue;\n const childPath = [...parentPath, i];\n consider(childIds[i], childPath);\n walk(childIds[i], childPath);\n }\n };\n walk(null, []);\n\n return chooseContainer(scene, mode, candidates);\n}\n"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { toPlane } from "../../../../core/viewport/parallax.js";
|
|
2
2
|
import { composeWorldPose } from "../../../../core/scene/composeFrame.js";
|
|
3
3
|
import { poseDescriptorForNode, translatePoseViaDescriptor } from "../../../../core/geometry/poseDescriptor.js";
|
|
4
|
-
import { carryPose, invertPlane, planeOf } from "../../planeInput.js";
|
|
5
4
|
import { scenePoseAdapter } from "../../../../core/scene/scenePoseAdapter.js";
|
|
5
|
+
import { carryPose, invertPlane, planeOf } from "../../planeInput.js";
|
|
6
6
|
import { grabbedPoseAdapter, planeDelta } from "../delta.js";
|
|
7
7
|
|
|
8
8
|
//#region src/interactions/actions/move/layout/dragged.ts
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { toPlane } from "../../../../core/viewport/parallax.js";
|
|
2
2
|
import { composeWorldPose, rebaseLocalPose } from "../../../../core/scene/composeFrame.js";
|
|
3
|
-
import {
|
|
3
|
+
import { translatePoseViaDescriptor } from "../../../../core/geometry/poseDescriptor.js";
|
|
4
4
|
import { scenePoseAdapter } from "../../../../core/scene/scenePoseAdapter.js";
|
|
5
|
+
import { carriedDescendants, sceneCarrySource } from "../../../../core/scene/carryDescendants.js";
|
|
6
|
+
import { asNodeId } from "../../../../core/scene/types.js";
|
|
5
7
|
import { carryDragged, gatherDragged, selectionCenter } from "./dragged.js";
|
|
6
8
|
import { pickContainer } from "./container.js";
|
|
7
9
|
|
|
@@ -105,6 +107,16 @@ function sourceReflow(session, dragged, destId) {
|
|
|
105
107
|
}
|
|
106
108
|
return sourceReflow;
|
|
107
109
|
}
|
|
110
|
+
/** The stored poses that bring `id`'s descendants along to `world`, where a reflow shows it. */
|
|
111
|
+
function reflowCarry(session, id, world, moving) {
|
|
112
|
+
const { scene, pc, projection: d } = session;
|
|
113
|
+
const a = d.getBounds(composeWorldPose(scenePoseAdapter(scene), id, pc.compose));
|
|
114
|
+
const b = d.getBounds(world);
|
|
115
|
+
const dx = b.x - a.x;
|
|
116
|
+
const dy = b.y - a.y;
|
|
117
|
+
if (dx === 0 && dy === 0) return /* @__PURE__ */ new Map();
|
|
118
|
+
return carriedDescendants(sceneCarrySource(scene), id, (pose) => translatePoseViaDescriptor(pose, dx, dy, d), moving);
|
|
119
|
+
}
|
|
108
120
|
/** One frame's layout result, or null with no layout dep or nothing dragged. */
|
|
109
121
|
function runDropPass(session, delta, pointer) {
|
|
110
122
|
if (!session.layout) return null;
|
|
@@ -146,6 +158,11 @@ function runDropPass(session, delta, pointer) {
|
|
|
146
158
|
reflow.set(asNodeId(cid), rebaseLocalPose(poseAdapter, pose, parent, pc.compose, pc.decompose));
|
|
147
159
|
reflowIds.add(asNodeId(cid));
|
|
148
160
|
}
|
|
161
|
+
const draggedIds = new Set(dragged.map((c) => c.id));
|
|
162
|
+
for (const [cid, pose] of [...placed.destReflow, ...leftovers]) for (const [id, carried] of reflowCarry(session, asNodeId(cid), pose, (d) => reflow.has(d) || draggedIds.has(d))) {
|
|
163
|
+
reflow.set(id, carried);
|
|
164
|
+
reflowIds.add(id);
|
|
165
|
+
}
|
|
149
166
|
return {
|
|
150
167
|
dropCenter,
|
|
151
168
|
pass: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dropPass.js","names":[],"sources":["../../../../../src/interactions/actions/move/layout/dropPass.ts"],"sourcesContent":["import { asNodeId, type NodeId } from 'core/scene/types';\nimport { toPlane } from 'core/viewport/parallax';\nimport { composeWorldPose, rebaseLocalPose } from 'core/scene/composePose';\nimport { scenePoseAdapter } from 'core/scene/scenePoseAdapter';\nimport type { LayoutChild, LayoutContainer } from '../../../../layout/types';\nimport type { MoveSession } from '../session';\nimport { pickContainer, type Candidate } from './container';\nimport { carryDragged, gatherDragged, selectionCenter, type DraggedChild } from './dragged';\nimport type { DropPass, LayoutPlacement } from './types';\n\n/** Dragged ids grouped by the container they are leaving, skipping any that\n * stay put (`exclude` is the destination) or that had no container. */\nexport function groupBySourceContainer(\n dragged: ReadonlyArray<{ id: NodeId; sourceContainerId: string | null }>,\n exclude: string | null,\n): Map<string, Set<NodeId>> {\n const out = new Map<string, Set<NodeId>>();\n for (const d of dragged) {\n const src = d.sourceContainerId;\n if (!src || src === exclude) continue;\n let set = out.get(src);\n if (!set) { set = new Set<NodeId>(); out.set(src, set); }\n set.add(d.id);\n }\n return out;\n}\n\n/** Place each dragged child in `dest` in turn. Null when the snap rejects\n * any of them: a container that cannot take every member takes none. */\nfunction placeAll(\n session: MoveSession,\n dest: Candidate,\n container: LayoutContainer,\n dragged: readonly DraggedChild[],\n probeOffset: { x: number; y: number },\n): { placements: LayoutPlacement[]; destReflow: Map<NodeId, unknown> } | null {\n const { scene, pc } = session;\n const poseAdapter = scenePoseAdapter(scene);\n const draggedIds = new Set<NodeId>(dragged.map((c) => c.id));\n const layout = dest.layout;\n // The container state the placements run against, advanced by each one.\n const working: LayoutChild<unknown>[] = scene.childrenOf(dest.id).map((cid) => ({\n id: cid as string,\n pose: composeWorldPose(poseAdapter, cid as string, pc.compose),\n }));\n const setWorking = (id: string, pose: unknown): void => {\n const at = working.findIndex((c) => c.id === id);\n if (at >= 0) working[at] = { id, pose };\n else working.push({ id, pose });\n };\n\n const placements: LayoutPlacement[] = [];\n const destReflow = new Map<NodeId, unknown>();\n const destPlane = dest.plane;\n for (const edited of dragged) {\n const dc = carryDragged(session, edited, destPlane);\n const children = working.map((c) => ({ ...c }));\n const targets = layout.getDropTargets(container, children, dc.arg);\n const probe = { x: edited.center.x + probeOffset.x, y: edited.center.y + probeOffset.y };\n const target = layout.snap.pickTarget(targets, destPlane ? toPlane(destPlane, probe) : probe);\n // All-or-nothing: a container that cannot take every member takes none\n // rather than splitting the selection between two homes.\n if (!target) return null;\n placements.push({ dragged: dc.arg, children, target });\n const poses = layout.reflowPoses(container, children, dc.arg, target);\n for (const [cid, pose] of poses) {\n setWorking(cid, pose);\n if (!draggedIds.has(asNodeId(cid))) destReflow.set(asNodeId(cid), pose);\n }\n setWorking(dc.arg.id, poses.get(dc.arg.id) ?? target.pose);\n }\n return { placements, destReflow };\n}\n\n/** World poses of the leftovers that moved in each container the selection left. */\nfunction sourceReflow(\n session: MoveSession, dragged: readonly DraggedChild[], destId: string,\n): Map<string, unknown> {\n const { scene, pc, projection: d } = session;\n const poseAdapter = scenePoseAdapter(scene);\n // Source reflow (cross-container) → fold changed leftovers into previews.\n // One pass per container the selection left behind, with everything that\n // left it withdrawn at once.\n const sourceReflow = new Map<string, unknown>();\n const layoutDep = session.layout;\n if (!layoutDep) return sourceReflow;\n for (const [srcId, leaving] of groupBySourceContainer(dragged.map((c) => ({\n id: c.id,\n sourceContainerId: c.arg.sourceContainerId,\n })), destId)) {\n const srcLayout = layoutDep.getLayout(srcId);\n const srcNode = scene.get(asNodeId(srcId));\n if (!srcLayout || !srcNode) continue;\n const srcContainer: LayoutContainer = {\n id: srcId,\n bounds: d.getBounds(composeWorldPose(poseAdapter, srcId, pc.compose)),\n };\n const srcChildren: LayoutChild<unknown>[] = scene.childrenOf(asNodeId(srcId))\n .filter((cid) => !leaving.has(cid))\n .map((cid) => ({\n id: cid as string,\n pose: composeWorldPose(poseAdapter, cid as string, pc.compose),\n }));\n for (const [cid, pose] of srcLayout.childPoses(srcContainer, srcChildren)) {\n const cur = d.getBounds(composeWorldPose(poseAdapter, cid, pc.compose));\n const next = d.getBounds(pose);\n const same = cur.x === next.x && cur.y === next.y\n && cur.width === next.width && cur.height === next.height;\n if (same) continue;\n sourceReflow.set(cid, pose); // WORLD — rebased at each consumption point\n }\n }\n return sourceReflow;\n}\n\n/** One frame's layout result, or null with no layout dep or nothing dragged. */\nexport function runDropPass(\n session: MoveSession,\n delta: { dx: number; dy: number },\n pointer: { x: number; y: number },\n): DropPass | null {\n if (!session.layout) return null;\n const { scene, pc } = session;\n const poseAdapter = scenePoseAdapter(scene);\n const dragged = gatherDragged(session, delta);\n if (dragged.length === 0) return null;\n const dropCenter = selectionCenter(session, dragged);\n // Each child is snapped at its own position, displaced by however far the\n // pointer sits from that center — the group keeps its shape, and a lone\n // child is still probed at the pointer itself.\n const probeOffset = {\n x: pointer.x - dropCenter.x,\n y: pointer.y - dropCenter.y,\n };\n\n const dest = pickContainer(session, dragged, dropCenter);\n if (!dest) return { dropCenter, pass: null, reflow: new Map() };\n\n const container: LayoutContainer = { id: dest.id as string, bounds: dest.bounds };\n const placed = placeAll(session, dest, container, dragged, probeOffset);\n if (!placed) return { dropCenter, pass: null, reflow: new Map() };\n\n // Destination reflow → fold into previews (the dragged children keep their\n // pointer-following ghosts). `reflowPoses` returns world; previews are\n // local, so rebase to the child's current parent frame first.\n const reflow = new Map<NodeId, unknown>();\n const reflowIds = new Set<NodeId>();\n for (const [cid, pose] of placed.destReflow) {\n const parent = scene.get(cid)?.parent ?? null;\n reflow.set(cid, rebaseLocalPose(poseAdapter, pose, parent, pc.compose, pc.decompose));\n reflowIds.add(cid);\n }\n\n const leftovers = sourceReflow(session, dragged, container.id);\n for (const [cid, pose] of leftovers) {\n const parent = scene.get(asNodeId(cid))?.parent ?? null;\n reflow.set(asNodeId(cid), rebaseLocalPose(poseAdapter, pose, parent, pc.compose, pc.decompose));\n reflowIds.add(asNodeId(cid));\n }\n\n return {\n dropCenter,\n pass: { layout: dest.layout, container, placements: placed.placements, sourceReflow: leftovers, reflowIds },\n reflow,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"dropPass.js","names":[],"sources":["../../../../../src/interactions/actions/move/layout/dropPass.ts"],"sourcesContent":["import { asNodeId, type NodeId } from 'core/scene/types';\nimport { toPlane } from 'core/viewport/parallax';\nimport { composeWorldPose, rebaseLocalPose } from 'core/scene/composePose';\nimport { scenePoseAdapter } from 'core/scene/scenePoseAdapter';\nimport { carriedDescendants, sceneCarrySource } from 'core/scene/carryDescendants';\nimport { translatePoseViaDescriptor } from 'core/geometry/poseDescriptor';\nimport type { LayoutChild, LayoutContainer } from '../../../../layout/types';\nimport type { MoveSession } from '../session';\nimport { pickContainer, type Candidate } from './container';\nimport { carryDragged, gatherDragged, selectionCenter, type DraggedChild } from './dragged';\nimport type { DropPass, LayoutPlacement } from './types';\n\n/** Dragged ids grouped by the container they are leaving, skipping any that\n * stay put (`exclude` is the destination) or that had no container. */\nexport function groupBySourceContainer(\n dragged: ReadonlyArray<{ id: NodeId; sourceContainerId: string | null }>,\n exclude: string | null,\n): Map<string, Set<NodeId>> {\n const out = new Map<string, Set<NodeId>>();\n for (const d of dragged) {\n const src = d.sourceContainerId;\n if (!src || src === exclude) continue;\n let set = out.get(src);\n if (!set) { set = new Set<NodeId>(); out.set(src, set); }\n set.add(d.id);\n }\n return out;\n}\n\n/** Place each dragged child in `dest` in turn. Null when the snap rejects\n * any of them: a container that cannot take every member takes none. */\nfunction placeAll(\n session: MoveSession,\n dest: Candidate,\n container: LayoutContainer,\n dragged: readonly DraggedChild[],\n probeOffset: { x: number; y: number },\n): { placements: LayoutPlacement[]; destReflow: Map<NodeId, unknown> } | null {\n const { scene, pc } = session;\n const poseAdapter = scenePoseAdapter(scene);\n const draggedIds = new Set<NodeId>(dragged.map((c) => c.id));\n const layout = dest.layout;\n // The container state the placements run against, advanced by each one.\n const working: LayoutChild<unknown>[] = scene.childrenOf(dest.id).map((cid) => ({\n id: cid as string,\n pose: composeWorldPose(poseAdapter, cid as string, pc.compose),\n }));\n const setWorking = (id: string, pose: unknown): void => {\n const at = working.findIndex((c) => c.id === id);\n if (at >= 0) working[at] = { id, pose };\n else working.push({ id, pose });\n };\n\n const placements: LayoutPlacement[] = [];\n const destReflow = new Map<NodeId, unknown>();\n const destPlane = dest.plane;\n for (const edited of dragged) {\n const dc = carryDragged(session, edited, destPlane);\n const children = working.map((c) => ({ ...c }));\n const targets = layout.getDropTargets(container, children, dc.arg);\n const probe = { x: edited.center.x + probeOffset.x, y: edited.center.y + probeOffset.y };\n const target = layout.snap.pickTarget(targets, destPlane ? toPlane(destPlane, probe) : probe);\n // All-or-nothing: a container that cannot take every member takes none\n // rather than splitting the selection between two homes.\n if (!target) return null;\n placements.push({ dragged: dc.arg, children, target });\n const poses = layout.reflowPoses(container, children, dc.arg, target);\n for (const [cid, pose] of poses) {\n setWorking(cid, pose);\n if (!draggedIds.has(asNodeId(cid))) destReflow.set(asNodeId(cid), pose);\n }\n setWorking(dc.arg.id, poses.get(dc.arg.id) ?? target.pose);\n }\n return { placements, destReflow };\n}\n\n/** World poses of the leftovers that moved in each container the selection left. */\nfunction sourceReflow(\n session: MoveSession, dragged: readonly DraggedChild[], destId: string,\n): Map<string, unknown> {\n const { scene, pc, projection: d } = session;\n const poseAdapter = scenePoseAdapter(scene);\n // Source reflow (cross-container) → fold changed leftovers into previews.\n // One pass per container the selection left behind, with everything that\n // left it withdrawn at once.\n const sourceReflow = new Map<string, unknown>();\n const layoutDep = session.layout;\n if (!layoutDep) return sourceReflow;\n for (const [srcId, leaving] of groupBySourceContainer(dragged.map((c) => ({\n id: c.id,\n sourceContainerId: c.arg.sourceContainerId,\n })), destId)) {\n const srcLayout = layoutDep.getLayout(srcId);\n const srcNode = scene.get(asNodeId(srcId));\n if (!srcLayout || !srcNode) continue;\n const srcContainer: LayoutContainer = {\n id: srcId,\n bounds: d.getBounds(composeWorldPose(poseAdapter, srcId, pc.compose)),\n };\n const srcChildren: LayoutChild<unknown>[] = scene.childrenOf(asNodeId(srcId))\n .filter((cid) => !leaving.has(cid))\n .map((cid) => ({\n id: cid as string,\n pose: composeWorldPose(poseAdapter, cid as string, pc.compose),\n }));\n for (const [cid, pose] of srcLayout.childPoses(srcContainer, srcChildren)) {\n const cur = d.getBounds(composeWorldPose(poseAdapter, cid, pc.compose));\n const next = d.getBounds(pose);\n const same = cur.x === next.x && cur.y === next.y\n && cur.width === next.width && cur.height === next.height;\n if (same) continue;\n sourceReflow.set(cid, pose); // WORLD — rebased at each consumption point\n }\n }\n return sourceReflow;\n}\n\n/** The stored poses that bring `id`'s descendants along to `world`, where a reflow shows it. */\nfunction reflowCarry(\n session: MoveSession, id: NodeId, world: unknown, moving: (id: NodeId) => boolean,\n): Map<NodeId, unknown> {\n const { scene, pc, projection: d } = session;\n const a = d.getBounds(composeWorldPose(scenePoseAdapter(scene), id as string, pc.compose));\n const b = d.getBounds(world);\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n if (dx === 0 && dy === 0) return new Map();\n return carriedDescendants(sceneCarrySource(scene), id, (pose) => translatePoseViaDescriptor(pose, dx, dy, d), moving);\n}\n\n/** One frame's layout result, or null with no layout dep or nothing dragged. */\nexport function runDropPass(\n session: MoveSession,\n delta: { dx: number; dy: number },\n pointer: { x: number; y: number },\n): DropPass | null {\n if (!session.layout) return null;\n const { scene, pc } = session;\n const poseAdapter = scenePoseAdapter(scene);\n const dragged = gatherDragged(session, delta);\n if (dragged.length === 0) return null;\n const dropCenter = selectionCenter(session, dragged);\n // Each child is snapped at its own position, displaced by however far the\n // pointer sits from that center — the group keeps its shape, and a lone\n // child is still probed at the pointer itself.\n const probeOffset = {\n x: pointer.x - dropCenter.x,\n y: pointer.y - dropCenter.y,\n };\n\n const dest = pickContainer(session, dragged, dropCenter);\n if (!dest) return { dropCenter, pass: null, reflow: new Map() };\n\n const container: LayoutContainer = { id: dest.id as string, bounds: dest.bounds };\n const placed = placeAll(session, dest, container, dragged, probeOffset);\n if (!placed) return { dropCenter, pass: null, reflow: new Map() };\n\n // Destination reflow → fold into previews (the dragged children keep their\n // pointer-following ghosts). `reflowPoses` returns world; previews are\n // local, so rebase to the child's current parent frame first.\n const reflow = new Map<NodeId, unknown>();\n const reflowIds = new Set<NodeId>();\n for (const [cid, pose] of placed.destReflow) {\n const parent = scene.get(cid)?.parent ?? null;\n reflow.set(cid, rebaseLocalPose(poseAdapter, pose, parent, pc.compose, pc.decompose));\n reflowIds.add(cid);\n }\n\n const leftovers = sourceReflow(session, dragged, container.id);\n for (const [cid, pose] of leftovers) {\n const parent = scene.get(asNodeId(cid))?.parent ?? null;\n reflow.set(asNodeId(cid), rebaseLocalPose(poseAdapter, pose, parent, pc.compose, pc.decompose));\n reflowIds.add(asNodeId(cid));\n }\n const draggedIds = new Set<NodeId>(dragged.map((c) => c.id));\n for (const [cid, pose] of [...placed.destReflow, ...leftovers] as [string, unknown][]) {\n for (const [id, carried] of reflowCarry(session, asNodeId(cid), pose, (d) => reflow.has(d) || draggedIds.has(d))) {\n reflow.set(id, carried);\n reflowIds.add(id);\n }\n }\n\n return {\n dropCenter,\n pass: { layout: dest.layout, container, placements: placed.placements, sourceReflow: leftovers, reflowIds },\n reflow,\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { toPlane } from "../../../../core/viewport/parallax.js";
|
|
2
2
|
import { composeWorldPose } from "../../../../core/scene/composeFrame.js";
|
|
3
3
|
import { poseDescriptorForNode } from "../../../../core/geometry/poseDescriptor.js";
|
|
4
|
-
import { planeOf } from "../../planeInput.js";
|
|
5
4
|
import { scenePoseAdapter } from "../../../../core/scene/scenePoseAdapter.js";
|
|
5
|
+
import { planeOf } from "../../planeInput.js";
|
|
6
6
|
import { pointInBounds } from "./container.js";
|
|
7
7
|
|
|
8
8
|
//#region src/interactions/actions/move/layout/exits.ts
|
|
9
9
|
/** Where each dragged root that leaves its layout container on release lands.
|
|
10
10
|
* A root leaves when the drop center falls outside the body of the layout
|
|
11
11
|
* container holding it, and lands under the innermost plain container beneath
|
|
12
|
-
* the drop — a layout container there has
|
|
13
|
-
* level of its layer. A root whose parent
|
|
14
|
-
* move; `reparentOnDrop` decides for those. */
|
|
12
|
+
* the drop that admits it (`canDropInto`) — a layout container there has
|
|
13
|
+
* already declined it — or at the top level of its layer. A root whose parent
|
|
14
|
+
* has no layout is not this pass's to move; `reparentOnDrop` decides for those. */
|
|
15
15
|
function resolveLayoutExits(session, dropCenter, ids) {
|
|
16
16
|
const out = /* @__PURE__ */ new Map();
|
|
17
17
|
const layoutDep = session.layout;
|
|
@@ -39,7 +39,7 @@ function resolveLayoutExits(session, dropCenter, ids) {
|
|
|
39
39
|
if (excluded.has(id)) continue;
|
|
40
40
|
const node = scene.get(id);
|
|
41
41
|
if (!node || node.kind !== "container") continue;
|
|
42
|
-
if (node.layer === layer && depth >= bestDepth && layoutDep.getLayout(id) === null && holds(id, null)) {
|
|
42
|
+
if (node.layer === layer && depth >= bestDepth && layoutDep.getLayout(id) === null && holds(id, null) && session.admits(id)) {
|
|
43
43
|
best = id;
|
|
44
44
|
bestDepth = depth;
|
|
45
45
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"exits.js","names":[],"sources":["../../../../../src/interactions/actions/move/layout/exits.ts"],"sourcesContent":["import type { NodeId } from 'core/scene/types';\nimport { poseDescriptorForNode } from 'core/geometry/poseDescriptor';\nimport { toPlane } from 'core/viewport/parallax';\nimport { composeWorldPose } from 'core/scene/composePose';\nimport { scenePoseAdapter } from 'core/scene/scenePoseAdapter';\nimport type { LayoutStrategy } from '../../../../layout/types';\nimport { planeOf } from '../../planeInput';\nimport type { MoveSession } from '../session';\nimport { pointInBounds } from './container';\n\n/** Where each dragged root that leaves its layout container on release lands.\n * A root leaves when the drop center falls outside the body of the layout\n * container holding it, and lands under the innermost plain container beneath\n * the drop — a layout container there has already declined it — or at the top
|
|
1
|
+
{"version":3,"file":"exits.js","names":[],"sources":["../../../../../src/interactions/actions/move/layout/exits.ts"],"sourcesContent":["import type { NodeId } from 'core/scene/types';\nimport { poseDescriptorForNode } from 'core/geometry/poseDescriptor';\nimport { toPlane } from 'core/viewport/parallax';\nimport { composeWorldPose } from 'core/scene/composePose';\nimport { scenePoseAdapter } from 'core/scene/scenePoseAdapter';\nimport type { LayoutStrategy } from '../../../../layout/types';\nimport { planeOf } from '../../planeInput';\nimport type { MoveSession } from '../session';\nimport { pointInBounds } from './container';\n\n/** Where each dragged root that leaves its layout container on release lands.\n * A root leaves when the drop center falls outside the body of the layout\n * container holding it, and lands under the innermost plain container beneath\n * the drop that admits it (`canDropInto`) — a layout container there has\n * already declined it — or at the top level of its layer. A root whose parent\n * has no layout is not this pass's to move; `reparentOnDrop` decides for those. */\nexport function resolveLayoutExits(\n session: MoveSession, dropCenter: { x: number; y: number } | null, ids: Iterable<NodeId>,\n): Map<NodeId, NodeId | null> {\n const out = new Map<NodeId, NodeId | null>();\n const layoutDep = session.layout;\n const center = dropCenter;\n if (!layoutDep || !center) return out;\n const { scene, pc, projection: d } = session;\n const poseAdapter = scenePoseAdapter(scene);\n const excluded = new Set<NodeId>([...session.ids, ...session.cascadeIds]);\n const holds = (id: NodeId, layout: LayoutStrategy<unknown> | null): boolean => {\n const node = scene.get(id)!;\n const plane = planeOf(session.view, node.layer);\n const at = plane ? toPlane(plane, center) : center;\n const pose = composeWorldPose(poseAdapter, id as string, pc.compose);\n if (layout?.contains) return layout.contains(pose, at);\n const b = poseDescriptorForNode(d, node).getBounds(pose);\n return pointInBounds(b, at);\n };\n const landings = new Map<string, NodeId | null>();\n const landingOn = (layer: string): NodeId | null => {\n if (landings.has(layer)) return landings.get(layer)!;\n // Deepest wins; among equals, the later sibling (painted over the other).\n let best: NodeId | null = null;\n let bestDepth = -1;\n const walk = (parentId: NodeId | null, depth: number): void => {\n for (const id of parentId === null ? scene.roots : scene.childrenOf(parentId)) {\n if (excluded.has(id)) continue;\n const node = scene.get(id);\n if (!node || node.kind !== 'container') continue;\n if (node.layer === layer && depth >= bestDepth\n && layoutDep.getLayout(id as string) === null && holds(id, null) && session.admits(id)) {\n best = id;\n bestDepth = depth;\n }\n walk(id, depth + 1);\n }\n };\n walk(null, 0);\n landings.set(layer, best);\n return best;\n };\n for (const id of ids) {\n const node = scene.get(id);\n const parent = node?.parent ?? null;\n if (!node || parent === null) continue;\n const layout = layoutDep.getLayout(parent as string);\n if (!layout || holds(parent, layout)) continue;\n out.set(id, landingOn(node.layer));\n }\n return out;\n}\n"],"mappings":";;;;;;;;;;;;;;AAgBA,SAAgB,mBACd,SAAsB,YAA6C,KACvC;CAC5B,MAAM,sBAAM,IAAI,IAA2B;CAC3C,MAAM,YAAY,QAAQ;CAC1B,MAAM,SAAS;CACf,IAAI,CAAC,aAAa,CAAC,QAAQ,OAAO;CAClC,MAAM,EAAE,OAAO,IAAI,YAAY,MAAM;CACrC,MAAM,cAAc,iBAAiB,KAAK;CAC1C,MAAM,2BAAW,IAAI,IAAY,CAAC,GAAG,QAAQ,KAAK,GAAG,QAAQ,UAAU,CAAC;CACxE,MAAM,SAAS,IAAY,WAAoD;EAC7E,MAAM,OAAO,MAAM,IAAI,EAAE;EACzB,MAAM,QAAQ,QAAQ,QAAQ,MAAM,KAAK,KAAK;EAC9C,MAAM,KAAK,QAAQ,QAAQ,OAAO,MAAM,IAAI;EAC5C,MAAM,OAAO,iBAAiB,aAAa,IAAc,GAAG,OAAO;EACnE,IAAI,QAAQ,UAAU,OAAO,OAAO,SAAS,MAAM,EAAE;EACrD,MAAM,IAAI,sBAAsB,GAAG,IAAI,CAAC,CAAC,UAAU,IAAI;EACvD,OAAO,cAAc,GAAG,EAAE;CAC5B;CACA,MAAM,2BAAW,IAAI,IAA2B;CAChD,MAAM,aAAa,UAAiC;EAClD,IAAI,SAAS,IAAI,KAAK,GAAG,OAAO,SAAS,IAAI,KAAK;EAElD,IAAI,OAAsB;EAC1B,IAAI,YAAY;EAChB,MAAM,QAAQ,UAAyB,UAAwB;GAC7D,KAAK,MAAM,MAAM,aAAa,OAAO,MAAM,QAAQ,MAAM,WAAW,QAAQ,GAAG;IAC7E,IAAI,SAAS,IAAI,EAAE,GAAG;IACtB,MAAM,OAAO,MAAM,IAAI,EAAE;IACzB,IAAI,CAAC,QAAQ,KAAK,SAAS,aAAa;IACxC,IAAI,KAAK,UAAU,SAAS,SAAS,aAChC,UAAU,UAAU,EAAY,MAAM,QAAQ,MAAM,IAAI,IAAI,KAAK,QAAQ,OAAO,EAAE,GAAG;KACxF,OAAO;KACP,YAAY;IACd;IACA,KAAK,IAAI,QAAQ,CAAC;GACpB;EACF;EACA,KAAK,MAAM,CAAC;EACZ,SAAS,IAAI,OAAO,IAAI;EACxB,OAAO;CACT;CACA,KAAK,MAAM,MAAM,KAAK;EACpB,MAAM,OAAO,MAAM,IAAI,EAAE;EACzB,MAAM,SAAS,MAAM,UAAU;EAC/B,IAAI,CAAC,QAAQ,WAAW,MAAM;EAC9B,MAAM,SAAS,UAAU,UAAU,MAAgB;EACnD,IAAI,CAAC,UAAU,MAAM,QAAQ,MAAM,GAAG;EACtC,IAAI,IAAI,IAAI,UAAU,KAAK,KAAK,CAAC;CACnC;CACA,OAAO;AACT"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { nodeDescriptors, poseDescriptorOf } from "../poseDescriptorDep.js";
|
|
2
|
+
import { transformFinisher } from "../transformFinish.js";
|
|
2
3
|
import { commitGestureOps, readGestureLifecycle } from "../gestureLifecycle.js";
|
|
3
4
|
import { gestureReaders } from "../../gestures/shared/screenTolerance.js";
|
|
4
5
|
import { moveSources } from "../selectionSubtree.js";
|
|
@@ -6,9 +7,15 @@ import { layoutDrop } from "./behaviors/layoutDrop.js";
|
|
|
6
7
|
import { reparentOnDrop } from "./behaviors/reparentOnDrop.js";
|
|
7
8
|
import { buildGestureContext, captureFrames, capturePlaneRefs, captureStartPoses } from "./capture.js";
|
|
8
9
|
import { moveGestureAdapter } from "./gestureAdapter.js";
|
|
10
|
+
import { lazySnapSession } from "../../../features/snap/lazySession.js";
|
|
9
11
|
import { DRAG_THRESHOLD_PX, isPathEditPart, resolveParams } from "@weasel-js/routing";
|
|
10
12
|
|
|
11
13
|
//#region src/interactions/actions/move/session.ts
|
|
14
|
+
function admitsOf(canDropInto, ids) {
|
|
15
|
+
if (canDropInto === void 0) return () => true;
|
|
16
|
+
const roots = ids;
|
|
17
|
+
return (parent) => canDropInto(parent, roots);
|
|
18
|
+
}
|
|
12
19
|
/** Capture a drag at press. Null when there is nothing to move. Runs each
|
|
13
20
|
* behavior's `onStart`. `frame` reads the drag's latest frame, for the
|
|
14
21
|
* behaviors appended to the binding's own. */
|
|
@@ -19,6 +26,7 @@ function beginMove(ctx, opts, frame) {
|
|
|
19
26
|
const layout = ctx.deps.layout;
|
|
20
27
|
const applyOps = ctx.deps.applyOps;
|
|
21
28
|
const geometryProjection = ctx.deps.geometryProjection;
|
|
29
|
+
const finish = transformFinisher(ctx.deps);
|
|
22
30
|
if (!selection || !scene) return null;
|
|
23
31
|
const pc = scene.composition;
|
|
24
32
|
if (isPathEditPart(ctx.drag?.affordance)) return null;
|
|
@@ -44,7 +52,8 @@ function beginMove(ctx, opts, frame) {
|
|
|
44
52
|
const adapter = moveGestureAdapter(scene, (ops, _label, through) => commitGestureOps({
|
|
45
53
|
scene,
|
|
46
54
|
applyOps,
|
|
47
|
-
adapter: through
|
|
55
|
+
adapter: through,
|
|
56
|
+
finish
|
|
48
57
|
}, lifecycle, ops), selection.adapterMethods);
|
|
49
58
|
const readers = gestureReaders(ctx.deps);
|
|
50
59
|
const gestureCtx = buildGestureContext(ctx, scene, ids, startPoses, adapter, readers);
|
|
@@ -68,17 +77,19 @@ function beginMove(ctx, opts, frame) {
|
|
|
68
77
|
layout,
|
|
69
78
|
pc,
|
|
70
79
|
applyOps,
|
|
80
|
+
finish,
|
|
71
81
|
geometryProjection,
|
|
72
82
|
lifecycle,
|
|
73
83
|
nodeAtPoint: ctx.deps.nodeAtPoint,
|
|
84
|
+
admits: admitsOf(ctx.deps.canDropInto, ids),
|
|
74
85
|
reparentOnDrop: () => resolveParams(opts?.params)?.["reparentOnDrop"] ?? "off",
|
|
75
86
|
dragThresholdPx,
|
|
76
|
-
snap: ctx.deps.snap
|
|
87
|
+
snap: lazySnapSession(ctx.deps.snap, {
|
|
77
88
|
gesture: "move",
|
|
78
89
|
ids,
|
|
79
90
|
press,
|
|
80
91
|
constrain: "axis"
|
|
81
|
-
})
|
|
92
|
+
}),
|
|
82
93
|
press
|
|
83
94
|
};
|
|
84
95
|
return {
|