@weasel-js/core 1.11.1 → 1.13.0-rc.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 +275 -0
- package/dist/WeaselProvider.js +1 -1
- package/dist/affordances/pathAnchors.js +10 -6
- package/dist/affordances/pathAnchors.js.map +1 -1
- package/dist/animation/poseTarget.js +46 -15
- package/dist/animation/poseTarget.js.map +1 -1
- package/dist/animation/poseTransition.js +3 -3
- package/dist/animation/poseTransition.js.map +1 -1
- package/dist/animation/reflow.js +3 -6
- package/dist/animation/reflow.js.map +1 -1
- package/dist/animation/rig/bindRig.js +2 -2
- package/dist/animation/rig/bindRig.js.map +1 -1
- package/dist/animation/rig/skinBinding.js +2 -2
- package/dist/animation/rig/skinBinding.js.map +1 -1
- package/dist/barrel/canvas.js +5 -1
- package/dist/barrel/chrome.js +3 -1
- package/dist/barrel/paint.js +4 -4
- package/dist/barrel/paths.js +9 -4
- package/dist/barrel/renderer.js +3 -2
- package/dist/barrel/routing.js +4 -4
- package/dist/barrel/scene.js +7 -1
- package/dist/barrel/text.js +2 -2
- package/dist/barrel/viewport.js +6 -2
- package/dist/canvas/Canvas.js +2 -1
- 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 +5 -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 +2 -0
- 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/canvasPassThrough.js +2 -1
- package/dist/canvas/SceneCanvas/canvasPassThrough.js.map +1 -1
- package/dist/canvas/SceneCanvas/defaultNodeRouting.js +2 -2
- package/dist/canvas/SceneCanvas/defaultNodeRouting.js.map +1 -1
- package/dist/canvas/SceneCanvas/props.js.map +1 -1
- package/dist/canvas/SceneCanvas/scenePointQuery.js +27 -5
- package/dist/canvas/SceneCanvas/scenePointQuery.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/useCanvasDevtoolsRoot.js +1 -0
- package/dist/canvas/SceneCanvas/useCanvasDevtoolsRoot.js.map +1 -1
- package/dist/canvas/SceneCanvas/useCanvasTools.js +10 -2
- package/dist/canvas/SceneCanvas/useCanvasTools.js.map +1 -1
- package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js +25 -19
- package/dist/canvas/SceneCanvas/usePreviewGhostLayer.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 +17 -2
- package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneCanvasTools.js +2 -0
- package/dist/canvas/SceneCanvas/useSceneCanvasTools.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneGestureDispatcher.js +19 -4
- package/dist/canvas/SceneCanvas/useSceneGestureDispatcher.js.map +1 -1
- package/dist/canvas/SceneCanvas/useScenePicking.js +31 -6
- package/dist/canvas/SceneCanvas/useScenePicking.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneSelectTool.js +4 -5
- package/dist/canvas/SceneCanvas/useSceneSelectTool.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneStandardActions.js +7 -4
- package/dist/canvas/SceneCanvas/useSceneStandardActions.js.map +1 -1
- package/dist/canvas/SceneCanvas.js +30 -12
- package/dist/canvas/SceneCanvas.js.map +1 -1
- package/dist/canvas/ViewMarker.js +35 -0
- package/dist/canvas/ViewMarker.js.map +1 -0
- package/dist/canvas/accentColor.js +26 -3
- package/dist/canvas/accentColor.js.map +1 -1
- package/dist/canvas/buildSceneTree.js +14 -20
- package/dist/canvas/buildSceneTree.js.map +1 -1
- package/dist/canvas/copiesAbove.js +1 -1
- package/dist/canvas/copiesAbove.js.map +1 -1
- package/dist/canvas/defaultDrawOne.js +11 -6
- package/dist/canvas/defaultDrawOne.js.map +1 -1
- package/dist/canvas/deps/areaSelect.js +5 -2
- package/dist/canvas/deps/areaSelect.js.map +1 -1
- package/dist/canvas/deps/booleans.js +3 -2
- package/dist/canvas/deps/booleans.js.map +1 -1
- package/dist/canvas/deps/enteredGroup.js +81 -0
- package/dist/canvas/deps/enteredGroup.js.map +1 -0
- package/dist/canvas/deps/hitTestArea.js +28 -16
- package/dist/canvas/deps/hitTestArea.js.map +1 -1
- package/dist/canvas/deps/insert.js +10 -38
- package/dist/canvas/deps/insert.js.map +1 -1
- package/dist/canvas/deps/insertSite.js +39 -0
- package/dist/canvas/deps/insertSite.js.map +1 -0
- package/dist/canvas/deps/lassoSelect.js +6 -3
- package/dist/canvas/deps/lassoSelect.js.map +1 -1
- package/dist/canvas/deps/pathEditCommits.js +3 -7
- package/dist/canvas/deps/pathEditCommits.js.map +1 -1
- package/dist/canvas/deps/pathLeaf.js +1 -1
- package/dist/canvas/deps/pathLeaf.js.map +1 -1
- package/dist/canvas/deps/slice.js +2 -1
- package/dist/canvas/deps/slice.js.map +1 -1
- package/dist/canvas/derivedPath.js +14 -6
- package/dist/canvas/derivedPath.js.map +1 -1
- package/dist/canvas/doubleClickTarget.js +9 -11
- package/dist/canvas/doubleClickTarget.js.map +1 -1
- package/dist/canvas/drawnBounds.js +26 -9
- package/dist/canvas/drawnBounds.js.map +1 -1
- package/dist/canvas/inheritedPaints.js +55 -0
- package/dist/canvas/inheritedPaints.js.map +1 -0
- package/dist/canvas/nodeShapes/derivedPainter.js +15 -16
- package/dist/canvas/nodeShapes/derivedPainter.js.map +1 -1
- package/dist/canvas/nodeShapes/nodePaint.js +7 -34
- package/dist/canvas/nodeShapes/nodePaint.js.map +1 -1
- package/dist/canvas/nodeShapes/pathPainter.js +7 -7
- 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 +9 -9
- 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/ownClip.js +24 -0
- package/dist/canvas/ownClip.js.map +1 -0
- package/dist/canvas/paintCull.js.map +1 -1
- package/dist/canvas/pickIndex/nodeBroadBox.js +86 -0
- package/dist/canvas/pickIndex/nodeBroadBox.js.map +1 -0
- package/dist/canvas/pickIndex/scenePickIndex.js +208 -0
- package/dist/canvas/pickIndex/scenePickIndex.js.map +1 -0
- package/dist/canvas/pickReach.js +3 -3
- package/dist/canvas/pickReach.js.map +1 -1
- package/dist/canvas/pickWalk.js +17 -91
- package/dist/canvas/pickWalk.js.map +1 -1
- package/dist/canvas/poseCascade.js +1 -1
- package/dist/canvas/poseCascade.js.map +1 -1
- package/dist/canvas/publishPreviews.js +97 -0
- package/dist/canvas/publishPreviews.js.map +1 -0
- package/dist/canvas/renderSceneToPixels.js +1 -1
- package/dist/canvas/renderSceneToPixels.js.map +1 -1
- package/dist/canvas/sceneAdapter.js +7 -5
- package/dist/canvas/sceneAdapter.js.map +1 -1
- package/dist/canvas/sceneClipboard.js +17 -10
- package/dist/canvas/sceneClipboard.js.map +1 -1
- package/dist/canvas/scenePickReads.js +37 -0
- package/dist/canvas/scenePickReads.js.map +1 -0
- package/dist/canvas/scenePickSource.js +74 -0
- package/dist/canvas/scenePickSource.js.map +1 -0
- package/dist/canvas/sceneSlotWiring.js +9 -3
- package/dist/canvas/sceneSlotWiring.js.map +1 -1
- package/dist/canvas/sceneViewRender.js +9 -4
- package/dist/canvas/sceneViewRender.js.map +1 -1
- package/dist/canvas/shownNodes.js +15 -0
- package/dist/canvas/shownNodes.js.map +1 -0
- package/dist/canvas/surfaceContribution.js +12 -8
- package/dist/canvas/surfaceContribution.js.map +1 -1
- package/dist/canvas/useCanvasView.js +4 -2
- package/dist/canvas/useCanvasView.js.map +1 -1
- package/dist/canvas/useLayerStack.js +6 -2
- package/dist/canvas/useLayerStack.js.map +1 -1
- package/dist/canvas/useSceneAdapter.js +5 -3
- package/dist/canvas/useSceneAdapter.js.map +1 -1
- package/dist/canvas/useViewAim.js +121 -0
- package/dist/canvas/useViewAim.js.map +1 -0
- 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 +2 -2
- package/dist/{clone-C3e0OTuF.d.ts → clone-qb2e1F5p.d.ts} +2 -2
- package/dist/clone.d.ts +3 -3
- package/dist/core/isPlainObject.js +2 -2
- package/dist/core/layers/layerGroup.js.map +1 -1
- package/dist/core/pages/pageEdits.js +2 -3
- package/dist/core/pages/pageEdits.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.map +1 -1
- package/dist/core/scene/arrivalWindow.js +1 -1
- package/dist/core/scene/arrivalWindow.js.map +1 -1
- package/dist/core/scene/clipNothing.js +10 -0
- package/dist/core/scene/clipNothing.js.map +1 -0
- package/dist/core/scene/declaredFieldSetters.js +44 -0
- package/dist/core/scene/declaredFieldSetters.js.map +1 -0
- package/dist/core/scene/depMemo.js +14 -3
- package/dist/core/scene/depMemo.js.map +1 -1
- package/dist/core/scene/dependents.js +9 -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/documentOf.js +43 -0
- package/dist/core/scene/documentOf.js.map +1 -0
- package/dist/core/scene/effectivePose.js +44 -15
- package/dist/core/scene/effectivePose.js.map +1 -1
- package/dist/core/scene/fieldEdits.js +17 -14
- 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/historyForm.js +4 -4
- package/dist/core/scene/historyForm.js.map +1 -1
- package/dist/core/scene/inheritedPaint.js +97 -0
- package/dist/core/scene/inheritedPaint.js.map +1 -0
- package/dist/core/scene/kitOps.js +3 -23
- package/dist/core/scene/kitOps.js.map +1 -1
- package/dist/core/scene/kitRegistry.js +5 -0
- package/dist/core/scene/kitRegistry.js.map +1 -1
- package/dist/core/scene/layoutPass.js +1 -2
- package/dist/core/scene/layoutPass.js.map +1 -1
- package/dist/core/scene/nodeAsShown.js +72 -0
- package/dist/core/scene/nodeAsShown.js.map +1 -0
- package/dist/core/scene/nodeFnFields.js +2 -10
- package/dist/core/scene/nodeFnFields.js.map +1 -1
- package/dist/core/scene/nodeMemo.js +21 -8
- package/dist/core/scene/nodeMemo.js.map +1 -1
- package/dist/core/scene/nodeStore.js +2 -4
- package/dist/core/scene/nodeStore.js.map +1 -1
- package/dist/core/scene/pathEffects/blend.js.map +1 -1
- package/dist/core/scene/pathEffects/derive.js +10 -4
- 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/foundHidden.js +35 -0
- package/dist/core/scene/pathEffects/foundHidden.js.map +1 -0
- package/dist/core/scene/pathEffects/textAlong.js +95 -0
- package/dist/core/scene/pathEffects/textAlong.js.map +1 -0
- package/dist/core/scene/plyStacks.js +89 -0
- package/dist/core/scene/plyStacks.js.map +1 -0
- package/dist/core/scene/poseHold.js +42 -24
- package/dist/core/scene/poseHold.js.map +1 -1
- package/dist/core/scene/poseOverrides.js +35 -38
- package/dist/core/scene/poseOverrides.js.map +1 -1
- package/dist/core/scene/posePlies.js +59 -0
- package/dist/core/scene/posePlies.js.map +1 -0
- package/dist/core/scene/reconcileSpecs.js +6 -15
- package/dist/core/scene/reconcileSpecs.js.map +1 -1
- package/dist/core/scene/renderOrder.js +10 -4
- package/dist/core/scene/renderOrder.js.map +1 -1
- package/dist/core/scene/sameValue.js +17 -0
- package/dist/core/scene/sameValue.js.map +1 -0
- package/dist/core/scene/scene.js +3 -3
- package/dist/core/scene/scene.js.map +1 -1
- package/dist/core/scene/sceneEdits.js +8 -0
- package/dist/core/scene/sceneEdits.js.map +1 -1
- package/dist/core/scene/sceneState.js +1 -2
- package/dist/core/scene/sceneState.js.map +1 -1
- package/dist/core/scene/serialization.js +45 -9
- package/dist/core/scene/serialization.js.map +1 -1
- package/dist/core/scene/staleReplay.js +5 -2
- package/dist/core/scene/staleReplay.js.map +1 -1
- package/dist/core/scene/statedFields.js +4 -2
- package/dist/core/scene/statedFields.js.map +1 -1
- package/dist/core/scene/treeEdits.js +2 -4
- package/dist/core/scene/treeEdits.js.map +1 -1
- package/dist/core/scene/treeOrder.js +3 -1
- package/dist/core/scene/treeOrder.js.map +1 -1
- package/dist/core/scene/treeReads.js +1 -2
- package/dist/core/scene/treeReads.js.map +1 -1
- package/dist/core/scene/treeShape.js +13 -0
- package/dist/core/scene/treeShape.js.map +1 -0
- package/dist/core/scene/types.js.map +1 -1
- package/dist/core/scene/useScene.js +1 -1
- package/dist/core/scene/useScene.js.map +1 -1
- package/dist/{cornerHandles-BHuoMs1o.d.ts → cornerHandles-CNCb7aTY.d.ts} +3 -2
- package/dist/{depSchema-BpZNOv7q.d.ts → depSchema-B1RS-IJx.d.ts} +39 -18
- package/dist/devtools/handlers.js +1 -1
- package/dist/devtools/handlers.js.map +1 -1
- package/dist/devtools/protocol.js.map +1 -1
- package/dist/devtools/registry.js +4 -4
- package/dist/devtools/registry.js.map +1 -1
- package/dist/devtools-protocol.d.ts +4 -3
- package/dist/devtools.d.ts +3 -2
- package/dist/features/measure/measureContribution.js +4 -2
- package/dist/features/measure/measureContribution.js.map +1 -1
- package/dist/features/measure/measureHit.js +5 -3
- package/dist/features/measure/measureHit.js.map +1 -1
- package/dist/features/measure/measurement.js +1 -1
- package/dist/features/measure/measurement.js.map +1 -1
- package/dist/features/modes/modeLayers.js +14 -7
- package/dist/features/modes/modeLayers.js.map +1 -1
- package/dist/features/modes/modeTriggers.js +10 -6
- package/dist/features/modes/modeTriggers.js.map +1 -1
- package/dist/features/pathEffects/effectSources.js +69 -0
- package/dist/features/pathEffects/effectSources.js.map +1 -0
- package/dist/features/pathEffects/readSource.js +18 -2
- 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 +53 -0
- package/dist/features/pathEffects/useEffectSourcesLayer.js.map +1 -0
- package/dist/features/paths/editablePath.js +1 -1
- package/dist/features/paths/editablePath.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/sceneIndex.js +1 -1
- package/dist/features/paths/pathSnap/sceneIndex.js.map +1 -1
- package/dist/features/selection/enteredGroupFrame.js +65 -0
- package/dist/features/selection/enteredGroupFrame.js.map +1 -0
- package/dist/features/selection/enteredGroupScope.js +44 -0
- package/dist/features/selection/enteredGroupScope.js.map +1 -0
- package/dist/features/text/sceneTextDrafts.js +64 -0
- package/dist/features/text/sceneTextDrafts.js.map +1 -0
- package/dist/features/text/textHitAt.js +34 -3
- package/dist/features/text/textHitAt.js.map +1 -1
- package/dist/features/text/useSceneTextEdit.js +23 -19
- 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/index.d.ts +709 -258
- package/dist/index.js +33 -12
- package/dist/interactions/actions/admitsChild.js +11 -0
- package/dist/interactions/actions/admitsChild.js.map +1 -0
- 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/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 +7 -4
- 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 +33 -11
- package/dist/interactions/actions/defaults/contextMenu.js.map +1 -1
- package/dist/interactions/actions/defaults/createPaintAction.js +5 -2
- package/dist/interactions/actions/defaults/createPaintAction.js.map +1 -1
- package/dist/interactions/actions/defaults/delete.js +28 -14
- package/dist/interactions/actions/defaults/delete.js.map +1 -1
- package/dist/interactions/actions/defaults/duplicate.js +11 -8
- package/dist/interactions/actions/defaults/duplicate.js.map +1 -1
- package/dist/interactions/actions/defaults/enterGroup.js +88 -0
- package/dist/interactions/actions/defaults/enterGroup.js.map +1 -0
- package/dist/interactions/actions/defaults/enterPathEdit.js +20 -10
- package/dist/interactions/actions/defaults/enterPathEdit.js.map +1 -1
- package/dist/interactions/actions/defaults/enterTextEdit.js +1 -1
- package/dist/interactions/actions/defaults/enterTextEdit.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 +26 -20
- package/dist/interactions/actions/defaults/group.js.map +1 -1
- package/dist/interactions/actions/defaults/ingest.js +10 -4
- 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 +8 -2
- 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 +15 -8
- package/dist/interactions/actions/defaults/selectAll.js.map +1 -1
- package/dist/interactions/actions/defaults/selectDeep.js +35 -0
- package/dist/interactions/actions/defaults/selectDeep.js.map +1 -0
- 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/drawnBoxes.js +2 -1
- package/dist/interactions/actions/drawnBoxes.js.map +1 -1
- package/dist/interactions/actions/edit-anchors/action.js +7 -4
- package/dist/interactions/actions/edit-anchors/action.js.map +1 -1
- package/dist/interactions/actions/flip/action.js +8 -2
- package/dist/interactions/actions/flip/action.js.map +1 -1
- package/dist/interactions/actions/insert/action.js +1 -0
- package/dist/interactions/actions/insert/action.js.map +1 -1
- package/dist/interactions/actions/insert/parent.js +7 -5
- package/dist/interactions/actions/insert/parent.js.map +1 -1
- package/dist/interactions/actions/insert/placeAction.js +3 -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 +2 -2
- package/dist/interactions/actions/insert/session.js.map +1 -1
- package/dist/interactions/actions/move/action.js +7 -4
- package/dist/interactions/actions/move/action.js.map +1 -1
- package/dist/interactions/actions/move/commit/reparent.js +1 -1
- package/dist/interactions/actions/move/commit/reparent.js.map +1 -1
- package/dist/interactions/actions/move/gestureAdapter.js +6 -7
- package/dist/interactions/actions/move/gestureAdapter.js.map +1 -1
- package/dist/interactions/actions/move/layout/exits.js +1 -1
- package/dist/interactions/actions/move/layout/exits.js.map +1 -1
- package/dist/interactions/actions/move/session.js +4 -4
- package/dist/interactions/actions/move/session.js.map +1 -1
- 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/pathCommands/pathNodes.js +14 -5
- package/dist/interactions/actions/pathCommands/pathNodes.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/selectionSubtree.js +12 -7
- package/dist/interactions/actions/selectionSubtree.js.map +1 -1
- package/dist/interactions/actions/transform-again/action.js +8 -5
- package/dist/interactions/actions/transform-again/action.js.map +1 -1
- package/dist/interactions/gestures/thresholdDrag/thresholdDrag.js +14 -2
- package/dist/interactions/gestures/thresholdDrag/thresholdDrag.js.map +1 -1
- package/dist/json.d.ts +4 -0
- package/dist/json.js +3 -0
- package/dist/kitSettingsSchema.js +8 -1
- package/dist/kitSettingsSchema.js.map +1 -1
- package/dist/{math-CrJULaZI.d.ts → math-C_elShP_.d.ts} +7 -1
- package/dist/math.d.ts +1 -1
- package/dist/math.js +2 -1
- package/dist/move.d.ts +4 -4
- package/dist/{options-DBxEryYq.d.ts → options-ClEm3SEl.d.ts} +1 -1
- package/dist/resize.d.ts +4 -4
- package/dist/test-seams.d.ts +6 -6
- 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/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/pressTarget.js +22 -0
- package/dist/tools/builtin/pressTarget.js.map +1 -0
- 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 +6 -5
- package/dist/tools/builtin/select/adapterPointQuery.js.map +1 -1
- package/dist/tools/builtin/select/collapseDeferred.js +40 -0
- package/dist/tools/builtin/select/collapseDeferred.js.map +1 -0
- package/dist/tools/builtin/select/groupEntry.js +82 -0
- package/dist/tools/builtin/select/groupEntry.js.map +1 -0
- 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 +74 -55
- 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/{types-7puAuVD2.d.ts → types-49uYJN3j.d.ts} +1 -1
- package/dist/{types-CniVctmk.d.ts → types-BEdRIhNc.d.ts} +272 -109
- package/dist/{types-oFeQ5VjV.d.ts → types-p2alu-R1.d.ts} +1 -1
- package/dist/util/paint.js +1 -3
- package/dist/util/paint.js.map +1 -1
- package/dist/version.js +1 -1
- package/package.json +29 -25
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { boundsOfPath, multiply, pathShape, placeAlongRun, rotate, runLength, trackRun, transformPath, translate } from "@weasel-js/geom";
|
|
2
|
+
|
|
3
|
+
//#region src/core/scene/pathEffects/textAlong.ts
|
|
4
|
+
/**
|
|
5
|
+
* Text along a path: a source's items — a text node's grapheme clusters, or a
|
|
6
|
+
* whole shape as one item — laid end to end along a path, each turned to it.
|
|
7
|
+
*/
|
|
8
|
+
var LEAD = {
|
|
9
|
+
start: 0,
|
|
10
|
+
center: .5,
|
|
11
|
+
end: 1
|
|
12
|
+
};
|
|
13
|
+
/** The parts `items` paint laid along `path` as `effect` says; `[]` when there is nothing to lay or nowhere to lay it. */
|
|
14
|
+
function textAlongParts(effect, items, path) {
|
|
15
|
+
const shape = pathShape(path);
|
|
16
|
+
if (shape === null || !(shape.length > 0) || items.length === 0) return [];
|
|
17
|
+
const L = shape.length;
|
|
18
|
+
const closed = shape.closed;
|
|
19
|
+
const lengths = items.map((it) => it.length);
|
|
20
|
+
const k = LEAD[effect.align ?? "start"];
|
|
21
|
+
const at = clamp01(effect.start ?? 0) * L;
|
|
22
|
+
const gap = effect.overflow === "fit" ? fitGap(lengths, roomAt(at, L, k, closed)) : 0;
|
|
23
|
+
const total = runLength(lengths, gap);
|
|
24
|
+
const c = at + (.5 - k) * total;
|
|
25
|
+
const about = closed ? (c / L % 1 + 1) % 1 : clamp01(c / L);
|
|
26
|
+
const run = trackRun(shape, 0, 1, {
|
|
27
|
+
side: effect.side ?? "auto",
|
|
28
|
+
about
|
|
29
|
+
});
|
|
30
|
+
const places = placeAlongRun(run, lengths, {
|
|
31
|
+
gap,
|
|
32
|
+
align: "center",
|
|
33
|
+
at: run.reversed ? L - c : c,
|
|
34
|
+
shift: finiteOr(effect.shift, 0),
|
|
35
|
+
wrap: closed
|
|
36
|
+
});
|
|
37
|
+
const center = effect.anchor === "center";
|
|
38
|
+
const out = [];
|
|
39
|
+
const firstStart = places[0].center - lengths[0] / 2;
|
|
40
|
+
places.forEach((place, i) => {
|
|
41
|
+
if (dropped(place, closed ? firstStart : null, L)) return;
|
|
42
|
+
const item = items[i];
|
|
43
|
+
const m = itemFrame(place, item.length, center ? item.middle : 0);
|
|
44
|
+
for (const part of item.parts) out.push({
|
|
45
|
+
...part,
|
|
46
|
+
path: transformPath(part.path, m)
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
return out;
|
|
50
|
+
}
|
|
51
|
+
/** `source`'s whole outline as one item: its bounds' left at x = 0 and their vertical middle on the anchor line. */
|
|
52
|
+
function wholeItem(source) {
|
|
53
|
+
const b = boundsOfPath(source.world);
|
|
54
|
+
return {
|
|
55
|
+
length: b.width,
|
|
56
|
+
middle: 0,
|
|
57
|
+
parts: [{
|
|
58
|
+
path: transformPath(source.world, translate(-b.x, -(b.y + b.height / 2))),
|
|
59
|
+
fill: source.fill,
|
|
60
|
+
stroke: source.stroke
|
|
61
|
+
}]
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/** SVG `textPath`'s rule: an item is not drawn once its middle is past an open path's ends, or on a closed path a whole
|
|
65
|
+
* lap or more on from the first item's start. Judged within a hair of rounding. */
|
|
66
|
+
function dropped(place, firstStart, L) {
|
|
67
|
+
const hair = 1e-9 * Math.max(1, L);
|
|
68
|
+
if (firstStart !== null) return place.center - firstStart >= L - hair;
|
|
69
|
+
return place.center < -hair || place.center > L + hair;
|
|
70
|
+
}
|
|
71
|
+
/** How much path the text has before it runs off, from `at`, with `k` of it laid back behind `at`. */
|
|
72
|
+
function roomAt(at, L, k, closed) {
|
|
73
|
+
if (closed) return L;
|
|
74
|
+
return k === 0 ? L - at : k === 1 ? at : 2 * Math.min(at, L - at);
|
|
75
|
+
}
|
|
76
|
+
/** The gap that makes `lengths` fill `room`, or 0 when they fit already. Never so negative that an item's step back
|
|
77
|
+
* from the one before it (its length plus the gap) goes below zero, so items keep their order in too short a room. */
|
|
78
|
+
function fitGap(lengths, room) {
|
|
79
|
+
const total = runLength(lengths, 0);
|
|
80
|
+
if (!(total > room) || lengths.length < 2) return 0;
|
|
81
|
+
let floor = -Infinity;
|
|
82
|
+
for (let i = 1; i < lengths.length; i++) floor = Math.max(floor, -(lengths[i - 1] + lengths[i]) / 2);
|
|
83
|
+
return Math.max((room - total) / (lengths.length - 1), floor);
|
|
84
|
+
}
|
|
85
|
+
/** Item frame to world: its middle on `place`, turned to it, its anchor line `lift` above y = 0 brought onto the path. */
|
|
86
|
+
function itemFrame(place, length, lift) {
|
|
87
|
+
const turn = multiply(rotate(place.angle * Math.PI / 180), translate(-length / 2, lift));
|
|
88
|
+
return multiply(translate(place.point.x, place.point.y), turn);
|
|
89
|
+
}
|
|
90
|
+
var clamp01 = (v) => v > 1 ? 1 : v > 0 ? v : 0;
|
|
91
|
+
var finiteOr = (v, d) => v !== void 0 && Number.isFinite(v) ? v : d;
|
|
92
|
+
|
|
93
|
+
//#endregion
|
|
94
|
+
export { textAlongParts, wholeItem };
|
|
95
|
+
//# sourceMappingURL=textAlong.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"textAlong.js","names":[],"sources":["../../../../src/core/scene/pathEffects/textAlong.ts"],"sourcesContent":["/**\n * Text along a path: a source's items — a text node's grapheme clusters, or a\n * whole shape as one item — laid end to end along a path, each turned to it.\n */\nimport {\n boundsOfPath, multiply, pathShape, placeAlongRun, rotate, runLength, trackRun, transformPath, translate,\n type Affine, type Path, type RunAlign, type RunPlace, type TrackSide,\n} from '@weasel-js/geom';\nimport type { DerivedPart } from '../derivedParts';\nimport type { EffectItem, EffectSource, PathEffectOptions } from './source';\n\n/**\n * Text (or any shape) laid along a path, item by item. Its sources are `[text, path]`. Only the text's first laid line\n * follows the path; a color glyph keeps its advance and paints nothing; underlines and other decorations are not drawn.\n * On an open path an item whose middle falls past either end is not drawn; on a closed one the text wraps past the\n * seam, and an item a whole lap on from the first item's start is not drawn.\n */\nexport interface TextAlongEffect extends PathEffectOptions {\n kind: 'textAlong';\n /** Which part of the text sits at `start`. Default `'start'`. */\n align?: RunAlign;\n /** Where the text sits, as a fraction 0..1 of the path's length from its first point. Default 0. */\n start?: number;\n /** How far the anchor line sits off the path, toward the glyphs' up, in world units. Default 0. */\n shift?: number;\n /** What sits on the path: the glyphs' baseline, or (`'center'`) their x-height middle. Default `'baseline'`. */\n anchor?: 'baseline' | 'center';\n /** Text longer than its room is cut at the path's end (`'clip'`), or has the gaps between items squeezed until it\n * fits (`'fit'`). Default `'clip'`. */\n overflow?: 'clip' | 'fit';\n /** Which side of the path the glyphs stand on; see `TrackSide`. Default `'auto'`, whichever reads upright. Turned over,\n * the text keeps the stretch of path it had, and on an open path drops whichever letters fall off it. */\n side?: TrackSide;\n}\n\nconst LEAD: Record<RunAlign, number> = { start: 0, center: 0.5, end: 1 };\n\n/** The parts `items` paint laid along `path` as `effect` says; `[]` when there is nothing to lay or nowhere to lay it. */\nexport function textAlongParts(effect: TextAlongEffect, items: readonly EffectItem[], path: Path): DerivedPart[] {\n const shape = pathShape(path);\n if (shape === null || !(shape.length > 0) || items.length === 0) return [];\n const L = shape.length;\n const closed = shape.closed;\n const lengths = items.map((it) => it.length);\n const k = LEAD[effect.align ?? 'start'];\n const at = clamp01(effect.start ?? 0) * L;\n const gap = effect.overflow === 'fit' ? fitGap(lengths, roomAt(at, L, k, closed)) : 0;\n const total = runLength(lengths, gap);\n const c = at + (0.5 - k) * total;\n const about = closed ? ((c / L) % 1 + 1) % 1 : clamp01(c / L);\n const run = trackRun(shape, 0, 1, { side: effect.side ?? 'auto', about });\n const places = placeAlongRun(run, lengths, {\n gap, align: 'center', at: run.reversed ? L - c : c, shift: finiteOr(effect.shift, 0), wrap: closed,\n });\n const center = effect.anchor === 'center';\n const out: DerivedPart[] = [];\n const firstStart = places[0]!.center - lengths[0]! / 2;\n places.forEach((place, i) => {\n // By center (SVG textPath's rule), not by RunPlace.clipped, which judges by extent.\n if (dropped(place, closed ? firstStart : null, L)) return;\n const item = items[i]!;\n const m = itemFrame(place, item.length, center ? item.middle : 0);\n for (const part of item.parts) out.push({ ...part, path: transformPath(part.path, m) });\n });\n return out;\n}\n\n/** `source`'s whole outline as one item: its bounds' left at x = 0 and their vertical middle on the anchor line. */\nexport function wholeItem(source: EffectSource): EffectItem {\n const b = boundsOfPath(source.world);\n return {\n length: b.width,\n middle: 0,\n parts: [{\n path: transformPath(source.world, translate(-b.x, -(b.y + b.height / 2))),\n fill: source.fill,\n stroke: source.stroke,\n }],\n };\n}\n\n/** SVG `textPath`'s rule: an item is not drawn once its middle is past an open path's ends, or on a closed path a whole\n * lap or more on from the first item's start. Judged within a hair of rounding. */\nfunction dropped(place: RunPlace, firstStart: number | null, L: number): boolean {\n const hair = 1e-9 * Math.max(1, L);\n if (firstStart !== null) return place.center - firstStart >= L - hair;\n return place.center < -hair || place.center > L + hair;\n}\n\n/** How much path the text has before it runs off, from `at`, with `k` of it laid back behind `at`. */\nfunction roomAt(at: number, L: number, k: number, closed: boolean): number {\n if (closed) return L;\n return k === 0 ? L - at : k === 1 ? at : 2 * Math.min(at, L - at);\n}\n\n/** The gap that makes `lengths` fill `room`, or 0 when they fit already. Never so negative that an item's step back\n * from the one before it (its length plus the gap) goes below zero, so items keep their order in too short a room. */\nfunction fitGap(lengths: readonly number[], room: number): number {\n const total = runLength(lengths, 0);\n if (!(total > room) || lengths.length < 2) return 0;\n let floor = -Infinity;\n for (let i = 1; i < lengths.length; i++) floor = Math.max(floor, -(lengths[i - 1]! + lengths[i]!) / 2);\n return Math.max((room - total) / (lengths.length - 1), floor);\n}\n\n/** Item frame to world: its middle on `place`, turned to it, its anchor line `lift` above y = 0 brought onto the path. */\nfunction itemFrame(place: RunPlace, length: number, lift: number): Affine {\n const turn = multiply(rotate((place.angle * Math.PI) / 180), translate(-length / 2, lift));\n return multiply(translate(place.point.x, place.point.y), turn);\n}\n\nconst clamp01 = (v: number): number => (v > 1 ? 1 : v > 0 ? v : 0);\nconst finiteOr = (v: number | undefined, d: number): number => (v !== undefined && Number.isFinite(v) ? v : d);\n"],"mappings":"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"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { carryBoxPath } from "./depFrame.js";
|
|
2
|
+
|
|
3
|
+
//#region src/core/scene/plyStacks.ts
|
|
4
|
+
/** Empty stacks. */
|
|
5
|
+
function createPlyStacks() {
|
|
6
|
+
const plies = /* @__PURE__ */ new Map();
|
|
7
|
+
/** Each entry's claim, in claiming order; outlives a full drop, so a reinstall goes back in place. */
|
|
8
|
+
const claims = /* @__PURE__ */ new WeakMap();
|
|
9
|
+
let claimed = 0;
|
|
10
|
+
/** How many nodes hold each number of plies. */
|
|
11
|
+
const sizes = [];
|
|
12
|
+
let deepest = 0;
|
|
13
|
+
const resized = (from, to) => {
|
|
14
|
+
if (from > 0) sizes[from]--;
|
|
15
|
+
if (to > 0) sizes[to] = (sizes[to] ?? 0) + 1;
|
|
16
|
+
if (to > deepest) deepest = to;
|
|
17
|
+
while (deepest > 0 && (sizes[deepest] ?? 0) === 0) deepest--;
|
|
18
|
+
};
|
|
19
|
+
return {
|
|
20
|
+
plies,
|
|
21
|
+
claim(id, entry) {
|
|
22
|
+
let stack = plies.get(id);
|
|
23
|
+
if (stack === void 0) plies.set(id, stack = []);
|
|
24
|
+
const at = stack.indexOf(entry);
|
|
25
|
+
if (at >= 0) stack.splice(at, 1);
|
|
26
|
+
let claim = at >= 0 ? void 0 : claims.get(entry);
|
|
27
|
+
if (claim === void 0) claims.set(entry, claim = ++claimed);
|
|
28
|
+
let i = stack.length;
|
|
29
|
+
while (i > 0 && claims.get(stack[i - 1]) > claim) i--;
|
|
30
|
+
stack.splice(i, 0, entry);
|
|
31
|
+
if (at < 0) resized(stack.length - 1, stack.length);
|
|
32
|
+
},
|
|
33
|
+
release(id, entry) {
|
|
34
|
+
claims.delete(entry);
|
|
35
|
+
const stack = plies.get(id);
|
|
36
|
+
const at = stack?.indexOf(entry) ?? -1;
|
|
37
|
+
if (stack === void 0 || at < 0) return false;
|
|
38
|
+
stack.splice(at, 1);
|
|
39
|
+
resized(stack.length + 1, stack.length);
|
|
40
|
+
if (stack.length === 0) plies.delete(id);
|
|
41
|
+
return true;
|
|
42
|
+
},
|
|
43
|
+
drop(id) {
|
|
44
|
+
const stack = plies.get(id);
|
|
45
|
+
if (stack === void 0) return false;
|
|
46
|
+
plies.delete(id);
|
|
47
|
+
resized(stack.length, 0);
|
|
48
|
+
return true;
|
|
49
|
+
},
|
|
50
|
+
dropAll() {
|
|
51
|
+
plies.clear();
|
|
52
|
+
sizes.length = 0;
|
|
53
|
+
deepest = 0;
|
|
54
|
+
},
|
|
55
|
+
depth: () => Math.max(deepest, 1)
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
var boxOf = (pose) => {
|
|
59
|
+
const p = pose;
|
|
60
|
+
return p !== null && typeof p === "object" && typeof p.x === "number" && typeof p.y === "number" && typeof p.width === "number" && typeof p.height === "number" ? p : null;
|
|
61
|
+
};
|
|
62
|
+
var sameBox = (a, b) => a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height;
|
|
63
|
+
/**
|
|
64
|
+
* The path `stack` shows, folded to `pose`: the topmost ply's path, in the box of the pose
|
|
65
|
+
* that ply gives beside it, carried to `pose` where a ply above gives another. A path given
|
|
66
|
+
* with no pose of its own is drawn where it is. `held` keeps the last carry.
|
|
67
|
+
*/
|
|
68
|
+
function plyPath(stack, pose, held) {
|
|
69
|
+
for (let k = stack.length - 1; k >= 0; k--) {
|
|
70
|
+
const ply = stack[k];
|
|
71
|
+
if (ply.path === void 0) continue;
|
|
72
|
+
const from = boxOf(ply.pose);
|
|
73
|
+
const to = boxOf(pose);
|
|
74
|
+
if (from === null || to === null || sameBox(from, to)) return ply.path;
|
|
75
|
+
const last = held.carried;
|
|
76
|
+
if (last !== void 0 && last.source === ply.path && sameBox(last.from, from) && sameBox(last.to, to)) return last.path;
|
|
77
|
+
held.carried = {
|
|
78
|
+
source: ply.path,
|
|
79
|
+
from: { ...from },
|
|
80
|
+
to: { ...to },
|
|
81
|
+
path: carryBoxPath(ply.path, from, to)
|
|
82
|
+
};
|
|
83
|
+
return held.carried.path;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
//#endregion
|
|
88
|
+
export { createPlyStacks, plyPath };
|
|
89
|
+
//# sourceMappingURL=plyStacks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plyStacks.js","names":[],"sources":["../../../src/core/scene/plyStacks.ts"],"sourcesContent":["/**\n * Each node's plies of overrides, kept in the order their writers claimed\n * the node, and the path a stack shows.\n */\nimport type { Path } from '@weasel-js/geom';\nimport { carryBoxPath } from './depFrame';\nimport type { NodeId, PoseOverride } from './types';\n\n/** {@link createPlyStacks}'s handle. */\nexport interface PlyStacks<Entry> {\n /** Per node, its plies bottom first. */\n readonly plies: ReadonlyMap<NodeId, readonly Entry[]>;\n /** Install `entry` on `id`: on top, or where it stood when a full drop took it off. An\n * installed entry moves to the top. */\n claim(id: NodeId, entry: Entry): void;\n /** Take `entry` off `id` and forget where it stood. Whether it was installed. */\n release(id: NodeId, entry: Entry): boolean;\n /** Take every ply off `id`, each keeping its place for when its writer reinstalls it.\n * Whether the node had any. */\n drop(id: NodeId): boolean;\n /** {@link PlyStacks.drop} for every node. */\n dropAll(): void;\n /** The deepest stack, and at least 1. */\n depth(): number;\n}\n\n/** Empty stacks. */\nexport function createPlyStacks<Entry extends object>(): PlyStacks<Entry> {\n const plies = new Map<NodeId, Entry[]>();\n /** Each entry's claim, in claiming order; outlives a full drop, so a reinstall goes back in place. */\n const claims = new WeakMap<Entry, number>();\n let claimed = 0;\n /** How many nodes hold each number of plies. */\n const sizes: number[] = [];\n let deepest = 0;\n\n const resized = (from: number, to: number): void => {\n if (from > 0) sizes[from]!--;\n if (to > 0) sizes[to] = (sizes[to] ?? 0) + 1;\n if (to > deepest) deepest = to;\n while (deepest > 0 && (sizes[deepest] ?? 0) === 0) deepest--;\n };\n\n return {\n plies,\n claim(id, entry) {\n let stack = plies.get(id);\n if (stack === undefined) plies.set(id, stack = []);\n const at = stack.indexOf(entry);\n if (at >= 0) stack.splice(at, 1);\n let claim = at >= 0 ? undefined : claims.get(entry);\n if (claim === undefined) claims.set(entry, claim = ++claimed);\n let i = stack.length;\n while (i > 0 && claims.get(stack[i - 1]!)! > claim) i--;\n stack.splice(i, 0, entry);\n if (at < 0) resized(stack.length - 1, stack.length);\n },\n release(id, entry) {\n claims.delete(entry);\n const stack = plies.get(id);\n const at = stack?.indexOf(entry) ?? -1;\n if (stack === undefined || at < 0) return false;\n stack.splice(at, 1);\n resized(stack.length + 1, stack.length);\n if (stack.length === 0) plies.delete(id);\n return true;\n },\n drop(id) {\n const stack = plies.get(id);\n if (stack === undefined) return false;\n plies.delete(id);\n resized(stack.length, 0);\n return true;\n },\n dropAll() {\n plies.clear();\n sizes.length = 0;\n deepest = 0;\n },\n depth: () => Math.max(deepest, 1),\n };\n}\n\ntype Box = { x: number; y: number; width: number; height: number };\n\nconst boxOf = (pose: unknown): Box | null => {\n const p = pose as Partial<Box> | null;\n return p !== null && typeof p === 'object' && typeof p.x === 'number' && typeof p.y === 'number'\n && typeof p.width === 'number' && typeof p.height === 'number'\n ? p as Box : null;\n};\n\nconst sameBox = (a: Box, b: Box): boolean => a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height;\n\n/** A carried path and what it was carried from and to, so a stack whose poses hold still shows one path. */\nexport interface CarriedPath {\n source: Path;\n from: Box;\n to: Box;\n path: Path;\n}\n\n/**\n * The path `stack` shows, folded to `pose`: the topmost ply's path, in the box of the pose\n * that ply gives beside it, carried to `pose` where a ply above gives another. A path given\n * with no pose of its own is drawn where it is. `held` keeps the last carry.\n */\nexport function plyPath<TPose, TData>(\n stack: readonly PoseOverride<TPose, TData>[],\n pose: TPose | undefined,\n held: { carried?: CarriedPath },\n): Path | undefined {\n for (let k = stack.length - 1; k >= 0; k--) {\n const ply = stack[k]!;\n if (ply.path === undefined) continue;\n const from = boxOf(ply.pose);\n const to = boxOf(pose);\n if (from === null || to === null || sameBox(from, to)) return ply.path;\n const last = held.carried;\n if (last !== undefined && last.source === ply.path && sameBox(last.from, from) && sameBox(last.to, to)) return last.path;\n held.carried = { source: ply.path, from: { ...from }, to: { ...to }, path: carryBoxPath(ply.path, from, to) };\n return held.carried.path;\n }\n return undefined;\n}\n"],"mappings":"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"}
|
|
@@ -1,47 +1,65 @@
|
|
|
1
1
|
//#region src/core/scene/poseHold.ts
|
|
2
|
-
/** Build the {@link PoseHold} a table hands out from `hold()`.
|
|
3
|
-
|
|
2
|
+
/** Build the {@link PoseHold} a table hands out from `hold()`. `pliesOf`
|
|
3
|
+
* answers a node's plies, bottom first. */
|
|
4
|
+
function createPoseHold(table, pliesOf) {
|
|
4
5
|
/** The entry published per id, held by reference so a frame mutates it in place. */
|
|
5
6
|
const held = /* @__PURE__ */ new Map();
|
|
6
7
|
const seen = /* @__PURE__ */ new Set();
|
|
8
|
+
const publish = (frame) => {
|
|
9
|
+
seen.clear();
|
|
10
|
+
for (const [id, shown] of frame) {
|
|
11
|
+
seen.add(id);
|
|
12
|
+
const existing = held.get(id);
|
|
13
|
+
if (existing) {
|
|
14
|
+
existing.pose = shown.pose;
|
|
15
|
+
existing.data = shown.data;
|
|
16
|
+
if (!table.has(id, existing)) table.set(id, existing);
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
const entry = {
|
|
20
|
+
pose: shown.pose,
|
|
21
|
+
data: shown.data
|
|
22
|
+
};
|
|
23
|
+
held.set(id, entry);
|
|
24
|
+
table.set(id, entry);
|
|
25
|
+
}
|
|
26
|
+
for (const [id, entry] of held) {
|
|
27
|
+
if (seen.has(id)) continue;
|
|
28
|
+
held.delete(id);
|
|
29
|
+
table.clear(id, entry);
|
|
30
|
+
}
|
|
31
|
+
table.commit();
|
|
32
|
+
};
|
|
7
33
|
return {
|
|
8
34
|
set(poses) {
|
|
9
|
-
|
|
10
|
-
for (const [id, pose] of poses) {
|
|
11
|
-
seen.add(id);
|
|
12
|
-
const existing = held.get(id);
|
|
13
|
-
if (existing) {
|
|
14
|
-
existing.pose = pose;
|
|
15
|
-
continue;
|
|
16
|
-
}
|
|
17
|
-
const entry = { pose };
|
|
18
|
-
held.set(id, entry);
|
|
19
|
-
table.set(id, entry);
|
|
20
|
-
}
|
|
21
|
-
for (const [id, entry] of held) {
|
|
22
|
-
if (seen.has(id)) continue;
|
|
23
|
-
held.delete(id);
|
|
24
|
-
if (table.get(id) === entry) table.clear(id);
|
|
25
|
-
}
|
|
26
|
-
table.commit();
|
|
35
|
+
publish(mapped(poses));
|
|
27
36
|
},
|
|
37
|
+
show: publish,
|
|
28
38
|
others() {
|
|
29
39
|
const out = /* @__PURE__ */ new Map();
|
|
30
40
|
for (const id of table.ids()) {
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
41
|
+
const stack = pliesOf(id) ?? [];
|
|
42
|
+
const mine = held.get(id);
|
|
43
|
+
for (let k = stack.length - 1; k >= 0; k--) {
|
|
44
|
+
const entry = stack[k];
|
|
45
|
+
if (entry === mine || entry.pose === void 0) continue;
|
|
46
|
+
out.set(id, entry.pose);
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
34
49
|
}
|
|
35
50
|
return out;
|
|
36
51
|
},
|
|
37
52
|
drop() {
|
|
38
53
|
if (held.size === 0) return;
|
|
39
|
-
for (const [id, entry] of held)
|
|
54
|
+
for (const [id, entry] of held) table.clear(id, entry);
|
|
40
55
|
held.clear();
|
|
41
56
|
table.commit();
|
|
42
57
|
}
|
|
43
58
|
};
|
|
44
59
|
}
|
|
60
|
+
function* mapped(poses) {
|
|
61
|
+
for (const [id, pose] of poses) yield [id, { pose }];
|
|
62
|
+
}
|
|
45
63
|
|
|
46
64
|
//#endregion
|
|
47
65
|
export { createPoseHold };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"poseHold.js","names":[],"sources":["../../../src/core/scene/poseHold.ts"],"sourcesContent":["import type { NodeId, PoseHold, PoseOverride, PoseOverrides } from './types';\n\n/** The table methods a hold writes through. */\ntype HoldTable<TPose> = Pick<PoseOverrides<TPose>, 'set' | '
|
|
1
|
+
{"version":3,"file":"poseHold.js","names":[],"sources":["../../../src/core/scene/poseHold.ts"],"sourcesContent":["import type { NodeId, PoseHold, PoseOverride, PoseOverrides, ShownOverride } from './types';\n\n/** The table methods a hold writes through. */\ntype HoldTable<TPose, TData> = Pick<PoseOverrides<TPose, TData>, 'set' | 'has' | 'ids' | 'clear' | 'commit'>;\n\n/** Build the {@link PoseHold} a table hands out from `hold()`. `pliesOf`\n * answers a node's plies, bottom first. */\nexport function createPoseHold<TPose, TData = unknown>(\n table: HoldTable<TPose, TData>,\n pliesOf: (id: NodeId) => readonly PoseOverride<TPose, TData>[] | undefined,\n): PoseHold<TPose, TData> {\n /** The entry published per id, held by reference so a frame mutates it in place. */\n const held = new Map<NodeId, PoseOverride<TPose, TData>>();\n const seen = new Set<NodeId>();\n\n const publish = (frame: Iterable<readonly [NodeId, ShownOverride<TPose, TData>]>): void => {\n seen.clear();\n for (const [id, shown] of frame) {\n seen.add(id);\n const existing = held.get(id);\n if (existing) {\n existing.pose = shown.pose;\n existing.data = shown.data;\n // The table drops a node's plies on its own when the node goes; put back the node, and the frame goes back too.\n if (!table.has(id, existing)) table.set(id, existing);\n continue;\n }\n const entry: PoseOverride<TPose, TData> = { pose: shown.pose, data: shown.data };\n held.set(id, entry);\n // `table.set` notifies per call, so an id is set once and mutated after.\n table.set(id, entry);\n }\n for (const [id, entry] of held) {\n if (seen.has(id)) continue;\n held.delete(id);\n table.clear(id, entry);\n }\n table.commit();\n };\n\n return {\n set(poses) {\n publish(mapped(poses));\n },\n show: publish,\n others() {\n const out = new Map<NodeId, TPose>();\n for (const id of table.ids()) {\n const stack = pliesOf(id) ?? [];\n const mine = held.get(id);\n for (let k = stack.length - 1; k >= 0; k--) {\n const entry = stack[k]!;\n if (entry === mine || entry.pose === undefined) continue;\n out.set(id, entry.pose);\n break;\n }\n }\n return out;\n },\n drop() {\n if (held.size === 0) return;\n for (const [id, entry] of held) table.clear(id, entry);\n held.clear();\n table.commit();\n },\n };\n}\n\nfunction* mapped<TPose, TData>(poses: Iterable<readonly [NodeId, TPose]>): Iterable<readonly [NodeId, ShownOverride<TPose, TData>]> {\n for (const [id, pose] of poses) yield [id, { pose }];\n}\n"],"mappings":";;;AAOA,SAAgB,eACd,OACA,SACwB;;CAExB,MAAM,uBAAO,IAAI,IAAwC;CACzD,MAAM,uBAAO,IAAI,IAAY;CAE7B,MAAM,WAAW,UAA0E;EACzF,KAAK,MAAM;EACX,KAAK,MAAM,CAAC,IAAI,UAAU,OAAO;GAC/B,KAAK,IAAI,EAAE;GACX,MAAM,WAAW,KAAK,IAAI,EAAE;GAC5B,IAAI,UAAU;IACZ,SAAS,OAAO,MAAM;IACtB,SAAS,OAAO,MAAM;IAEtB,IAAI,CAAC,MAAM,IAAI,IAAI,QAAQ,GAAG,MAAM,IAAI,IAAI,QAAQ;IACpD;GACF;GACA,MAAM,QAAoC;IAAE,MAAM,MAAM;IAAM,MAAM,MAAM;GAAK;GAC/E,KAAK,IAAI,IAAI,KAAK;GAElB,MAAM,IAAI,IAAI,KAAK;EACrB;EACA,KAAK,MAAM,CAAC,IAAI,UAAU,MAAM;GAC9B,IAAI,KAAK,IAAI,EAAE,GAAG;GAClB,KAAK,OAAO,EAAE;GACd,MAAM,MAAM,IAAI,KAAK;EACvB;EACA,MAAM,OAAO;CACf;CAEA,OAAO;EACL,IAAI,OAAO;GACT,QAAQ,OAAO,KAAK,CAAC;EACvB;EACA,MAAM;EACN,SAAS;GACP,MAAM,sBAAM,IAAI,IAAmB;GACnC,KAAK,MAAM,MAAM,MAAM,IAAI,GAAG;IAC5B,MAAM,QAAQ,QAAQ,EAAE,KAAK,CAAC;IAC9B,MAAM,OAAO,KAAK,IAAI,EAAE;IACxB,KAAK,IAAI,IAAI,MAAM,SAAS,GAAG,KAAK,GAAG,KAAK;KAC1C,MAAM,QAAQ,MAAM;KACpB,IAAI,UAAU,QAAQ,MAAM,SAAS,QAAW;KAChD,IAAI,IAAI,IAAI,MAAM,IAAI;KACtB;IACF;GACF;GACA,OAAO;EACT;EACA,OAAO;GACL,IAAI,KAAK,SAAS,GAAG;GACrB,KAAK,MAAM,CAAC,IAAI,UAAU,MAAM,MAAM,MAAM,IAAI,KAAK;GACrD,KAAK,MAAM;GACX,MAAM,OAAO;EACf;CACF;AACF;AAEA,UAAU,OAAqB,OAAqG;CAClI,KAAK,MAAM,CAAC,IAAI,SAAS,OAAO,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC;AACrD"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { dropPoseKeyedMemoSlots } from "./nodeMemo.js";
|
|
2
|
+
import { shownCopyOf } from "./nodeAsShown.js";
|
|
2
3
|
import { createPoseHold } from "./poseHold.js";
|
|
4
|
+
import { foldPlies } from "./posePlies.js";
|
|
5
|
+
import { createPlyStacks, plyPath } from "./plyStacks.js";
|
|
3
6
|
import { createEmitter } from "@weasel-js/registry";
|
|
4
|
-
import { kit, last, mix, mul, patch } from "@msb235/blits";
|
|
5
7
|
|
|
6
8
|
//#region src/core/scene/poseOverrides.ts
|
|
7
|
-
/** What the table's voice says about a node it holds no entry for. */
|
|
8
|
-
var NOTHING = Object.freeze({});
|
|
9
9
|
/**
|
|
10
10
|
* Build a {@link PoseOverrides} map.
|
|
11
11
|
*
|
|
@@ -13,53 +13,48 @@ var NOTHING = Object.freeze({});
|
|
|
13
13
|
* `onInvalidate` lets the scene invalidate derived nodes from the same
|
|
14
14
|
* chokepoint.
|
|
15
15
|
*
|
|
16
|
-
* What `read` answers is
|
|
17
|
-
*
|
|
16
|
+
* What `read` answers is folded from the node's plies by `foldPlies`, its
|
|
17
|
+
* path by `plyPath`; a node holding no entry is never probed.
|
|
18
18
|
*/
|
|
19
19
|
function createPoseOverrides(getNode, onInvalidate) {
|
|
20
|
-
const
|
|
20
|
+
const stacks = createPlyStacks();
|
|
21
|
+
const { plies } = stacks;
|
|
22
|
+
const fold = foldPlies(plies);
|
|
21
23
|
const listeners = createEmitter();
|
|
22
24
|
let generation = 0;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
alpha: mul(),
|
|
26
|
-
path: last()
|
|
27
|
-
}));
|
|
28
|
-
folded.cue({ patch: patch(0, (_phase, id) => entries.get(id) ?? NOTHING, { writes: [
|
|
29
|
-
"pose",
|
|
30
|
-
"alpha",
|
|
31
|
-
"path"
|
|
32
|
-
] }) });
|
|
33
|
-
let clock = 0;
|
|
34
|
-
folded.sync(clock);
|
|
35
|
-
/** Per node: the object `read` folds into and returns, and the generation
|
|
36
|
-
* it was last folded at. */
|
|
25
|
+
/** Per node: the object `read` folds into and returns, the generation it
|
|
26
|
+
* was last folded at, and the last path it carried. */
|
|
37
27
|
const reads = /* @__PURE__ */ new Map();
|
|
38
28
|
function invalidate(id) {
|
|
39
29
|
const node = getNode(id);
|
|
40
|
-
if (node)
|
|
30
|
+
if (node) {
|
|
31
|
+
dropPoseKeyedMemoSlots(node);
|
|
32
|
+
const shown = shownCopyOf(node);
|
|
33
|
+
if (shown) dropPoseKeyedMemoSlots(shown);
|
|
34
|
+
}
|
|
41
35
|
onInvalidate?.(id);
|
|
42
36
|
}
|
|
43
37
|
function published() {
|
|
44
38
|
generation++;
|
|
45
|
-
|
|
39
|
+
fold.publish(stacks.depth());
|
|
46
40
|
listeners.emit();
|
|
47
41
|
}
|
|
48
42
|
function forget(id) {
|
|
49
43
|
reads.delete(id);
|
|
50
|
-
|
|
44
|
+
fold.drop(id);
|
|
51
45
|
}
|
|
52
46
|
const table = {
|
|
53
47
|
set(id, entry) {
|
|
54
|
-
|
|
48
|
+
stacks.claim(id, entry);
|
|
55
49
|
invalidate(id);
|
|
56
50
|
published();
|
|
57
51
|
},
|
|
58
52
|
get(id) {
|
|
59
|
-
return
|
|
53
|
+
return plies.get(id)?.at(-1);
|
|
60
54
|
},
|
|
61
55
|
read(id) {
|
|
62
|
-
|
|
56
|
+
const stack = plies.get(id);
|
|
57
|
+
if (stack === void 0) return void 0;
|
|
63
58
|
let held = reads.get(id);
|
|
64
59
|
if (held === void 0) {
|
|
65
60
|
held = {
|
|
@@ -69,41 +64,43 @@ function createPoseOverrides(getNode, onInvalidate) {
|
|
|
69
64
|
reads.set(id, held);
|
|
70
65
|
}
|
|
71
66
|
if (held.at !== generation) {
|
|
72
|
-
|
|
67
|
+
fold.probe(id, held.out);
|
|
68
|
+
held.out.path = plyPath(stack, held.out.pose, held);
|
|
73
69
|
held.at = generation;
|
|
74
70
|
}
|
|
75
71
|
return held.out;
|
|
76
72
|
},
|
|
77
|
-
has(id) {
|
|
78
|
-
|
|
73
|
+
has(id, entry) {
|
|
74
|
+
const stack = plies.get(id);
|
|
75
|
+
return stack !== void 0 && (entry === void 0 || stack.includes(entry));
|
|
79
76
|
},
|
|
80
77
|
ids() {
|
|
81
|
-
return [...
|
|
78
|
+
return [...plies.keys()];
|
|
82
79
|
},
|
|
83
|
-
clear(id) {
|
|
84
|
-
if (!
|
|
85
|
-
forget(id);
|
|
80
|
+
clear(id, entry) {
|
|
81
|
+
if (!(entry === void 0 ? stacks.drop(id) : stacks.release(id, entry))) return;
|
|
82
|
+
if (!plies.has(id)) forget(id);
|
|
86
83
|
invalidate(id);
|
|
87
84
|
published();
|
|
88
85
|
},
|
|
89
86
|
clearAll() {
|
|
90
|
-
if (
|
|
91
|
-
for (const id of
|
|
87
|
+
if (plies.size === 0) return;
|
|
88
|
+
for (const id of plies.keys()) {
|
|
92
89
|
forget(id);
|
|
93
90
|
invalidate(id);
|
|
94
91
|
}
|
|
95
|
-
|
|
92
|
+
stacks.dropAll();
|
|
96
93
|
published();
|
|
97
94
|
},
|
|
98
95
|
commit() {
|
|
99
|
-
for (const id of
|
|
96
|
+
for (const id of plies.keys()) invalidate(id);
|
|
100
97
|
published();
|
|
101
98
|
},
|
|
102
99
|
subscribe: listeners.subscribe,
|
|
103
100
|
getGeneration() {
|
|
104
101
|
return generation;
|
|
105
102
|
},
|
|
106
|
-
hold: () => createPoseHold(table)
|
|
103
|
+
hold: () => createPoseHold(table, (id) => plies.get(id))
|
|
107
104
|
};
|
|
108
105
|
return table;
|
|
109
106
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"poseOverrides.js","names":[],"sources":["../../../src/core/scene/poseOverrides.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"file":"poseOverrides.js","names":[],"sources":["../../../src/core/scene/poseOverrides.ts"],"sourcesContent":["import { createEmitter } from '@weasel-js/registry';\nimport { dropPoseKeyedMemoSlots } from './nodeMemo';\nimport { shownCopyOf } from './nodeAsShown';\nimport { createPoseHold } from './poseHold';\nimport { foldPlies } from './posePlies';\nimport { createPlyStacks, plyPath, type CarriedPath } from './plyStacks';\nimport type { NodeId, PoseOverride, PoseOverrides } from './types';\n\n/**\n * Build a {@link PoseOverrides} map.\n *\n * `getNode` resolves an id to the node object the painter memo is keyed on.\n * `onInvalidate` lets the scene invalidate derived nodes from the same\n * chokepoint.\n *\n * What `read` answers is folded from the node's plies by `foldPlies`, its\n * path by `plyPath`; a node holding no entry is never probed.\n */\nexport function createPoseOverrides<TPose, TData = unknown>(\n getNode: (id: NodeId) => { data?: unknown } | undefined,\n onInvalidate?: (id: NodeId) => void,\n): PoseOverrides<TPose, TData> {\n type Entry = PoseOverride<TPose, TData>;\n const stacks = createPlyStacks<Entry>();\n const { plies } = stacks;\n const fold = foldPlies(plies);\n const listeners = createEmitter();\n let generation = 0;\n\n /** Per node: the object `read` folds into and returns, the generation it\n * was last folded at, and the last path it carried. */\n const reads = new Map<NodeId, { out: Entry; at: number; carried?: CarriedPath }>();\n\n function invalidate(id: NodeId): void {\n const node = getNode(id);\n if (node) {\n dropPoseKeyedMemoSlots(node);\n // A painter handed the node as it shows memoized against that copy.\n const shown = shownCopyOf(node);\n if (shown) dropPoseKeyedMemoSlots(shown);\n }\n onInvalidate?.(id);\n }\n\n function published(): void {\n generation++;\n fold.publish(stacks.depth());\n listeners.emit();\n }\n\n function forget(id: NodeId): void {\n reads.delete(id);\n fold.drop(id);\n }\n\n const table: PoseOverrides<TPose, TData> = {\n set(id, entry) {\n stacks.claim(id, entry);\n invalidate(id);\n published();\n },\n get(id) {\n return plies.get(id)?.at(-1);\n },\n read(id) {\n const stack = plies.get(id);\n if (stack === undefined) return undefined;\n let held = reads.get(id);\n if (held === undefined) {\n held = { out: {}, at: -1 };\n reads.set(id, held);\n }\n if (held.at !== generation) {\n fold.probe(id, held.out);\n held.out.path = plyPath(stack, held.out.pose, held);\n held.at = generation;\n }\n return held.out;\n },\n has(id, entry) {\n const stack = plies.get(id);\n return stack !== undefined && (entry === undefined || stack.includes(entry));\n },\n ids() {\n return [...plies.keys()];\n },\n clear(id, entry) {\n if (!(entry === undefined ? stacks.drop(id) : stacks.release(id, entry))) return;\n if (!plies.has(id)) forget(id);\n invalidate(id);\n published();\n },\n clearAll() {\n if (plies.size === 0) return;\n for (const id of plies.keys()) {\n forget(id);\n invalidate(id);\n }\n stacks.dropAll();\n published();\n },\n commit() {\n for (const id of plies.keys()) invalidate(id);\n published();\n },\n subscribe: listeners.subscribe,\n getGeneration() {\n return generation;\n },\n hold: () => createPoseHold(table, (id) => plies.get(id)),\n };\n return table;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAkBA,SAAgB,oBACd,SACA,cAC6B;CAE7B,MAAM,SAAS,gBAAuB;CACtC,MAAM,EAAE,UAAU;CAClB,MAAM,OAAO,UAAU,KAAK;CAC5B,MAAM,YAAY,cAAc;CAChC,IAAI,aAAa;;;CAIjB,MAAM,wBAAQ,IAAI,IAA+D;CAEjF,SAAS,WAAW,IAAkB;EACpC,MAAM,OAAO,QAAQ,EAAE;EACvB,IAAI,MAAM;GACR,uBAAuB,IAAI;GAE3B,MAAM,QAAQ,YAAY,IAAI;GAC9B,IAAI,OAAO,uBAAuB,KAAK;EACzC;EACA,eAAe,EAAE;CACnB;CAEA,SAAS,YAAkB;EACzB;EACA,KAAK,QAAQ,OAAO,MAAM,CAAC;EAC3B,UAAU,KAAK;CACjB;CAEA,SAAS,OAAO,IAAkB;EAChC,MAAM,OAAO,EAAE;EACf,KAAK,KAAK,EAAE;CACd;CAEA,MAAM,QAAqC;EACzC,IAAI,IAAI,OAAO;GACb,OAAO,MAAM,IAAI,KAAK;GACtB,WAAW,EAAE;GACb,UAAU;EACZ;EACA,IAAI,IAAI;GACN,OAAO,MAAM,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE;EAC7B;EACA,KAAK,IAAI;GACP,MAAM,QAAQ,MAAM,IAAI,EAAE;GAC1B,IAAI,UAAU,QAAW,OAAO;GAChC,IAAI,OAAO,MAAM,IAAI,EAAE;GACvB,IAAI,SAAS,QAAW;IACtB,OAAO;KAAE,KAAK,CAAC;KAAG,IAAI;IAAG;IACzB,MAAM,IAAI,IAAI,IAAI;GACpB;GACA,IAAI,KAAK,OAAO,YAAY;IAC1B,KAAK,MAAM,IAAI,KAAK,GAAG;IACvB,KAAK,IAAI,OAAO,QAAQ,OAAO,KAAK,IAAI,MAAM,IAAI;IAClD,KAAK,KAAK;GACZ;GACA,OAAO,KAAK;EACd;EACA,IAAI,IAAI,OAAO;GACb,MAAM,QAAQ,MAAM,IAAI,EAAE;GAC1B,OAAO,UAAU,WAAc,UAAU,UAAa,MAAM,SAAS,KAAK;EAC5E;EACA,MAAM;GACJ,OAAO,CAAC,GAAG,MAAM,KAAK,CAAC;EACzB;EACA,MAAM,IAAI,OAAO;GACf,IAAI,EAAE,UAAU,SAAY,OAAO,KAAK,EAAE,IAAI,OAAO,QAAQ,IAAI,KAAK,IAAI;GAC1E,IAAI,CAAC,MAAM,IAAI,EAAE,GAAG,OAAO,EAAE;GAC7B,WAAW,EAAE;GACb,UAAU;EACZ;EACA,WAAW;GACT,IAAI,MAAM,SAAS,GAAG;GACtB,KAAK,MAAM,MAAM,MAAM,KAAK,GAAG;IAC7B,OAAO,EAAE;IACT,WAAW,EAAE;GACf;GACA,OAAO,QAAQ;GACf,UAAU;EACZ;EACA,SAAS;GACP,KAAK,MAAM,MAAM,MAAM,KAAK,GAAG,WAAW,EAAE;GAC5C,UAAU;EACZ;EACA,WAAW,UAAU;EACrB,gBAAgB;GACd,OAAO;EACT;EACA,YAAY,eAAe,QAAQ,OAAO,MAAM,IAAI,EAAE,CAAC;CACzD;CACA,OAAO;AACT"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { kit, last, mix, mul, patch } from "@msb235/blits";
|
|
2
|
+
|
|
3
|
+
//#region src/core/scene/posePlies.ts
|
|
4
|
+
/** What a ply says about a node with fewer plies than its depth. */
|
|
5
|
+
var NOTHING = Object.freeze({});
|
|
6
|
+
/** Per lower function, per upper one, the two run in turn: kept, so a node
|
|
7
|
+
* shows one function while neither ply replaces its own. */
|
|
8
|
+
var composed = /* @__PURE__ */ new WeakMap();
|
|
9
|
+
function after(lower, upper) {
|
|
10
|
+
let byUpper = composed.get(lower);
|
|
11
|
+
if (byUpper === void 0) composed.set(lower, byUpper = /* @__PURE__ */ new WeakMap());
|
|
12
|
+
let both = byUpper.get(upper);
|
|
13
|
+
if (both === void 0) byUpper.set(upper, both = (stored) => upper(lower(stored)));
|
|
14
|
+
return both;
|
|
15
|
+
}
|
|
16
|
+
/** A later ply's data runs on what the plies under it show. */
|
|
17
|
+
var DATA = {
|
|
18
|
+
merge: after,
|
|
19
|
+
lerp: (a, b, u) => u < .5 ? a : b
|
|
20
|
+
};
|
|
21
|
+
/** A fold over `plies`, each node's entries bottom first. */
|
|
22
|
+
function foldPlies(plies) {
|
|
23
|
+
const folded = mix(kit({
|
|
24
|
+
pose: last(),
|
|
25
|
+
alpha: mul(),
|
|
26
|
+
path: last(),
|
|
27
|
+
data: DATA
|
|
28
|
+
}));
|
|
29
|
+
/** One voice per depth, bottom first; only ever cut from the top, so cue order stays depth order. */
|
|
30
|
+
const voices = [];
|
|
31
|
+
let clock = 0;
|
|
32
|
+
const publish = (depth) => {
|
|
33
|
+
while (voices.length > depth) voices.pop().fade({ over: 0 });
|
|
34
|
+
while (voices.length < depth) {
|
|
35
|
+
const k = voices.length;
|
|
36
|
+
voices.push(folded.cue({ patch: patch(0, (_phase, id) => plies.get(id)?.[k] ?? NOTHING, { writes: [
|
|
37
|
+
"pose",
|
|
38
|
+
"alpha",
|
|
39
|
+
"path",
|
|
40
|
+
"data"
|
|
41
|
+
] }) }));
|
|
42
|
+
}
|
|
43
|
+
folded.sync(clock++);
|
|
44
|
+
};
|
|
45
|
+
publish(1);
|
|
46
|
+
return {
|
|
47
|
+
probe: (id, out) => {
|
|
48
|
+
folded.probe(id, out);
|
|
49
|
+
},
|
|
50
|
+
publish,
|
|
51
|
+
drop: (id) => {
|
|
52
|
+
folded.drop(id);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
//#endregion
|
|
58
|
+
export { foldPlies };
|
|
59
|
+
//# sourceMappingURL=posePlies.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"posePlies.js","names":[],"sources":["../../../src/core/scene/posePlies.ts"],"sourcesContent":["/**\n * The fold behind `PoseOverrides.read`: a blits mix over each node's plies of\n * overrides, one voice per depth, cued bottom first, so a later ply folds\n * over an earlier one.\n */\nimport type { Path } from '@weasel-js/geom';\nimport { kit, last, mix, mul, patch, type Channel, type Handle } from '@msb235/blits';\nimport type { NodeId, PoseOverride } from './types';\n\n/** What a ply says about a node with fewer plies than its depth. */\nconst NOTHING: PoseOverride<never> = Object.freeze({});\n\ntype ShowData = (stored: never) => unknown;\n\n/** Per lower function, per upper one, the two run in turn: kept, so a node\n * shows one function while neither ply replaces its own. */\nconst composed = new WeakMap<ShowData, WeakMap<ShowData, ShowData>>();\n\nfunction after(lower: ShowData, upper: ShowData): ShowData {\n let byUpper = composed.get(lower);\n if (byUpper === undefined) composed.set(lower, byUpper = new WeakMap());\n let both = byUpper.get(upper);\n if (both === undefined) byUpper.set(upper, both = (stored) => upper(lower(stored) as never));\n return both;\n}\n\n/** A later ply's data runs on what the plies under it show. */\nconst DATA: Channel<ShowData> = { merge: after, lerp: (a, b, u) => (u < 0.5 ? a : b) };\n\n/** {@link foldPlies}'s handle. */\nexport interface PlyFold<Entry> {\n /** Fold `id`'s plies into `out`, as of the last `publish`. */\n probe(id: NodeId, out: Entry): void;\n /** Make the next probe of every node fold afresh, `depth` plies deep. */\n publish(depth: number): void;\n /** Forget what the fold keeps for `id`. */\n drop(id: NodeId): void;\n}\n\n/** A fold over `plies`, each node's entries bottom first. */\nexport function foldPlies<TPose, TData>(\n plies: ReadonlyMap<NodeId, readonly PoseOverride<TPose, TData>[]>,\n): PlyFold<PoseOverride<TPose, TData>> {\n type Entry = PoseOverride<TPose, TData>;\n const folded = mix<NodeId, Entry>(\n kit<Entry>({\n pose: last<NonNullable<TPose>>(),\n alpha: mul(),\n path: last<Path>(),\n data: DATA as unknown as Channel<NonNullable<Entry['data']>>,\n }),\n );\n /** One voice per depth, bottom first; only ever cut from the top, so cue order stays depth order. */\n const voices: Handle<NodeId>[] = [];\n // Mix time only has to move between publishes, so a probe after one never\n // hands back the delta a probe before it cached.\n let clock = 0;\n const publish = (depth: number): void => {\n while (voices.length > depth) voices.pop()!.fade({ over: 0 });\n while (voices.length < depth) {\n const k = voices.length;\n voices.push(folded.cue({\n patch: patch<NodeId, Entry>(\n 0,\n (_phase, id) => plies.get(id)?.[k] ?? (NOTHING as Entry),\n { writes: ['pose', 'alpha', 'path', 'data'] },\n ),\n }));\n }\n folded.sync(clock++);\n };\n publish(1);\n return {\n probe: (id, out) => { folded.probe(id, out); },\n publish,\n drop: (id) => { folded.drop(id); },\n };\n}\n"],"mappings":";;;;AAUA,IAAM,UAA+B,OAAO,OAAO,CAAC,CAAC;;;AAMrD,IAAM,2BAAW,IAAI,QAA+C;AAEpE,SAAS,MAAM,OAAiB,OAA2B;CACzD,IAAI,UAAU,SAAS,IAAI,KAAK;CAChC,IAAI,YAAY,QAAW,SAAS,IAAI,OAAO,0BAAU,IAAI,QAAQ,CAAC;CACtE,IAAI,OAAO,QAAQ,IAAI,KAAK;CAC5B,IAAI,SAAS,QAAW,QAAQ,IAAI,OAAO,QAAQ,WAAW,MAAM,MAAM,MAAM,CAAU,CAAC;CAC3F,OAAO;AACT;;AAGA,IAAM,OAA0B;CAAE,OAAO;CAAO,OAAO,GAAG,GAAG,MAAO,IAAI,KAAM,IAAI;AAAG;;AAarF,SAAgB,UACd,OACqC;CAErC,MAAM,SAAS,IACb,IAAW;EACT,MAAM,KAAyB;EAC/B,OAAO,IAAI;EACX,MAAM,KAAW;EACjB,MAAM;CACR,CAAC,CACH;;CAEA,MAAM,SAA2B,CAAC;CAGlC,IAAI,QAAQ;CACZ,MAAM,WAAW,UAAwB;EACvC,OAAO,OAAO,SAAS,OAAO,OAAO,IAAI,CAAC,CAAE,KAAK,EAAE,MAAM,EAAE,CAAC;EAC5D,OAAO,OAAO,SAAS,OAAO;GAC5B,MAAM,IAAI,OAAO;GACjB,OAAO,KAAK,OAAO,IAAI,EACrB,OAAO,MACL,IACC,QAAQ,OAAO,MAAM,IAAI,EAAE,CAAC,GAAG,MAAO,SACvC,EAAE,QAAQ;IAAC;IAAQ;IAAS;IAAQ;GAAM,EAAE,CAC9C,EACF,CAAC,CAAC;EACJ;EACA,OAAO,KAAK,OAAO;CACrB;CACA,QAAQ,CAAC;CACT,OAAO;EACL,QAAQ,IAAI,QAAQ;GAAE,OAAO,MAAM,IAAI,GAAG;EAAG;EAC7C;EACA,OAAO,OAAO;GAAE,OAAO,KAAK,EAAE;EAAG;CACnC;AACF"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { sameValue } from "./sameValue.js";
|
|
2
2
|
|
|
3
3
|
//#region src/core/scene/reconcileSpecs.ts
|
|
4
4
|
/**
|
|
@@ -39,10 +39,11 @@ function reconcileSpecs(scene, prev, next) {
|
|
|
39
39
|
const parent = spec.parent ?? null;
|
|
40
40
|
if (parent !== (before.parent ?? null)) scene.move(id, parent);
|
|
41
41
|
if (spec.layer !== before.layer) scene.setLayer(id, spec.layer);
|
|
42
|
-
if (!
|
|
43
|
-
if (!
|
|
44
|
-
if (
|
|
45
|
-
if (
|
|
42
|
+
if (!sameValue(spec.data, before.data)) scene.update(id, { data: spec.data });
|
|
43
|
+
if (!sameValue(spec.dependsOn, before.dependsOn)) scene.setDependsOn(id, spec.dependsOn);
|
|
44
|
+
if (!sameValue(spec.units, before.units)) scene.setUnits(id, spec.units ?? null);
|
|
45
|
+
if (spec.clip !== before.clip) scene.setClip(id, spec.clip ?? null);
|
|
46
|
+
if (!sameValue(spec.pose, before.pose)) scene.setPose(id, spec.pose);
|
|
46
47
|
if (spec.hidden === true !== (before.hidden === true)) scene.setHidden(id, spec.hidden === true);
|
|
47
48
|
if (spec.locked === true && before.locked !== true) scene.setLocked(id, true);
|
|
48
49
|
}
|
|
@@ -61,16 +62,6 @@ function byId(specs) {
|
|
|
61
62
|
function needsReplace(a, b) {
|
|
62
63
|
return a.kind !== b.kind || a.pickable !== b.pickable || a.derivePath !== b.derivePath || a.derivePose !== b.derivePose || a.clipFromPose !== b.clipFromPose || a.copiesFromPose !== b.copiesFromPose || a.layout !== b.layout;
|
|
63
64
|
}
|
|
64
|
-
/** Structural equality over plain objects and arrays; anything else by identity. */
|
|
65
|
-
function same(a, b) {
|
|
66
|
-
if (Object.is(a, b)) return true;
|
|
67
|
-
if (Array.isArray(a) && Array.isArray(b)) return a.length === b.length && a.every((v, i) => same(v, b[i]));
|
|
68
|
-
if (isPlainObject(a) && isPlainObject(b)) {
|
|
69
|
-
const ka = Object.keys(a);
|
|
70
|
-
return ka.length === Object.keys(b).length && ka.every((k) => k in b && same(a[k], b[k]));
|
|
71
|
-
}
|
|
72
|
-
return false;
|
|
73
|
-
}
|
|
74
65
|
|
|
75
66
|
//#endregion
|
|
76
67
|
export { reconcileSpecs };
|