@weasel-js/core 1.13.0-rc.0 → 1.14.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 +408 -0
- package/README.md +8 -12
- package/dist/affordances/hitAffordanceRegions.js +1 -1
- package/dist/affordances/hitAffordanceRegions.js.map +1 -1
- package/dist/affordances/pathAnchors.js.map +1 -1
- package/dist/animation/clipTargets.js +1 -1
- package/dist/animation/clipTargets.js.map +1 -1
- package/dist/animation/poseTarget.js +5 -32
- package/dist/animation/poseTarget.js.map +1 -1
- package/dist/{autoPoseDescriptor-CZ1eXbzY.d.ts → autoPoseDescriptor-C25QVb0W.d.ts} +1 -1
- package/dist/barrel/canvas.js +8 -8
- package/dist/barrel/chrome.js +9 -9
- package/dist/barrel/input.js +1 -1
- package/dist/barrel/interactions.js +3 -3
- package/dist/barrel/paint.js +2 -2
- package/dist/barrel/paths.js +19 -17
- package/dist/barrel/renderer.js +11 -7
- package/dist/barrel/routing.js +4 -1
- package/dist/barrel/scene.js +16 -12
- package/dist/barrel/text.js +5 -5
- package/dist/barrel/viewport.js +8 -8
- package/dist/canvas/Canvas.js +2 -2
- package/dist/canvas/Canvas.js.map +1 -1
- package/dist/canvas/CanvasView.js +20 -14
- package/dist/canvas/CanvasView.js.map +1 -1
- package/dist/canvas/GestureReason.js +64 -0
- package/dist/canvas/GestureReason.js.map +1 -0
- package/dist/canvas/GestureReason.module.js +7 -0
- package/dist/canvas/GestureReason.module.js.map +1 -0
- package/dist/canvas/LeanSceneCanvas.js +3 -1
- package/dist/canvas/LeanSceneCanvas.js.map +1 -1
- package/dist/canvas/NodeShape.js +2 -0
- package/dist/canvas/NodeShape.js.map +1 -1
- package/dist/canvas/PickHud.js +7 -3
- package/dist/canvas/PickHud.js.map +1 -1
- package/dist/canvas/SceneCanvas/CanvasKitProviders.js +1 -1
- package/dist/canvas/SceneCanvas/CanvasKitProviders.js.map +1 -1
- package/dist/canvas/SceneCanvas/DevHuds.js +2 -2
- package/dist/canvas/SceneCanvas/DevHuds.js.map +1 -1
- package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js +4 -2
- package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js.map +1 -1
- package/dist/canvas/SceneCanvas/SceneCanvasInput.js +3 -1
- package/dist/canvas/SceneCanvas/SceneCanvasInput.js.map +1 -1
- package/dist/canvas/SceneCanvas/brushOverlay.js.map +1 -1
- package/dist/canvas/SceneCanvas/builtinToolSets.js +17 -9
- package/dist/canvas/SceneCanvas/builtinToolSets.js.map +1 -1
- package/dist/canvas/SceneCanvas/canvasPassThrough.js +2 -1
- package/dist/canvas/SceneCanvas/canvasPassThrough.js.map +1 -1
- package/dist/canvas/SceneCanvas/defaultNodeProperties.js +75 -19
- package/dist/canvas/SceneCanvas/defaultNodeProperties.js.map +1 -1
- package/dist/canvas/SceneCanvas/defaultNodeRouting.js +7 -1
- package/dist/canvas/SceneCanvas/defaultNodeRouting.js.map +1 -1
- package/dist/canvas/SceneCanvas/defaultTextEditor.js +108 -0
- package/dist/canvas/SceneCanvas/defaultTextEditor.js.map +1 -0
- package/dist/canvas/SceneCanvas/describePresets.js +47 -0
- package/dist/canvas/SceneCanvas/describePresets.js.map +1 -0
- package/dist/canvas/SceneCanvas/features.js +57 -16
- package/dist/canvas/SceneCanvas/features.js.map +1 -1
- package/dist/canvas/SceneCanvas/mergeLayers.js +10 -1
- package/dist/canvas/SceneCanvas/mergeLayers.js.map +1 -1
- package/dist/canvas/SceneCanvas/namedPresets.js +52 -24
- package/dist/canvas/SceneCanvas/namedPresets.js.map +1 -1
- package/dist/canvas/SceneCanvas/presets/arrange.js +35 -10
- package/dist/canvas/SceneCanvas/presets/arrange.js.map +1 -1
- package/dist/canvas/SceneCanvas/presets/baseline.js +9 -0
- package/dist/canvas/SceneCanvas/presets/baseline.js.map +1 -0
- package/dist/canvas/SceneCanvas/presets/chrome.js.map +1 -1
- package/dist/canvas/SceneCanvas/presets/composites.js +43 -0
- package/dist/canvas/SceneCanvas/presets/composites.js.map +1 -0
- package/dist/canvas/SceneCanvas/presets/edit.js +79 -26
- package/dist/canvas/SceneCanvas/presets/edit.js.map +1 -1
- package/dist/canvas/SceneCanvas/presets/ingest.js +1 -0
- package/dist/canvas/SceneCanvas/presets/ingest.js.map +1 -1
- package/dist/canvas/SceneCanvas/presets/paths.js +58 -16
- package/dist/canvas/SceneCanvas/presets/paths.js.map +1 -1
- package/dist/canvas/SceneCanvas/presets/select.js +4 -2
- package/dist/canvas/SceneCanvas/presets/select.js.map +1 -1
- package/dist/canvas/SceneCanvas/presets/tools.js +24 -0
- package/dist/canvas/SceneCanvas/presets/tools.js.map +1 -0
- package/dist/canvas/SceneCanvas/presets/transform.js +4 -0
- package/dist/canvas/SceneCanvas/presets/transform.js.map +1 -1
- package/dist/canvas/SceneCanvas/presets/view.js +3 -1
- package/dist/canvas/SceneCanvas/presets/view.js.map +1 -1
- package/dist/canvas/SceneCanvas/props.js.map +1 -1
- package/dist/canvas/SceneCanvas/shapeGeneratorProperties.js +1 -1
- package/dist/canvas/SceneCanvas/shapeGeneratorProperties.js.map +1 -1
- package/dist/canvas/SceneCanvas/toolRegistry.js +5 -4
- package/dist/canvas/SceneCanvas/toolRegistry.js.map +1 -1
- package/dist/canvas/SceneCanvas/useCanvasTools.js +26 -10
- package/dist/canvas/SceneCanvas/useCanvasTools.js.map +1 -1
- package/dist/canvas/SceneCanvas/useContributionRoles.js +17 -2
- package/dist/canvas/SceneCanvas/useContributionRoles.js.map +1 -1
- package/dist/canvas/SceneCanvas/useDepartureGhostLayer.js +5 -4
- package/dist/canvas/SceneCanvas/useDepartureGhostLayer.js.map +1 -1
- package/dist/canvas/SceneCanvas/useDispatcherOverlayLayer.js +1 -1
- package/dist/canvas/SceneCanvas/useNodeAtPoint.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js +9 -8
- package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneCanvasPathEdit.js +2 -2
- package/dist/canvas/SceneCanvas/useSceneCanvasPathEdit.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneCanvasTools.js +4 -1
- package/dist/canvas/SceneCanvas/useSceneCanvasTools.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneChrome.js +7 -4
- package/dist/canvas/SceneCanvas/useSceneChrome.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneGestureDispatcher.js +9 -9
- package/dist/canvas/SceneCanvas/useSceneGestureDispatcher.js.map +1 -1
- package/dist/canvas/SceneCanvas/useScenePicking.js +4 -7
- package/dist/canvas/SceneCanvas/useScenePicking.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneRedrawSources.js +2 -1
- package/dist/canvas/SceneCanvas/useSceneRedrawSources.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneSelectTool.js +6 -6
- package/dist/canvas/SceneCanvas/useSceneSelectTool.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSceneStandardActions.js +2 -2
- package/dist/canvas/SceneCanvas/useSceneStandardActions.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSelectionOverlayLayer.js +1 -1
- package/dist/canvas/SceneCanvas/useSelectionOverlayLayer.js.map +1 -1
- package/dist/canvas/SceneCanvas/useSurfaceViewInputs.js.map +1 -1
- package/dist/canvas/SceneCanvas/useToolKeybindings.js +2 -2
- package/dist/canvas/SceneCanvas/useToolKeybindings.js.map +1 -1
- package/dist/canvas/SceneCanvas/useViewportActions.js +5 -2
- package/dist/canvas/SceneCanvas/useViewportActions.js.map +1 -1
- package/dist/canvas/SceneCanvas/worldPointAt.js.map +1 -1
- package/dist/canvas/SceneCanvas.js +22 -11
- package/dist/canvas/SceneCanvas.js.map +1 -1
- package/dist/canvas/SceneViewCanvas.js +1 -0
- package/dist/canvas/SceneViewCanvas.js.map +1 -1
- package/dist/canvas/ViewMarker.js.map +1 -1
- package/dist/canvas/accentColor.js +14 -1
- package/dist/canvas/accentColor.js.map +1 -1
- package/dist/canvas/affordanceAt.js +2 -2
- package/dist/canvas/affordanceAt.js.map +1 -1
- package/dist/canvas/buildSceneLayer.js +1 -1
- package/dist/canvas/buildSceneLayer.js.map +1 -1
- package/dist/canvas/buildSceneTree.js +5 -3
- package/dist/canvas/buildSceneTree.js.map +1 -1
- package/dist/canvas/canvasRenderer.js +6 -2
- package/dist/canvas/canvasRenderer.js.map +1 -1
- package/dist/canvas/deps/editAnchors.js +4 -4
- package/dist/canvas/deps/editAnchors.js.map +1 -1
- package/dist/canvas/deps/enteredGroup.js +14 -5
- package/dist/canvas/deps/enteredGroup.js.map +1 -1
- package/dist/canvas/deps/ingestion.js +5 -1
- package/dist/canvas/deps/ingestion.js.map +1 -1
- package/dist/canvas/deps/insert.js.map +1 -1
- package/dist/canvas/deps/insertSite.js +5 -3
- package/dist/canvas/deps/insertSite.js.map +1 -1
- package/dist/canvas/deps/nodeAtPoint.js +1 -12
- package/dist/canvas/deps/nodeAtPoint.js.map +1 -1
- package/dist/canvas/deps/pathEditCommits.js +3 -3
- package/dist/canvas/deps/pathEditCommits.js.map +1 -1
- package/dist/canvas/deps/slice.js +16 -2
- package/dist/canvas/deps/slice.js.map +1 -1
- package/dist/canvas/deps/snap.js +5 -5
- package/dist/canvas/deps/snap.js.map +1 -1
- package/dist/canvas/deps/textEdit.js +5 -6
- package/dist/canvas/deps/textEdit.js.map +1 -1
- package/dist/canvas/derivedPath.js +8 -3
- package/dist/canvas/derivedPath.js.map +1 -1
- package/dist/canvas/getNodeAtPoint.js +2 -2
- package/dist/canvas/getNodeAtPoint.js.map +1 -1
- package/dist/canvas/insertPreviewExtent.js.map +1 -1
- package/dist/canvas/layerSlots.js.map +1 -1
- package/dist/canvas/nodeShapes/measurePainter.js +1 -1
- package/dist/canvas/nodeShapes/measurePainter.js.map +1 -1
- package/dist/canvas/nodeShapes/strokedBounds.js +5 -3
- package/dist/canvas/nodeShapes/strokedBounds.js.map +1 -1
- package/dist/canvas/overlayRoleStrokes.js +6 -0
- package/dist/canvas/overlayRoleStrokes.js.map +1 -1
- package/dist/canvas/pickIndex/scenePickIndex.js +10 -12
- package/dist/canvas/pickIndex/scenePickIndex.js.map +1 -1
- package/dist/canvas/sceneAdapter.js +10 -19
- package/dist/canvas/sceneAdapter.js.map +1 -1
- package/dist/canvas/sceneClipboard.js +17 -4
- package/dist/canvas/sceneClipboard.js.map +1 -1
- package/dist/canvas/sceneViewRender.js +7 -5
- package/dist/canvas/sceneViewRender.js.map +1 -1
- package/dist/canvas/surfaceContribution.js.map +1 -1
- package/dist/canvas/useCanvasPaint.js +12 -4
- package/dist/canvas/useCanvasPaint.js.map +1 -1
- package/dist/canvas/useHitObserver.js +1 -1
- package/dist/canvas/useHitObserver.js.map +1 -1
- package/dist/canvas/useViewAim.js +1 -1
- package/dist/canvas/useViewAim.js.map +1 -1
- package/dist/canvas/useViewHelpers.js +8 -5
- package/dist/canvas/useViewHelpers.js.map +1 -1
- package/dist/canvas/useViewNesting.js +39 -12
- package/dist/canvas/useViewNesting.js.map +1 -1
- package/dist/canvas/viewInputs.js.map +1 -1
- package/dist/canvas/viewMarkers.js +2 -2
- package/dist/canvas/viewMarkers.js.map +1 -1
- package/dist/canvas/viewRegistry.js +2 -2
- package/dist/canvas/viewRegistry.js.map +1 -1
- package/dist/canvas/viewSnap.js +67 -0
- package/dist/canvas/viewSnap.js.map +1 -0
- package/dist/clipboard.d.ts +6 -12
- package/dist/{clone-qb2e1F5p.d.ts → clone-Bz4iqGfE.d.ts} +10 -5
- package/dist/clone.d.ts +5 -5
- package/dist/core/geometry/booleanOfPaths.js +23 -0
- package/dist/core/geometry/booleanOfPaths.js.map +1 -0
- package/dist/core/geometry/pathPoseDescriptor.js +12 -9
- package/dist/core/geometry/pathPoseDescriptor.js.map +1 -1
- package/dist/core/geometry/poseDescriptor.js +12 -3
- package/dist/core/geometry/poseDescriptor.js.map +1 -1
- package/dist/core/geometry/targetFrame.js +2 -13
- package/dist/core/geometry/targetFrame.js.map +1 -1
- package/dist/core/layers/render.js +2 -1
- package/dist/core/layers/render.js.map +1 -1
- package/dist/core/layers/retain.js +5 -3
- package/dist/core/layers/retain.js.map +1 -1
- package/dist/core/ops/setPath.js +3 -0
- package/dist/core/ops/setPath.js.map +1 -1
- package/dist/core/paint/meshKindLazy.js.map +1 -1
- package/dist/core/paint/paintKindEntry.js.map +1 -1
- package/dist/core/paint/paintKinds.js +8 -1
- package/dist/core/paint/paintKinds.js.map +1 -1
- package/dist/core/scene/NodeProperties.js.map +1 -1
- package/dist/core/scene/NodeRouting.js.map +1 -1
- package/dist/core/scene/booleanGroup.js +33 -0
- package/dist/core/scene/booleanGroup.js.map +1 -0
- package/dist/core/scene/booleanOfChildren.js +53 -0
- package/dist/core/scene/booleanOfChildren.js.map +1 -0
- package/dist/core/scene/carryDescendants.js +18 -6
- package/dist/core/scene/carryDescendants.js.map +1 -1
- package/dist/core/scene/composeFrame.js +42 -5
- package/dist/core/scene/composeFrame.js.map +1 -1
- package/dist/core/scene/composePose.js +35 -16
- package/dist/core/scene/composePose.js.map +1 -1
- package/dist/core/scene/depMemo.js +36 -18
- package/dist/core/scene/depMemo.js.map +1 -1
- package/dist/core/scene/derivedParts.js +2 -23
- package/dist/core/scene/derivedParts.js.map +1 -1
- package/dist/core/scene/effectivePose.js +10 -0
- package/dist/core/scene/effectivePose.js.map +1 -1
- package/dist/core/scene/historyForm.js +5 -4
- package/dist/core/scene/historyForm.js.map +1 -1
- package/dist/core/scene/kitOps.js +5 -71
- 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/layerOps.js +82 -0
- package/dist/core/scene/layerOps.js.map +1 -0
- package/dist/core/scene/layoutPass.js +14 -12
- package/dist/core/scene/layoutPass.js.map +1 -1
- package/dist/core/scene/lockGuard.js +9 -3
- package/dist/core/scene/lockGuard.js.map +1 -1
- package/dist/core/scene/nestedHit.js +5 -5
- package/dist/core/scene/nestedHit.js.map +1 -1
- package/dist/core/scene/nodeFlags.js +8 -2
- package/dist/core/scene/nodeFlags.js.map +1 -1
- package/dist/core/scene/nodeGates.js +31 -2
- package/dist/core/scene/nodeGates.js.map +1 -1
- package/dist/core/scene/pathEffects/effects.js +22 -3
- package/dist/core/scene/pathEffects/effects.js.map +1 -1
- package/dist/core/scene/pathEffects/textAlong.js +16 -3
- package/dist/core/scene/pathEffects/textAlong.js.map +1 -1
- package/dist/core/scene/pathEffects/textAlongBands.js +65 -0
- package/dist/core/scene/pathEffects/textAlongBands.js.map +1 -0
- package/dist/core/scene/reconcileSpecs.js +1 -1
- package/dist/core/scene/reconcileSpecs.js.map +1 -1
- package/dist/core/scene/scene.js +11 -5
- package/dist/core/scene/scene.js.map +1 -1
- package/dist/core/scene/sceneEdits.js +5 -2
- package/dist/core/scene/sceneEdits.js.map +1 -1
- package/dist/core/scene/scenePoseAdapter.js +10 -1
- package/dist/core/scene/scenePoseAdapter.js.map +1 -1
- package/dist/core/scene/scrollOffsets.js +93 -0
- package/dist/core/scene/scrollOffsets.js.map +1 -0
- package/dist/core/scene/serialization.js +15 -5
- package/dist/core/scene/serialization.js.map +1 -1
- package/dist/core/scene/statedFields.js +2 -1
- package/dist/core/scene/statedFields.js.map +1 -1
- package/dist/core/scene/strategyView.js +35 -0
- package/dist/core/scene/strategyView.js.map +1 -0
- package/dist/core/scene/types.js.map +1 -1
- package/dist/core/scene/useScene.js +2 -0
- package/dist/core/scene/useScene.js.map +1 -1
- package/dist/core/scene/worldSave.js +87 -0
- package/dist/core/scene/worldSave.js.map +1 -0
- package/dist/core/selection/selectionTarget.js +1 -1
- package/dist/core/selection/selectionTarget.js.map +1 -1
- package/dist/{cornerHandles-CNCb7aTY.d.ts → cornerHandles-DpmQM_z5.d.ts} +1 -1
- package/dist/{depSchema-B1RS-IJx.d.ts → depSchema-C3BwxitB.d.ts} +130 -104
- package/dist/devtools-protocol.d.ts +2 -2
- package/dist/devtools.d.ts +2 -2
- package/dist/{features → domains}/chrome-caps/buildChromeCtx.js +1 -1
- package/dist/domains/chrome-caps/buildChromeCtx.js.map +1 -0
- package/dist/{features → domains}/chrome-caps/conditions.js +1 -1
- package/dist/domains/chrome-caps/conditions.js.map +1 -0
- package/dist/{features → domains}/chrome-caps/defaults.js +1 -1
- package/dist/domains/chrome-caps/defaults.js.map +1 -0
- package/dist/{features → domains}/chrome-caps/resolve.js +1 -1
- package/dist/domains/chrome-caps/resolve.js.map +1 -0
- package/dist/{features → domains}/chrome-caps/useChromeCaps.js +1 -1
- package/dist/domains/chrome-caps/useChromeCaps.js.map +1 -0
- package/dist/{features → domains}/chrome-caps/useHoverTracking.js +1 -1
- package/dist/domains/chrome-caps/useHoverTracking.js.map +1 -0
- package/dist/{features → domains}/ingestion/contentHandlers.js +20 -3
- package/dist/domains/ingestion/contentHandlers.js.map +1 -0
- package/dist/domains/ingestion/ghost.js +56 -0
- package/dist/domains/ingestion/ghost.js.map +1 -0
- package/dist/{features → domains}/ingestion/imageHandler.js +1 -1
- package/dist/domains/ingestion/imageHandler.js.map +1 -0
- package/dist/domains/ingestion/kitHandlers.js +22 -0
- package/dist/domains/ingestion/kitHandlers.js.map +1 -0
- package/dist/{features → domains}/ingestion/openFilePicker.js +1 -1
- package/dist/domains/ingestion/openFilePicker.js.map +1 -0
- package/dist/{features → domains}/ingestion/placement.js +1 -1
- package/dist/domains/ingestion/placement.js.map +1 -0
- package/dist/{features → domains}/ingestion/svgHandler.js +1 -1
- package/dist/domains/ingestion/svgHandler.js.map +1 -0
- package/dist/{features → domains}/ingestion/textHandler.js +9 -7
- package/dist/domains/ingestion/textHandler.js.map +1 -0
- package/dist/{features → domains}/ingestion/useCanvasIngestion.js +13 -15
- package/dist/domains/ingestion/useCanvasIngestion.js.map +1 -0
- package/dist/{features → domains}/ingestion/weaselJsonHandler.js +1 -1
- package/dist/domains/ingestion/weaselJsonHandler.js.map +1 -0
- package/dist/{features → domains}/longPress/longPressFeedback.js +1 -1
- package/dist/domains/longPress/longPressFeedback.js.map +1 -0
- package/dist/{features → domains}/measure/actionIds.js +1 -1
- package/dist/domains/measure/actionIds.js.map +1 -0
- package/dist/{features → domains}/measure/measureCommands.js +1 -1
- package/dist/domains/measure/measureCommands.js.map +1 -0
- package/dist/{features → domains}/measure/measureContribution.js +1 -1
- package/dist/domains/measure/measureContribution.js.map +1 -0
- package/dist/{features → domains}/measure/measureEdits.js +1 -1
- package/dist/domains/measure/measureEdits.js.map +1 -0
- package/dist/{features → domains}/measure/measureGestures.js +4 -7
- package/dist/domains/measure/measureGestures.js.map +1 -0
- package/dist/{features → domains}/measure/measureHit.js +1 -1
- package/dist/domains/measure/measureHit.js.map +1 -0
- package/dist/{features → domains}/measure/measureLayer.js +1 -1
- package/dist/domains/measure/measureLayer.js.map +1 -0
- package/dist/{features → domains}/measure/measurement.js +1 -1
- package/dist/domains/measure/measurement.js.map +1 -0
- package/dist/{features → domains}/measure/measurements.js +2 -2
- package/dist/domains/measure/measurements.js.map +1 -0
- package/dist/{features → domains}/modes/modeLayers.js +1 -1
- package/dist/domains/modes/modeLayers.js.map +1 -0
- package/dist/{features → domains}/modes/modeTriggers.js +3 -6
- package/dist/domains/modes/modeTriggers.js.map +1 -0
- package/dist/{features → domains}/pathEffects/effectSources.js +1 -1
- package/dist/domains/pathEffects/effectSources.js.map +1 -0
- package/dist/{features → domains}/pathEffects/index.js +1 -1
- package/dist/domains/pathEffects/index.js.map +1 -0
- package/dist/{features → domains}/pathEffects/readSource.js +1 -1
- package/dist/domains/pathEffects/readSource.js.map +1 -0
- package/dist/{features → domains}/pathEffects/textItems.js +11 -2
- package/dist/domains/pathEffects/textItems.js.map +1 -0
- package/dist/{features → domains}/pathEffects/useEffectSourcesLayer.js +1 -1
- package/dist/domains/pathEffects/useEffectSourcesLayer.js.map +1 -0
- package/dist/{features → domains}/paths/anchorData.js +1 -1
- package/dist/domains/paths/anchorData.js.map +1 -0
- package/dist/{features → domains}/paths/anchorMarkers.js +9 -7
- package/dist/domains/paths/anchorMarkers.js.map +1 -0
- package/dist/{features → domains}/paths/editablePath.js +1 -1
- package/dist/domains/paths/editablePath.js.map +1 -0
- package/dist/{features → domains}/paths/index.js +3 -3
- package/dist/{features → domains}/paths/originProjection.js +1 -1
- package/dist/domains/paths/originProjection.js.map +1 -0
- package/dist/{features → domains}/paths/pathEditExtension.js +1 -1
- package/dist/domains/paths/pathEditExtension.js.map +1 -0
- package/dist/{features → domains}/paths/pathEditState.js +1 -1
- package/dist/domains/paths/pathEditState.js.map +1 -0
- package/dist/{features → domains}/paths/pathEditingOverlayLayer.js +1 -1
- package/dist/domains/paths/pathEditingOverlayLayer.js.map +1 -0
- package/dist/{features → domains}/paths/pathLayer.js +1 -1
- package/dist/domains/paths/pathLayer.js.map +1 -0
- package/dist/{features → domains}/paths/pathRepresentation.js +1 -1
- package/dist/domains/paths/pathRepresentation.js.map +1 -0
- package/dist/{features → domains}/paths/pathSnap/glyphs.js +1 -1
- package/dist/domains/paths/pathSnap/glyphs.js.map +1 -0
- package/dist/{features → domains}/paths/pathSnap/pathSnapSource.js +1 -1
- package/dist/domains/paths/pathSnap/pathSnapSource.js.map +1 -0
- package/dist/{features → domains}/paths/pathSnap/sceneIndex.js +1 -1
- package/dist/domains/paths/pathSnap/sceneIndex.js.map +1 -0
- package/dist/{features → domains}/paths/pathSnap/snapGeometry.js +3 -2
- package/dist/domains/paths/pathSnap/snapGeometry.js.map +1 -0
- package/dist/{features → domains}/paths/penPreviewLayer.js +1 -1
- package/dist/domains/paths/penPreviewLayer.js.map +1 -0
- package/dist/{features → domains}/paths/shapeGenerator.js +6 -4
- package/dist/domains/paths/shapeGenerator.js.map +1 -0
- package/dist/{features → domains}/paths/strokeOutline.js +1 -1
- package/dist/domains/paths/strokeOutline.js.map +1 -0
- package/dist/{features → domains}/paths/useAnchorFields.js +1 -1
- package/dist/domains/paths/useAnchorFields.js.map +1 -0
- package/dist/{features → domains}/paths/usePathEdit.js +1 -1
- package/dist/domains/paths/usePathEdit.js.map +1 -0
- package/dist/{features → domains}/poseRun/usePoseRun.js +1 -1
- package/dist/domains/poseRun/usePoseRun.js.map +1 -0
- package/dist/{features → domains}/selection/enteredGroupFrame.js +49 -10
- package/dist/domains/selection/enteredGroupFrame.js.map +1 -0
- package/dist/{features → domains}/selection/enteredGroupScope.js +1 -1
- package/dist/domains/selection/enteredGroupScope.js.map +1 -0
- package/dist/domains/selection/enteredOperands.js +29 -0
- package/dist/domains/selection/enteredOperands.js.map +1 -0
- package/dist/{features → domains}/selection/handleCommands.js +1 -1
- package/dist/domains/selection/handleCommands.js.map +1 -0
- package/dist/{features → domains}/selection/overlay.js +1 -1
- package/dist/domains/selection/overlay.js.map +1 -0
- package/dist/{features → domains}/selection/selectionPose.js +1 -1
- package/dist/domains/selection/selectionPose.js.map +1 -0
- package/dist/{features → domains}/snap/angle2d.js +1 -1
- package/dist/domains/snap/angle2d.js.map +1 -0
- package/dist/{features → domains}/snap/debugCandidates.js +1 -1
- package/dist/domains/snap/debugCandidates.js.map +1 -0
- package/dist/{features → domains}/snap/gather.js +1 -1
- package/dist/domains/snap/gather.js.map +1 -0
- package/dist/{features → domains}/snap/inputSubspace.js +1 -1
- package/dist/domains/snap/inputSubspace.js.map +1 -0
- package/dist/{features → domains}/snap/lazySession.js +1 -1
- package/dist/domains/snap/lazySession.js.map +1 -0
- package/dist/{features → domains}/snap/marks.js +1 -1
- package/dist/domains/snap/marks.js.map +1 -0
- package/dist/{features → domains}/snap/outcomeStore.js +1 -1
- package/dist/domains/snap/outcomeStore.js.map +1 -0
- package/dist/{features → domains}/snap/pointSnap.js +1 -1
- package/dist/domains/snap/pointSnap.js.map +1 -0
- package/dist/{features → domains}/snap/probes2d.js +1 -1
- package/dist/domains/snap/probes2d.js.map +1 -0
- package/dist/{features → domains}/snap/readoutDraw.js +1 -1
- package/dist/domains/snap/readoutDraw.js.map +1 -0
- package/dist/{features → domains}/snap/readoutLayer.js +1 -1
- package/dist/domains/snap/readoutLayer.js.map +1 -0
- package/dist/{features → domains}/snap/registry.js +1 -1
- package/dist/domains/snap/registry.js.map +1 -0
- package/dist/{features → domains}/snap/resizeBox.js +1 -1
- package/dist/domains/snap/resizeBox.js.map +1 -0
- package/dist/{features → domains}/snap/roles.js +1 -1
- package/dist/domains/snap/roles.js.map +1 -0
- package/dist/{features → domains}/snap/rotationSource.js +1 -1
- package/dist/domains/snap/rotationSource.js.map +1 -0
- package/dist/{features → domains}/snap/sceneReads.js +24 -3
- package/dist/domains/snap/sceneReads.js.map +1 -0
- package/dist/{features → domains}/snap/sceneSession2d.js +3 -2
- package/dist/domains/snap/sceneSession2d.js.map +1 -0
- package/dist/{features → domains}/snap/screen.js +1 -1
- package/dist/domains/snap/screen.js.map +1 -0
- package/dist/{features → domains}/snap/session2d.js +3 -2
- package/dist/domains/snap/session2d.js.map +1 -0
- package/dist/{features → domains}/snap/spanSnap.js +1 -1
- package/dist/domains/snap/spanSnap.js.map +1 -0
- package/dist/{features → domains}/snap/stepAngles.js +1 -1
- package/dist/domains/snap/stepAngles.js.map +1 -0
- package/dist/{features → domains}/text/editingDrawOne.js +4 -4
- package/dist/domains/text/editingDrawOne.js.map +1 -0
- package/dist/domains/text/hostTextEditors.js +24 -0
- package/dist/domains/text/hostTextEditors.js.map +1 -0
- package/dist/{features → domains}/text/index.js +1 -1
- package/dist/{features → domains}/text/sceneTextDrafts.js +1 -1
- package/dist/domains/text/sceneTextDrafts.js.map +1 -0
- package/dist/{features → domains}/text/textHitAt.js +18 -2
- package/dist/domains/text/textHitAt.js.map +1 -0
- package/dist/{features → domains}/text/textLayer.js +1 -1
- package/dist/domains/text/textLayer.js.map +1 -0
- package/dist/{features → domains}/text/useSceneTextEdit.js +11 -3
- package/dist/domains/text/useSceneTextEdit.js.map +1 -0
- package/dist/{features → domains}/viewports/aim.js +1 -1
- package/dist/domains/viewports/aim.js.map +1 -0
- package/dist/{features → domains}/viewports/viewMarker.js +23 -5
- package/dist/domains/viewports/viewMarker.js.map +1 -0
- package/dist/{features → domains}/viewports/viewMarkerDrag.js +3 -3
- package/dist/domains/viewports/viewMarkerDrag.js.map +1 -0
- package/dist/{features → domains}/viewports/viewResolver.js +1 -1
- package/dist/domains/viewports/viewResolver.js.map +1 -0
- package/dist/{features → domains}/viewports/viewportLayer.js +3 -2
- package/dist/domains/viewports/viewportLayer.js.map +1 -0
- package/dist/icons.table.js +1 -1
- package/dist/icons.table.js.map +1 -1
- package/dist/icons.table.json +106 -6
- package/dist/index.d.ts +1445 -1053
- package/dist/index.js +90 -77
- package/dist/interactions/actions/admitsChild.js +6 -2
- package/dist/interactions/actions/admitsChild.js.map +1 -1
- package/dist/interactions/actions/align/align.js +1 -4
- package/dist/interactions/actions/align/align.js.map +1 -1
- package/dist/interactions/actions/booleans/booleanGroupAction.js +66 -0
- package/dist/interactions/actions/booleans/booleanGroupAction.js.map +1 -0
- package/dist/interactions/actions/booleans/keymap.js +52 -0
- package/dist/interactions/actions/booleans/keymap.js.map +1 -0
- package/dist/interactions/actions/booleans/operands.js +1 -1
- package/dist/interactions/actions/booleans/pieces.js +4 -11
- package/dist/interactions/actions/booleans/pieces.js.map +1 -1
- package/dist/interactions/actions/clipboard/action.js +3 -7
- package/dist/interactions/actions/clipboard/action.js.map +1 -1
- package/dist/interactions/actions/clipboard/clipboardOps.js +1 -1
- package/dist/interactions/actions/clipboard/clipboardOps.js.map +1 -1
- package/dist/interactions/actions/clipboard/materializePaste.js.map +1 -1
- package/dist/interactions/actions/defaults/anchorEditing.js +6 -6
- package/dist/interactions/actions/defaults/anchorEditing.js.map +1 -1
- package/dist/interactions/actions/defaults/bendSegment.js +1 -1
- package/dist/interactions/actions/defaults/bendSegment.js.map +1 -1
- package/dist/interactions/actions/defaults/containerScroll.js +170 -0
- package/dist/interactions/actions/defaults/containerScroll.js.map +1 -0
- package/dist/interactions/actions/defaults/contextMenu.js +2 -5
- package/dist/interactions/actions/defaults/contextMenu.js.map +1 -1
- package/dist/interactions/actions/defaults/delete.js +1 -1
- package/dist/interactions/actions/defaults/delete.js.map +1 -1
- package/dist/interactions/actions/defaults/duplicate.js +1 -3
- package/dist/interactions/actions/defaults/duplicate.js.map +1 -1
- package/dist/interactions/actions/defaults/enterGroup.js +7 -12
- package/dist/interactions/actions/defaults/enterGroup.js.map +1 -1
- package/dist/interactions/actions/defaults/enterPathEdit.js +4 -8
- package/dist/interactions/actions/defaults/enterPathEdit.js.map +1 -1
- package/dist/interactions/actions/defaults/group.js +12 -24
- package/dist/interactions/actions/defaults/group.js.map +1 -1
- package/dist/interactions/actions/defaults/ingest.js +18 -10
- package/dist/interactions/actions/defaults/ingest.js.map +1 -1
- package/dist/interactions/actions/defaults/insertPathAnchor.js +3 -3
- package/dist/interactions/actions/defaults/insertPathAnchor.js.map +1 -1
- package/dist/interactions/actions/defaults/nudgeSteps.js +3 -21
- package/dist/interactions/actions/defaults/nudgeSteps.js.map +1 -1
- package/dist/interactions/actions/defaults/pathEditMarks.js.map +1 -1
- package/dist/interactions/actions/defaults/selectDeep.js +2 -2
- package/dist/interactions/actions/defaults/selectDeep.js.map +1 -1
- package/dist/interactions/actions/distribute/distribute.js.map +1 -1
- package/dist/interactions/actions/dropVerdict.js +9 -0
- package/dist/interactions/actions/dropVerdict.js.map +1 -0
- package/dist/interactions/actions/edit-anchors/action.js +2 -2
- package/dist/interactions/actions/edit-anchors/action.js.map +1 -1
- package/dist/interactions/actions/edit-anchors/extensionDrags.js.map +1 -1
- package/dist/interactions/actions/edit-anchors/geometry.js +8 -6
- package/dist/interactions/actions/edit-anchors/geometry.js.map +1 -1
- package/dist/interactions/actions/edit-anchors/handleDrag.js.map +1 -1
- package/dist/interactions/actions/edit-anchors/preview.js +1 -1
- package/dist/interactions/actions/edit-anchors/preview.js.map +1 -1
- package/dist/interactions/actions/flip/action.js +3 -2
- package/dist/interactions/actions/flip/action.js.map +1 -1
- package/dist/interactions/actions/geometryProjection.js +8 -3
- package/dist/interactions/actions/geometryProjection.js.map +1 -1
- package/dist/interactions/actions/gestureFrames.js +1 -0
- package/dist/interactions/actions/gestureFrames.js.map +1 -1
- package/dist/interactions/actions/insert/action.js +6 -2
- package/dist/interactions/actions/insert/action.js.map +1 -1
- package/dist/interactions/actions/insert/frame.js +1 -1
- package/dist/interactions/actions/insert/frame.js.map +1 -1
- package/dist/interactions/actions/insert/placeAction.js +6 -8
- package/dist/interactions/actions/insert/placeAction.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 +6 -15
- package/dist/interactions/actions/move/action.js.map +1 -1
- package/dist/interactions/actions/move/behaviors/layoutDrop.js +12 -2
- package/dist/interactions/actions/move/behaviors/layoutDrop.js.map +1 -1
- package/dist/interactions/actions/move/behaviors/reparentOnDrop.js +29 -10
- package/dist/interactions/actions/move/behaviors/reparentOnDrop.js.map +1 -1
- package/dist/interactions/actions/move/behaviors/snapToContainer.js +42 -6
- package/dist/interactions/actions/move/behaviors/snapToContainer.js.map +1 -1
- package/dist/interactions/actions/move/capture.js +4 -8
- package/dist/interactions/actions/move/capture.js.map +1 -1
- package/dist/interactions/actions/move/commit/index.js.map +1 -1
- package/dist/interactions/actions/move/commit/layoutDrop.js +4 -3
- package/dist/interactions/actions/move/commit/layoutDrop.js.map +1 -1
- package/dist/interactions/actions/move/commit/layoutRelease.js +15 -9
- package/dist/interactions/actions/move/commit/layoutRelease.js.map +1 -1
- package/dist/interactions/actions/move/commit/reparent.js +19 -13
- package/dist/interactions/actions/move/commit/reparent.js.map +1 -1
- package/dist/interactions/actions/move/delta.js +51 -5
- package/dist/interactions/actions/move/delta.js.map +1 -1
- package/dist/interactions/actions/move/frame.js +8 -4
- package/dist/interactions/actions/move/frame.js.map +1 -1
- package/dist/interactions/actions/move/layout/container.js +19 -9
- package/dist/interactions/actions/move/layout/container.js.map +1 -1
- package/dist/interactions/actions/move/layout/dragged.js +2 -2
- package/dist/interactions/actions/move/layout/dragged.js.map +1 -1
- package/dist/interactions/actions/move/layout/dropPass.js +36 -18
- package/dist/interactions/actions/move/layout/dropPass.js.map +1 -1
- package/dist/interactions/actions/move/layout/exits.js +2 -2
- package/dist/interactions/actions/move/layout/exits.js.map +1 -1
- package/dist/interactions/actions/move/layout/glide.js +5 -5
- package/dist/interactions/actions/move/layout/glide.js.map +1 -1
- package/dist/interactions/actions/move/layout/view.js +55 -0
- package/dist/interactions/actions/move/layout/view.js.map +1 -0
- package/dist/interactions/actions/move/refusal.js +52 -0
- package/dist/interactions/actions/move/refusal.js.map +1 -0
- package/dist/interactions/actions/move/session.js +9 -8
- package/dist/interactions/actions/move/session.js.map +1 -1
- package/dist/interactions/actions/move/translate.js +10 -4
- package/dist/interactions/actions/move/translate.js.map +1 -1
- package/dist/interactions/actions/moveNodes.js +21 -5
- package/dist/interactions/actions/moveNodes.js.map +1 -1
- package/dist/interactions/actions/pathCommands/pathNodes.js +3 -3
- package/dist/interactions/actions/pathCommands/pathNodes.js.map +1 -1
- package/dist/interactions/actions/planeInput.js +14 -13
- package/dist/interactions/actions/planeInput.js.map +1 -1
- package/dist/interactions/actions/poseFrame.js +21 -8
- package/dist/interactions/actions/poseFrame.js.map +1 -1
- package/dist/interactions/actions/resize/action.js +1 -1
- package/dist/interactions/actions/resize/action.js.map +1 -1
- package/dist/interactions/actions/resize/aspect.js +1 -1
- package/dist/interactions/actions/resize/aspect.js.map +1 -1
- package/dist/interactions/actions/resize/commit.js +10 -1
- package/dist/interactions/actions/resize/commit.js.map +1 -1
- package/dist/interactions/actions/resize/frame.js +3 -2
- package/dist/interactions/actions/resize/frame.js.map +1 -1
- package/dist/interactions/actions/resize/held.js +44 -0
- package/dist/interactions/actions/resize/held.js.map +1 -0
- package/dist/interactions/actions/resize/session.js +3 -1
- package/dist/interactions/actions/resize/session.js.map +1 -1
- package/dist/interactions/actions/resolveOverlays.js +9 -0
- package/dist/interactions/actions/resolveOverlays.js.map +1 -1
- package/dist/interactions/actions/resolvePreviews.js +23 -7
- package/dist/interactions/actions/resolvePreviews.js.map +1 -1
- package/dist/interactions/actions/rotate/action.js +1 -1
- package/dist/interactions/actions/rotate/action.js.map +1 -1
- package/dist/interactions/actions/rotate/frame.js +1 -1
- package/dist/interactions/actions/rotate/frame.js.map +1 -1
- package/dist/interactions/actions/rotate/session.js +2 -2
- package/dist/interactions/actions/rotate/session.js.map +1 -1
- package/dist/interactions/actions/selectionSubtree.js +2 -4
- package/dist/interactions/actions/selectionSubtree.js.map +1 -1
- package/dist/interactions/actions/spatialReference.js +4 -9
- package/dist/interactions/actions/spatialReference.js.map +1 -1
- package/dist/interactions/gestures/dragRadial/dragRadial.js.map +1 -1
- package/dist/interactions/gestures/dragRect/dragRect.js.map +1 -1
- package/dist/kitSettingsSchema.js +2 -2
- package/dist/kitSettingsSchema.js.map +1 -1
- package/dist/{math-C_elShP_.d.ts → math-B_unOnF4.d.ts} +2 -2
- package/dist/math.d.ts +3 -3
- package/dist/move.d.ts +6 -6
- package/dist/{options-ClEm3SEl.d.ts → options-DAjkhbcs.d.ts} +5 -5
- package/dist/{poseDescriptor-DN2yfnq_.d.ts → poseDescriptor-CvSxVhCd.d.ts} +17 -4
- package/dist/resize.d.ts +6 -6
- package/dist/style.css +14 -0
- package/dist/test-seams.d.ts +11 -15
- package/dist/test-seams.js +1 -1
- package/dist/tools/builtin/eyedropper/useEyedropperTool.js +3 -6
- package/dist/tools/builtin/eyedropper/useEyedropperTool.js.map +1 -1
- package/dist/tools/builtin/line/useLineTool.js.map +1 -1
- package/dist/tools/builtin/measure/useMeasureTool.js +2 -2
- package/dist/tools/builtin/measure/useMeasureTool.js.map +1 -1
- package/dist/tools/builtin/pen/penHandle.js +2 -2
- package/dist/tools/builtin/pen/penHandle.js.map +1 -1
- package/dist/tools/builtin/pen/usePenTool.js +13 -19
- package/dist/tools/builtin/pen/usePenTool.js.map +1 -1
- package/dist/tools/builtin/polygon/usePolygonTool.js +1 -1
- package/dist/tools/builtin/polygon/usePolygonTool.js.map +1 -1
- package/dist/tools/builtin/select/groupEntry.js +1 -1
- package/dist/tools/builtin/select/groupEntry.js.map +1 -1
- package/dist/tools/builtin/select/selectionContributions.js +1 -1
- package/dist/tools/builtin/select/selectionContributions.js.map +1 -1
- package/dist/tools/builtin/select/useSelectTool.js +7 -7
- package/dist/tools/builtin/select/useSelectTool.js.map +1 -1
- package/dist/tools/builtin/slice/useSliceTool.js +5 -8
- package/dist/tools/builtin/slice/useSliceTool.js.map +1 -1
- package/dist/tools/builtin/star/useStarTool.js +1 -1
- package/dist/tools/builtin/star/useStarTool.js.map +1 -1
- package/dist/tools/index.js +2 -1
- package/dist/{types-49uYJN3j.d.ts → types-A_sNJYRd.d.ts} +8 -0
- package/dist/{types-BEdRIhNc.d.ts → types-DW14eu9B.d.ts} +131 -36
- package/dist/{types-p2alu-R1.d.ts → types-VCtfchp-.d.ts} +4 -6
- package/dist/util/color.js +12 -14
- package/dist/util/color.js.map +1 -1
- package/dist/version.js +1 -1
- package/package.json +25 -24
- package/dist/canvas/poseCascade.js +0 -65
- package/dist/canvas/poseCascade.js.map +0 -1
- package/dist/features/chrome-caps/buildChromeCtx.js.map +0 -1
- package/dist/features/chrome-caps/conditions.js.map +0 -1
- package/dist/features/chrome-caps/defaults.js.map +0 -1
- package/dist/features/chrome-caps/resolve.js.map +0 -1
- package/dist/features/chrome-caps/useChromeCaps.js.map +0 -1
- package/dist/features/chrome-caps/useHoverTracking.js.map +0 -1
- package/dist/features/ingestion/contentHandlers.js.map +0 -1
- package/dist/features/ingestion/imageHandler.js.map +0 -1
- package/dist/features/ingestion/openFilePicker.js.map +0 -1
- package/dist/features/ingestion/placement.js.map +0 -1
- package/dist/features/ingestion/registerKitHandlers.js +0 -43
- package/dist/features/ingestion/registerKitHandlers.js.map +0 -1
- package/dist/features/ingestion/svgHandler.js.map +0 -1
- package/dist/features/ingestion/textHandler.js.map +0 -1
- package/dist/features/ingestion/useCanvasIngestion.js.map +0 -1
- package/dist/features/ingestion/weaselJsonHandler.js.map +0 -1
- package/dist/features/longPress/longPressFeedback.js.map +0 -1
- package/dist/features/measure/actionIds.js.map +0 -1
- package/dist/features/measure/measureCommands.js.map +0 -1
- package/dist/features/measure/measureContribution.js.map +0 -1
- package/dist/features/measure/measureEdits.js.map +0 -1
- package/dist/features/measure/measureGestures.js.map +0 -1
- package/dist/features/measure/measureHit.js.map +0 -1
- package/dist/features/measure/measureLayer.js.map +0 -1
- package/dist/features/measure/measurement.js.map +0 -1
- package/dist/features/measure/measurements.js.map +0 -1
- package/dist/features/modes/modeLayers.js.map +0 -1
- package/dist/features/modes/modeTriggers.js.map +0 -1
- package/dist/features/pathEffects/effectSources.js.map +0 -1
- package/dist/features/pathEffects/index.js.map +0 -1
- package/dist/features/pathEffects/readSource.js.map +0 -1
- package/dist/features/pathEffects/textItems.js.map +0 -1
- package/dist/features/pathEffects/useEffectSourcesLayer.js.map +0 -1
- package/dist/features/paths/anchorData.js.map +0 -1
- package/dist/features/paths/anchorMarkers.js.map +0 -1
- package/dist/features/paths/editablePath.js.map +0 -1
- package/dist/features/paths/originProjection.js.map +0 -1
- package/dist/features/paths/pathEditExtension.js.map +0 -1
- package/dist/features/paths/pathEditState.js.map +0 -1
- package/dist/features/paths/pathEditingOverlayLayer.js.map +0 -1
- package/dist/features/paths/pathLayer.js.map +0 -1
- package/dist/features/paths/pathRepresentation.js.map +0 -1
- package/dist/features/paths/pathSnap/glyphs.js.map +0 -1
- package/dist/features/paths/pathSnap/pathSnapSource.js.map +0 -1
- package/dist/features/paths/pathSnap/sceneIndex.js.map +0 -1
- package/dist/features/paths/pathSnap/snapGeometry.js.map +0 -1
- package/dist/features/paths/penPreviewLayer.js.map +0 -1
- package/dist/features/paths/shapeGenerator.js.map +0 -1
- package/dist/features/paths/strokeOutline.js.map +0 -1
- package/dist/features/paths/useAnchorFields.js.map +0 -1
- package/dist/features/paths/usePathEdit.js.map +0 -1
- package/dist/features/poseRun/usePoseRun.js.map +0 -1
- package/dist/features/selection/enteredGroupFrame.js.map +0 -1
- package/dist/features/selection/enteredGroupScope.js.map +0 -1
- package/dist/features/selection/handleCommands.js.map +0 -1
- package/dist/features/selection/overlay.js.map +0 -1
- package/dist/features/selection/selectionPose.js.map +0 -1
- package/dist/features/snap/angle2d.js.map +0 -1
- package/dist/features/snap/debugCandidates.js.map +0 -1
- package/dist/features/snap/gather.js.map +0 -1
- package/dist/features/snap/inputSubspace.js.map +0 -1
- package/dist/features/snap/lazySession.js.map +0 -1
- package/dist/features/snap/marks.js.map +0 -1
- package/dist/features/snap/outcomeStore.js.map +0 -1
- package/dist/features/snap/pointSnap.js.map +0 -1
- package/dist/features/snap/probes2d.js.map +0 -1
- package/dist/features/snap/readoutDraw.js.map +0 -1
- package/dist/features/snap/readoutLayer.js.map +0 -1
- package/dist/features/snap/registry.js.map +0 -1
- package/dist/features/snap/resizeBox.js.map +0 -1
- package/dist/features/snap/roles.js.map +0 -1
- package/dist/features/snap/rotationSource.js.map +0 -1
- package/dist/features/snap/sceneReads.js.map +0 -1
- package/dist/features/snap/sceneSession2d.js.map +0 -1
- package/dist/features/snap/screen.js.map +0 -1
- package/dist/features/snap/session2d.js.map +0 -1
- package/dist/features/snap/spanSnap.js.map +0 -1
- package/dist/features/snap/stepAngles.js.map +0 -1
- package/dist/features/text/editingDrawOne.js.map +0 -1
- package/dist/features/text/sceneTextDrafts.js.map +0 -1
- package/dist/features/text/textHitAt.js.map +0 -1
- package/dist/features/text/textLayer.js.map +0 -1
- package/dist/features/text/useSceneTextEdit.js.map +0 -1
- package/dist/features/viewports/aim.js.map +0 -1
- package/dist/features/viewports/viewMarker.js.map +0 -1
- package/dist/features/viewports/viewMarkerDrag.js.map +0 -1
- package/dist/features/viewports/viewResolver.js.map +0 -1
- package/dist/features/viewports/viewportLayer.js.map +0 -1
- /package/dist/{features → domains}/chrome-caps/index.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"composePose.js","names":[],"sources":["../../../src/core/scene/composePose.ts"],"sourcesContent":["/**\n * Pose composition for hierarchical scene graphs.\n *\n * `getPose(id)` on adapters returns the **local** pose — relative to the\n * object's direct parent. Anything in the kit that needs world coordinates\n * routes through `composeWorldPose`, which folds local poses together via a\n * consumer-supplied `compose`.\n */\n\nimport { applyToPoint, multiply, poseFrameInverseOf, poseFrameOf, poseLinearOf, rotate, type Affine } from '@weasel-js/geom';\nimport type { RectPose } from 'core/scene/types';\nexport type { RectPose };\n\nimport {\n IDENTITY_POSE_COMPOSITION,\n composesFrames,\n composeWorldPose,\n frameAtOrAbove,\n rebaseLocalPose,\n type PoseAdapter,\n type PoseClosure,\n type PoseComposition,\n} from 'core/scene/composeFrame';\nexport { IDENTITY_POSE_COMPOSITION, composesFrames, composeWorldPose, frameAtOrAbove, rebaseLocalPose };\nexport type { PoseAdapter, PoseClosure, PoseComposition };\n\n/**\n * `compose` for axis-aligned rectangles under a translation-only hierarchy.\n * Adds translation; every other field is taken from the child unchanged.\n */\nexport function composeRectPose<TPose extends RectPose>(parent: TPose, child: TPose): TPose {\n return {\n ...child,\n x: parent.x + child.x,\n y: parent.y + child.y,\n };\n}\n\n/** Translate a `RectPose`-shaped pose by `(dx, dy)`; other fields are preserved. */\nexport function translateRectPose<TPose extends RectPose>(pose: TPose, dx: number, dy: number): TPose {\n return { ...pose, x: pose.x + dx, y: pose.y + dy };\n}\n\n/** Inverse of `composeRectPose` — subtracts parent translation. */\nexport function decomposeRectPose<TPose extends RectPose>(parent: TPose, world: TPose): TPose {\n return {\n ...world,\n x: world.x - parent.x,\n y: world.y - parent.y,\n };\n}\n\n/** `pose` with the linear part `linear` held as `rotation` and whatever is\n * left over as `transform`, which is dropped when nothing is. */\nfunction withLinear<TPose extends RectPose>(pose: TPose, rotation: number, linear: Affine): TPose {\n const [a, b, c, d] = multiply(rotate(-rotation), linear);\n const plain = Math.abs(a - 1) < 1e-12 && Math.abs(b) < 1e-12 && Math.abs(c) < 1e-12 && Math.abs(d - 1) < 1e-12;\n const next: RectPose = { ...pose, rotation };\n if (plain) delete next.transform;\n else next.transform = [a, b, c, d];\n return next as TPose;\n}\n\n/** `pose` moved so its box center is at `(cx, cy)`. */\nfunction centeredAt<TPose extends RectPose>(pose: TPose, cx: number, cy: number): TPose {\n return { ...pose, x: cx - pose.width / 2, y: cy - pose.height / 2 };\n}\n\nconst NO_FRAME: Affine = [1, 0, 0, 1, 0, 0];\n\n/** Turn `(x, y)` about `(cx, cy)` by `r` radians. */\nfunction turn(cx: number, cy: number, r: number, x: number, y: number): [number, number] {\n const c = Math.cos(r);\n const s = Math.sin(r);\n return [cx + (x - cx) * c - (y - cy) * s, cy + (x - cx) * s + (y - cy) * c];\n}\n\n/**\n * `compose` for a container whose pose defines a **frame**: the child's local\n * pose is offset into the parent's unrotated box, then the whole thing is\n * turned about the parent's center. Rotations add; the child keeps its size.\n *\n * Reduces to `composeRectPose` when the parent is upright. A parent's\n * `transform` composes too, and what the child's box and rotation cannot hold\n * of the result lands in the child's own `transform`.\n */\nexport function composeRigidPose<TPose extends RectPose>(parent: TPose, child: TPose): TPose {\n const pr = parent.rotation ?? 0;\n const frame = poseLinearOf(parent) && poseFrameOf(parent);\n if (frame) {\n const [cx, cy] = applyToPoint(frame, parent.x + child.x + child.width / 2, parent.y + child.y + child.height / 2);\n const linear = multiply(frame, poseFrameOf(child) ?? NO_FRAME);\n return withLinear(centeredAt(child, cx, cy), (child.rotation ?? 0) + pr, linear);\n }\n const [wcx, wcy] = turn(\n parent.x + parent.width / 2,\n parent.y + parent.height / 2,\n pr,\n parent.x + child.x + child.width / 2,\n parent.y + child.y + child.height / 2,\n );\n return {\n ...child,\n x: wcx - child.width / 2,\n y: wcy - child.height / 2,\n rotation: (child.rotation ?? 0) + pr,\n };\n}\n\n/** Inverse of `composeRigidPose` — un-turns about the parent's center, then\n * subtracts the parent's offset. */\nexport function decomposeRigidPose<TPose extends RectPose>(parent: TPose, world: TPose): TPose {\n const pr = parent.rotation ?? 0;\n // A singular transform has no inverse: the container draws nothing, and the turn alone is undone.\n const back = poseLinearOf(parent) && poseFrameInverseOf(parent);\n if (back) {\n const [ux, uy] = applyToPoint(back, world.x + world.width / 2, world.y + world.height / 2);\n const linear = multiply(back, poseFrameOf(world) ?? NO_FRAME);\n return withLinear(centeredAt(world, ux - parent.x, uy - parent.y), (world.rotation ?? 0) - pr, linear);\n }\n const [ux, uy] = turn(\n parent.x + parent.width / 2,\n parent.y + parent.height / 2,\n -pr,\n world.x + world.width / 2,\n world.y + world.height / 2,\n );\n return {\n ...world,\n x: ux - parent.x - world.width / 2,\n y: uy - parent.y - world.height / 2,\n rotation: (world.rotation ?? 0) - pr,\n };\n}\n\n/** Translation-only composition over `RectPose`. What a scene wants when a\n * container groups its children but never turns them. */\nexport const RECT_POSE_COMPOSITION: PoseComposition<RectPose> = {\n compose: composeRectPose,\n decompose: decomposeRectPose,\n closure: 'translation',\n};\n\n/** Composition over `RectPose` where a container's pose is a frame: rotating\n * the container rotates its contents. */\nexport const RIGID_POSE_COMPOSITION: PoseComposition<RectPose> = {\n compose: composeRigidPose,\n decompose: decomposeRigidPose,\n closure: 'rigid',\n};\n\n/**\n * Build a `(id) => world pose | null` callback over a `PoseAdapter`, for\n * RenderLayers that take a `getPose` callback.\n *\n * Returns `null` when `adapter.getPose` or `adapter.getParent` throws — the\n * common case is an id removed mid-render between selection state and the\n * next paint. Layers should treat `null` as \"skip this id.\"\n */\nexport function worldPoseLookup<TPose>(\n adapter: PoseAdapter<TPose>,\n compose: (parent: TPose, child: TPose) => TPose,\n): (id: string) => TPose | null {\n return (id: string) => {\n try {\n return composeWorldPose(adapter, id, compose);\n } catch {\n return null;\n }\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"composePose.js","names":[],"sources":["../../../src/core/scene/composePose.ts"],"sourcesContent":["/**\n * Pose composition for hierarchical scene graphs.\n *\n * `getPose(id)` on adapters returns the **local** pose — relative to the\n * object's direct parent. Anything in the kit that needs world coordinates\n * routes through `composeWorldPose`, which folds local poses together via a\n * consumer-supplied `compose`.\n */\n\nimport { applyToPoint, multiply, poseFrameInverseOf, poseFrameOf, poseLinearOf, rotate, type Affine } from '@weasel-js/geom';\nimport type { RectPose } from 'core/scene/types';\nexport type { RectPose };\n\nimport {\n IDENTITY_POSE_COMPOSITION,\n composesFrames,\n composeWorldPose,\n frameAtOrAbove,\n rebaseLocalPose,\n composeChildFrame,\n childFrameAt,\n type PoseAdapter,\n type PoseClosure,\n type PoseComposition,\n type ScrollOffset,\n} from 'core/scene/composeFrame';\nexport { IDENTITY_POSE_COMPOSITION, childFrameAt, composeChildFrame, composesFrames, composeWorldPose, frameAtOrAbove, rebaseLocalPose };\nexport type { PoseAdapter, PoseClosure, PoseComposition, ScrollOffset };\n\n/**\n * `compose` for axis-aligned rectangles under a translation-only hierarchy.\n * Adds translation; every other field is taken from the child unchanged.\n */\nexport function composeRectPose<TPose extends RectPose>(parent: TPose, child: TPose): TPose {\n return {\n ...child,\n x: parent.x + child.x,\n y: parent.y + child.y,\n };\n}\n\n/** Translate a `RectPose`-shaped pose by `(dx, dy)`; other fields are preserved. */\nexport function translateRectPose<TPose extends RectPose>(pose: TPose, dx: number, dy: number): TPose {\n return { ...pose, x: pose.x + dx, y: pose.y + dy };\n}\n\n/** Inverse of `composeRectPose` — subtracts parent translation. */\nexport function decomposeRectPose<TPose extends RectPose>(parent: TPose, world: TPose): TPose {\n return {\n ...world,\n x: world.x - parent.x,\n y: world.y - parent.y,\n };\n}\n\n/** `pose` turned to `rotation`, which a pose that named none keeps unnamed\n * while it is zero. */\nfunction withRotation<TPose extends RectPose>(pose: TPose, rotation: number): TPose {\n if (rotation === 0 && pose.rotation === undefined) return pose;\n return { ...pose, rotation };\n}\n\n/** `pose` with the linear part `linear` held as `rotation` and whatever is\n * left over as `transform`, which is dropped when nothing is. */\nfunction withLinear<TPose extends RectPose>(pose: TPose, rotation: number, linear: Affine): TPose {\n const [a, b, c, d] = multiply(rotate(-rotation), linear);\n const plain = Math.abs(a - 1) < 1e-12 && Math.abs(b) < 1e-12 && Math.abs(c) < 1e-12 && Math.abs(d - 1) < 1e-12;\n const next: RectPose = withRotation({ ...pose }, rotation);\n if (plain) delete next.transform;\n else next.transform = [a, b, c, d];\n return next as TPose;\n}\n\n/** `pose` moved so its box center is at `(cx, cy)`. */\nfunction centeredAt<TPose extends RectPose>(pose: TPose, cx: number, cy: number): TPose {\n return { ...pose, x: cx - pose.width / 2, y: cy - pose.height / 2 };\n}\n\nconst NO_FRAME: Affine = [1, 0, 0, 1, 0, 0];\n\n/** Turn `(x, y)` about `(cx, cy)` by `r` radians. */\nfunction turn(cx: number, cy: number, r: number, x: number, y: number): [number, number] {\n const c = Math.cos(r);\n const s = Math.sin(r);\n return [cx + (x - cx) * c - (y - cy) * s, cy + (x - cx) * s + (y - cy) * c];\n}\n\n/**\n * `compose` for a container whose pose defines a **frame**: the child's local\n * pose is offset into the parent's unrotated box, then the whole thing is\n * turned about the parent's center. Rotations add; the child keeps its size.\n *\n * Reduces to `composeRectPose` when the parent is upright. A parent's\n * `transform` composes too, and what the child's box and rotation cannot hold\n * of the result lands in the child's own `transform`.\n */\nexport function composeRigidPose<TPose extends RectPose>(parent: TPose, child: TPose): TPose {\n const pr = parent.rotation ?? 0;\n const frame = poseLinearOf(parent) && poseFrameOf(parent);\n if (frame) {\n const [cx, cy] = applyToPoint(frame, parent.x + child.x + child.width / 2, parent.y + child.y + child.height / 2);\n const linear = multiply(frame, poseFrameOf(child) ?? NO_FRAME);\n return withLinear(centeredAt(child, cx, cy), (child.rotation ?? 0) + pr, linear);\n }\n const [wcx, wcy] = turn(\n parent.x + parent.width / 2,\n parent.y + parent.height / 2,\n pr,\n parent.x + child.x + child.width / 2,\n parent.y + child.y + child.height / 2,\n );\n return withRotation({ ...child, x: wcx - child.width / 2, y: wcy - child.height / 2 }, (child.rotation ?? 0) + pr);\n}\n\n/** Inverse of `composeRigidPose` — un-turns about the parent's center, then\n * subtracts the parent's offset. */\nexport function decomposeRigidPose<TPose extends RectPose>(parent: TPose, world: TPose): TPose {\n const pr = parent.rotation ?? 0;\n // A singular transform has no inverse: the container draws nothing, and the turn alone is undone.\n const back = poseLinearOf(parent) && poseFrameInverseOf(parent);\n if (back) {\n const [ux, uy] = applyToPoint(back, world.x + world.width / 2, world.y + world.height / 2);\n const linear = multiply(back, poseFrameOf(world) ?? NO_FRAME);\n return withLinear(centeredAt(world, ux - parent.x, uy - parent.y), (world.rotation ?? 0) - pr, linear);\n }\n const [ux, uy] = turn(\n parent.x + parent.width / 2,\n parent.y + parent.height / 2,\n -pr,\n world.x + world.width / 2,\n world.y + world.height / 2,\n );\n return withRotation({ ...world, x: ux - parent.x - world.width / 2, y: uy - parent.y - world.height / 2 }, (world.rotation ?? 0) - pr);\n}\n\n/** `scroll` for `composeRectPose`: the frame moved by minus `offset`. */\nexport function scrollRectPose<TPose extends RectPose>(frame: TPose, offset: ScrollOffset): TPose {\n return translateRectPose(frame, -offset.x, -offset.y);\n}\n\n/** `scroll` for `composeRigidPose`: the frame moved by minus `offset` taken\n * through its own rotation and `transform`, so content scrolls along the\n * container's axes however it is turned. */\nexport function scrollRigidPose<TPose extends RectPose>(frame: TPose, offset: ScrollOffset): TPose {\n const m = poseFrameOf(frame);\n if (!m) return scrollRectPose(frame, offset);\n const [a, b, c, d] = m;\n return translateRectPose(frame, -(a * offset.x + c * offset.y), -(b * offset.x + d * offset.y));\n}\n\n/** Translation-only composition over `RectPose`. What a scene wants when a\n * container groups its children but never turns them. */\nexport const RECT_POSE_COMPOSITION: PoseComposition<RectPose> = {\n compose: composeRectPose,\n decompose: decomposeRectPose,\n closure: 'translation',\n scroll: scrollRectPose,\n};\n\n/** Composition over `RectPose` where a container's pose is a frame: rotating\n * the container rotates its contents. */\nexport const RIGID_POSE_COMPOSITION: PoseComposition<RectPose> = {\n compose: composeRigidPose,\n decompose: decomposeRigidPose,\n closure: 'rigid',\n scroll: scrollRigidPose,\n};\n\n/**\n * Build a `(id) => world pose | null` callback over a `PoseAdapter`, for\n * RenderLayers that take a `getPose` callback.\n *\n * Returns `null` when `adapter.getPose` or `adapter.getParent` throws — the\n * common case is an id removed mid-render between selection state and the\n * next paint. Layers should treat `null` as \"skip this id.\"\n */\nexport function worldPoseLookup<TPose>(\n adapter: PoseAdapter<TPose>,\n compose: (parent: TPose, child: TPose) => TPose,\n): (id: string) => TPose | null {\n return (id: string) => {\n try {\n return composeWorldPose(adapter, id, compose);\n } catch {\n return null;\n }\n };\n}\n"],"mappings":"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"}
|
|
@@ -9,6 +9,7 @@ function emptyDepRecord() {
|
|
|
9
9
|
data: [],
|
|
10
10
|
layers: [],
|
|
11
11
|
paths: [],
|
|
12
|
+
children: [],
|
|
12
13
|
faces: null
|
|
13
14
|
};
|
|
14
15
|
}
|
|
@@ -16,40 +17,51 @@ function emptyDepRecord() {
|
|
|
16
17
|
* class for the reason `SceneDep` is one: a prototype accessor is cheap. */
|
|
17
18
|
var RecordedDep = class {
|
|
18
19
|
dep;
|
|
19
|
-
|
|
20
|
+
record;
|
|
20
21
|
index;
|
|
21
22
|
node;
|
|
22
23
|
pose;
|
|
23
|
-
constructor(dep,
|
|
24
|
+
constructor(dep, record, index) {
|
|
24
25
|
this.dep = dep;
|
|
25
|
-
this.
|
|
26
|
+
this.record = record;
|
|
26
27
|
this.index = index;
|
|
27
28
|
this.node = dep.node;
|
|
28
29
|
this.pose = dep.pose;
|
|
29
30
|
}
|
|
30
31
|
get path() {
|
|
31
|
-
return this.paths[this.index] = this.dep.path;
|
|
32
|
+
return this.record.paths[this.index] = this.dep.path;
|
|
32
33
|
}
|
|
33
34
|
get inherited() {
|
|
34
35
|
return this.dep.inherited;
|
|
35
36
|
}
|
|
37
|
+
get children() {
|
|
38
|
+
const kids = this.dep.children;
|
|
39
|
+
if (kids === void 0) return void 0;
|
|
40
|
+
return recordDeps(this.record.children[this.index] = emptyDepRecord(), kids);
|
|
41
|
+
}
|
|
36
42
|
};
|
|
37
|
-
/**
|
|
38
|
-
|
|
39
|
-
function deriveRecorded(into, deps, derive) {
|
|
43
|
+
/** `deps` wrapped to note what is read of them in `into`, which is cleared first. */
|
|
44
|
+
function recordDeps(into, deps) {
|
|
40
45
|
into.nodes.length = 0;
|
|
41
46
|
into.poses.length = 0;
|
|
42
47
|
into.data.length = 0;
|
|
43
48
|
into.layers.length = 0;
|
|
44
49
|
into.paths.length = 0;
|
|
45
|
-
|
|
50
|
+
into.children.length = 0;
|
|
51
|
+
return deps.map((dep, i) => {
|
|
46
52
|
into.nodes.push(dep?.node);
|
|
47
53
|
into.poses.push(dep === void 0 ? void 0 : snapshotPose(dep.pose));
|
|
48
54
|
into.data.push(dep?.node.data);
|
|
49
55
|
into.layers.push(dep?.node.layer);
|
|
50
56
|
into.paths.push(void 0);
|
|
51
|
-
|
|
57
|
+
into.children.push(void 0);
|
|
58
|
+
return dep === void 0 ? void 0 : new RecordedDep(dep, into, i);
|
|
52
59
|
});
|
|
60
|
+
}
|
|
61
|
+
/** Run `derive` against `deps`, recording in place what it was run against.
|
|
62
|
+
* Mutating the record is what updates the memo slot, which holds this object. */
|
|
63
|
+
function deriveRecorded(into, deps, derive) {
|
|
64
|
+
const handed = recordDeps(into, deps);
|
|
53
65
|
const generation = fontGeneration();
|
|
54
66
|
const { value, fonts } = withFontReads(() => derive(handed));
|
|
55
67
|
into.faces = fonts ? generation : null;
|
|
@@ -61,18 +73,24 @@ function deriveRecorded(into, deps, derive) {
|
|
|
61
73
|
function sameDeps(record, ids, depOf) {
|
|
62
74
|
if (record.nodes.length !== ids.length) return false;
|
|
63
75
|
if (record.faces !== null && record.faces !== fontGeneration()) return false;
|
|
64
|
-
for (let i = 0; i < ids.length; i++)
|
|
65
|
-
const dep = depOf(ids[i]);
|
|
66
|
-
if (record.nodes[i] !== (dep === void 0 ? void 0 : dep.node)) return false;
|
|
67
|
-
if (dep === void 0) continue;
|
|
68
|
-
if (record.data[i] !== dep.node.data || record.layers[i] !== dep.node.layer) return false;
|
|
69
|
-
if (!samePoseValue(record.poses[i], dep.pose)) return false;
|
|
70
|
-
const path = record.paths[i];
|
|
71
|
-
if (path !== void 0 && path !== dep.path) return false;
|
|
72
|
-
}
|
|
76
|
+
for (let i = 0; i < ids.length; i++) if (!sameDep(record, i, depOf(ids[i]))) return false;
|
|
73
77
|
if (record.faces !== null) noteFontRead();
|
|
74
78
|
return true;
|
|
75
79
|
}
|
|
80
|
+
/** Whether `dep` resolves to what `record` took at `i`, its children too where they were read. */
|
|
81
|
+
function sameDep(record, i, dep) {
|
|
82
|
+
if (record.nodes[i] !== (dep === void 0 ? void 0 : dep.node)) return false;
|
|
83
|
+
if (dep === void 0) return true;
|
|
84
|
+
if (record.data[i] !== dep.node.data || record.layers[i] !== dep.node.layer) return false;
|
|
85
|
+
if (!samePoseValue(record.poses[i], dep.pose)) return false;
|
|
86
|
+
const path = record.paths[i];
|
|
87
|
+
if (path !== void 0 && path !== dep.path) return false;
|
|
88
|
+
const kids = record.children[i];
|
|
89
|
+
if (kids === void 0) return true;
|
|
90
|
+
const now = dep.children;
|
|
91
|
+
if (now === void 0 || now.length !== kids.nodes.length) return false;
|
|
92
|
+
return now.every((child, k) => sameDep(kids, k, child));
|
|
93
|
+
}
|
|
76
94
|
|
|
77
95
|
//#endregion
|
|
78
96
|
export { deriveRecorded, emptyDepRecord, sameDeps };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"depMemo.js","names":[],"sources":["../../../src/core/scene/depMemo.ts"],"sourcesContent":["/**\n * What a memoized derivation was derived *from*, so a hit can re-check it.\n *\n * A derivation keyed on the deriving node's own authored pose only notices a\n * change someone pushed. A dependency that changed with nothing pushed behind\n * it — an ancestor's frame moving, a removal, a dependency appearing, a lookup\n * answering nodes no scene edits — is invisible to that key. Recording what\n * the derivation was handed and comparing it on the hit path is what notices\n * it without a trigger.\n *\n * What is recorded is what a derivation may read of a dependency: its node (an\n * identity), its pose (by value), its `data` (a reference, which every edit\n * replaces), its `layer`, and its path where the derivation read it. Anything\n * else on the node — its parent, its children — still needs a push. A\n * derivation that read glyph outlines also records the face generation, since\n * a face landing changes its result with nothing in the scene changed.\n */\nimport type { Path } from '@weasel-js/geom';\nimport type { InheritedPaint } from './inheritedPaint';\nimport { fontGeneration, noteFontRead, withFontReads } from './fontReads';\nimport { samePoseValue, snapshotPose } from './poseSnapshot';\nimport type { DerivedDep, Node, NodeId } from './types';\n\n/** Each dependency's node — an identity, so a restored clone is a different\n * one — with a copy of the pose it resolved to, its `data` and `layer`, and\n * the path it answered, `undefined` where the derivation never asked. */\nexport interface DepRecord<TPose> {\n nodes: (object | undefined)[];\n poses: (TPose | undefined)[];\n data: unknown[];\n layers: (string | undefined)[];\n paths: (Path | null | undefined)[];\n /** The face generation it was derived under, or `null` when it read no\n * glyph outlines. */\n faces: number | null;\n}\n\nexport function emptyDepRecord<TPose>(): DepRecord<TPose> {\n return { nodes: [], poses: [], data: [], layers: [], paths: [], faces: null };\n}\n\n/** A dependency as the derivation is handed it, noting a read of its path. A\n * class for the reason `SceneDep` is one: a prototype accessor is cheap. */\nclass RecordedDep<TPose> implements DerivedDep<TPose> {\n readonly node: Node<unknown, string, TPose>;\n readonly pose: TPose;\n\n constructor(\n private readonly dep: DerivedDep<TPose>,\n private readonly
|
|
1
|
+
{"version":3,"file":"depMemo.js","names":[],"sources":["../../../src/core/scene/depMemo.ts"],"sourcesContent":["/**\n * What a memoized derivation was derived *from*, so a hit can re-check it.\n *\n * A derivation keyed on the deriving node's own authored pose only notices a\n * change someone pushed. A dependency that changed with nothing pushed behind\n * it — an ancestor's frame moving, a removal, a dependency appearing, a lookup\n * answering nodes no scene edits — is invisible to that key. Recording what\n * the derivation was handed and comparing it on the hit path is what notices\n * it without a trigger.\n *\n * What is recorded is what a derivation may read of a dependency: its node (an\n * identity), its pose (by value), its `data` (a reference, which every edit\n * replaces), its `layer`, and its path where the derivation read it. Anything\n * else on the node — its parent, its children — still needs a push. A\n * derivation that read glyph outlines also records the face generation, since\n * a face landing changes its result with nothing in the scene changed.\n */\nimport type { Path } from '@weasel-js/geom';\nimport type { InheritedPaint } from './inheritedPaint';\nimport { fontGeneration, noteFontRead, withFontReads } from './fontReads';\nimport { samePoseValue, snapshotPose } from './poseSnapshot';\nimport type { DerivedDep, Node, NodeId } from './types';\n\n/** Each dependency's node — an identity, so a restored clone is a different\n * one — with a copy of the pose it resolved to, its `data` and `layer`, and\n * the path it answered, `undefined` where the derivation never asked. */\nexport interface DepRecord<TPose> {\n nodes: (object | undefined)[];\n poses: (TPose | undefined)[];\n data: unknown[];\n layers: (string | undefined)[];\n paths: (Path | null | undefined)[];\n /** What each dependency's children resolved to, where the derivation read them. */\n children: (DepRecord<TPose> | undefined)[];\n /** The face generation it was derived under, or `null` when it read no\n * glyph outlines. */\n faces: number | null;\n}\n\nexport function emptyDepRecord<TPose>(): DepRecord<TPose> {\n return { nodes: [], poses: [], data: [], layers: [], paths: [], children: [], faces: null };\n}\n\n/** A dependency as the derivation is handed it, noting a read of its path. A\n * class for the reason `SceneDep` is one: a prototype accessor is cheap. */\nclass RecordedDep<TPose> implements DerivedDep<TPose> {\n readonly node: Node<unknown, string, TPose>;\n readonly pose: TPose;\n\n constructor(\n private readonly dep: DerivedDep<TPose>,\n private readonly record: DepRecord<TPose>,\n private readonly index: number,\n ) {\n this.node = dep.node;\n this.pose = dep.pose;\n }\n\n get path(): Path | null {\n return (this.record.paths[this.index] = this.dep.path);\n }\n\n get inherited(): InheritedPaint | undefined {\n return this.dep.inherited;\n }\n\n get children(): readonly (DerivedDep<TPose> | undefined)[] | undefined {\n const kids = this.dep.children;\n if (kids === undefined) return undefined;\n const into = (this.record.children[this.index] = emptyDepRecord<TPose>());\n return recordDeps(into, kids);\n }\n}\n\n/** `deps` wrapped to note what is read of them in `into`, which is cleared first. */\nfunction recordDeps<TPose>(\n into: DepRecord<TPose>,\n deps: readonly (DerivedDep<TPose> | undefined)[],\n): (DerivedDep<TPose> | undefined)[] {\n into.nodes.length = 0;\n into.poses.length = 0;\n into.data.length = 0;\n into.layers.length = 0;\n into.paths.length = 0;\n into.children.length = 0;\n return deps.map((dep, i) => {\n into.nodes.push(dep?.node);\n into.poses.push(dep === undefined ? undefined : snapshotPose(dep.pose));\n into.data.push(dep?.node.data);\n into.layers.push(dep?.node.layer);\n into.paths.push(undefined);\n into.children.push(undefined);\n return dep === undefined ? undefined : new RecordedDep(dep, into, i);\n });\n}\n\n/** Run `derive` against `deps`, recording in place what it was run against.\n * Mutating the record is what updates the memo slot, which holds this object. */\nexport function deriveRecorded<TPose, T>(\n into: DepRecord<TPose>,\n deps: readonly (DerivedDep<TPose> | undefined)[],\n derive: (deps: readonly (DerivedDep<TPose> | undefined)[]) => T,\n): T {\n const handed = recordDeps(into, deps);\n const generation = fontGeneration();\n const { value, fonts } = withFontReads(() => derive(handed));\n into.faces = fonts ? generation : null;\n return value;\n}\n\n/** Whether the dependencies still resolve to what the record was taken from.\n * Resolves them one at a time rather than taking an array: this is the hit\n * path, and it walks every derived node's every dependency on every frame. */\nexport function sameDeps<TPose>(\n record: DepRecord<TPose>,\n ids: readonly NodeId[],\n depOf: (id: NodeId) => DerivedDep<TPose> | undefined,\n): boolean {\n if (record.nodes.length !== ids.length) return false;\n if (record.faces !== null && record.faces !== fontGeneration()) return false;\n for (let i = 0; i < ids.length; i++) if (!sameDep(record, i, depOf(ids[i]))) return false;\n // A hit is still a read, for any derivation enclosing this one.\n if (record.faces !== null) noteFontRead();\n return true;\n}\n\n/** Whether `dep` resolves to what `record` took at `i`, its children too where they were read. */\nfunction sameDep<TPose>(record: DepRecord<TPose>, i: number, dep: DerivedDep<TPose> | undefined): boolean {\n if (record.nodes[i] !== (dep === undefined ? undefined : dep.node)) return false;\n if (dep === undefined) return true;\n if (record.data[i] !== dep.node.data || record.layers[i] !== dep.node.layer) return false;\n if (!samePoseValue(record.poses[i], dep.pose)) return false;\n const path = record.paths[i];\n if (path !== undefined && path !== dep.path) return false;\n const kids = record.children[i];\n if (kids === undefined) return true;\n const now = dep.children;\n if (now === undefined || now.length !== kids.nodes.length) return false;\n return now.every((child, k) => sameDep(kids, k, child));\n}\n"],"mappings":";;;;AAuCA,SAAgB,iBAA0C;CACxD,OAAO;EAAE,OAAO,CAAC;EAAG,OAAO,CAAC;EAAG,MAAM,CAAC;EAAG,QAAQ,CAAC;EAAG,OAAO,CAAC;EAAG,UAAU,CAAC;EAAG,OAAO;CAAK;AAC5F;;;AAIA,IAAM,cAAN,MAAsD;CAKjC;CACA;CACA;CANnB;CACA;CAEA,YACE,KACA,QACA,OACA;EAHiB,KAAA,MAAA;EACA,KAAA,SAAA;EACA,KAAA,QAAA;EAEjB,KAAK,OAAO,IAAI;EAChB,KAAK,OAAO,IAAI;CAClB;CAEA,IAAI,OAAoB;EACtB,OAAQ,KAAK,OAAO,MAAM,KAAK,SAAS,KAAK,IAAI;CACnD;CAEA,IAAI,YAAwC;EAC1C,OAAO,KAAK,IAAI;CAClB;CAEA,IAAI,WAAmE;EACrE,MAAM,OAAO,KAAK,IAAI;EACtB,IAAI,SAAS,QAAW,OAAO;EAE/B,OAAO,WAAW,AADJ,KAAK,OAAO,SAAS,KAAK,SAAS,eAAsB,GAC/C,IAAI;CAC9B;AACF;;AAGA,SAAS,WACP,MACA,MACmC;CACnC,KAAK,MAAM,SAAS;CACpB,KAAK,MAAM,SAAS;CACpB,KAAK,KAAK,SAAS;CACnB,KAAK,OAAO,SAAS;CACrB,KAAK,MAAM,SAAS;CACpB,KAAK,SAAS,SAAS;CACvB,OAAO,KAAK,KAAK,KAAK,MAAM;EAC1B,KAAK,MAAM,KAAK,KAAK,IAAI;EACzB,KAAK,MAAM,KAAK,QAAQ,SAAY,SAAY,aAAa,IAAI,IAAI,CAAC;EACtE,KAAK,KAAK,KAAK,KAAK,KAAK,IAAI;EAC7B,KAAK,OAAO,KAAK,KAAK,KAAK,KAAK;EAChC,KAAK,MAAM,KAAK,MAAS;EACzB,KAAK,SAAS,KAAK,MAAS;EAC5B,OAAO,QAAQ,SAAY,SAAY,IAAI,YAAY,KAAK,MAAM,CAAC;CACrE,CAAC;AACH;;;AAIA,SAAgB,eACd,MACA,MACA,QACG;CACH,MAAM,SAAS,WAAW,MAAM,IAAI;CACpC,MAAM,aAAa,eAAe;CAClC,MAAM,EAAE,OAAO,UAAU,oBAAoB,OAAO,MAAM,CAAC;CAC3D,KAAK,QAAQ,QAAQ,aAAa;CAClC,OAAO;AACT;;;;AAKA,SAAgB,SACd,QACA,KACA,OACS;CACT,IAAI,OAAO,MAAM,WAAW,IAAI,QAAQ,OAAO;CAC/C,IAAI,OAAO,UAAU,QAAQ,OAAO,UAAU,eAAe,GAAG,OAAO;CACvE,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK,IAAI,CAAC,QAAQ,QAAQ,GAAG,MAAM,IAAI,EAAE,CAAC,GAAG,OAAO;CAEpF,IAAI,OAAO,UAAU,MAAM,aAAa;CACxC,OAAO;AACT;;AAGA,SAAS,QAAe,QAA0B,GAAW,KAA6C;CACxG,IAAI,OAAO,MAAM,QAAQ,QAAQ,SAAY,SAAY,IAAI,OAAO,OAAO;CAC3E,IAAI,QAAQ,QAAW,OAAO;CAC9B,IAAI,OAAO,KAAK,OAAO,IAAI,KAAK,QAAQ,OAAO,OAAO,OAAO,IAAI,KAAK,OAAO,OAAO;CACpF,IAAI,CAAC,cAAc,OAAO,MAAM,IAAI,IAAI,IAAI,GAAG,OAAO;CACtD,MAAM,OAAO,OAAO,MAAM;CAC1B,IAAI,SAAS,UAAa,SAAS,IAAI,MAAM,OAAO;CACpD,MAAM,OAAO,OAAO,SAAS;CAC7B,IAAI,SAAS,QAAW,OAAO;CAC/B,MAAM,MAAM,IAAI;CAChB,IAAI,QAAQ,UAAa,IAAI,WAAW,KAAK,MAAM,QAAQ,OAAO;CAClE,OAAO,IAAI,OAAO,OAAO,MAAM,QAAQ,MAAM,GAAG,KAAK,CAAC;AACxD"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { cubicContoursToPath, pathToCubicContours } from "@weasel-js/geom";
|
|
1
|
+
import { cubicContoursToPath, joinPaths, pathToCubicContours } from "@weasel-js/geom";
|
|
2
2
|
import { resolveFill, resolveStroke } from "@weasel-js/paint";
|
|
3
3
|
|
|
4
4
|
//#region src/core/scene/derivedParts.ts
|
|
@@ -28,28 +28,7 @@ function derivedPartsOf(path) {
|
|
|
28
28
|
return path == null ? void 0 : PARTS.get(path);
|
|
29
29
|
}
|
|
30
30
|
function concatPaths(paths) {
|
|
31
|
-
|
|
32
|
-
let commands = 0;
|
|
33
|
-
let coords = 0;
|
|
34
|
-
for (const p of polys) {
|
|
35
|
-
commands += p.commands.length;
|
|
36
|
-
coords += p.coords.length;
|
|
37
|
-
}
|
|
38
|
-
const out = {
|
|
39
|
-
kind: "polygon",
|
|
40
|
-
commands: new Uint8Array(commands),
|
|
41
|
-
coords: new Float32Array(coords),
|
|
42
|
-
fillRule: "nonzero"
|
|
43
|
-
};
|
|
44
|
-
let ci = 0;
|
|
45
|
-
let xi = 0;
|
|
46
|
-
for (const p of polys) {
|
|
47
|
-
out.commands.set(p.commands, ci);
|
|
48
|
-
out.coords.set(p.coords, xi);
|
|
49
|
-
ci += p.commands.length;
|
|
50
|
-
xi += p.coords.length;
|
|
51
|
-
}
|
|
52
|
-
return out;
|
|
31
|
+
return joinPaths(paths.map((p) => p.kind === "rect" ? cubicContoursToPath(pathToCubicContours(p)) : p));
|
|
53
32
|
}
|
|
54
33
|
|
|
55
34
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"derivedParts.js","names":[],"sources":["../../../src/core/scene/derivedParts.ts"],"sourcesContent":["/**\n * A derived path that paints in several parts, each with its own fill and\n * stroke: the steps of a blend, the copies of a repeat.\n *\n * A derivation returns one `Path`, which is what picking, bounds and every\n * reader of `DerivedDep.path` see. {@link pathFromParts} makes that path out\n * of the parts and remembers the parts against it, so the derived-node\n * painter, handed the path, can paint each part as itself. The parts live as\n * long as the path does — in the derivation's memo.\n */\nimport type { InheritedPaint } from './inheritedPaint';\nimport {
|
|
1
|
+
{"version":3,"file":"derivedParts.js","names":[],"sources":["../../../src/core/scene/derivedParts.ts"],"sourcesContent":["/**\n * A derived path that paints in several parts, each with its own fill and\n * stroke: the steps of a blend, the copies of a repeat.\n *\n * A derivation returns one `Path`, which is what picking, bounds and every\n * reader of `DerivedDep.path` see. {@link pathFromParts} makes that path out\n * of the parts and remembers the parts against it, so the derived-node\n * painter, handed the path, can paint each part as itself. The parts live as\n * long as the path does — in the derivation's memo.\n */\nimport type { InheritedPaint } from './inheritedPaint';\nimport {\n cubicContoursToPath, joinPaths, pathToCubicContours, type Path, type PolygonPath,\n} from '@weasel-js/geom';\nimport {\n resolveFill, resolveStroke, type Fill, type Inherit, type PaintedFill, type PaintedStroke, type Stroke,\n} from '@weasel-js/paint';\n\n/** One painted piece of a derived path. */\nexport interface DerivedPart {\n path: Path;\n /** The part's fill, read as a node's is: absent paints none, and\n * `INHERIT` takes the node's own `data.fill`. */\n fill?: Fill | Inherit | null;\n /** The part's stroke, on the same terms as `fill`. */\n stroke?: Stroke | Inherit | null;\n}\n\n/** What `part` paints, its `INHERIT` taken from `own`, the deriving node's\n * data — whose own `INHERIT` takes `inherited`, its container's. */\nexport function resolvePartPaint(\n part: DerivedPart,\n own: { fill?: Fill | Inherit | null; stroke?: Stroke | Inherit | null } | null | undefined,\n inherited?: InheritedPaint,\n): { fill: PaintedFill | null; stroke: PaintedStroke | null } {\n return {\n fill: resolveFill(part.fill, resolveFill(own?.fill, inherited?.fill)),\n stroke: resolveStroke(part.stroke, resolveStroke(own?.stroke, inherited?.stroke)),\n };\n}\n\nconst PARTS = new WeakMap<Path, readonly DerivedPart[]>();\n\n/**\n * One path holding every part's outline, with the parts remembered against\n * it for the painter. Return it from a `derivePath`. `null` for no parts.\n */\nexport function pathFromParts(parts: readonly DerivedPart[]): Path | null {\n if (parts.length === 0) return null;\n const whole = parts.length === 1 ? parts[0]!.path : concatPaths(parts.map((p) => p.path));\n // A one-part path is the part's own, which another reader may hold; the\n // painter must not mistake that path for a painted one elsewhere.\n const key = whole === parts[0]!.path ? { ...whole } as Path : whole;\n PARTS.set(key, parts);\n return key;\n}\n\n/** The parts `path` was made from by {@link pathFromParts}, or `undefined`\n * for any other path. */\nexport function derivedPartsOf(path: Path | null | undefined): readonly DerivedPart[] | undefined {\n return path == null ? undefined : PARTS.get(path);\n}\n\nfunction concatPaths(paths: readonly Path[]): PolygonPath {\n return joinPaths(paths.map((p) => (p.kind === 'rect' ? cubicContoursToPath(pathToCubicContours(p)) : p)));\n}\n"],"mappings":";;;;;;AA8BA,SAAgB,iBACd,MACA,KACA,WAC4D;CAC5D,OAAO;EACL,MAAM,YAAY,KAAK,MAAM,YAAY,KAAK,MAAM,WAAW,IAAI,CAAC;EACpE,QAAQ,cAAc,KAAK,QAAQ,cAAc,KAAK,QAAQ,WAAW,MAAM,CAAC;CAClF;AACF;AAEA,IAAM,wBAAQ,IAAI,QAAsC;;;;;AAMxD,SAAgB,cAAc,OAA4C;CACxE,IAAI,MAAM,WAAW,GAAG,OAAO;CAC/B,MAAM,QAAQ,MAAM,WAAW,IAAI,MAAM,EAAE,CAAE,OAAO,YAAY,MAAM,KAAK,MAAM,EAAE,IAAI,CAAC;CAGxF,MAAM,MAAM,UAAU,MAAM,EAAE,CAAE,OAAO,EAAE,GAAG,MAAM,IAAY;CAC9D,MAAM,IAAI,KAAK,KAAK;CACpB,OAAO;AACT;;;AAIA,SAAgB,eAAe,MAAmE;CAChG,OAAO,QAAQ,OAAO,SAAY,MAAM,IAAI,IAAI;AAClD;AAEA,SAAS,YAAY,OAAqC;CACxD,OAAO,UAAU,MAAM,KAAK,MAAO,EAAE,SAAS,SAAS,oBAAoB,oBAAoB,CAAC,CAAC,IAAI,CAAE,CAAC;AAC1G"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { composesFrames } from "./composeFrame.js";
|
|
1
2
|
import { deriveRecorded, emptyDepRecord, sameDeps } from "./depMemo.js";
|
|
2
3
|
import { carryDepPath, depFrameRebase, pathAsPainted } from "./depFrame.js";
|
|
3
4
|
import { dependencyIdsOf } from "./dependents.js";
|
|
@@ -175,6 +176,15 @@ var SceneDep = class {
|
|
|
175
176
|
const { source, reading } = this;
|
|
176
177
|
return inheritedPaintIn(reading === "effective" ? shownLookup(source) : source, this.posed);
|
|
177
178
|
}
|
|
179
|
+
get children() {
|
|
180
|
+
const { source, reading } = this;
|
|
181
|
+
const pc = source.composition;
|
|
182
|
+
const compose = pc && composesFrames(pc) && definesFrame(this.posed) ? pc.compose : null;
|
|
183
|
+
return source.childrenOf(this.posed.id).map((id) => {
|
|
184
|
+
const dep = depIn(source, id, reading);
|
|
185
|
+
return dep === void 0 || compose === null ? dep : new RebasedDep(dep, compose(this.pose, dep.pose));
|
|
186
|
+
});
|
|
187
|
+
}
|
|
178
188
|
};
|
|
179
189
|
/** `node` as `reading` reads it: with the data an override shows it with in the effective
|
|
180
190
|
* reading, as stored in the document one. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"effectivePose.js","names":[],"sources":["../../../src/core/scene/effectivePose.ts"],"sourcesContent":["/**\n * `effectivePose` — the pose to draw, pick and measure a node at.\n *\n * Three answers, in order: the ephemeral override a gesture published, the\n * pose the node derives from its dependencies, or the pose the document\n * stores. A reader of `node.pose` disagrees with the render about where a\n * dragged or derived node is.\n */\nimport { deriveRecorded, emptyDepRecord, sameDeps, type DepRecord } from './depMemo';\nimport type { PoseComposition } from './composeFrame';\nimport { carryDepPath, depFrameRebase, pathAsPainted } from './depFrame';\nimport { dependencyIdsOf } from './dependents';\nimport { resolveDerivedPath } from './derivedPath';\nimport { inheritedPaintIn, type InheritedPaint } from './inheritedPaint';\nimport { isDocument } from './documentOf';\nimport { nodeAsShown, shownLookup } from './nodeAsShown';\nimport { dropPoseKeyedMemoSlots, nodeMemo } from './nodeMemo';\nimport type { Path } from '@weasel-js/geom';\nimport type { DerivedDep, DerivePathFn, DerivePoseFn, Node, NodeId, PoseOverrides } from './types';\n\n/**\n * Which pose a resolution answers: `effective` honors overrides all the way\n * down the dependency chain, `document` ignores them all the way down. A\n * `documentOf` view is read as `document` by every entry point. Each\n * reading memoizes in its own slots — the memo key is the node and its\n * authored pose, which is the same for both.\n */\ntype Reading = 'effective' | 'document';\n\nconst POSE_SLOT: Record<Reading, string> = {\n effective: 'kit:derivedPose',\n document: 'kit:derivedPose:document',\n};\nconst PATH_SLOT: Record<Reading, string | undefined> = {\n effective: undefined,\n document: 'kit:derivedPath:document',\n};\n\n/** The subset of a node this module reads. Structural so a `Node` satisfies\n * it without importing the full generic shape. */\nexport interface PosedNode<TPose> {\n id: NodeId;\n kind?: 'mark' | 'group';\n pose: TPose;\n /** Read only by the memo, which keys on its reference alongside the pose. */\n data?: unknown;\n dependsOn?: readonly NodeId[] | 'children';\n /** Read under a composing strategy, to find the frame its pose is in. */\n parent?: NodeId | null;\n derivePose?: DerivePoseFn<TPose>;\n /** Read only when something asks a dependency for its `path`. */\n derivePath?: DerivePathFn<TPose>;\n}\n\n/** What resolving a pose needs: the overrides, and enough of the scene to\n * reach a node's dependencies. A `Scene` satisfies it. */\nexport interface PoseSource<TPose> {\n readonly overrides: Pick<PoseOverrides<TPose>, 'read'>;\n get(id: NodeId): PosedNode<TPose> | undefined;\n childrenOf(id: NodeId): readonly NodeId[];\n /** When it composes frames, a derivation reads each dependency in the\n * frame of the node deriving. */\n readonly composition?: PoseComposition<TPose>;\n}\n\n/** A cached derived pose, with what it was derived from. */\ninterface PoseMemo<TPose> extends DepRecord<TPose> {\n value: TPose | null;\n}\n\n/** Ids whose derivation is on the stack. A dependency graph is meant to be\n * acyclic and `dependsOn` is unvalidated, so a cycle resolves to the authored\n * pose at whichever node closes it rather than overflowing the stack. */\nconst resolving = new Set<NodeId>();\n\n/** Bumped each time the guard above fires. A derivation that closed a cycle\n * answered from a fallback rather than from its dependencies, so its value is\n * an artifact of which node was asked first and must not be cached. */\nlet cycleHits = 0;\n\n/**\n * The pose `node` computes from its dependencies, or `null` when it derives\n * nothing — it has no `derivePose`, nothing to derive from, or its\n * `derivePose` returned `null`.\n *\n * A dependency is read through {@link effectivePose}, so a group of groups\n * resolves bottom-up and a dragged dependency's override reaches the\n * derivation the same frame it is published.\n */\nexport function derivedPose<TPose>(\n source: PoseSource<TPose>,\n node: PosedNode<TPose>,\n): TPose | null {\n return derivedPoseIn(source, node, readingOf(source));\n}\n\n/** How `source` is read: as its document holds it when it is a `documentOf` view. */\nfunction readingOf(source: PoseSource<unknown>): Reading {\n return isDocument(source) ? 'document' : 'effective';\n}\n\nfunction derivedPoseIn<TPose>(\n source: PoseSource<TPose>,\n stored: PosedNode<TPose>,\n reading: Reading,\n): TPose | null {\n const node = shownIn(source, stored, reading);\n const derive = node.derivePose;\n if (derive === undefined) return null;\n const ids = dependencyIdsOf(node, source.childrenOf);\n if (ids.length === 0) return null;\n if (resolving.has(node.id)) {\n cycleHits++;\n return null;\n }\n resolving.add(node.id);\n const hitsBefore = cycleHits;\n try {\n const depOf = depsAsRead(source, node, reading);\n // Keyed on the authored pose, which only sees a change someone pushed, so\n // the record also carries what the derivation read and re-checks it by\n // value on a hit — see `depMemo.ts`.\n let computed = false;\n const record = nodeMemo<PoseMemo<TPose>>(node, POSE_SLOT[reading], node.pose, () => {\n computed = true;\n return run(node, derive, ids.map(depOf), { ...emptyDepRecord<TPose>(), value: null });\n });\n // Mutating the record in place is what updates the memo slot, which holds\n // this object.\n if (!computed && !sameDeps(record, ids, depOf)) {\n run(node, derive, ids.map(depOf), record);\n }\n if (cycleHits !== hitsBefore) dropPoseKeyedMemoSlots(node);\n return record.value;\n } finally {\n resolving.delete(node.id);\n }\n}\n\n/** Run `derivePose` against `deps` and record what it was run against. */\nfunction run<TPose>(\n node: PosedNode<TPose>,\n derive: NonNullable<PosedNode<TPose>['derivePose']>,\n deps: readonly (DerivedDep<TPose> | undefined)[],\n into: PoseMemo<TPose>,\n): PoseMemo<TPose> {\n into.value = deriveRecorded(into, deps, (handed) => derive(node as never, handed));\n return into;\n}\n\n/**\n * `id` as a derivation sees it: the node, the pose it is painted at, and the\n * path it derives.\n *\n * The pose is resolved eagerly — every derivation reads it — and the path\n * lazily, because most do not and resolving a route costs a router run. Both\n * resolve *through* this function, so a dependency that is itself derived is\n * resolved before it is read.\n */\nexport function derivedDepOf<TPose>(\n source: PoseSource<TPose>,\n id: NodeId,\n reader?: PosedNode<TPose>,\n): DerivedDep<TPose> | undefined {\n const reading = readingOf(source);\n return reader === undefined ? depIn(source, id, reading) : depsAsRead(source, reader, reading)(id);\n}\n\n/** `id` as {@link derivedDepOf} answers it, but at the pose, path and data the\n * document holds: no override anywhere down its dependencies counts. The same\n * reading as `derivedDepOf(documentOf(source), …)`, for a reader that must not\n * see an in-flight gesture or an open edit, such as an edit pass. */\nexport function documentDepOf<TPose>(\n source: PoseSource<TPose>,\n id: NodeId,\n reader?: PosedNode<TPose>,\n): DerivedDep<TPose> | undefined {\n return reader === undefined ? depIn(source, id, 'document') : depsAsRead(source, reader, 'document')(id);\n}\n\n/** `(id) => that dependency as `reader`'s derivation is handed it`: its pose\n * in `reader`'s frame where the scene composes frames. A `'children'`\n * dependent shares its children's frame, so it reads them as they are. */\nfunction depsAsRead<TPose>(\n source: PoseSource<TPose>,\n reader: PosedNode<TPose>,\n reading: Reading,\n): (id: NodeId) => DerivedDep<TPose> | undefined {\n const plain = (id: NodeId) => depIn(source, id, reading);\n if (reader.dependsOn === 'children') return plain;\n const rebase = depFrameRebase(\n source.composition,\n reader,\n (id) => source.get(id),\n (id) => poseIn(source, source.get(id)!, reading),\n (id) => {\n const n = source.get(id);\n return n === undefined || definesFrame(n);\n },\n );\n if (rebase === null) return plain;\n return (id) => {\n const dep = plain(id);\n if (dep === undefined) return undefined;\n const pose = rebase(id, dep.pose);\n return pose === dep.pose ? dep : new RebasedDep(dep, pose);\n };\n}\n\n/** A dependency read from another frame: its pose rebased, and its path\n * carried by the same frame change when asked for. */\nclass RebasedDep<TPose> implements DerivedDep<TPose> {\n readonly node: Node<unknown, string, TPose>;\n\n constructor(private readonly dep: DerivedDep<TPose>, readonly pose: TPose) {\n this.node = dep.node;\n }\n\n get path(): Path | null {\n const path = this.dep.path;\n return path === null ? null : carryDepPath(path, this.dep.pose, this.pose);\n }\n\n get inherited(): InheritedPaint | undefined {\n return this.dep.inherited;\n }\n}\n\nfunction depIn<TPose>(\n source: PoseSource<TPose>,\n id: NodeId,\n reading: Reading,\n): DerivedDep<TPose> | undefined {\n const node = source.get(id);\n if (node === undefined) return undefined;\n return new SceneDep(source, node, reading);\n}\n\n/**\n * A class rather than an object literal with a `get path()`: one of these is\n * built per dependency per derived node per frame, and an own accessor costs\n * an order of magnitude more to define than a prototype one does to inherit.\n */\nclass SceneDep<TPose> implements DerivedDep<TPose> {\n readonly node: Node<unknown, string, TPose>;\n readonly pose: TPose;\n private readonly shown: Path | undefined;\n\n private readonly posed: PosedNode<TPose>;\n\n constructor(\n private readonly source: PoseSource<TPose>,\n stored: PosedNode<TPose>,\n private readonly reading: Reading,\n ) {\n const posed = shownIn(source, stored, reading);\n this.posed = posed;\n this.node = posed as unknown as Node<unknown, string, TPose>;\n const override = reading === 'effective' ? source.overrides.read(posed.id) : undefined;\n this.shown = override?.path;\n this.pose = override?.pose ?? derivedPoseIn(source, posed, reading) ?? posed.pose;\n }\n\n get path(): Path | null {\n if (this.shown !== undefined) return pathAsPainted(this.shown, this.pose, this.pose);\n const { source, reading } = this;\n return resolveDerivedPath(\n this.posed,\n depsAsRead(source, this.posed, reading),\n (depId) => source.childrenOf(depId),\n PATH_SLOT[reading],\n );\n }\n\n get inherited(): InheritedPaint | undefined {\n const { source, reading } = this;\n return inheritedPaintIn(reading === 'effective' ? shownLookup(source) : source, this.posed);\n }\n}\n\n/** `node` as `reading` reads it: with the data an override shows it with in the effective\n * reading, as stored in the document one. */\nfunction shownIn<TPose>(source: PoseSource<TPose>, node: PosedNode<TPose>, reading: Reading): PosedNode<TPose> {\n return reading === 'effective' ? nodeAsShown(source.overrides, node) : node;\n}\n\nfunction poseIn<TPose>(\n source: PoseSource<TPose>,\n node: PosedNode<TPose>,\n reading: Reading,\n): TPose {\n if (reading === 'effective') {\n const override = source.overrides.read(node.id)?.pose;\n if (override !== undefined) return override;\n }\n return derivedPoseIn(source, node, reading) ?? node.pose;\n}\n\n/**\n * The pose the *document* says `node` is at: derived when it derives, else\n * authored. `effectivePose` minus the override step, at every link of the\n * dependency chain — a derived node's document pose holds still while\n * something it derives from is being dragged.\n *\n * For a reader that must not see an in-flight gesture, such as an action\n * capturing the `from` of a transform op. The same reading as\n * `effectivePose(documentOf(source), node)`.\n */\nexport function documentPose<TPose>(\n source: PoseSource<TPose>,\n node: PosedNode<TPose>,\n): TPose {\n return poseIn(source, node, 'document');\n}\n\n/**\n * The pose to draw, pick and measure `node` at. Every pose a reader acts on\n * comes from here.\n */\nexport function effectivePose<TPose>(\n source: PoseSource<TPose>,\n node: PosedNode<TPose>,\n): TPose {\n return poseIn(source, node, readingOf(source));\n}\n\n/**\n * Whether `node`'s pose is a frame its children are expressed in, under a\n * composing strategy.\n *\n * A container that derives its pose from its children cannot be one: moving\n * the frame to cover the children would move the children, and a `RectPose`\n * frame's origin is its corner, so no envelope leaves them in place. Such a\n * container is an envelope instead — its children are stored in its own\n * frame — and the composition fold passes over it.\n */\nexport function definesFrame(node: { dependsOn?: unknown; derivePose?: unknown }): boolean {\n return !isEnvelope(node);\n}\n\n/** Whether `node` derives its pose from its children: a group that is its\n * members, so moving them moves it. */\nexport function isEnvelope(node: { dependsOn?: unknown; derivePose?: unknown }): boolean {\n return node.dependsOn === 'children' && node.derivePose !== undefined;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"effectivePose.js","names":[],"sources":["../../../src/core/scene/effectivePose.ts"],"sourcesContent":["/**\n * `effectivePose` — the pose to draw, pick and measure a node at.\n *\n * Three answers, in order: the ephemeral override a gesture published, the\n * pose the node derives from its dependencies, or the pose the document\n * stores. A reader of `node.pose` disagrees with the render about where a\n * dragged or derived node is.\n */\nimport { deriveRecorded, emptyDepRecord, sameDeps, type DepRecord } from './depMemo';\nimport { composesFrames, type PoseComposition } from './composeFrame';\nimport { carryDepPath, depFrameRebase, pathAsPainted } from './depFrame';\nimport { dependencyIdsOf } from './dependents';\nimport { resolveDerivedPath } from './derivedPath';\nimport { inheritedPaintIn, type InheritedPaint } from './inheritedPaint';\nimport { isDocument } from './documentOf';\nimport { nodeAsShown, shownLookup } from './nodeAsShown';\nimport { dropPoseKeyedMemoSlots, nodeMemo } from './nodeMemo';\nimport type { Path } from '@weasel-js/geom';\nimport type { DerivedDep, DerivePathFn, DerivePoseFn, Node, NodeId, PoseOverrides } from './types';\n\n/**\n * Which pose a resolution answers: `effective` honors overrides all the way\n * down the dependency chain, `document` ignores them all the way down. A\n * `documentOf` view is read as `document` by every entry point. Each\n * reading memoizes in its own slots — the memo key is the node and its\n * authored pose, which is the same for both.\n */\ntype Reading = 'effective' | 'document';\n\nconst POSE_SLOT: Record<Reading, string> = {\n effective: 'kit:derivedPose',\n document: 'kit:derivedPose:document',\n};\nconst PATH_SLOT: Record<Reading, string | undefined> = {\n effective: undefined,\n document: 'kit:derivedPath:document',\n};\n\n/** The subset of a node this module reads. Structural so a `Node` satisfies\n * it without importing the full generic shape. */\nexport interface PosedNode<TPose> {\n id: NodeId;\n kind?: 'mark' | 'group';\n pose: TPose;\n /** Read only by the memo, which keys on its reference alongside the pose. */\n data?: unknown;\n dependsOn?: readonly NodeId[] | 'children';\n /** Read under a composing strategy, to find the frame its pose is in. */\n parent?: NodeId | null;\n derivePose?: DerivePoseFn<TPose>;\n /** Read only when something asks a dependency for its `path`. */\n derivePath?: DerivePathFn<TPose>;\n}\n\n/** What resolving a pose needs: the overrides, and enough of the scene to\n * reach a node's dependencies. A `Scene` satisfies it. */\nexport interface PoseSource<TPose> {\n readonly overrides: Pick<PoseOverrides<TPose>, 'read'>;\n get(id: NodeId): PosedNode<TPose> | undefined;\n childrenOf(id: NodeId): readonly NodeId[];\n /** When it composes frames, a derivation reads each dependency in the\n * frame of the node deriving. */\n readonly composition?: PoseComposition<TPose>;\n}\n\n/** A cached derived pose, with what it was derived from. */\ninterface PoseMemo<TPose> extends DepRecord<TPose> {\n value: TPose | null;\n}\n\n/** Ids whose derivation is on the stack. A dependency graph is meant to be\n * acyclic and `dependsOn` is unvalidated, so a cycle resolves to the authored\n * pose at whichever node closes it rather than overflowing the stack. */\nconst resolving = new Set<NodeId>();\n\n/** Bumped each time the guard above fires. A derivation that closed a cycle\n * answered from a fallback rather than from its dependencies, so its value is\n * an artifact of which node was asked first and must not be cached. */\nlet cycleHits = 0;\n\n/**\n * The pose `node` computes from its dependencies, or `null` when it derives\n * nothing — it has no `derivePose`, nothing to derive from, or its\n * `derivePose` returned `null`.\n *\n * A dependency is read through {@link effectivePose}, so a group of groups\n * resolves bottom-up and a dragged dependency's override reaches the\n * derivation the same frame it is published.\n */\nexport function derivedPose<TPose>(\n source: PoseSource<TPose>,\n node: PosedNode<TPose>,\n): TPose | null {\n return derivedPoseIn(source, node, readingOf(source));\n}\n\n/** How `source` is read: as its document holds it when it is a `documentOf` view. */\nfunction readingOf(source: PoseSource<unknown>): Reading {\n return isDocument(source) ? 'document' : 'effective';\n}\n\nfunction derivedPoseIn<TPose>(\n source: PoseSource<TPose>,\n stored: PosedNode<TPose>,\n reading: Reading,\n): TPose | null {\n const node = shownIn(source, stored, reading);\n const derive = node.derivePose;\n if (derive === undefined) return null;\n const ids = dependencyIdsOf(node, source.childrenOf);\n if (ids.length === 0) return null;\n if (resolving.has(node.id)) {\n cycleHits++;\n return null;\n }\n resolving.add(node.id);\n const hitsBefore = cycleHits;\n try {\n const depOf = depsAsRead(source, node, reading);\n // Keyed on the authored pose, which only sees a change someone pushed, so\n // the record also carries what the derivation read and re-checks it by\n // value on a hit — see `depMemo.ts`.\n let computed = false;\n const record = nodeMemo<PoseMemo<TPose>>(node, POSE_SLOT[reading], node.pose, () => {\n computed = true;\n return run(node, derive, ids.map(depOf), { ...emptyDepRecord<TPose>(), value: null });\n });\n // Mutating the record in place is what updates the memo slot, which holds\n // this object.\n if (!computed && !sameDeps(record, ids, depOf)) {\n run(node, derive, ids.map(depOf), record);\n }\n if (cycleHits !== hitsBefore) dropPoseKeyedMemoSlots(node);\n return record.value;\n } finally {\n resolving.delete(node.id);\n }\n}\n\n/** Run `derivePose` against `deps` and record what it was run against. */\nfunction run<TPose>(\n node: PosedNode<TPose>,\n derive: NonNullable<PosedNode<TPose>['derivePose']>,\n deps: readonly (DerivedDep<TPose> | undefined)[],\n into: PoseMemo<TPose>,\n): PoseMemo<TPose> {\n into.value = deriveRecorded(into, deps, (handed) => derive(node as never, handed));\n return into;\n}\n\n/**\n * `id` as a derivation sees it: the node, the pose it is painted at, and the\n * path it derives.\n *\n * The pose is resolved eagerly — every derivation reads it — and the path\n * lazily, because most do not and resolving a route costs a router run. Both\n * resolve *through* this function, so a dependency that is itself derived is\n * resolved before it is read.\n */\nexport function derivedDepOf<TPose>(\n source: PoseSource<TPose>,\n id: NodeId,\n reader?: PosedNode<TPose>,\n): DerivedDep<TPose> | undefined {\n const reading = readingOf(source);\n return reader === undefined ? depIn(source, id, reading) : depsAsRead(source, reader, reading)(id);\n}\n\n/** `id` as {@link derivedDepOf} answers it, but at the pose, path and data the\n * document holds: no override anywhere down its dependencies counts. The same\n * reading as `derivedDepOf(documentOf(source), …)`, for a reader that must not\n * see an in-flight gesture or an open edit, such as an edit pass. */\nexport function documentDepOf<TPose>(\n source: PoseSource<TPose>,\n id: NodeId,\n reader?: PosedNode<TPose>,\n): DerivedDep<TPose> | undefined {\n return reader === undefined ? depIn(source, id, 'document') : depsAsRead(source, reader, 'document')(id);\n}\n\n/** `(id) => that dependency as `reader`'s derivation is handed it`: its pose\n * in `reader`'s frame where the scene composes frames. A `'children'`\n * dependent shares its children's frame, so it reads them as they are. */\nfunction depsAsRead<TPose>(\n source: PoseSource<TPose>,\n reader: PosedNode<TPose>,\n reading: Reading,\n): (id: NodeId) => DerivedDep<TPose> | undefined {\n const plain = (id: NodeId) => depIn(source, id, reading);\n if (reader.dependsOn === 'children') return plain;\n const rebase = depFrameRebase(\n source.composition,\n reader,\n (id) => source.get(id),\n (id) => poseIn(source, source.get(id)!, reading),\n (id) => {\n const n = source.get(id);\n return n === undefined || definesFrame(n);\n },\n );\n if (rebase === null) return plain;\n return (id) => {\n const dep = plain(id);\n if (dep === undefined) return undefined;\n const pose = rebase(id, dep.pose);\n return pose === dep.pose ? dep : new RebasedDep(dep, pose);\n };\n}\n\n/** A dependency read from another frame: its pose rebased, and its path\n * carried by the same frame change when asked for. */\nclass RebasedDep<TPose> implements DerivedDep<TPose> {\n readonly node: Node<unknown, string, TPose>;\n\n constructor(private readonly dep: DerivedDep<TPose>, readonly pose: TPose) {\n this.node = dep.node;\n }\n\n get path(): Path | null {\n const path = this.dep.path;\n return path === null ? null : carryDepPath(path, this.dep.pose, this.pose);\n }\n\n get inherited(): InheritedPaint | undefined {\n return this.dep.inherited;\n }\n}\n\nfunction depIn<TPose>(\n source: PoseSource<TPose>,\n id: NodeId,\n reading: Reading,\n): DerivedDep<TPose> | undefined {\n const node = source.get(id);\n if (node === undefined) return undefined;\n return new SceneDep(source, node, reading);\n}\n\n/**\n * A class rather than an object literal with a `get path()`: one of these is\n * built per dependency per derived node per frame, and an own accessor costs\n * an order of magnitude more to define than a prototype one does to inherit.\n */\nclass SceneDep<TPose> implements DerivedDep<TPose> {\n readonly node: Node<unknown, string, TPose>;\n readonly pose: TPose;\n private readonly shown: Path | undefined;\n\n private readonly posed: PosedNode<TPose>;\n\n constructor(\n private readonly source: PoseSource<TPose>,\n stored: PosedNode<TPose>,\n private readonly reading: Reading,\n ) {\n const posed = shownIn(source, stored, reading);\n this.posed = posed;\n this.node = posed as unknown as Node<unknown, string, TPose>;\n const override = reading === 'effective' ? source.overrides.read(posed.id) : undefined;\n this.shown = override?.path;\n this.pose = override?.pose ?? derivedPoseIn(source, posed, reading) ?? posed.pose;\n }\n\n get path(): Path | null {\n if (this.shown !== undefined) return pathAsPainted(this.shown, this.pose, this.pose);\n const { source, reading } = this;\n return resolveDerivedPath(\n this.posed,\n depsAsRead(source, this.posed, reading),\n (depId) => source.childrenOf(depId),\n PATH_SLOT[reading],\n );\n }\n\n get inherited(): InheritedPaint | undefined {\n const { source, reading } = this;\n return inheritedPaintIn(reading === 'effective' ? shownLookup(source) : source, this.posed);\n }\n\n get children(): readonly (DerivedDep<TPose> | undefined)[] {\n const { source, reading } = this;\n const pc = source.composition;\n const compose = pc && composesFrames(pc) && definesFrame(this.posed) ? pc.compose : null;\n return source.childrenOf(this.posed.id).map((id) => {\n const dep = depIn(source, id, reading);\n return dep === undefined || compose === null ? dep : new RebasedDep(dep, compose(this.pose, dep.pose));\n });\n }\n}\n\n/** `node` as `reading` reads it: with the data an override shows it with in the effective\n * reading, as stored in the document one. */\nfunction shownIn<TPose>(source: PoseSource<TPose>, node: PosedNode<TPose>, reading: Reading): PosedNode<TPose> {\n return reading === 'effective' ? nodeAsShown(source.overrides, node) : node;\n}\n\nfunction poseIn<TPose>(\n source: PoseSource<TPose>,\n node: PosedNode<TPose>,\n reading: Reading,\n): TPose {\n if (reading === 'effective') {\n const override = source.overrides.read(node.id)?.pose;\n if (override !== undefined) return override;\n }\n return derivedPoseIn(source, node, reading) ?? node.pose;\n}\n\n/**\n * The pose the *document* says `node` is at: derived when it derives, else\n * authored. `effectivePose` minus the override step, at every link of the\n * dependency chain — a derived node's document pose holds still while\n * something it derives from is being dragged.\n *\n * For a reader that must not see an in-flight gesture, such as an action\n * capturing the `from` of a transform op. The same reading as\n * `effectivePose(documentOf(source), node)`.\n */\nexport function documentPose<TPose>(\n source: PoseSource<TPose>,\n node: PosedNode<TPose>,\n): TPose {\n return poseIn(source, node, 'document');\n}\n\n/**\n * The pose to draw, pick and measure `node` at. Every pose a reader acts on\n * comes from here.\n */\nexport function effectivePose<TPose>(\n source: PoseSource<TPose>,\n node: PosedNode<TPose>,\n): TPose {\n return poseIn(source, node, readingOf(source));\n}\n\n/**\n * Whether `node`'s pose is a frame its children are expressed in, under a\n * composing strategy.\n *\n * A container that derives its pose from its children cannot be one: moving\n * the frame to cover the children would move the children, and a `RectPose`\n * frame's origin is its corner, so no envelope leaves them in place. Such a\n * container is an envelope instead — its children are stored in its own\n * frame — and the composition fold passes over it.\n */\nexport function definesFrame(node: { dependsOn?: unknown; derivePose?: unknown }): boolean {\n return !isEnvelope(node);\n}\n\n/** Whether `node` derives its pose from its children: a group that is its\n * members, so moving them moves it. */\nexport function isEnvelope(node: { dependsOn?: unknown; derivePose?: unknown }): boolean {\n return node.dependsOn === 'children' && node.derivePose !== undefined;\n}\n"],"mappings":"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"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
//#region src/core/scene/historyForm.ts
|
|
2
2
|
/** The form a scene's undo entries are recorded in. A serialized history
|
|
3
|
-
* carries it, and one carrying another is not restored. Form
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
|
|
3
|
+
* carries it, and one carrying another is not restored. Form 4 records a
|
|
4
|
+
* child's pose in its container's frame; form 3 named nodes `mark` and
|
|
5
|
+
* `group`; form 2 held the scene's own ops for every edit, and before it an
|
|
6
|
+
* `applyBatch` entry held the ops it was given. */
|
|
7
|
+
var SCENE_HISTORY_FORM = 4;
|
|
7
8
|
|
|
8
9
|
//#endregion
|
|
9
10
|
export { SCENE_HISTORY_FORM };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"historyForm.js","names":[],"sources":["../../../src/core/scene/historyForm.ts"],"sourcesContent":["import type { SerializedHistory } from '@weasel-js/history';\n\n/** The form a scene's undo entries are recorded in. A serialized history\n * carries it, and one carrying another is not restored. Form
|
|
1
|
+
{"version":3,"file":"historyForm.js","names":[],"sources":["../../../src/core/scene/historyForm.ts"],"sourcesContent":["import type { SerializedHistory } from '@weasel-js/history';\n\n/** The form a scene's undo entries are recorded in. A serialized history\n * carries it, and one carrying another is not restored. Form 4 records a\n * child's pose in its container's frame; form 3 named nodes `mark` and\n * `group`; form 2 held the scene's own ops for every edit, and before it an\n * `applyBatch` entry held the ops it was given. */\nexport const SCENE_HISTORY_FORM = 4;\n\n/** What `Scene.serializeHistory` answers with. */\nexport interface SerializedSceneHistory extends SerializedHistory {\n form: typeof SCENE_HISTORY_FORM;\n}\n"],"mappings":";;;;;;AAOA,IAAa,qBAAqB"}
|
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
import { dwarn } from "../../debug/flag.js";
|
|
2
2
|
import { restoreFn } from "./nodeFnFields.js";
|
|
3
3
|
import { statedFields } from "./statedFields.js";
|
|
4
|
+
import { registerLayerOps } from "./layerOps.js";
|
|
4
5
|
|
|
5
6
|
//#region src/core/scene/kitOps.ts
|
|
6
|
-
function setParallax(record, to) {
|
|
7
|
-
if (to === void 0) delete record.parallax;
|
|
8
|
-
else record.parallax = to;
|
|
9
|
-
}
|
|
10
7
|
/** Register every kit op kind. Answers with the table a live `kit:setLayout`
|
|
11
8
|
* payload's strategies are kept in, which `scene.setLayout` fills. */
|
|
12
9
|
function registerKitOps(env) {
|
|
13
|
-
const { state, requireLayerIndex,
|
|
10
|
+
const { state, requireLayerIndex, invalidateOrder, fnFields } = env;
|
|
14
11
|
const { dependents, childDerived, invalidateDependents, invalidateChildDerivedFrom, trackChildDerived, retarget, requireNode, detach, attach, addedFns, restoreNodeFunctions } = env.store;
|
|
15
12
|
function registerKitOp(kind, handler) {
|
|
16
13
|
env.register(kind, handler);
|
|
@@ -30,6 +27,7 @@ function registerKitOps(env) {
|
|
|
30
27
|
attach(p.id, p.parent, p.index);
|
|
31
28
|
if (p.dependsOn !== void 0) node.dependsOn = p.dependsOn;
|
|
32
29
|
Object.assign(node, statedFields(p));
|
|
30
|
+
env.noteWritten(node);
|
|
33
31
|
dependents.add(p.id, p.dependsOn === "children" ? [] : p.dependsOn ?? []);
|
|
34
32
|
trackChildDerived(p.id, p.dependsOn);
|
|
35
33
|
const target = node;
|
|
@@ -76,6 +74,7 @@ function registerKitOps(env) {
|
|
|
76
74
|
} : { ...n };
|
|
77
75
|
restoreNodeFunctions(clone, keys.get(n.id));
|
|
78
76
|
state.nodes.set(n.id, clone);
|
|
77
|
+
env.noteWritten(clone);
|
|
79
78
|
dependents.add(n.id, clone.dependsOn === "children" ? [] : clone.dependsOn ?? []);
|
|
80
79
|
trackChildDerived(n.id, clone.dependsOn);
|
|
81
80
|
}
|
|
@@ -163,72 +162,7 @@ function registerKitOps(env) {
|
|
|
163
162
|
invalidateDependents(p.id);
|
|
164
163
|
}
|
|
165
164
|
});
|
|
166
|
-
|
|
167
|
-
apply: (p) => {
|
|
168
|
-
state.layers[requireLayerIndex(p.layer)].visible = p.to;
|
|
169
|
-
if (!p.to) env.narrowSelection();
|
|
170
|
-
},
|
|
171
|
-
revert: (p) => {
|
|
172
|
-
state.layers[requireLayerIndex(p.layer)].visible = p.from;
|
|
173
|
-
}
|
|
174
|
-
});
|
|
175
|
-
registerKitOp("kit:setLayerLocked", {
|
|
176
|
-
apply: (p) => {
|
|
177
|
-
state.layers[requireLayerIndex(p.layer)].locked = p.to;
|
|
178
|
-
if (p.to) env.narrowSelection();
|
|
179
|
-
},
|
|
180
|
-
revert: (p) => {
|
|
181
|
-
state.layers[requireLayerIndex(p.layer)].locked = p.from;
|
|
182
|
-
}
|
|
183
|
-
});
|
|
184
|
-
registerKitOp("kit:setLayerParallax", {
|
|
185
|
-
apply: (p) => {
|
|
186
|
-
setParallax(state.layers[requireLayerIndex(p.layer)], p.to);
|
|
187
|
-
},
|
|
188
|
-
revert: (p) => {
|
|
189
|
-
setParallax(state.layers[requireLayerIndex(p.layer)], p.from);
|
|
190
|
-
}
|
|
191
|
-
});
|
|
192
|
-
registerKitOp("kit:addLayer", {
|
|
193
|
-
apply: (p) => {
|
|
194
|
-
state.layers.splice(p.index, 0, { ...p.record });
|
|
195
|
-
rebuildLayerIndex();
|
|
196
|
-
},
|
|
197
|
-
revert: (p) => {
|
|
198
|
-
state.layers.splice(p.index, 1);
|
|
199
|
-
rebuildLayerIndex();
|
|
200
|
-
}
|
|
201
|
-
});
|
|
202
|
-
registerKitOp("kit:removeLayer", {
|
|
203
|
-
apply: (p) => {
|
|
204
|
-
state.layers.splice(p.index, 1);
|
|
205
|
-
rebuildLayerIndex();
|
|
206
|
-
},
|
|
207
|
-
revert: (p) => {
|
|
208
|
-
state.layers.splice(p.index, 0, { ...p.record });
|
|
209
|
-
rebuildLayerIndex();
|
|
210
|
-
}
|
|
211
|
-
});
|
|
212
|
-
registerKitOp("kit:renameLayer", {
|
|
213
|
-
apply: (p) => {
|
|
214
|
-
state.layers[requireLayerIndex(p.layer)].name = p.to;
|
|
215
|
-
},
|
|
216
|
-
revert: (p) => {
|
|
217
|
-
state.layers[requireLayerIndex(p.layer)].name = p.from;
|
|
218
|
-
}
|
|
219
|
-
});
|
|
220
|
-
/** Finds the layer by id, not by where the payload last left it: moves of
|
|
221
|
-
* one layer coalesce, and the entry then reverts the first payload from
|
|
222
|
-
* wherever the last one put the layer. */
|
|
223
|
-
function placeLayer(layer, index) {
|
|
224
|
-
const [rec] = state.layers.splice(requireLayerIndex(layer), 1);
|
|
225
|
-
state.layers.splice(index, 0, rec);
|
|
226
|
-
rebuildLayerIndex();
|
|
227
|
-
}
|
|
228
|
-
registerKitOp("kit:moveLayer", {
|
|
229
|
-
apply: (p) => placeLayer(p.layer, p.to),
|
|
230
|
-
revert: (p) => placeLayer(p.layer, p.from)
|
|
231
|
-
});
|
|
165
|
+
registerLayerOps(env);
|
|
232
166
|
return { layoutRefs };
|
|
233
167
|
}
|
|
234
168
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kitOps.js","names":[],"sources":["../../../src/core/scene/kitOps.ts"],"sourcesContent":["/**\n * The kit's own op kinds: `kit:add`, `kit:remove`, `kit:setPose`, and the\n * rest. They are registered like any other op; the scene's mutation methods\n * build serializable payloads and route through the same log and replay\n * machinery a consumer's ops do.\n */\nimport type { UnitScope } from '@weasel-js/quantity';\nimport type { ParallaxOpts } from 'core/viewport/parallax';\nimport { dwarn } from 'debug/flag';\nimport type { LayoutStrategy } from '../../layout/types';\nimport { restoreFn, type FnBearingNode, type NodeFnField } from './nodeFnFields';\nimport { statedFields } from './statedFields';\nimport type { createNodeStore } from './nodeStore';\nimport type {\n LayerRecord, Node, NodeClip, NodeId, RegisteredOp, UserLayerRecord,\n} from './types';\n\n/**\n * Snapshot of every node a removal deletes, so revert restores it exactly.\n *\n * A cascade unlinks several disjoint subtrees, not one, so `detached` names\n * each node the tree has to re-link; everything else in `nodes` has a parent\n * that is also going and rides back in that parent's cloned `children`.\n * Entries are sorted by ascending sibling index — globally rather than\n * per-parent, because only same-parent order constrains re-insertion and\n * entries under different parents never interact.\n */\nexport interface RemoveSnapshot<TData, TLayer extends string, TPose> {\n nodes: Node<TData, TLayer, TPose>[];\n detached: { id: NodeId; parent: NodeId | null; index: number }[];\n /** Registry keys for the function-valued fields on `nodes`. The functions\n * themselves do not survive a persisted history, so revert re-resolves\n * them the way `kit:add` does. */\n fnKeys?: ({ id: NodeId } & Record<string, string | undefined>)[];\n}\n\n/** What a `kit:setLayout` op carries: the container, and each side's layout\n * by registry key when it has one. */\nexport interface SetLayoutPayload { id: NodeId; fromKey?: string; toKey?: string }\n\n/** What the op table needs from the scene it mutates. */\nexport interface KitOpsEnv<TData, TLayer extends string, TPose> {\n state: {\n nodes: Map<NodeId, Node<TData, TLayer, TPose>>;\n layers: LayerRecord<TLayer>[];\n };\n register(kind: string, handler: RegisteredOp<unknown>): void;\n store: ReturnType<typeof createNodeStore<TData, TLayer, TPose>>;\n requireLayerIndex(layer: TLayer): number;\n rebuildLayerIndex(): void;\n invalidateOrder(): void;\n fnFields: readonly NodeFnField[];\n /** Drop from the selection whatever a lock or a hide just put out of\n * reach, and the ids in `gone`. */\n narrowSelection(gone?: ReadonlySet<NodeId>): void;\n /** Drop the pose override of a node that is about to leave the scene: ids\n * are reusable, and one left behind would attach itself to whatever is\n * added under that id next. */\n clearOverride(id: NodeId): void;\n}\n\nfunction setParallax(record: { parallax?: ParallaxOpts }, to: ParallaxOpts | undefined): void {\n if (to === undefined) delete record.parallax;\n else record.parallax = to;\n}\n\n/** Register every kit op kind. Answers with the table a live `kit:setLayout`\n * payload's strategies are kept in, which `scene.setLayout` fills. */\nexport function registerKitOps<TData, TLayer extends string, TPose>(\n env: KitOpsEnv<TData, TLayer, TPose>,\n): {\n layoutRefs: WeakMap<object, { from: LayoutStrategy<TPose> | null; to: LayoutStrategy<TPose> | null }>;\n} {\n const { state, requireLayerIndex, rebuildLayerIndex, invalidateOrder, fnFields } = env;\n const {\n dependents, childDerived, invalidateDependents, invalidateChildDerivedFrom, trackChildDerived, retarget,\n requireNode, detach, attach, addedFns, restoreNodeFunctions,\n } = env.store;\n\n function registerKitOp<P>(kind: string, handler: RegisteredOp<P>): void {\n env.register(kind, handler as RegisteredOp<unknown>);\n }\n\n registerKitOp<{\n id: NodeId; kind: 'mark' | 'group'; layer: TLayer; pose: TPose; data: TData;\n parent: NodeId | null; index: number;\n dependsOn?: readonly NodeId[] | 'children';\n pickable?: boolean; hidden?: boolean; locked?: boolean;\n units?: UnitScope; clip?: NodeClip;\n } & Record<string, unknown>>('kit:add', {\n apply: (p) => {\n if (state.nodes.has(p.id)) {\n throw new Error(`Scene: id collision on \"${p.id}\"`);\n }\n const node = {\n kind: p.kind, id: p.id, layer: p.layer, pose: p.pose, data: p.data, parent: p.parent,\n } as Node<TData, TLayer, TPose>;\n state.nodes.set(p.id, node);\n attach(p.id, p.parent, p.index);\n if (p.dependsOn !== undefined) node.dependsOn = p.dependsOn;\n Object.assign(node, statedFields(p));\n dependents.add(p.id, p.dependsOn === 'children' ? [] : p.dependsOn ?? []);\n trackChildDerived(p.id, p.dependsOn);\n // Two ways a function field comes back. Redo of a live add reads\n // what `scene.add` attached, since it replays the op without a spec.\n // A restored history has only the registry key the payload carries.\n const target = node as unknown as FnBearingNode;\n const attached = addedFns.get(p);\n for (const field of fnFields) {\n const fn = attached?.get(field);\n if (fn !== undefined) {\n field.write(target, fn);\n continue;\n }\n const key = p[field.spec.opKey] as string | undefined;\n if (key !== undefined) restoreFn(field, target, key, 'kit:add', dwarn);\n }\n invalidateDependents(p.id);\n },\n revert: (p) => {\n env.clearOverride(p.id);\n detach(p.id);\n state.nodes.delete(p.id);\n dependents.remove(p.id);\n childDerived.delete(p.id);\n invalidateChildDerivedFrom(p.parent);\n invalidateDependents(p.id);\n },\n });\n\n // Neither half invalidates dependents: removal's closure takes every live one.\n registerKitOp<RemoveSnapshot<TData, TLayer, TPose>>('kit:remove', {\n apply: (p) => {\n for (const n of p.nodes) env.clearOverride(n.id);\n for (const d of p.detached) detach(d.id);\n for (const n of p.nodes) {\n state.nodes.delete(n.id);\n dependents.remove(n.id);\n childDerived.delete(n.id);\n }\n // A `dependsOn: 'children'` container the removal did not take is now\n // hugging a smaller set.\n for (const d of p.detached) invalidateChildDerivedFrom(d.parent);\n env.narrowSelection(new Set(p.nodes.map((n) => n.id)));\n },\n revert: (p) => {\n const keys = new Map((p.fnKeys ?? []).map((k) => [k.id, k]));\n // Order-independent: every clone carries its own parent and children.\n for (const n of p.nodes) {\n const clone: Node<TData, TLayer, TPose> = n.children\n ? { ...n, children: [...n.children] }\n : { ...n };\n restoreNodeFunctions(clone, keys.get(n.id));\n state.nodes.set(n.id, clone);\n dependents.add(n.id, clone.dependsOn === 'children' ? [] : clone.dependsOn ?? []);\n trackChildDerived(n.id, clone.dependsOn);\n }\n for (const d of p.detached) attach(d.id, d.parent, d.index);\n for (const d of p.detached) invalidateChildDerivedFrom(d.parent);\n },\n });\n\n registerKitOp<{ id: NodeId; from: TPose; to: TPose }>('kit:setPose', {\n apply: (p) => {\n (requireNode(p.id) as { pose: TPose }).pose = p.to;\n invalidateDependents(p.id);\n },\n revert: (p) => {\n (requireNode(p.id) as { pose: TPose }).pose = p.from;\n invalidateDependents(p.id);\n },\n });\n\n // A derivation is handed its dependencies' nodes, not only their poses, so a\n // connector reading `data` or `layer` goes stale on these two exactly as it\n // does on a move.\n registerKitOp<{ id: NodeId; from: TData; to: TData }>('kit:setData', {\n apply: (p) => {\n (requireNode(p.id) as { data: TData }).data = p.to;\n invalidateDependents(p.id);\n },\n revert: (p) => {\n (requireNode(p.id) as { data: TData }).data = p.from;\n invalidateDependents(p.id);\n },\n });\n\n registerKitOp<{ id: NodeId; from: TLayer; to: TLayer }>('kit:setLayer', {\n apply: (p) => {\n requireLayerIndex(p.to);\n (requireNode(p.id) as { layer: TLayer }).layer = p.to;\n invalidateOrder();\n invalidateDependents(p.id);\n },\n revert: (p) => {\n (requireNode(p.id) as { layer: TLayer }).layer = p.from;\n invalidateOrder();\n invalidateDependents(p.id);\n },\n });\n\n registerKitOp<{\n id: NodeId;\n from: Node<TData, TLayer, TPose>['dependsOn'];\n to: Node<TData, TLayer, TPose>['dependsOn'];\n }>('kit:setDependsOn', {\n apply: (p) => { retarget(p.id, p.to); },\n revert: (p) => { retarget(p.id, p.from); },\n });\n\n /** The strategies each live `kit:setLayout` payload swaps between. A payload\n * replayed from a persisted history has none, and resolves its keys. */\n const layoutRefs = new WeakMap<object, { from: LayoutStrategy<TPose> | null; to: LayoutStrategy<TPose> | null }>();\n function placeLayout(p: SetLayoutPayload, side: 'from' | 'to'): void {\n const node = requireNode(p.id) as unknown as FnBearingNode;\n const field = fnFields.find((f) => f.spec.field === 'layout')!;\n const live = layoutRefs.get(p);\n const key = side === 'from' ? p.fromKey : p.toKey;\n if (live === undefined && key !== undefined) {\n delete node.layout;\n restoreFn(field, node, key, 'kit:setLayout', dwarn);\n return;\n }\n const layout = live?.[side] ?? null;\n if (layout === null) delete node.layout;\n else field.write(node, layout);\n }\n registerKitOp<SetLayoutPayload>('kit:setLayout', {\n apply: (p) => { placeLayout(p, 'to'); },\n revert: (p) => { placeLayout(p, 'from'); },\n });\n\n registerKitOp<{\n id: NodeId; fromParent: NodeId | null; fromIndex: number;\n toParent: NodeId | null; toIndex: number;\n }>('kit:move', {\n apply: (p) => {\n detach(p.id);\n attach(p.id, p.toParent, p.toIndex);\n // Both ends: the container it left no longer hugs it, and the one it\n // joined now does.\n invalidateChildDerivedFrom(p.fromParent);\n invalidateDependents(p.id);\n },\n revert: (p) => {\n detach(p.id);\n attach(p.id, p.fromParent, p.fromIndex);\n invalidateChildDerivedFrom(p.toParent);\n invalidateDependents(p.id);\n },\n });\n\n registerKitOp<{ layer: TLayer; from: boolean; to: boolean }>('kit:setLayerVisible', {\n apply: (p) => { state.layers[requireLayerIndex(p.layer)].visible = p.to; if (!p.to) env.narrowSelection(); },\n revert: (p) => { state.layers[requireLayerIndex(p.layer)].visible = p.from; },\n });\n\n registerKitOp<{ layer: TLayer; from: boolean; to: boolean }>('kit:setLayerLocked', {\n apply: (p) => { state.layers[requireLayerIndex(p.layer)].locked = p.to; if (p.to) env.narrowSelection(); },\n revert: (p) => { state.layers[requireLayerIndex(p.layer)].locked = p.from; },\n });\n\n registerKitOp<{ layer: TLayer; from?: ParallaxOpts; to?: ParallaxOpts }>('kit:setLayerParallax', {\n apply: (p) => { setParallax(state.layers[requireLayerIndex(p.layer)], p.to); },\n revert: (p) => { setParallax(state.layers[requireLayerIndex(p.layer)], p.from); },\n });\n\n registerKitOp<{ record: UserLayerRecord<TLayer>; index: number }>('kit:addLayer', {\n apply: (p) => { state.layers.splice(p.index, 0, { ...p.record }); rebuildLayerIndex(); },\n revert: (p) => { state.layers.splice(p.index, 1); rebuildLayerIndex(); },\n });\n\n registerKitOp<{ record: LayerRecord<TLayer>; index: number }>('kit:removeLayer', {\n apply: (p) => { state.layers.splice(p.index, 1); rebuildLayerIndex(); },\n revert: (p) => { state.layers.splice(p.index, 0, { ...p.record } as LayerRecord<TLayer>); rebuildLayerIndex(); },\n });\n\n registerKitOp<{ layer: TLayer; from: string; to: string }>('kit:renameLayer', {\n apply: (p) => { (state.layers[requireLayerIndex(p.layer)] as UserLayerRecord<TLayer>).name = p.to; },\n revert: (p) => { (state.layers[requireLayerIndex(p.layer)] as UserLayerRecord<TLayer>).name = p.from; },\n });\n\n /** Finds the layer by id, not by where the payload last left it: moves of\n * one layer coalesce, and the entry then reverts the first payload from\n * wherever the last one put the layer. */\n function placeLayer(layer: TLayer, index: number): void {\n const [rec] = state.layers.splice(requireLayerIndex(layer), 1);\n state.layers.splice(index, 0, rec);\n rebuildLayerIndex();\n }\n\n registerKitOp<{ layer: TLayer; from: number; to: number }>('kit:moveLayer', {\n apply: (p) => placeLayer(p.layer, p.to),\n revert: (p) => placeLayer(p.layer, p.from),\n });\n\n return { layoutRefs };\n}\n"],"mappings":";;;;;AA6DA,SAAS,YAAY,QAAqC,IAAoC;CAC5F,IAAI,OAAO,QAAW,OAAO,OAAO;MAC/B,OAAO,WAAW;AACzB;;;AAIA,SAAgB,eACd,KAGA;CACA,MAAM,EAAE,OAAO,mBAAmB,mBAAmB,iBAAiB,aAAa;CACnF,MAAM,EACJ,YAAY,cAAc,sBAAsB,4BAA4B,mBAAmB,UAC/F,aAAa,QAAQ,QAAQ,UAAU,yBACrC,IAAI;CAER,SAAS,cAAiB,MAAc,SAAgC;EACtE,IAAI,SAAS,MAAM,OAAgC;CACrD;CAEA,cAM6B,WAAW;EACtC,QAAQ,MAAM;GACZ,IAAI,MAAM,MAAM,IAAI,EAAE,EAAE,GACtB,MAAM,IAAI,MAAM,2BAA2B,EAAE,GAAG,EAAE;GAEpD,MAAM,OAAO;IACX,MAAM,EAAE;IAAM,IAAI,EAAE;IAAI,OAAO,EAAE;IAAO,MAAM,EAAE;IAAM,MAAM,EAAE;IAAM,QAAQ,EAAE;GAChF;GACA,MAAM,MAAM,IAAI,EAAE,IAAI,IAAI;GAC1B,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK;GAC9B,IAAI,EAAE,cAAc,QAAW,KAAK,YAAY,EAAE;GAClD,OAAO,OAAO,MAAM,aAAa,CAAC,CAAC;GACnC,WAAW,IAAI,EAAE,IAAI,EAAE,cAAc,aAAa,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;GACxE,kBAAkB,EAAE,IAAI,EAAE,SAAS;GAInC,MAAM,SAAS;GACf,MAAM,WAAW,SAAS,IAAI,CAAC;GAC/B,KAAK,MAAM,SAAS,UAAU;IAC5B,MAAM,KAAK,UAAU,IAAI,KAAK;IAC9B,IAAI,OAAO,QAAW;KACpB,MAAM,MAAM,QAAQ,EAAE;KACtB;IACF;IACA,MAAM,MAAM,EAAE,MAAM,KAAK;IACzB,IAAI,QAAQ,QAAW,UAAU,OAAO,QAAQ,KAAK,WAAW,KAAK;GACvE;GACA,qBAAqB,EAAE,EAAE;EAC3B;EACA,SAAS,MAAM;GACb,IAAI,cAAc,EAAE,EAAE;GACtB,OAAO,EAAE,EAAE;GACX,MAAM,MAAM,OAAO,EAAE,EAAE;GACvB,WAAW,OAAO,EAAE,EAAE;GACtB,aAAa,OAAO,EAAE,EAAE;GACxB,2BAA2B,EAAE,MAAM;GACnC,qBAAqB,EAAE,EAAE;EAC3B;CACF,CAAC;CAGD,cAAoD,cAAc;EAChE,QAAQ,MAAM;GACZ,KAAK,MAAM,KAAK,EAAE,OAAO,IAAI,cAAc,EAAE,EAAE;GAC/C,KAAK,MAAM,KAAK,EAAE,UAAU,OAAO,EAAE,EAAE;GACvC,KAAK,MAAM,KAAK,EAAE,OAAO;IACvB,MAAM,MAAM,OAAO,EAAE,EAAE;IACvB,WAAW,OAAO,EAAE,EAAE;IACtB,aAAa,OAAO,EAAE,EAAE;GAC1B;GAGA,KAAK,MAAM,KAAK,EAAE,UAAU,2BAA2B,EAAE,MAAM;GAC/D,IAAI,gBAAgB,IAAI,IAAI,EAAE,MAAM,KAAK,MAAM,EAAE,EAAE,CAAC,CAAC;EACvD;EACA,SAAS,MAAM;GACb,MAAM,OAAO,IAAI,KAAK,EAAE,UAAU,CAAC,EAAA,CAAG,KAAK,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;GAE3D,KAAK,MAAM,KAAK,EAAE,OAAO;IACvB,MAAM,QAAoC,EAAE,WACxC;KAAE,GAAG;KAAG,UAAU,CAAC,GAAG,EAAE,QAAQ;IAAE,IAClC,EAAE,GAAG,EAAE;IACX,qBAAqB,OAAO,KAAK,IAAI,EAAE,EAAE,CAAC;IAC1C,MAAM,MAAM,IAAI,EAAE,IAAI,KAAK;IAC3B,WAAW,IAAI,EAAE,IAAI,MAAM,cAAc,aAAa,CAAC,IAAI,MAAM,aAAa,CAAC,CAAC;IAChF,kBAAkB,EAAE,IAAI,MAAM,SAAS;GACzC;GACA,KAAK,MAAM,KAAK,EAAE,UAAU,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK;GAC1D,KAAK,MAAM,KAAK,EAAE,UAAU,2BAA2B,EAAE,MAAM;EACjE;CACF,CAAC;CAED,cAAsD,eAAe;EACnE,QAAQ,MAAM;GACZ,YAAa,EAAE,EAAE,CAAC,CAAqB,OAAO,EAAE;GAChD,qBAAqB,EAAE,EAAE;EAC3B;EACA,SAAS,MAAM;GACb,YAAa,EAAE,EAAE,CAAC,CAAqB,OAAO,EAAE;GAChD,qBAAqB,EAAE,EAAE;EAC3B;CACF,CAAC;CAKD,cAAsD,eAAe;EACnE,QAAQ,MAAM;GACZ,YAAa,EAAE,EAAE,CAAC,CAAqB,OAAO,EAAE;GAChD,qBAAqB,EAAE,EAAE;EAC3B;EACA,SAAS,MAAM;GACb,YAAa,EAAE,EAAE,CAAC,CAAqB,OAAO,EAAE;GAChD,qBAAqB,EAAE,EAAE;EAC3B;CACF,CAAC;CAED,cAAwD,gBAAgB;EACtE,QAAQ,MAAM;GACZ,kBAAkB,EAAE,EAAE;GACtB,YAAa,EAAE,EAAE,CAAC,CAAuB,QAAQ,EAAE;GACnD,gBAAgB;GAChB,qBAAqB,EAAE,EAAE;EAC3B;EACA,SAAS,MAAM;GACb,YAAa,EAAE,EAAE,CAAC,CAAuB,QAAQ,EAAE;GACnD,gBAAgB;GAChB,qBAAqB,EAAE,EAAE;EAC3B;CACF,CAAC;CAED,cAIG,oBAAoB;EACrB,QAAQ,MAAM;GAAE,SAAS,EAAE,IAAI,EAAE,EAAE;EAAG;EACtC,SAAS,MAAM;GAAE,SAAS,EAAE,IAAI,EAAE,IAAI;EAAG;CAC3C,CAAC;;;CAID,MAAM,6BAAa,IAAI,QAA0F;CACjH,SAAS,YAAY,GAAqB,MAA2B;EACnE,MAAM,OAAO,YAAY,EAAE,EAAE;EAC7B,MAAM,QAAQ,SAAS,MAAM,MAAM,EAAE,KAAK,UAAU,QAAQ;EAC5D,MAAM,OAAO,WAAW,IAAI,CAAC;EAC7B,MAAM,MAAM,SAAS,SAAS,EAAE,UAAU,EAAE;EAC5C,IAAI,SAAS,UAAa,QAAQ,QAAW;GAC3C,OAAO,KAAK;GACZ,UAAU,OAAO,MAAM,KAAK,iBAAiB,KAAK;GAClD;EACF;EACA,MAAM,SAAS,OAAO,SAAS;EAC/B,IAAI,WAAW,MAAM,OAAO,KAAK;OAC5B,MAAM,MAAM,MAAM,MAAM;CAC/B;CACA,cAAgC,iBAAiB;EAC/C,QAAQ,MAAM;GAAE,YAAY,GAAG,IAAI;EAAG;EACtC,SAAS,MAAM;GAAE,YAAY,GAAG,MAAM;EAAG;CAC3C,CAAC;CAED,cAGG,YAAY;EACb,QAAQ,MAAM;GACZ,OAAO,EAAE,EAAE;GACX,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO;GAGlC,2BAA2B,EAAE,UAAU;GACvC,qBAAqB,EAAE,EAAE;EAC3B;EACA,SAAS,MAAM;GACb,OAAO,EAAE,EAAE;GACX,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS;GACtC,2BAA2B,EAAE,QAAQ;GACrC,qBAAqB,EAAE,EAAE;EAC3B;CACF,CAAC;CAED,cAA6D,uBAAuB;EAClF,QAAQ,MAAM;GAAE,MAAM,OAAO,kBAAkB,EAAE,KAAK,EAAE,CAAC,UAAU,EAAE;GAAI,IAAI,CAAC,EAAE,IAAI,IAAI,gBAAgB;EAAG;EAC3G,SAAS,MAAM;GAAE,MAAM,OAAO,kBAAkB,EAAE,KAAK,EAAE,CAAC,UAAU,EAAE;EAAM;CAC9E,CAAC;CAED,cAA6D,sBAAsB;EACjF,QAAQ,MAAM;GAAE,MAAM,OAAO,kBAAkB,EAAE,KAAK,EAAE,CAAC,SAAS,EAAE;GAAI,IAAI,EAAE,IAAI,IAAI,gBAAgB;EAAG;EACzG,SAAS,MAAM;GAAE,MAAM,OAAO,kBAAkB,EAAE,KAAK,EAAE,CAAC,SAAS,EAAE;EAAM;CAC7E,CAAC;CAED,cAAyE,wBAAwB;EAC/F,QAAQ,MAAM;GAAE,YAAY,MAAM,OAAO,kBAAkB,EAAE,KAAK,IAAI,EAAE,EAAE;EAAG;EAC7E,SAAS,MAAM;GAAE,YAAY,MAAM,OAAO,kBAAkB,EAAE,KAAK,IAAI,EAAE,IAAI;EAAG;CAClF,CAAC;CAED,cAAkE,gBAAgB;EAChF,QAAQ,MAAM;GAAE,MAAM,OAAO,OAAO,EAAE,OAAO,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC;GAAG,kBAAkB;EAAG;EACvF,SAAS,MAAM;GAAE,MAAM,OAAO,OAAO,EAAE,OAAO,CAAC;GAAG,kBAAkB;EAAG;CACzE,CAAC;CAED,cAA8D,mBAAmB;EAC/E,QAAQ,MAAM;GAAE,MAAM,OAAO,OAAO,EAAE,OAAO,CAAC;GAAG,kBAAkB;EAAG;EACtE,SAAS,MAAM;GAAE,MAAM,OAAO,OAAO,EAAE,OAAO,GAAG,EAAE,GAAG,EAAE,OAAO,CAAwB;GAAG,kBAAkB;EAAG;CACjH,CAAC;CAED,cAA2D,mBAAmB;EAC5E,QAAQ,MAAM;GAAE,MAAO,OAAO,kBAAkB,EAAE,KAAK,EAAE,CAA6B,OAAO,EAAE;EAAI;EACnG,SAAS,MAAM;GAAE,MAAO,OAAO,kBAAkB,EAAE,KAAK,EAAE,CAA6B,OAAO,EAAE;EAAM;CACxG,CAAC;;;;CAKD,SAAS,WAAW,OAAe,OAAqB;EACtD,MAAM,CAAC,OAAO,MAAM,OAAO,OAAO,kBAAkB,KAAK,GAAG,CAAC;EAC7D,MAAM,OAAO,OAAO,OAAO,GAAG,GAAG;EACjC,kBAAkB;CACpB;CAEA,cAA2D,iBAAiB;EAC1E,QAAQ,MAAM,WAAW,EAAE,OAAO,EAAE,EAAE;EACtC,SAAS,MAAM,WAAW,EAAE,OAAO,EAAE,IAAI;CAC3C,CAAC;CAED,OAAO,EAAE,WAAW;AACtB"}
|
|
1
|
+
{"version":3,"file":"kitOps.js","names":[],"sources":["../../../src/core/scene/kitOps.ts"],"sourcesContent":["/**\n * The kit's own op kinds: `kit:add`, `kit:remove`, `kit:setPose`, and the\n * rest. They are registered like any other op; the scene's mutation methods\n * build serializable payloads and route through the same log and replay\n * machinery a consumer's ops do.\n */\nimport type { UnitScope } from '@weasel-js/quantity';\nimport { dwarn } from 'debug/flag';\nimport type { LayoutStrategy } from '../../layout/types';\nimport { registerLayerOps } from './layerOps';\nimport { restoreFn, type FnBearingNode, type NodeFnField } from './nodeFnFields';\nimport { statedFields } from './statedFields';\nimport type { createNodeStore } from './nodeStore';\nimport type {\n LayerRecord, Node, NodeClip, NodeId, RegisteredOp,\n} from './types';\n\n/**\n * Snapshot of every node a removal deletes, so revert restores it exactly.\n *\n * A cascade unlinks several disjoint subtrees, not one, so `detached` names\n * each node the tree has to re-link; everything else in `nodes` has a parent\n * that is also going and rides back in that parent's cloned `children`.\n * Entries are sorted by ascending sibling index — globally rather than\n * per-parent, because only same-parent order constrains re-insertion and\n * entries under different parents never interact.\n */\nexport interface RemoveSnapshot<TData, TLayer extends string, TPose> {\n nodes: Node<TData, TLayer, TPose>[];\n detached: { id: NodeId; parent: NodeId | null; index: number }[];\n /** Registry keys for the function-valued fields on `nodes`. The functions\n * themselves do not survive a persisted history, so revert re-resolves\n * them the way `kit:add` does. */\n fnKeys?: ({ id: NodeId } & Record<string, string | undefined>)[];\n}\n\n/** What a `kit:setLayout` op carries: the container, and each side's layout\n * by registry key when it has one. */\nexport interface SetLayoutPayload { id: NodeId; fromKey?: string; toKey?: string }\n\n/** What the op table needs from the scene it mutates. */\nexport interface KitOpsEnv<TData, TLayer extends string, TPose> {\n state: {\n nodes: Map<NodeId, Node<TData, TLayer, TPose>>;\n layers: LayerRecord<TLayer>[];\n };\n register(kind: string, handler: RegisteredOp<unknown>): void;\n store: ReturnType<typeof createNodeStore<TData, TLayer, TPose>>;\n requireLayerIndex(layer: TLayer): number;\n rebuildLayerIndex(): void;\n invalidateOrder(): void;\n fnFields: readonly NodeFnField[];\n /** Drop from the selection whatever a lock or a hide just put out of\n * reach, and the ids in `gone`. */\n narrowSelection(gone?: ReadonlySet<NodeId>): void;\n /** Drop the pose override of a node that is about to leave the scene: ids\n * are reusable, and one left behind would attach itself to whatever is\n * added under that id next. */\n clearOverride(id: NodeId): void;\n /** See `LockGuard.noteWritten`. */\n noteWritten(node: Node<TData, TLayer, TPose>): void;\n}\n\n/** Register every kit op kind. Answers with the table a live `kit:setLayout`\n * payload's strategies are kept in, which `scene.setLayout` fills. */\nexport function registerKitOps<TData, TLayer extends string, TPose>(\n env: KitOpsEnv<TData, TLayer, TPose>,\n): {\n layoutRefs: WeakMap<object, { from: LayoutStrategy<TPose> | null; to: LayoutStrategy<TPose> | null }>;\n} {\n const { state, requireLayerIndex, invalidateOrder, fnFields } = env;\n const {\n dependents, childDerived, invalidateDependents, invalidateChildDerivedFrom, trackChildDerived, retarget,\n requireNode, detach, attach, addedFns, restoreNodeFunctions,\n } = env.store;\n\n function registerKitOp<P>(kind: string, handler: RegisteredOp<P>): void {\n env.register(kind, handler as RegisteredOp<unknown>);\n }\n\n registerKitOp<{\n id: NodeId; kind: 'mark' | 'group'; layer: TLayer; pose: TPose; data: TData;\n parent: NodeId | null; index: number;\n dependsOn?: readonly NodeId[] | 'children';\n pickable?: boolean; hidden?: boolean; locked?: boolean;\n units?: UnitScope; clip?: NodeClip; consumesChildren?: boolean;\n } & Record<string, unknown>>('kit:add', {\n apply: (p) => {\n if (state.nodes.has(p.id)) {\n throw new Error(`Scene: id collision on \"${p.id}\"`);\n }\n const node = {\n kind: p.kind, id: p.id, layer: p.layer, pose: p.pose, data: p.data, parent: p.parent,\n } as Node<TData, TLayer, TPose>;\n state.nodes.set(p.id, node);\n attach(p.id, p.parent, p.index);\n if (p.dependsOn !== undefined) node.dependsOn = p.dependsOn;\n Object.assign(node, statedFields(p));\n env.noteWritten(node);\n dependents.add(p.id, p.dependsOn === 'children' ? [] : p.dependsOn ?? []);\n trackChildDerived(p.id, p.dependsOn);\n // Two ways a function field comes back. Redo of a live add reads\n // what `scene.add` attached, since it replays the op without a spec.\n // A restored history has only the registry key the payload carries.\n const target = node as unknown as FnBearingNode;\n const attached = addedFns.get(p);\n for (const field of fnFields) {\n const fn = attached?.get(field);\n if (fn !== undefined) {\n field.write(target, fn);\n continue;\n }\n const key = p[field.spec.opKey] as string | undefined;\n if (key !== undefined) restoreFn(field, target, key, 'kit:add', dwarn);\n }\n invalidateDependents(p.id);\n },\n revert: (p) => {\n env.clearOverride(p.id);\n detach(p.id);\n state.nodes.delete(p.id);\n dependents.remove(p.id);\n childDerived.delete(p.id);\n invalidateChildDerivedFrom(p.parent);\n invalidateDependents(p.id);\n },\n });\n\n // Neither half invalidates dependents: removal's closure takes every live one.\n registerKitOp<RemoveSnapshot<TData, TLayer, TPose>>('kit:remove', {\n apply: (p) => {\n for (const n of p.nodes) env.clearOverride(n.id);\n for (const d of p.detached) detach(d.id);\n for (const n of p.nodes) {\n state.nodes.delete(n.id);\n dependents.remove(n.id);\n childDerived.delete(n.id);\n }\n // A `dependsOn: 'children'` container the removal did not take is now\n // hugging a smaller set.\n for (const d of p.detached) invalidateChildDerivedFrom(d.parent);\n env.narrowSelection(new Set(p.nodes.map((n) => n.id)));\n },\n revert: (p) => {\n const keys = new Map((p.fnKeys ?? []).map((k) => [k.id, k]));\n // Order-independent: every clone carries its own parent and children.\n for (const n of p.nodes) {\n const clone: Node<TData, TLayer, TPose> = n.children\n ? { ...n, children: [...n.children] }\n : { ...n };\n restoreNodeFunctions(clone, keys.get(n.id));\n state.nodes.set(n.id, clone);\n env.noteWritten(clone);\n dependents.add(n.id, clone.dependsOn === 'children' ? [] : clone.dependsOn ?? []);\n trackChildDerived(n.id, clone.dependsOn);\n }\n for (const d of p.detached) attach(d.id, d.parent, d.index);\n for (const d of p.detached) invalidateChildDerivedFrom(d.parent);\n },\n });\n\n registerKitOp<{ id: NodeId; from: TPose; to: TPose }>('kit:setPose', {\n apply: (p) => {\n (requireNode(p.id) as { pose: TPose }).pose = p.to;\n invalidateDependents(p.id);\n },\n revert: (p) => {\n (requireNode(p.id) as { pose: TPose }).pose = p.from;\n invalidateDependents(p.id);\n },\n });\n\n // A derivation is handed its dependencies' nodes, not only their poses, so a\n // connector reading `data` or `layer` goes stale on these two exactly as it\n // does on a move.\n registerKitOp<{ id: NodeId; from: TData; to: TData }>('kit:setData', {\n apply: (p) => {\n (requireNode(p.id) as { data: TData }).data = p.to;\n invalidateDependents(p.id);\n },\n revert: (p) => {\n (requireNode(p.id) as { data: TData }).data = p.from;\n invalidateDependents(p.id);\n },\n });\n\n registerKitOp<{ id: NodeId; from: TLayer; to: TLayer }>('kit:setLayer', {\n apply: (p) => {\n requireLayerIndex(p.to);\n (requireNode(p.id) as { layer: TLayer }).layer = p.to;\n invalidateOrder();\n invalidateDependents(p.id);\n },\n revert: (p) => {\n (requireNode(p.id) as { layer: TLayer }).layer = p.from;\n invalidateOrder();\n invalidateDependents(p.id);\n },\n });\n\n registerKitOp<{\n id: NodeId;\n from: Node<TData, TLayer, TPose>['dependsOn'];\n to: Node<TData, TLayer, TPose>['dependsOn'];\n }>('kit:setDependsOn', {\n apply: (p) => { retarget(p.id, p.to); },\n revert: (p) => { retarget(p.id, p.from); },\n });\n\n /** The strategies each live `kit:setLayout` payload swaps between. A payload\n * replayed from a persisted history has none, and resolves its keys. */\n const layoutRefs = new WeakMap<object, { from: LayoutStrategy<TPose> | null; to: LayoutStrategy<TPose> | null }>();\n function placeLayout(p: SetLayoutPayload, side: 'from' | 'to'): void {\n const node = requireNode(p.id) as unknown as FnBearingNode;\n const field = fnFields.find((f) => f.spec.field === 'layout')!;\n const live = layoutRefs.get(p);\n const key = side === 'from' ? p.fromKey : p.toKey;\n if (live === undefined && key !== undefined) {\n delete node.layout;\n restoreFn(field, node, key, 'kit:setLayout', dwarn);\n return;\n }\n const layout = live?.[side] ?? null;\n if (layout === null) delete node.layout;\n else field.write(node, layout);\n }\n registerKitOp<SetLayoutPayload>('kit:setLayout', {\n apply: (p) => { placeLayout(p, 'to'); },\n revert: (p) => { placeLayout(p, 'from'); },\n });\n\n registerKitOp<{\n id: NodeId; fromParent: NodeId | null; fromIndex: number;\n toParent: NodeId | null; toIndex: number;\n }>('kit:move', {\n apply: (p) => {\n detach(p.id);\n attach(p.id, p.toParent, p.toIndex);\n // Both ends: the container it left no longer hugs it, and the one it\n // joined now does.\n invalidateChildDerivedFrom(p.fromParent);\n invalidateDependents(p.id);\n },\n revert: (p) => {\n detach(p.id);\n attach(p.id, p.fromParent, p.fromIndex);\n invalidateChildDerivedFrom(p.toParent);\n invalidateDependents(p.id);\n },\n });\n\n registerLayerOps(env);\n\n return { layoutRefs };\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { unionAABB } from "../geometry/unionBounds.js";
|
|
2
|
+
import { BOOLEAN_OF_CHILDREN, booleanOfChildren } from "./booleanOfChildren.js";
|
|
2
3
|
import { CLIP_NOTHING, clipNothing } from "./clipNothing.js";
|
|
3
4
|
|
|
4
5
|
//#region src/core/scene/kitRegistry.ts
|
|
@@ -53,6 +54,10 @@ function withKitRegistry(registry) {
|
|
|
53
54
|
[CLIP_NOTHING]: clipNothing,
|
|
54
55
|
...registry.clipFromPose
|
|
55
56
|
},
|
|
57
|
+
derivePath: {
|
|
58
|
+
[BOOLEAN_OF_CHILDREN]: booleanOfChildren,
|
|
59
|
+
...registry.derivePath
|
|
60
|
+
},
|
|
56
61
|
derivePose: {
|
|
57
62
|
[UNION_OF_CHILDREN]: unionOfChildren,
|
|
58
63
|
...registry.derivePose
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kitRegistry.js","names":[],"sources":["../../../src/core/scene/kitRegistry.ts"],"sourcesContent":["/**\n * The `SceneRegistry` entries the kit owns.\n *\n * A registry-keyed function has to be resolvable by key in whatever scene\n * loads a snapshot, so a function the *kit* attaches to a node cannot live in\n * the consumer's registry alone — a document saved with a grouped container\n * would come back with a dead key. `createScene` merges these under the\n * consumer's, which stays the winner on a key collision.\n */\nimport { unionAABB } from '../geometry/unionBounds';\nimport type { RectPose, SceneRegistry } from './types';\nimport { CLIP_NOTHING, clipNothing } from './clipNothing';\n\n/** Registry key for {@link unionOfChildren}. */\nexport const UNION_OF_CHILDREN = 'kit:unionOfChildren';\n\n/**\n * A container's pose as the envelope of what it holds — `unionAABB`, so a\n * rotated member contributes the extent of its ink rather than its unrotated\n * box. Paired with `dependsOn: 'children'`, this is what makes a group's\n * bounds track its members.\n *\n * Returns `null` for an emptied container, which falls back to its authored\n * pose.\n *\n * Reads members as rect poses only: a scene whose poses are shaped otherwise\n * gets `null` here and its container keeps its authored pose. To make such a\n * container track its members, register `unionOfChildrenVia(itsDescriptor)`\n * under {@link UNION_OF_CHILDREN} — the consumer's entry wins the collision.\n */\nexport function unionOfChildren<TPose>(\n _node: unknown,\n deps: readonly ({ pose: TPose } | undefined)[],\n): TPose | null {\n const poses: RectPose[] = [];\n for (const d of deps) {\n if (d === undefined) continue;\n const rect = asRectPose(d.pose);\n if (rect === null) return null;\n poses.push(rect);\n }\n if (poses.length === 0) return null;\n const union = unionAABB(poses);\n // Sound by the check above: every member read as a rect, so the union is one\n // too, and a scene holding rect poses is a scene whose `TPose` is one.\n return union === null ? null : (union as unknown as TPose);\n}\n\n/** `pose` as a rect, or `null` when it is some other shape entirely. */\nexport function asRectPose(pose: unknown): RectPose | null {\n if (pose === null || typeof pose !== 'object') return null;\n const p = pose as Partial<RectPose>;\n const rect = typeof p.x === 'number' && typeof p.y === 'number'\n && typeof p.width === 'number' && typeof p.height === 'number';\n return rect ? (pose as RectPose) : null;\n}\n\n/** Merge the kit's own entries under a consumer registry. */\nexport function withKitRegistry<TPose, TData = unknown, TLayer extends string = string>(\n registry: SceneRegistry<TPose, TData, TLayer>,\n): SceneRegistry<TPose, TData, TLayer> {\n return {\n ...registry,\n clipFromPose: {\n [CLIP_NOTHING]: clipNothing,\n ...registry.clipFromPose,\n },\n derivePose: {\n [UNION_OF_CHILDREN]: unionOfChildren as NonNullable<\n SceneRegistry<TPose, TData, TLayer>['derivePose']\n >[string],\n ...registry.derivePose,\n },\n };\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"kitRegistry.js","names":[],"sources":["../../../src/core/scene/kitRegistry.ts"],"sourcesContent":["/**\n * The `SceneRegistry` entries the kit owns.\n *\n * A registry-keyed function has to be resolvable by key in whatever scene\n * loads a snapshot, so a function the *kit* attaches to a node cannot live in\n * the consumer's registry alone — a document saved with a grouped container\n * would come back with a dead key. `createScene` merges these under the\n * consumer's, which stays the winner on a key collision.\n */\nimport { unionAABB } from '../geometry/unionBounds';\nimport type { RectPose, SceneRegistry } from './types';\nimport { CLIP_NOTHING, clipNothing } from './clipNothing';\nimport { BOOLEAN_OF_CHILDREN, booleanOfChildren } from './booleanOfChildren';\n\n/** Registry key for {@link unionOfChildren}. */\nexport const UNION_OF_CHILDREN = 'kit:unionOfChildren';\n\n/**\n * A container's pose as the envelope of what it holds — `unionAABB`, so a\n * rotated member contributes the extent of its ink rather than its unrotated\n * box. Paired with `dependsOn: 'children'`, this is what makes a group's\n * bounds track its members.\n *\n * Returns `null` for an emptied container, which falls back to its authored\n * pose.\n *\n * Reads members as rect poses only: a scene whose poses are shaped otherwise\n * gets `null` here and its container keeps its authored pose. To make such a\n * container track its members, register `unionOfChildrenVia(itsDescriptor)`\n * under {@link UNION_OF_CHILDREN} — the consumer's entry wins the collision.\n */\nexport function unionOfChildren<TPose>(\n _node: unknown,\n deps: readonly ({ pose: TPose } | undefined)[],\n): TPose | null {\n const poses: RectPose[] = [];\n for (const d of deps) {\n if (d === undefined) continue;\n const rect = asRectPose(d.pose);\n if (rect === null) return null;\n poses.push(rect);\n }\n if (poses.length === 0) return null;\n const union = unionAABB(poses);\n // Sound by the check above: every member read as a rect, so the union is one\n // too, and a scene holding rect poses is a scene whose `TPose` is one.\n return union === null ? null : (union as unknown as TPose);\n}\n\n/** `pose` as a rect, or `null` when it is some other shape entirely. */\nexport function asRectPose(pose: unknown): RectPose | null {\n if (pose === null || typeof pose !== 'object') return null;\n const p = pose as Partial<RectPose>;\n const rect = typeof p.x === 'number' && typeof p.y === 'number'\n && typeof p.width === 'number' && typeof p.height === 'number';\n return rect ? (pose as RectPose) : null;\n}\n\n/** Merge the kit's own entries under a consumer registry. */\nexport function withKitRegistry<TPose, TData = unknown, TLayer extends string = string>(\n registry: SceneRegistry<TPose, TData, TLayer>,\n): SceneRegistry<TPose, TData, TLayer> {\n return {\n ...registry,\n clipFromPose: {\n [CLIP_NOTHING]: clipNothing,\n ...registry.clipFromPose,\n },\n derivePath: {\n [BOOLEAN_OF_CHILDREN]: booleanOfChildren as NonNullable<\n SceneRegistry<TPose, TData, TLayer>['derivePath']\n >[string],\n ...registry.derivePath,\n },\n derivePose: {\n [UNION_OF_CHILDREN]: unionOfChildren as NonNullable<\n SceneRegistry<TPose, TData, TLayer>['derivePose']\n >[string],\n ...registry.derivePose,\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;AAeA,IAAa,oBAAoB;;;;;;;;;;;;;;;AAgBjC,SAAgB,gBACd,OACA,MACc;CACd,MAAM,QAAoB,CAAC;CAC3B,KAAK,MAAM,KAAK,MAAM;EACpB,IAAI,MAAM,QAAW;EACrB,MAAM,OAAO,WAAW,EAAE,IAAI;EAC9B,IAAI,SAAS,MAAM,OAAO;EAC1B,MAAM,KAAK,IAAI;CACjB;CACA,IAAI,MAAM,WAAW,GAAG,OAAO;CAC/B,MAAM,QAAQ,UAAU,KAAK;CAG7B,OAAO,UAAU,OAAO,OAAQ;AAClC;;AAGA,SAAgB,WAAW,MAAgC;CACzD,IAAI,SAAS,QAAQ,OAAO,SAAS,UAAU,OAAO;CACtD,MAAM,IAAI;CAGV,OAFa,OAAO,EAAE,MAAM,YAAY,OAAO,EAAE,MAAM,YAClD,OAAO,EAAE,UAAU,YAAY,OAAO,EAAE,WAAW,WACzC,OAAoB;AACrC;;AAGA,SAAgB,gBACd,UACqC;CACrC,OAAO;EACL,GAAG;EACH,cAAc;IACX,eAAe;GAChB,GAAG,SAAS;EACd;EACA,YAAY;IACT,sBAAsB;GAGvB,GAAG,SAAS;EACd;EACA,YAAY;IACT,oBAAoB;GAGrB,GAAG,SAAS;EACd;CACF;AACF"}
|